From 5faec10f7cd2831835fe27038142036f21828437 Mon Sep 17 00:00:00 2001 From: quadrismegistus Date: Fri, 21 Aug 2020 18:52:21 +0100 Subject: [PATCH] this is so cool --- app/config.py | 2 +- app/main.py | 145 ++++++++++++++++++------------------- app/misc.py | 9 +++ app/screens/base.py | 9 ++- app/screens/login/login.kv | 19 +---- app/screens/login/login.py | 50 ++++++++----- p2p/api.py | 18 ++++- p2p/crypto.py | 5 +- 8 files changed, 138 insertions(+), 119 deletions(-) diff --git a/app/config.py b/app/config.py index 9cf57e2..d3a357b 100644 --- a/app/config.py +++ b/app/config.py @@ -1,4 +1,4 @@ -DEFAULT_SCREEN='profile' +DEFAULT_URI='/login/' import random HORIZONTAL = False #random.choice([True,True,True,False]) diff --git a/app/main.py b/app/main.py index 61a375d..45d163f 100644 --- a/app/main.py +++ b/app/main.py @@ -65,11 +65,23 @@ class MyLayout(MDBoxLayout): scr_mngr = ObjectProperty(None) post_id = ObjectProperty() + @property + def app(self): + if not hasattr(self,'_app'): + from kivy.app import App + self._app = App.get_running_app() + return self._app + def rgb(self,r,g,b,a=1): return rgb(r,g,b,a=a) def change_screen(self, screen, *args): self.scr_mngr.current = screen + + def change_screen_from_uri(self,uri,*args): + screen_name = route(uri) + self.app.screen = screen_name + return self.change_screen(screen_name,*args) def view_post(self,post_id): self.post_id=post_id @@ -160,10 +172,19 @@ def draw_background(widget, img_fn='assets/bg.png'): +def route(uri): + prefix,channel,rest = uri.split('/',3) + mapd = { + 'inbox':'feed', + 'outbox':'feed', + 'login':'login', + } + return mapd.get(prefix,None) +# DEFAULT_SCREEN = route(DEFAULT_URI) class MainApp(MDApp): title = 'Komrade' @@ -178,6 +199,14 @@ class MainApp(MDApp): # self.node = p2p.connect() def rgb(self,*_): return rgb(*_) + def change_screen(self, screen, *args): + self.screen=screen + self.root.change_screen(screen,*args) + + def change_screen_from_uri(self,uri,*args): + self.uri=uri + return self.root.change_screen_from_uri(uri,*args) + @property def logger(self): if not hasattr(self,'_logger'): @@ -196,24 +225,20 @@ class MainApp(MDApp): def __init__(self, **kwargs): super().__init__(**kwargs) - # start looping - - # self.log('PATH',sys.path) - # sys.path.append('./p2p') - - - self.event_loop_worker = None self.loop=asyncio.get_event_loop() # load json storage self.username='' self.load_store() - + self.uri=DEFAULT_URI # connect to API self.api = api.Api(log=self.log) - + @property + def channel(self): + return self.uri.split('/')[1] if self.uri and self.uri.count('/')>=2 else None + @@ -248,11 +273,7 @@ class MainApp(MDApp): logo.pos_hint={'center_y':0.43} logo.text_color=root.rgb(*COLOR_LOGO) - # logged in? - if not self.is_logged_in(): - self.root.change_screen('login') - else: - self.root.change_screen(DEFAULT_SCREEN) + self.root.change_screen_from_uri(self.uri if self.uri else DEFAULT_URI) return self.root @@ -262,69 +283,23 @@ class MainApp(MDApp): def load_store(self): if not self.store.exists('user'): return userd=self.store.get('user') - if not userd: userd={} - self.logged_in_when = userd.get('logged_in_when') - self.username = userd.get('username','') - - def is_logged_in(self,just_check_timestamp=True, use_caching=True): - # self.username='root' - # return True - if self.logged_in: return True - if not use_caching: return False - - ### - if not self.store.exists('user'): return False - userd=self.store.get('user') - if not userd: userd={} - if userd.get('logged_in'): - un=userd.get('username') - timestamp=userd.get('logged_in_when') - - # just a time check - if timestamp and just_check_timestamp: - if time.time() - timestamp < self.login_expiry: - self.logged_in=True - #self.username=un - return True - - return False - - def save_login(self,dat): - self.logged_in=True - self.username=dat.get('username') - # self.store.put('username',self.username) - privkey = data.get('private_key') - pubkey = data.get('public_key') - self.store.put('user', - username=un, - private_key = privkey, - public_key = pubkey, - logged_in=True, - logged_in_when=time.time()) - self.root.change_screen('feed') - - - def login(self,un=None,pw=None): - async def do(): - # if not self.store.exists('_keys'): - # {'error':'No login keys present on this device'} - dat = await self.api.login(un,pw) - self.log(dat) - if 'success' in dat: - self.save_login(un) - elif 'error' in dat: - self.root.ids.login_screen.login_status.text=dat['error'] - return False - asyncio.create_task(do()) + if not userd: return - def register(self,un,pw): + self.username = userd.get('username','') + + def register(self,un): async def do(): - dat = await self.api.register(un,pw) + dat = await self.api.register(un) if 'success' in dat: - self.save_login(dat) + self.root.ids.login_screen.login_status.text=dat['success'] + self.root.ids.login_screen.login_status.theme_text_color='Custom' + self.root.ids.login_screen.login_status.text_color=rgb(*COLOR_ACCENT) + await asyncio.sleep(1) + #self.save_login(dat) return True elif 'error' in dat: self.root.ids.login_screen.login_status.text=dat['error'] + await asyncio.sleep(1) return False asyncio.create_task(do()) @@ -371,13 +346,14 @@ class MainApp(MDApp): return {'post_id':res['post_id']} - + @property + def keys(self): + return self.api.keys - async def get_post(self,post_id): return await self.api.get_post(post_id) - async def get_posts(self,uri='/posts/channel/earth'): + async def get_posts(self,uri='/channel/earth'): self.log(f'app.get_posts(uri={uri} -> ...') data = await self.api.get_posts(uri) self.log @@ -392,9 +368,26 @@ class MainApp(MDApp): # return index return newdata - async def get_my_posts(self): + async def get_channel_posts(self,channel,prefix='inbox'): + # am I allowed to? + if not channel in self.keys: + self.log('!! tsk tsk dont be nosy') + return + return await self.get_posts(uri=os.path.join(prefix,channel)) + + async def get_channel_inbox(self,channel): + return await self.get_channel_posts(channel=channel,prefix='inbox') + + async def get_channel_outbox(self,channel): + return await self.get_channel_posts(channel=channel,prefix='outbox') + + async def get_my_posts(self,username=None): + if username is None and self.username: username=self.username + if not username: + self.log(f'!! whose posts?') + return self.log(f'get_my_posts({self.username})') - return await self.get_posts(uri='/posts/author/'+self.username) + return await self.get_channel(username) diff --git a/app/misc.py b/app/misc.py index dea25af..6750dfa 100644 --- a/app/misc.py +++ b/app/misc.py @@ -78,9 +78,17 @@ Builder.load_string( font_name: "assets/font.otf" font_size: "18sp" + + + + """ + ) +def get_separator(height): + from kivymd.uix.boxlayout import MDBoxLayout + return MDBoxLayout(height=height,size_hint=(None,None)) class MyChip(BoxLayout, ThemableBehavior): label = StringProperty() @@ -186,3 +194,4 @@ class MDChooseChip(MDStackLayout): def add_widget(self, widget, index=0, canvas=None): if isinstance(widget, MyChip): return super().add_widget(widget) + diff --git a/app/screens/base.py b/app/screens/base.py index 7864ecb..e92d53b 100644 --- a/app/screens/base.py +++ b/app/screens/base.py @@ -21,8 +21,11 @@ class BaseScreen(MDScreen): def log(self,*x): return self.app.log(*x) + @property + def channel(self): + return self.app.channel + class ProtectedScreen(BaseScreen): def on_pre_enter(self): - if not self.app.is_logged_in(): - self.root.change_screen('login') - + if not self.channel in self.app.keys: + return diff --git a/app/screens/login/login.kv b/app/screens/login/login.kv index 8caa558..84746e1 100644 --- a/app/screens/login/login.kv +++ b/app/screens/login/login.kv @@ -43,7 +43,7 @@ # md_bg_color:1,1,0,1 : - text: 'Enter, Komrade' + # text: 'Enter, Komrade' halign: 'center' size_hint_x: 1 theme_text_color: 'Custom' @@ -117,22 +117,9 @@ size_hint:None,None pos_hint: {'center_x': .5}#, 'bottom':1} -: - text: "login" - on_release: - app.login(self.parent.parent.parent.username_field.text, self.parent.parent.parent.password_field.text) - #app.root.change_screen("welcome") - theme_text_color: "Custom" - text_color: rgb(*COLOR_TEXT) - md_bg_color: 0,0,0,1 - size_hint:None,None - # font_size:'24sp' - # pos_hint: {'center_x': .5, 'bottom':1} - : - text: "join" - on_release: - app.register(self.parent.parent.parent.username_field.text, self.parent.parent.parent.password_field.text) + text: "" + on_release: self.register() theme_text_color: "Custom" text_color: rgb(*COLOR_TEXT) md_bg_color: 0,0,0,1 diff --git a/app/screens/login/login.py b/app/screens/login/login.py index 30aeaa5..025517b 100644 --- a/app/screens/login/login.py +++ b/app/screens/login/login.py @@ -6,13 +6,22 @@ from kivymd.uix.label import MDLabel from kivymd.uix.card import MDSeparator from kivy.uix.label import Label from main import MyLabel,rgb,COLOR_TEXT,COLOR_ICON,COLOR_ACCENT,COLOR_CARD +from misc import * +from kivy.app import App class LoginBoxLayout(MDBoxLayout): pass class LoginButtonLayout(MDBoxLayout): pass class UsernameField(MDTextField): pass class PasswordField(MDTextField): pass class LoginButton(MDRectangleFlatButton): pass -class RegisterButton(MDRectangleFlatButton): pass +class RegisterButton(MDRectangleFlatButton): + def register(self): + un=self.parent.parent.parent.username_field.text + app=App.get_running_app() + app.register(un) + app.change_screen_from_uri(f'/inbox/{un}') + + pass class LoginStatus(MDLabel): pass class UsernameLayout(MDBoxLayout): pass @@ -34,14 +43,15 @@ class LoginScreen(BaseScreen): self.label_title.bold=True self.label_title.markup=True self.label_title.color=rgb(*COLOR_TEXT) + self.label_title.text='Welcome,' # self.label_title.font_size*=1.5 self.layout.add_widget(self.label_title) - self.layout.add_widget(MDSeparator(height='100sp',color=rgb(*COLOR_CARD))) - self.label_username = UsernameLabel(text="username:") + self.layout.add_widget(get_separator('30sp')) + # self.layout.add_widget(MySeparator()) self.layout_username = UsernameLayout() - self.label_username = UsernameLabel(text="username:") + self.label_username = UsernameLabel(text="Komrade") self.username_field = UsernameField() self.username_field.line_color_focus=rgb(*COLOR_TEXT) @@ -55,27 +65,28 @@ class LoginScreen(BaseScreen): #log(self.username_field) # self.username_field.text='hello????' - self.layout_password = UsernameLayout() - self.label_password = UsernameLabel(text='password:') + # self.layout_password = UsernameLayout() + # self.label_password = UsernameLabel(text='password:') - self.label_password.font_name='assets/font.otf' + # self.label_password.font_name='assets/font.otf' self.label_username.font_name='assets/font.otf' - self.password_field = PasswordField() - self.password_field.line_color_focus=rgb(*COLOR_TEXT) - self.password_field.line_color_normal=rgb(*COLOR_TEXT,a=0.25) - self.password_field.font_name='assets/font.otf' + # self.password_field = PasswordField() + # self.password_field.line_color_focus=rgb(*COLOR_TEXT) + # self.password_field.line_color_normal=rgb(*COLOR_TEXT,a=0.25) + # self.password_field.font_name='assets/font.otf' - self.layout_password.add_widget(self.label_password) - self.layout_password.add_widget(self.password_field) - self.layout.add_widget(self.layout_password) + # self.layout_password.add_widget(self.label_password) + # self.layout_password.add_widget(self.password_field) + # self.layout.add_widget(self.layout_password) self.layout_buttons = LoginButtonLayout() + self.layout.add_widget(get_separator('10sp')) self.layout.add_widget(self.layout_buttons) - self.login_button = LoginButton() - self.login_button.font_name='assets/font.otf' - self.layout_buttons.add_widget(self.login_button) + # self.login_button = LoginButton() + # self.login_button.font_name='assets/font.otf' + # self.layout_buttons.add_widget(self.login_button) self.register_button = RegisterButton() self.register_button.font_name='assets/font.otf' @@ -88,10 +99,11 @@ class LoginScreen(BaseScreen): self.layout.add_widget(self.login_status) self.label_title.font_size='22sp' - self.label_password.font_size='18sp' + # self.label_password.font_size='18sp' self.label_username.font_size='18sp' - self.login_button.font_size='12sp' + # self.login_button.font_size='12sp' self.register_button.font_size='12sp' + self.register_button.text='enter' diff --git a/p2p/api.py b/p2p/api.py index ca01167..948a157 100644 --- a/p2p/api.py +++ b/p2p/api.py @@ -412,7 +412,19 @@ class Api(object): async def register(self,name,passkey=None): # if not (name and passkey): return {'error':'Name and password needed'} person = await self.get_person(name) - if person is not None: return {'error':'Person already exists'} + if person is not None: + # try to log in + self.log('my keys',self.keys.keys()) + if not name in self.keys: + return {'error':'Person already exists'} + + # test 3 conditions + privkey=self.keys[name] + pubkey=load_pubkey(person) + + if simple_lock_test(privkey,pubkey): + self.username=name + return {'success':'Logging back in...'} private_key = generate_rsa_key() public_key = private_key.public_key() @@ -428,7 +440,7 @@ class Api(object): write_key_b(pem_private_key, fn_privkey) # good - return {'success':'Account created', 'username':name} + return {'success':'Person created ...', 'username':name} def load_private_key(self,password): @@ -480,7 +492,6 @@ class Api(object): def get_keys(self): res={} for priv_key_fn in os.listdir(KEYDIR): - print(priv_key_fn) if (not priv_key_fn.startswith('.') or not priv_key_fn.endswith('.key')): continue fnfn = os.path.join(KEYDIR,priv_key_fn) print(fnfn) @@ -488,6 +499,7 @@ class Api(object): pub_key=priv_key.public_key() name_key= '.'.join(priv_key_fn.split('.')[1:-1]) res[name_key] = (pub_key, priv_key) + self.log(f'[API] found key {name_key} and added to keychain') return res diff --git a/p2p/crypto.py b/p2p/crypto.py index b8d7ad1..c46c688 100644 --- a/p2p/crypto.py +++ b/p2p/crypto.py @@ -289,4 +289,7 @@ def aes_rsa_decrypt(aes_ciphertext, rsa_priv, encry_aes_key, iv): #, hmac, hmac_ # msg_encr, # sender_encr, # signature_encr - # ]) \ No newline at end of file + # ]) + +def simple_lock_test(privkey,pubkey): + return privkey.public_key().public_numbers() == pubkey.public_numbers() \ No newline at end of file