def login(self, code=None): """See :http:post:`/api/login`. The logged-in user is set as current *user*. """ if code: id = self.r.hget('auth_secret_map', code) if not id: raise ValueError('code_invalid') user = self.users[id.decode()] else: id = 'User:'******'Guest', email=None, auth_secret=randstr()) self.r.oset(user.id, user) self.r.rpush('users', user.id) self.r.hset('auth_secret_map', user.auth_secret, user.id) # Promote first user to staff if len(self.users) == 1: settings = self.settings # pylint: disable=protected-access; Settings is a friend settings._staff = [user.id] self.r.oset(settings.id, settings) return self.authenticate(user.auth_secret)
def set_email(self, email): """See :http:post:`/api/users/(id)/set-email`.""" if self.app.user != self: raise PermissionError() check_email(email) code = randstr() auth_request = AuthRequest(id='AuthRequest:' + randstr(), trashed=False, app=self.app, email=email, code=code) self.app.r.oset(auth_request.id, auth_request) self.app.r.expire(auth_request.id, 10 * 60) if self.app.render_email_auth_message: self._send_email(email, self.app.render_email_auth_message(email, auth_request, code)) return auth_request
def create_meeting(self, title, time=None, location=None, description=None): """See :http:post:`/api/meetings`.""" if not self.user: raise PermissionError() e = InputError() if not str_or_none(title): e.errors['title'] = 'empty' e.trigger() meeting = Meeting(id='Meeting:' + randstr(), trashed=False, app=self, authors=[self.user.id], title=title, time=time.isoformat() + 'Z' if time else None, location=str_or_none(location), description=str_or_none(description)) self.r.oset(meeting.id, meeting) self.r.rpush('meetings', meeting.id) self.activity.publish( Event.create('create-meeting', None, {'meeting': meeting}, app=self)) return meeting
def test_update_db_fresh(self) -> None: files_path = str(Path(gettempdir(), randstr())) app = CatApp(redis_url='15', files_path=files_path) app.r.flushdb() app.update() # type: ignore[no-untyped-call] self.assertEqual(app.settings.title, 'CatApp') self.assertTrue(Path(files_path).is_dir())
async def _create(self, title, *, text=None, resource=None, location=None): # pylint: disable=protected-access; List is a friend self.host[0]._check_permission(self.app.user, 'list-modify') attrs = await WithContent.process_attrs( { 'text': text, 'resource': resource }, app=self.app) if str_or_none(title) is None: raise micro.ValueError('title_empty') item = Item(id='Item:{}'.format(randstr()), app=self.app, authors=[self.app.user.id], trashed=False, text=attrs['text'], resource=attrs['resource'], list_id=self.host[0].id, title=title, location=location.json() if location else None, checked=False) self.app.r.oset(item.id, item) self.app.r.rpush(self.map_key, item.id) self.host[0].activity.publish( Event.create('list-create-item', self.host[0], {'item': item}, self.app)) return item
def create_meeting(self, title, time=None, location=None, description=None): """See :http:post:`/api/meetings`.""" if not self.user: raise PermissionError() e = InputError() if not str_or_none(title): e.errors['title'] = 'empty' e.trigger() meeting = Meeting( id='Meeting:' + randstr(), trashed=False, app=self, authors=[self.user.id], title=title, time=time, location=str_or_none(location), description=str_or_none(description)) self.r.oset(meeting.id, meeting) self.r.rpush('meetings', meeting.id) return meeting
async def create(self, text: Optional[str], resource: Optional[str]) -> Greeting: """Create a :class:`Greeting` and return it.""" user = context.user.get() if not user: raise error.PermissionError() attrs = await WithContent.process_attrs({'text': text, 'resource': resource}, app=self.app) if not (attrs['text'] or attrs['resource']): raise error.ValueError('No text and resource') greeting = Greeting( id='Greeting:{}'.format(randstr()), app=self.app, authors=[user.id], text=attrs['text'], resource=attrs['resource']) self.app.r.oset(greeting.id, greeting) self.app.r.lpush(self.ids.key, greeting.id) self.app.activity.publish( Event.create('greetings-create', None, detail={'greeting': greeting}, app=self.app)) return greeting
def create_agenda_item(self, title, duration=None, description=None): """See :http:post:`/api/meetings/(id)/items`.""" if not self.app.user: raise PermissionError() e = InputError() if str_or_none(title) is None: e.errors['title'] = 'empty' if duration is not None and duration <= 0: e.errors['duration'] = 'not_positive' description = str_or_none(description) e.trigger() item = AgendaItem( id='AgendaItem:' + randstr(), trashed=False, app=self.app, authors=[self.app.user.id], title=title, duration=duration, description=description) self.app.r.oset(item.id, item) self.app.r.rpush(self._items_key, item.id) return item
def create(self, use_case='simple', *, v=2): """See :http:post:`/api/lists`.""" # pylint: disable=unused-argument; former feature toggle # Compatibility for endpoint version (deprecated since 0.22.0) if not self.app.user: raise PermissionError() if use_case not in _USE_CASES: raise micro.ValueError('use_case_unknown') data = _USE_CASES[use_case] id = 'List:{}'.format(randstr()) lst = List( id=id, app=self.app, authors=[self.app.user.id], title=data['title'], description=None, features=data['features'], mode=data.get('mode', 'collaborate'), activity=Activity('{}.activity'.format(id), self.app, subscriber_ids=[])) self.app.r.oset(lst.id, lst) self.app.r.zadd('{}.users'.format(lst.id), {self.app.user.id.encode(): -time()}) self.app.r.rpush(self.map_key, lst.id) self.app.user.lists.add(lst, user=self.app.user) self.app.activity.publish( Event.create('create-list', None, {'lst': lst}, app=self.app)) return lst
def create(self, use_case=None, description=None, title=None, v=1): """See :http:post:`/api/lists`.""" if v == 1: # create(title, description=None) title = title or use_case if title is None: raise TypeError() lst = self.create('simple', v=2) lst.edit(title=title, description=description) return lst if v == 2: # create(use_case='simple') use_case = use_case or 'simple' else: raise NotImplementedError() if not self.app.user: raise PermissionError() if use_case not in _USE_CASES: raise micro.ValueError('use_case_unknown') data = _USE_CASES[use_case] id = 'List:{}'.format(randstr()) lst = List(id=id, app=self.app, authors=[self.app.user.id], title=data['title'], description=None, features=data['features'], mode='collaborate', activity=Activity('{}.activity'.format(id), self.app, subscriber_ids=[])) self.app.r.oset(lst.id, lst) self.app.r.rpush(self.map_key, lst.id) self.app.user.lists.add(lst, user=self.app.user) self.app.activity.publish( Event.create('create-list', None, {'lst': lst}, app=self.app)) return lst
def create_agenda_item(self, title, duration=None, description=None): """See :http:post:`/api/meetings/(id)/items`.""" if not self.app.user: raise PermissionError() e = InputError() if str_or_none(title) is None: e.errors['title'] = 'empty' if duration is not None and duration <= 0: e.errors['duration'] = 'not_positive' description = str_or_none(description) e.trigger() item = AgendaItem(id='AgendaItem:' + randstr(), trashed=False, app=self.app, authors=[self.app.user.id], title=title, duration=duration, description=description) self.app.r.oset(item.id, item) self.app.r.rpush(self._items_key, item.id) return item