diff --git a/komrade/app/app.json b/komrade/app/app.json deleted file mode 100644 index c3a1436..0000000 --- a/komrade/app/app.json +++ /dev/null @@ -1 +0,0 @@ -{"user": {"username": "marx"}} \ No newline at end of file diff --git a/komrade/app/assets/avatars/elon.png b/komrade/app/assets/avatars/elonely.png similarity index 100% rename from komrade/app/assets/avatars/elon.png rename to komrade/app/assets/avatars/elonely.png diff --git a/komrade/app/assets/avatars/marx.png b/komrade/app/assets/avatars/marxbot.png similarity index 100% rename from komrade/app/assets/avatars/marx.png rename to komrade/app/assets/avatars/marxbot.png diff --git a/komrade/app/assets/avatars/marxxx.png b/komrade/app/assets/avatars/marxxx.png new file mode 100644 index 0000000..0088c20 Binary files /dev/null and b/komrade/app/assets/avatars/marxxx.png differ diff --git a/komrade/app/assets/avatars/zuck.png b/komrade/app/assets/avatars/zuckbot.png similarity index 100% rename from komrade/app/assets/avatars/zuck.png rename to komrade/app/assets/avatars/zuckbot.png diff --git a/komrade/app/config.py b/komrade/app/config.py index d0f0c01..affe23e 100644 --- a/komrade/app/config.py +++ b/komrade/app/config.py @@ -31,7 +31,7 @@ if platform.platform().startswith('Linux'): HEIGHT *= 1.25 -WINDOW_SIZE=int(HEIGHT * ASPECT_RATIO),int(HEIGHT) +WINDOW_SIZE=int(HEIGHT),int(HEIGHT * ASPECT_RATIO) BG_IMG='assets/bg-brown.png' diff --git a/komrade/app/main.py b/komrade/app/main.py index 3a5294f..6b1d392 100644 --- a/komrade/app/main.py +++ b/komrade/app/main.py @@ -5,7 +5,8 @@ from config import * import os,sys; sys.path.append(os.path.abspath(os.path.join(os.path.abspath(os.path.join(os.path.dirname(__file__),'..')),'..'))) from komrade import * from komrade.api import Api - +import logging +logger=logging.getLogger(__name__) # monkeypatching the things that asyncio needs import subprocess @@ -94,6 +95,15 @@ class MyLayout(MDBoxLayout): self.post_id=post_id self.change_screen('view') + + + + + + + + + class ProgressPopup(MDDialog): pass class MessagePopup(MDDialog): pass class MyBoxLayout(MDBoxLayout): pass @@ -134,28 +144,6 @@ class MyToolbar(MDToolbar): -def get_tor_proxy_session(): - session = requests.session() - # Tor uses the 9050 port as the default socks port - session.proxies = {'http': 'socks5://127.0.0.1:9150', - 'https': 'socks5://127.0.0.1:9150'} - return session - -def get_async_tor_proxy_session(): - from requests_futures.sessions import FuturesSession - session = FuturesSession() - # Tor uses the 9050 port as the default socks port - session.proxies = {'http': 'socks5://127.0.0.1:9150', - 'https': 'socks5://127.0.0.1:9150'} - return session - - -def get_tor_python_session(): - from torpy.http.requests import TorRequests - with TorRequests() as tor_requests: - with tor_requests.get_session() as s: - return s - def draw_background(widget, img_fn='assets/bg.png'): from kivy.core.image import Image as CoreImage from kivy.graphics import Color, Rectangle @@ -195,74 +183,39 @@ def route(uri): # DEFAULT_SCREEN = route(DEFAULT_URI) -class MainApp(MDApp): +class MainApp(MDApp, Logger): title = 'Komrade' logged_in=False - # store = JsonStore('../p2p/.keys.json') - # store_global = JsonStore('../p2p/.keys.global.json') - store = JsonStore('app.json') login_expiry = 60 * 60 * 24 * 7 # once a week texture = ObjectProperty() - uri = '/inbox/world' + uri='/do/login' - # def connect(self): - # # connect to kad? - # self.node = p2p.connect() def rgb(self,*_): return rgb(*_) def change_screen(self, screen, *args): self.screen=screen self.root.change_screen(screen,*args) - @property - def channel(self): - if not hasattr(self,'uri'): return None - if self.uri.count('/')<2: return None - return self.uri.split('/')[2] - - def change_screen_from_uri(self,uri,*args): - self.uri=uri - self.log('CHANGING SCREEN',uri,'??') - return self.root.change_screen_from_uri(uri,*args) + def get_username(self): return self._name @property - def logger(self): - if not hasattr(self,'_logger'): - import logging - handler = logging.StreamHandler() - formatter = logging.Formatter('[%(asctime)s]\n%(message)s\n') - handler.setFormatter(formatter) - self._logger = logger = logging.getLogger('komrade') - logger.addHandler(handler) - logger.setLevel(logging.DEBUG) - return self._logger - - def log(self,*args,**msgs): - line = ' '.join(str(x) for x in args) - self.logger.debug(line) + def crypt(self): + if not hasattr(self,'_crypt'): + from komrade.backend.crypt import Crypt + self._crypt = Crypt( + fn=PATH_CRYPT_CA_DATA, + encrypt_values=False, + ) + return self._crypt def __init__(self, **kwargs): super().__init__(**kwargs) 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(log=self.log) - - @property - async def node(self): - return await self.api.node - - def get_username(self): - if hasattr(self,'username'): return self.username - self.load_store() - if hasattr(self,'username'): return self.username - return '' + self.komrade=None + self._name='' def build(self): @@ -288,7 +241,9 @@ class MainApp(MDApp): return self.root - + # def boot(self,username): + # kommie = Komrade(username) + # if self.exists_locally_as_contact() def load_store(self): @@ -355,34 +310,14 @@ class MainApp(MDApp): @property def keys(self): - return self.api.keys + return self.komrade.contacts() async def get_post(self,post_id): - return await self.api.get_post(post_id) - - async def get_posts(self,uri=b'/inbox/world'): - return await self.persona.read_inbox(uri) - + return self.komrade.read_post() - # if uri.count('/')<2: raise Exception('not a URI: '+uri) - # if 'login' in uri: - # raise Exception('!!!! '+uri) - - # self.log(f'app.get_posts(uri={uri} -> ...') - # data = await self.api.get_posts(uri) - # self.log(f'app.get_posts() got back from api.get_posts() a {type(data)}') - - # newdata=[] - # for d in data: - # # self.log('data d:',d) - # if not 'val' in d: continue - # newdict = dict(d['val'].items()) - # newdict['timestamp']=float(d['time']) - # newdict['to_name']=d['channel'] - # newdata.append(newdict) + def get_posts(self,uri=b'/inbox/world'): + return self.komrade.posts() - # # return index - # return newdata async def get_channel_posts(self,channel,prefix='inbox'): # am I allowed to? @@ -408,17 +343,17 @@ class MainApp(MDApp): are finished ''' # self.other_task = asyncio.ensure_future(self.waste_time_freely()) - self.other_task = asyncio.ensure_future(self.api.connect_forever()) + # self.other_task = asyncio.ensure_future(self.api.connect_forever()) async def run_wrapper(): # we don't actually need to set asyncio as the lib because it is # the default, but it doesn't hurt to be explicit await self.async_run() #async_lib='asyncio') print('App done') - self.other_task.cancel() - - return asyncio.gather(run_wrapper(), self.other_task) + # self.other_task.cancel() + # return asyncio.gather(run_wrapper(), self.other_task) + asyncio.run(run_wrapper()) @@ -431,12 +366,21 @@ class MainApp(MDApp): self.dialog.open() #stop + def stat(self,msg,komrade_name='Telephone',pause=False,**y): + logger.info(msg) + # self.open_msg_dialog(msg) + self.root.add_card({ + 'author':komrade_name, + 'to_name':self.komrade.name if self.komrade else '?', + 'content':str(msg) + }) + def open_msg_dialog(self,msg): from screens.post.post import MessagePopup,ProgressPopup if not hasattr(self,'msg_dialog') or not self.msg_dialog: self.msg_dialog = MessagePopup() - self.msg_dialog.ids.msg_label.text=msg - self.msg_dialog.open() + self.msg_dialog.ids.msg_label.text=msg + self.msg_dialog.open() def close_dialog(self): if hasattr(self,'dialog'): diff --git a/komrade/app/root.kv b/komrade/app/root.kv index cffa19c..afb227b 100644 --- a/komrade/app/root.kv +++ b/komrade/app/root.kv @@ -164,7 +164,7 @@ MyLayout: background_palette: 'Red' theme_text_color:'Custom' background_hue: '500' - right_action_items: [['account-circle-outline', partial(root.change_screen, 'profile')],['card-text', partial(root.change_screen_from_uri, '/inbox/world')],['message-outline', partial(root.change_screen, 'messages')],['pencil-plus-outline', partial(root.change_screen, 'post')],['exit-run', partial(root.change_screen, 'login')]] + right_action_items: [['account-circle-outline', partial(root.change_screen, 'profile')],['card-text', partial(root.change_screen, 'feed')],['message-outline', partial(root.change_screen, 'messages')],['pencil-plus-outline', partial(root.change_screen, 'post')],['exit-run', partial(root.change_screen, 'login')]] #left_action_items: [[f"assets/fist2.png", partial(root.change_screen, 'feed')]] # ['bell-outline', partial(root.change_screen, 'login')] diff --git a/komrade/app/screens/base.py b/komrade/app/screens/base.py index 2104aad..304602f 100644 --- a/komrade/app/screens/base.py +++ b/komrade/app/screens/base.py @@ -11,6 +11,7 @@ import asyncio ### Base screens class BaseScreen(MDScreen): + @property def root(self): return self.app.root @@ -28,6 +29,14 @@ class BaseScreen(MDScreen): + + + + + + + + class ProtectedScreen(BaseScreen): pass # def on_pre_enter(self): # if not self.channel in self.app.api.keys: diff --git a/komrade/app/screens/feed/feed.kv b/komrade/app/screens/feed/feed.kv index 93a4905..3ae9065 100644 --- a/komrade/app/screens/feed/feed.kv +++ b/komrade/app/screens/feed/feed.kv @@ -143,7 +143,7 @@ id: post_content text: '' pos_hint: {'center_y':1} - font_size:'13sp' + font_size:'24sp' # font_style:'H5' #font_name: "Strengthen" # height: '400' @@ -162,8 +162,8 @@ id: post orientation: "vertical" padding: "20dp" - size_hint: (None, None) - size:('500sp','800sp') + size_hint: (0.75, None) + # size:('800sp','800sp') # adaptive_height: True pos_hint: {"center_x": .5, "center_y": .5} md_bg_color: rgb(*COLOR_CARD) diff --git a/komrade/app/screens/feed/feed.py b/komrade/app/screens/feed/feed.py index 94625f0..01449ef 100644 --- a/komrade/app/screens/feed/feed.py +++ b/komrade/app/screens/feed/feed.py @@ -142,7 +142,7 @@ class PostCard(MDCard): recip='@'+recip if recip and recip[0].isalpha() else recip self.author_label.text+='\n[size=14sp]to '+recip+'[/size]' self.author_label.markup=True - self.author_label.font_size = '18sp' + self.author_label.font_size = '24sp' self.author_avatar = author_avatar = PostAuthorAvatar(source=f'assets/avatars/{self.author}.png') #self.img_src) self.author_section_layout.add_widget(author_avatar) self.author_section_layout.add_widget(author_label) @@ -175,6 +175,8 @@ class PostCard(MDCard): # self.log(image.image_ratio) self.post_content = PostContent(text=self.content) + self.post_content.font_size = '24sp' + # post_layout = PostGridLayout() #content = PostContent() @@ -241,27 +243,56 @@ class PostCard(MDCard): class FeedScreen(BaseScreen): posts = ListProperty() - def on_pre_enter(self): - super().on_pre_enter() + # def on_pre_enter(self): + # if not hasattr(self,'get_posts'): self.get_posts=self.app.komrade.posts + # super().on_pre_enter() + # for post in self.posts: + # self.ids.post_carousel.remove_widget(post) - async def go(): - # self.log('ids:' +str(self.ids.post_carousel.ids)) - for post in self.posts: - self.ids.post_carousel.remove_widget(post) - - i=0 - lim=25 - posts=await self.app.get_posts(self.app.uri) - for i,post in enumerate(reversed(posts)): - # for i,post in enumerate(posts)): - #if ln.startswith('@') or ln.startswith('RT '): continue - #i+=1 - if i>lim: break - - #post = Post(title=f'Marx Zuckerberg', content=ln.strip()) - #self.log('???') - post_obj = PostCard(post) - self.posts.append(post_obj) - self.ids.post_carousel.add_widget(post_obj) - asyncio.create_task(go()) + # i=0 + # lim=25 + # self.app.komrade.get_updates() + # posts=self.get_posts() + # for i,post in enumerate(reversed(posts)): + # if i>lim: break + # data = { + # 'author':post.from_name, + # 'to_name':post.to_name, + # 'content':post.msg.get('txt') if type(post.msg)==dict else str(post.msg) + # } + # post_obj = PostCard(data) + # self.posts.append(post_obj) + # self.ids.post_carousel.add_widget(post_obj) + + def on_pre_enter(self): + self.clear_deck() + # for i,x + + + + + #### + # + + @property + def cards(self): + if not hasattr(self,'_cards'): self._cards=[] + return self._cards + + def clear_deck(self): + for card in self.cards: + self.ids.post_carousel.remove_widget(card) + + def add_card(self,data): + card = PostCard(data) + if not hasattr(self,'_cards'): self._cards=[] + self._cards.append(card) + + self.app.log('card!',data) + self.app.log('ids:',self.ids.keys(), type(self)) + self.app.log('card obj?',card) + # self.ids.post_carousel.add_widget(card) + stop + + diff --git a/komrade/app/screens/login/login.kv b/komrade/app/screens/login/login.kv index ac8e7b8..080292e 100644 --- a/komrade/app/screens/login/login.kv +++ b/komrade/app/screens/login/login.kv @@ -118,9 +118,44 @@ size_hint:None,None pos_hint: {'center_x': .5}#, 'bottom':1} +: + id: passpopup + type: "custom" + size: ('300dp','300dp') + + MDBoxLayout: + id: msg_popup_box_layout + size_hint:(None,None) + orientation: 'vertical' + cols:1 + md_bg_color: rgb(*COLOR_CARD) + spacing:'0dp' + padding:'0dp' + pos_hint: {'center_x':0.5, 'center_y':0.5} + radius:[20,] + border_radius:20 + canvas: + Color: + rgba: rgb(*COLOR_CARD_BORDER,a=0.5) + Line: + width: 1 + rounded_rectangle: (self.x, self.y, self.width, self.height, 20, 20, 20, 20) + + + + : text: "" - on_release: self.register() + on_release: self.enter() + theme_text_color: "Custom" + text_color: rgb(*COLOR_TEXT) + md_bg_color: 0,0,0,1 + # font_size:'24sp' + # size_hint:1,None + +: + text: "" + on_release: self.login() theme_text_color: "Custom" text_color: rgb(*COLOR_TEXT) md_bg_color: 0,0,0,1 diff --git a/komrade/app/screens/login/login.py b/komrade/app/screens/login/login.py index 13ef49c..f88073a 100644 --- a/komrade/app/screens/login/login.py +++ b/komrade/app/screens/login/login.py @@ -1,24 +1,36 @@ -from screens.base import BaseScreen -from kivymd.uix.boxlayout import MDBoxLayout -from kivymd.uix.textfield import MDTextField -from kivymd.uix.button import MDRectangleFlatButton -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 +import os,sys; sys.path.append(os.path.abspath(os.path.join(os.path.abspath(os.path.join(os.path.dirname(__file__),'..')),'..'))) +from komrade import * +from screens.base import * +from kivymd.uix.boxlayout import * +from kivymd.uix.textfield import * +from kivymd.uix.button import * +from kivymd.uix.label import * +from kivymd.uix.card import * +from kivy.uix.label import * +from kivymd.uix.dialog import * +from main import * from misc import * -from kivy.app import App +from kivy.app import * + +import logging +logger = logging.getLogger(__name__) class LoginBoxLayout(MDBoxLayout): pass class LoginButtonLayout(MDBoxLayout): pass class UsernameField(MDTextField): pass class PasswordField(MDTextField): pass class LoginButton(MDRectangleFlatButton): pass -class RegisterButton(MDRectangleFlatButton): - def register(self): +class RegisterButton(MDRectangleFlatButton,Logger): + def enter(self): un=self.parent.parent.parent.username_field.text - app=App.get_running_app() - app.register(un) + login_screen = self.parent.parent.parent + + login_screen.boot(un) + + # logger.info('types',type(self.parent),type(self.parent.parent.parent)) + + # app=App.get_running_app() + # app.boot(un) # app.change_screen_from_uri(f'/inbox/{un}') pass @@ -28,6 +40,8 @@ class UsernameLayout(MDBoxLayout): pass class UsernameLabel(MDLabel): pass class WelcomeLabel(MDLabel): pass +class PasswordPopup(MDDialog): pass + class LoginScreen(BaseScreen): #def on_pre_enter(self): # global app @@ -36,6 +50,8 @@ class LoginScreen(BaseScreen): def on_pre_enter(self): #log(self.ids) #log('hello?') + self.dialog=None + self.pass_added=False self.layout = LoginBoxLayout() self.label_title = WelcomeLabel() self.label_title.font_name='assets/font.otf' @@ -66,27 +82,27 @@ 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('20sp')) self.layout.add_widget(self.layout_buttons) - # self.login_button = LoginButton() - # self.login_button.font_name='assets/font.otf' + self.login_button = LoginButton() + self.login_button.font_name='assets/font.otf' # self.layout_buttons.add_widget(self.login_button) self.register_button = RegisterButton() @@ -100,9 +116,9 @@ class LoginScreen(BaseScreen): self.layout.add_widget(self.login_status) self.label_title.font_size='18sp' - # self.label_password.font_size='18sp' + self.label_password.font_size='18sp' self.label_username.font_size='20sp' - # self.login_button.font_size='12sp' + self.login_button.font_size='12sp' self.register_button.font_size='9sp' self.register_button.text='enter' self.username_field.font_size='20sp' @@ -117,7 +133,59 @@ class LoginScreen(BaseScreen): #pass - def on_enter(self): - un=self.app.get_username() - if un: self.username_field.text = un - \ No newline at end of file + # def on_enter(self): + # un=self.app.get_username() + # if un: self.username_field.text = un + + def show_pass_opt(self): + if not self.pass_added: + self.layout.add_widget(self.layout_password,index=2) + self.pass_added=True + + def show_pass_opt1(self,button_text='login'): + if not self.dialog: + self.dialog = PasswordPopup( + title="password:", + type="custom", + content_cls=MDTextField(password=True), + buttons=[ + MDFlatButton( + text="login" + ), + ], + ) + self.dialog.open() + + def getpass_func(self,why_msg): + return self.password_field.text + + def boot(self,un): + kommie = Komrade(un,getpass_func=self.getpass_func) + # self.show_pass_opt() + if kommie.exists_locally_as_account(): + self.login_status.text='You should be able to log into this account.' + if kommie.privkey: + self.login_status.text=f'Welcome back, Komrade @{un}' + self.app.is_logged_in=True + self.app.username=kommie.name + self.app.komrade=kommie + self.remove_widget(self.layout) + self.root.change_screen('feed') + else: + self.login_status.text='Login failed...' + + # self.layout.add_widget(self.layout_password) + elif kommie.exists_locally_as_contact(): + self.login_status.text='Komrade exists as a contact of yours.' + else: + self.login_status.text='Komrade not known on this device. Registering...' + res = kommie.register(logfunc=self.app.stat) + if kommie.privkey: + self.login_status.text='Registered' + self.app.is_logged_in=True + self.app.username=kommie.name + self.app.komrade=kommie + self.remove_widget(self.layout) + self.app.change_screen('feed') + else: + self.login_status.text = 'Sign up failed...' \ No newline at end of file diff --git a/komrade/app/screens/messages/messages.py b/komrade/app/screens/messages/messages.py index 99d9497..a90050c 100644 --- a/komrade/app/screens/messages/messages.py +++ b/komrade/app/screens/messages/messages.py @@ -4,8 +4,8 @@ from screens.post.post import * class MessagesScreen(FeedScreen): def on_pre_enter(self): - if not self.app.username: return + if not self.app.komrade: return - self.app.uri = '/inbox/'+self.app.username + self.get_posts = self.app.komrade.messages super().on_pre_enter() diff --git a/komrade/backend/keymaker.py b/komrade/backend/keymaker.py index 5100fda..4b458eb 100644 --- a/komrade/backend/keymaker.py +++ b/komrade/backend/keymaker.py @@ -10,6 +10,8 @@ from pythemis.skeygen import GenerateSymmetricKey from pythemis.scell import SCellSeal from pythemis.exception import ThemisError +import logging +logger=logging.getLogger(__name__) class KomradeKey(ABC,Logger): @@ -65,12 +67,14 @@ class KomradeSymmetricKeyWithPassphrase(KomradeSymmetricKey): def passhash(self): if not self._passhash: try: - self._passhash = hasher(getpass(WHY_MSG)) + self._passhash = hasher(self.getpass_func(WHY_MSG)) except (KeyboardInterrupt,EOFError) as e: exit('@Keymaker: Incorrect password. Goodbye.') return self._passhash - def __init__(self,passphrase=None,passhash=None): + def __init__(self,passphrase=None,passhash=None,getpass_func=None): + self.getpass_func = getpass_func if getpass_func else getpass + # logger.info('Pass key started with getpass func:',self.getpass_func) if passhash: self._passhash = passhash elif passphrase: @@ -229,13 +233,13 @@ KEYMAKER_DEFAULT_KEY_TYPES = { -def get_key_obj(keyname,data,key_types=KEYMAKER_DEFAULT_KEY_TYPES): +def get_key_obj(keyname,data,key_types=KEYMAKER_DEFAULT_KEY_TYPES,getpass_func=None): if keyname.endswith('_decr'): # print('get_key_obj',keyname,data)#,key_types) try: data_s = data.decode() if data_s in {KEY_TYPE_SYMMETRIC_WITH_PASSPHRASE,KomradeSymmetricKeyWithPassphrase.__name__}: - return KomradeSymmetricKeyWithPassphrase() + return KomradeSymmetricKeyWithPassphrase(getpass_func=getpass_func) except UnicodeDecodeError: return KomradeSymmetricKeyWithoutPassphrase(data) @@ -256,7 +260,8 @@ class Keymaker(Logger): keychain={}, path_crypt_keys=PATH_CRYPT_CA_KEYS, path_crypt_data=PATH_CRYPT_CA_DATA, - callbacks={}): + callbacks={}, + getpass_func=None): # init logger with callbacks super().__init__(callbacks=callbacks) @@ -268,6 +273,8 @@ class Keymaker(Logger): self._keychain={**keychain} self.path_crypt_keys=path_crypt_keys self.path_crypt_data=path_crypt_data + self.getpass_func=getpass_func + # logger.info('Keymaker booted with getpass_func',getpass_func) # boot keychain self._keychain = self.keychain() @@ -308,7 +315,7 @@ class Keymaker(Logger): def load_keychain_from_bytes(self,keychain): for keyname,keyval in keychain.items(): - keychain[keyname] = get_key_obj(keyname,keyval) + keychain[keyname] = get_key_obj(keyname,keyval,getpass_func=self.getpass_func) return keychain def keychain(self,look_for=KEYMAKER_DEFAULT_ALL_KEY_NAMES): @@ -328,7 +335,7 @@ class Keymaker(Logger): if keyname in keys and keys[keyname]: continue key = self.crypt_keys.get(uri,prefix=f'/{keyname}/') # print('found in crypt:',key,'for',keyname) - if key: keys[keyname]=get_key_obj(keyname,key) + if key: keys[keyname]=get_key_obj(keyname,key,getpass_func=self.getpass_func) # try to assemble keys = self.assemble(self.assemble(keys)) @@ -506,12 +513,12 @@ class Keymaker(Logger): encr_key = keychain.get(encr_key_name) # self.log(f'about to decrypt {encr_key} with {decr_key} and {decr_key.cell}') unencr_key = decr_key.decrypt(encr_key.data) - keychain[unencr_key_name] = get_key_obj(unencr_key_name,unencr_key) + keychain[unencr_key_name] = get_key_obj(unencr_key_name,unencr_key,getpass_func=self.getpass_func) else: # unencr_key = keychain.get(unencr_key_name) # self.log(f'about to encrypt {unencr_key} with {decr_key}') encr_key = decr_key.encrypt(unencr_key.data) - keychain[encr_key_name] = get_key_obj(encr_key_name,encr_key) + keychain[encr_key_name] = get_key_obj(encr_key_name,encr_key,getpass_func=self.getpass_func) except ThemisError as e: #exit('Incorrect password.') #self.log('error!!',e,decrypt,decr_key,encr_key,decr_key_name,encr_key_name) diff --git a/komrade/backend/komrades.py b/komrade/backend/komrades.py index 84b5bc6..8d5e230 100644 --- a/komrade/backend/komrades.py +++ b/komrade/backend/komrades.py @@ -4,7 +4,8 @@ from komrade.backend import * from komrade.backend.keymaker import * from komrade.backend.messages import Message - +import logging +logger = logging.getLogger(__name__) @@ -13,8 +14,9 @@ from komrade.backend.messages import Message class KomradeX(Caller): - def __init__(self, name=None, pubkey=None, callbacks={}): - super().__init__(name=name, callbacks=callbacks) + def __init__(self, name=None, pubkey=None, callbacks={}, getpass_func=None): + # logger.info('booting KomradeX with getpass_func:',getpass_func) + super().__init__(name=name, callbacks=callbacks, getpass_func=getpass_func) self.log(f'Starting up with callbacks: {self._callbacks}') self.boot(create=False) # special? @@ -143,7 +145,7 @@ class KomradeX(Caller): qr_str=self.qr_str(pubkey.data_b64) logfunc(f'(1) You may store your public key both on your device hardware, as well as share it with anyone you wish:\n\n{pubkey.data_b64_s}\n\nIt will also be stored as a QR code on your device:\n{qr_str}',pause=True,clear=True) logfunc('You must also register your username and public key with Komrade @Operator on the remote server.\n\nShall Komrade @Telephone send them over?',pause=False,clear=False)#),dict_format(data,tab=2),pause=True) - ok_to_send = input(f'\n@{name}: [Y/n] ') + ok_to_send = 'y' #input(f'\n@{name}: [Y/n] ') if ok_to_send.strip().lower()=='n': logfunc('Cancelling registration.') return @@ -181,6 +183,8 @@ class KomradeX(Caller): ## 3) Have passphrase? if SHOW_STATUS and not passphrase: passphrase = self.cli.status_keymaker_part2(name,passphrase,pubkey,privkey,hasher,self) + elif not passphrase and self.getpass_func: + passphrase=self.getpass_func(WHY_MSG) else: if not passphrase: passphrase = DEBUG_DEFAULT_PASSPHRASE while not passphrase: @@ -661,7 +665,11 @@ class KomradeX(Caller): posts=[] for post_id in inbox: self.log('???',post_id,inbox_prefix) - res_post = self.read_post(post_id) + try: + res_post = self.read_post(post_id) + except ThemisError as e: + self.log('!! ',e) + continue self.log('got post:',res_post) if res_post.get('success') and res_post.get('post'): post=res_post.get('post') diff --git a/komrade/backend/operators.py b/komrade/backend/operators.py index 9d72137..9d39213 100644 --- a/komrade/backend/operators.py +++ b/komrade/backend/operators.py @@ -86,7 +86,8 @@ class Operator(Keymaker): keychain = {}, path_crypt_keys=PATH_CRYPT_CA_KEYS, path_crypt_data=PATH_CRYPT_CA_DATA, - callbacks={} + callbacks={}, + getpass_func=None ): global PHONEBOOK @@ -97,7 +98,8 @@ class Operator(Keymaker): keychain=keychain, path_crypt_keys=path_crypt_keys, path_crypt_data=path_crypt_data, - callbacks=callbacks + callbacks=callbacks, + getpass_func=getpass_func ) diff --git a/komrade/constants.py b/komrade/constants.py index db36557..8b88e22 100644 --- a/komrade/constants.py +++ b/komrade/constants.py @@ -4,8 +4,8 @@ KOMRADE_ONION = 'u7spnj3dmwumzoa4.onion' KOMRADE_ONION2 = 'rwg4zcnpwshv4laq.onion' #'128.232.229.63' #'komrade.app' -OPERATOR_API_URL = f'http://{KOMRADE_ONION}/op/' -# OPERATOR_API_URL = f'http://{KOMRADE_URL}/op/' +# OPERATOR_API_URL = f'http://{KOMRADE_ONION}/op/' +OPERATOR_API_URL = f'http://{KOMRADE_URL}/op/' # paths @@ -17,6 +17,7 @@ PATH_KOMRADE_DATA = os.path.join(PATH_KOMRADE,'.data') PATH_CRYPT_OP_KEYS = os.path.join(PATH_KOMRADE_KEYS,'.op.db.keys.crypt') PATH_CRYPT_OP_DATA = os.path.join(PATH_KOMRADE_DATA,'.op.db.data.crypt') + # PATH_CRYPT_CA_KEYS = os.path.join(PATH_KOMRADE_KEYS,'.ca.db.keys.crypt') # PATH_CRYPT_CA_DATA = os.path.join(PATH_KOMRADE_DATA,'.ca.db.data.encr') PATH_CRYPT_CA_KEYS = PATH_CRYPT_OP_KEYS @@ -26,6 +27,8 @@ PATH_QRCODES = os.path.join(PATH_KOMRADE,'contacts') PATH_SECRETS = PATH_SUPER_SECRETS = os.path.join(PATH_USER_HOME,'.secrets') PATH_SUPER_SECRET_OP_KEY = os.path.join(PATH_SUPER_SECRETS,'.komrade.op.key') + + PATH_LOG_OUTPUT = os.path.join(PATH_KOMRADE,'logs') diff --git a/komrade/utils.py b/komrade/utils.py index d909b3a..db73b15 100644 --- a/komrade/utils.py +++ b/komrade/utils.py @@ -28,17 +28,17 @@ class CallbackHandler(Handler): # log_entry, headers={"Content-type": "application/json"}).content -def logger(): +def logger(name=__name__): import logging handler = logging.StreamHandler() formatter = logging.Formatter('[%(asctime)s]\n%(message)s\n') handler.setFormatter(formatter) - logger = logging.getLogger('komrade') + logger = logging.getLogger(name) logger.addHandler(handler) logger.setLevel(logging.DEBUG) return logger -LOG = None +LOG = logger().info def log(*x,off=False): global LOG