def check_grace_period(self): sess = self.request.session if "tos_grace_period_expires" not in self.request.session: self.logger.debug( "%s started grace period of %s seconds", self.request.authenticated_userid, self.grace_seconds, ) sess["tos_grace_period_expires"] = utcnow() + timedelta( seconds=self.grace_seconds ) if utcnow() > sess["tos_grace_period_expires"]: raise TermsNotAccepted()
def __init__(self, title = "", key = None, ip = None, login = utcnow(), last = utcnow(), active = True, max_valid = None, user_agent = None, api_key = None, ip_locked = ()): self.title = title self.key = key self.ip = ip self.login = login self.last = last self.active = active self.max_valid = max_valid self.user_agent = user_agent self.api_key = api_key self.ip_locked = frozenset(ip_locked)
def claim_ticket(ticket, request, user_identifier): #Is the ticket open? if ticket.get_workflow_state() != 'open': raise HTTPForbidden("Access already granted with this ticket") #Find required resources and do some basic validation meeting = find_interface(ticket, IMeeting) root = find_root(ticket) assert meeting assert root if '@' in user_identifier: user = root['users'].get_user_by_email(user_identifier, None) else: user = root['users'].get(user_identifier, None) if user is None: raise HTTPForbidden("No user could be looked up via: %r" % user_identifier) meeting.add_groups(user.userid, ticket.roles) ticket.claimed_by = user.userid ticket.set_workflow_state(request, 'closed') ticket.closed = utcnow() #If ticket and user profile has the same email, consider that email validated #This will notify and perhaps fetch other tickets as well if user.email == ticket.email: user.email_validated = True return user
def __init__(self, userid, data, id, timestamp = None): if timestamp == None: timestamp = utcnow() self.userid = userid self.data = OOBTree(data) self.id = id self.timestamp = timestamp
def needs_check(self): try: return self.request.session["tos_check_again_at"] < utcnow() except KeyError: pass if self.agreed_tos is not None: return True
def add(self, userid, event_name): # It shouldn't be possible to the same event several times, # so we don't need to check for that if userid not in self: self[userid] = PersistentList() if event_name == "checkin": self[userid].append({"in": utcnow()}) elif event_name == "checkout": try: self[userid][-1]["in"] except (KeyError, IndexError): # in case logging was added while users where checked in, they won't exist return self[userid][-1]["out"] = utcnow() else: # pragma: no coverage raise ValueError("Wrong event name")
def __init__(self, number, token, creator): self.number = number self.created = utcnow() self.claimed = None self.claimed_by = None self.token = token self.created_by = creator
def __init__(self, data=None, **kwargs): if 'creator' in kwargs and 'creators' not in kwargs: # Arche compat hack kwargs['creators'] = kwargs.pop('creator') if not kwargs.get('creators', None): request = get_current_request() if request is None: # request will be None in some tests userid = None else: userid = request.authenticated_userid if userid: kwargs['creators'] = (userid,) else: #FIXME: We'd like some sort of logging here, #but if we log in voteit.core, any poll plugin test will die very strangely #It has something with cleanup of logging in multithreading in setuptools pass #pragma : no cover #Set owner - if it is in kwargs now if 'creators' in kwargs: userid = kwargs['creators'][0] #Don't send updated event on add self.local_roles[userid] = (ROLE_OWNER,) if 'created' not in kwargs: kwargs['created'] = utcnow() if 'modified' not in kwargs: kwargs['modified'] = kwargs['created'] if 'uid' not in kwargs: kwargs['uid'] = unicode(uuid4()) super(BaseContent, self).__init__(data=data) self.set_field_appstruct(kwargs, notify = False, mark_modified = True)
def add_close_timestamp(obj, event): """ Add timestamps when a meeting, ai or poll is closed. """ #Note: Use set_field_appstruct since we want the IObjectUpdatedEvent to be sent so the catalog gets reindexed. if event.new_state == 'closed': obj.set_field_appstruct({'end_time': utcnow()}) #Clear end time when something was moved from closed to something else, Ie reopened. if event.old_state == 'closed': obj.set_field_appstruct({'end_time': None})
def send_invite_ticket(ticket, request, message = ""): if ticket.closed: #Just as a precaution return meeting = find_interface(ticket, IMeeting) html = render_invite_ticket(ticket, request, message = message) subject = _(u"Invitation to ${meeting_title}", mapping = {'meeting_title': meeting.title}) if send_email(request, subject = subject, recipients = ticket.email, html = html, send_immediately = True): ticket.sent_dates.append(utcnow())
def add_start_timestamp(obj, event): """ Add timestamps when a meeting, ai or poll is started. """ #Note: Use set_field_appstruct since we want the IObjectUpdatedEvent to be sent so the catalog gets reindexed. if event.old_state == 'upcoming' and event.new_state == 'ongoing': obj.set_field_appstruct({'start_time': utcnow()}) #Clear start_time if it is moved to upcoming again if event.old_state == 'ongoing' and event.new_state == 'upcoming': obj.set_field_appstruct({'start_time': None})
def add_and_start_entry(request, context): assert request.authenticated_userid profile = request.root['users'][request.authenticated_userid] factory = request.content_factories['TimeEntry'] obj = factory(created=utcnow()) context[obj.uid] = obj profile.ongoing_entry = obj.uid return obj
def stop_entry(request): assert request.authenticated_userid profile = request.root['users'][request.authenticated_userid] if profile.ongoing_entry: entry = request.resolve_uid(profile.ongoing_entry) entry.stop_time = utcnow() profile.ongoing_entry = "" return entry
def close_poll(self): """ Close the poll. """ self.ballots = self.calculate_ballots() poll_plugin = self.get_poll_plugin() poll_plugin.handle_close() uid_states = poll_plugin.change_states_of() if uid_states: self.adjust_proposal_states(uid_states) self.set_field_appstruct({'end_time': utcnow()})
def new(self, userid, **kw): data = {'ip': self.request.client_addr, 'login': utcnow(), 'last': utcnow(), 'active': True, 'user_agent': self.request.user_agent, 'max_valid': self.default_max_valid} data.update(kw) if userid not in self.sessions: self.sessions[userid] = LOBTree() self.cleanup(userid) try: next_key = self.sessions[userid].maxKey() + 1 except ValueError: next_key = 1 self.sessions[userid][next_key] = ad = AuthData(key = next_key, **data) self.disable_inactive(userid) return ad
def total(self, userid): """ Check total time, returns timedelta. """ if userid not in self: return None total = timedelta() for item in self.get(userid, ()): checkin = item["in"] checkout = item.get("out", utcnow()) total += checkout - checkin return total
def endorsements(self, value): if not isinstance(self._endorsements, OOBTree): self._endorsements = OOBTree() # Add new with timestamp for userid in set(value) - set(self._endorsements): self.local_roles.add(userid, ROLE_VIEWER) self._endorsements[userid] = utcnow() # Remove no longer endorsing userids for userid in set(self._endorsements) - set(value): del self._endorsements[userid] self.local_roles.remove(userid, ROLE_VIEWER)
def test_end_time(self): obj = self._add_mock_meeting() now = utcnow() now_unix = timegm(now.timetuple()) obj.update(end_time=now) self.assertEqual( self.query("end_time == %s and path == '/meeting'" % now_unix)[0], 1) qy = ("%s < end_time < %s and path == '/meeting'" % (now_unix - 1, now_unix + 1)) self.assertEqual(self.query(qy)[0], 1)
def validate(self, userid, token, ip_addr): try: assert userid, _("Token not found or used already") assert userid in self, _("No token related to userid ${userid}", mapping = {'userid': userid}) data = self[userid] assert utcnow() < data['link_valid'], _("Link expired") assert token == data['token'] #Is this even needed since it wouldn't be found otherwise? assert ip_addr == data['client_ip'], _("IP address doesn't match") except AssertionError as exc: raise ConsumeTokenError(str(exc))
def export_into_meeting( request, motion_process, meeting, as_userid="", view_perm=True, clear_ownership=False, states=["endorsed"], ): results = {"prop": 0, "ai": 0} creators = set() for motion in _get_motions(request, motion_process, states): creators.update(set(motion.creator)) results["ai"] += 1 ai = request.content_factories["AgendaItem"]( title=motion.title, description=motion.description, body=_transform_text(motion.body), hashtag=motion.hashtag, motion_uid=motion.uid, ) name = generate_slug(meeting, ai.title) meeting[name] = ai now = utcnow() offset = 0 for prop_text in motion.proposals: results["prop"] += 1 if as_userid: creator = (as_userid, ) else: creator = tuple(motion.creator) created = now + timedelta(seconds=offset) offset += 2 proposal = request.content_factories["Proposal"](text=prop_text, creator=creator, created=created) name = generate_slug(ai, proposal.text) ai[name] = proposal # There might be several subscribers that check for # ownership when an object is added to the resource tree. # Hence do this check afterwards. if clear_ownership: users_to_clear = set( proposal.local_roles.get_any_local_with(ROLE_OWNER)) for userid in users_to_clear: proposal.local_roles.remove(userid, ROLE_OWNER, event=False) if users_to_clear: proposal.local_roles.send_event() if view_perm: for userid in creators: meeting.local_roles.add(userid, ROLE_VIEWER) return results
def __init__(self, context_uid, message, tags=(), userid=None, scripted=None): self.created = utcnow() self.context_uid = context_uid self.message = message self.tags = tuple(tags) self.userid = userid self.scripted = scripted
def cleanup(self, userid, keep_days = None): """ Clean up old sessions for a specific userid. Will also clear active sessions if there's no recent activity. """ if keep_days is None: keep_days = self.max_keep_days keep_timestamp = timedelta(days = keep_days) remove_ids = set() for ad in self.get_data(userid): if ad.last + keep_timestamp < utcnow(): remove_ids.add(ad.key) for id in remove_ids: del self.sessions[userid][id]
def send_invite_ticket(ticket, request, message=""): if ticket.closed: #Just as a precaution return meeting = find_interface(ticket, IMeeting) html = render_invite_ticket(ticket, request, message=message) subject = _(u"Invitation to ${meeting_title}", mapping={'meeting_title': meeting.title}) if send_email(request, subject=subject, recipients=ticket.email, html=html, send_immediately=True): ticket.sent_dates.append(utcnow())
def claim_and_send_notification(ticket, request, message = ""): """ When a ticket was added for a user that already has a validated email address, that ticket should be used right away, and the user notified. """ if ticket.closed: #Just as a precaution return user = claim_ticket(ticket, request, ticket.email) meeting = find_interface(ticket, IMeeting) html = render_claimed_ticket_notification(ticket, request, message = message, user = user) subject = _(u"${meeting_title} is now accessible", mapping = {'meeting_title': meeting.title}) if send_email(request, subject = subject, recipients = ticket.email, html = html, send_immediately = True): ticket.sent_dates.append(utcnow())
def __init__(self, email, roles, sent_by = None): self.email = email.lower() for role in roles: if role not in SELECTABLE_ROLES: raise ValueError("InviteTicket got '%s' as a role, and that isn't selectable." % role) self.roles = roles self.created = utcnow() self.closed = None self.claimed_by = None self.sent_by = sent_by self.token = ''.join([choice(string.letters + string.digits) for x in range(30)]) self.sent_dates = PersistentList() self.uid = unicode(uuid4()) super(InviteTicket, self).__init__()
def archive_current(self): if self.open: try: next_key = self.archive.maxKey() + 1 except ValueError: next_key = 1 self.archive[next_key] = OOBTree( present_userids = frozenset(self.present_userids), start_time = self.start_time, end_time = utcnow(), ) del self.start_time else: #pragma: no coverage raise ValueError("Check not open, no archive can be created")
def __init__(self, **kwargs): #IContent should be the same iface registered by the roles adapter if 'local_roles' not in kwargs and ILocalRoles.providedBy(self): request = get_current_request() #Check creators attribute? userid = getattr(request, 'authenticated_userid', None) if userid: kwargs['local_roles'] = {userid: [ROLE_OWNER]} if 'uid' not in kwargs: kwargs['uid'] = unicode(uuid4()) if 'created' not in kwargs and hasattr(self, 'created'): kwargs['created'] = utcnow() if 'data' in kwargs: #Shouldn't be set here. Create a proper blocklist? del kwargs['data'] self.update(event=False, **kwargs)
def activity(self): ad = self.get_active() if ad: now = utcnow() if isinstance(ad.max_valid, int): if timedelta(minutes = ad.max_valid) + ad.last < now: self.close(logout=True) raise HTTPForbidden("Login expired") if ad.user_agent and ad.user_agent != self.request.user_agent: raise HTTPForbidden("User agent missmatches login info") if (now - ad.last) > timedelta(seconds = self.activity_update): ad.last = now if not ad and self.request.authenticated_userid: self._logout() raise HTTPForbidden("Logged out")
def __init__(self, **kwargs): # IContent should be the same iface registered by the roles adapter if "local_roles" not in kwargs and ILocalRoles.providedBy(self): request = get_current_request() # Check creators attribute? userid = getattr(request, "authenticated_userid", None) if userid: kwargs["local_roles"] = {userid: [ROLE_OWNER]} if "uid" not in kwargs: kwargs["uid"] = unicode(uuid4()) if "created" not in kwargs and hasattr(self, "created"): kwargs["created"] = utcnow() if "data" in kwargs: # Shouldn't be set here. Create a proper blocklist? del kwargs["data"] self.update(event=False, **kwargs)
def _ordering_fixture(self): self.config.include('arche.testing.catalog') from voteit.core.models.agenda_item import AgendaItem from voteit.core.models.meeting import Meeting from voteit.core.models.proposal import Proposal root = bootstrap_and_fixture(self.config) root['m'] = m = Meeting() m['ai'] = ai = AgendaItem() now = utcnow() ai['p1'] = Proposal(created=now, text='Abc', uid='a') ai['p2'] = Proposal(created=now+timedelta(seconds=2), text='aa', uid='b') ai['p3'] = Proposal(created=now+timedelta(seconds=4), text='cc', uid='c') ai['p4'] = Proposal(created=now+timedelta(seconds=6), text='zz', uid='d') ai['p5'] = Proposal(created=now+timedelta(seconds=8), text='C', uid='e') ai['poll'] = self._cut(proposals=['a', 'b', 'c', 'd', 'e']) return root
def new(self, request, userid, client_ip = '', login_max_valid = 30, link_valid = 20, redirect_url = ''): link_valid = utcnow() + timedelta(seconds = link_valid) token = ''.join([choice(string.ascii_letters + string.digits) for x in range(50)]) if not redirect_url: # I.e. Root redirect_url = request.resource_url(self.context) obj = OOBTree(dict(client_ip = client_ip, login_max_valid = login_max_valid, link_valid = link_valid, token = token, redirect_url = redirect_url)) self[userid] = obj return request.resource_url(self.context, '_t_auth', token)
def __init__(self, context_uid, message, tags=(), userid=None, scripted=None): self.created = utcnow() self.context_uid = context_uid self.message = message self.tags = tuple(tags) self.userid = userid self.scripted = scripted # def includeme(config): # """ Include to activate log components. # like: config.include('voteit.core.models.logs') # """ # #Register LogHandler adapter # config.registry.registerAdapter(LogHandler, (IBaseContent,), ILogHandler)
def update(self, event = True, **kwargs): _marker = object() changed_attributes = set() for (key, value) in kwargs.items(): if not hasattr(self, key): raise AttributeError("%r doesn't have any '%s' attribute." % (self, key)) if value == null: value = None if getattr(self, key, _marker) != value: setattr(self, key, value) changed_attributes.add(key) if hasattr(self, 'modified') and 'modified' not in kwargs and changed_attributes: self.modified = utcnow() changed_attributes.add('modified') if event: event_obj = ObjectUpdatedEvent(self, changed = changed_attributes) objectEventNotify(event_obj) return changed_attributes
def __init__(self, email, roles, sent_by=None): self.email = email.lower() for role in roles: if role not in SELECTABLE_ROLES: raise ValueError( "InviteTicket got '%s' as a role, and that isn't selectable." % role) assert len(roles), "Can't create an invite ticket without roles" self.roles = roles self.created = utcnow() self.closed = None self.claimed_by = None self.sent_by = sent_by self.token = ''.join( [choice(string.letters + string.digits) for x in range(30)]) self.sent_dates = PersistentList() self.uid = unicode(uuid4()) super(InviteTicket, self).__init__()
def test_start_time(self): obj = self._add_mock_meeting() now = utcnow() now_unix = timegm(now.timetuple()) #Shouldn't return anything self.assertEqual( self.query("start_time == %s and path == '/meeting'" % now_unix)[0], 0) qy = ("%s < start_time < %s and path == '/meeting'" % (now_unix - 1, now_unix + 1)) self.assertEqual(self.query(qy)[0], 0) #So let's set it and return stuff obj.update(start_time=now) self.assertEqual( self.query("start_time == %s and path == '/meeting'" % now_unix)[0], 1) qy = ("%s < start_time < %s and path == '/meeting'" % (now_unix - 1, now_unix + 1)) self.assertEqual(self.query(qy)[0], 1)
def __init__(self, request = None, **kwargs): #IContent should be the same iface registered by the roles adapter if request is None: request = get_current_request() userid = getattr(request, 'authenticated_userid', None) if 'local_roles' not in kwargs and ILocalRoles.providedBy(self): #Check creators attribute? if userid: kwargs['local_roles'] = {userid: [ROLE_OWNER]} if 'uid' not in kwargs: kwargs['uid'] = text_type(uuid4()) if 'created' not in kwargs and hasattr(self, 'created'): kwargs['created'] = utcnow() if 'creator' not in kwargs and hasattr(self, 'creator'): if userid: kwargs['creator'] = [userid] if 'data' in kwargs: #Shouldn't be set here. Create a proper blocklist? del kwargs['data'] self.update(event = False, **kwargs)
def update(self, event=True, **kwargs): _marker = object() changed_attributes = set() for (key, value) in kwargs.items(): if not hasattr(self, key): raise AttributeError( "This class doesn't have any '%s' attribute." % key) if value == null: value = None if getattr(self, key, _marker) != value: setattr(self, key, value) changed_attributes.add(key) if hasattr(self, 'modified' ) and 'modified' not in kwargs and changed_attributes: self.modified = utcnow() changed_attributes.add('modified') if event: event_obj = ObjectUpdatedEvent(self, changed=changed_attributes) objectEventNotify(event_obj) return changed_attributes
def claim_and_send_notification(ticket, request, message=""): """ When a ticket was added for a user that already has a validated email address, that ticket should be used right away, and the user notified. """ if ticket.closed: #Just as a precaution return user = claim_ticket(ticket, request, ticket.email) meeting = find_interface(ticket, IMeeting) html = render_claimed_ticket_notification(ticket, request, message=message, user=user) subject = _(u"${meeting_title} is now accessible", mapping={'meeting_title': meeting.title}) if send_email(request, subject=subject, recipients=ticket.email, html=html, send_immediately=True): ticket.sent_dates.append(utcnow())
def _ordering_fixture(self): self.config.include('arche.testing.catalog') from voteit.core.models.agenda_item import AgendaItem from voteit.core.models.meeting import Meeting from voteit.core.models.proposal import Proposal root = bootstrap_and_fixture(self.config) root['m'] = m = Meeting() m['ai'] = ai = AgendaItem() now = utcnow() ai['p1'] = Proposal(created=now, text='Abc', uid='a') ai['p2'] = Proposal(created=now + timedelta(seconds=2), text='aa', uid='b') ai['p3'] = Proposal(created=now + timedelta(seconds=4), text='cc', uid='c') ai['p4'] = Proposal(created=now + timedelta(seconds=6), text='zz', uid='d') ai['p5'] = Proposal(created=now + timedelta(seconds=8), text='C', uid='e') ai['poll'] = self._cut(proposals=['a', 'b', 'c', 'd', 'e']) return root
def expired(self): return utcnow() > self.expires
def __init__(self, size = 40, hours = 3): self.token = ''.join([choice(string.ascii_letters + string.digits) for x in range(size)]) self.created = utcnow() if hours: self.expires = self.created + timedelta(hours = hours)
def valid(self): if self.expires is None: return True return self.expires and utcnow()
def add(self, userid): self[userid] = timegm(utcnow().timetuple())
def __init__(self, userid, token, minutes): self.userid = userid self.created = utcnow() self.token = token self.expires = self.created + timedelta(minutes = minutes)
def revoke_tos(self, uid): self[uid] = utcnow().date()
def accept_tos(self, uid): self[uid] = utcnow().date()
def claim(self, userid): if self.claimed or self.claimed_by: raise TicketAlreadyClaimedError(u"Ticket already claimed") self.claimed = utcnow() self.claimed_by = userid
def mark_modified(self): """ Mark content as modified. """ self.modified = utcnow()
def mark_checked(self): self.request.session["tos_check_again_at"] = utcnow() + timedelta( seconds=self.check_interval ) self.request.session.changed() self.logger.debug("%s mark terms checked", self.request.authenticated_userid)
def start_check(self): self.present_userids.clear() self.start_time = utcnow()
def utcnow(self): return utcnow()
def __init__(self, size=40, hours=3): self.token = ''.join( [choice(string.letters + string.digits) for x in range(size)]) self.created = utcnow() if hours: self.expires = self.created + timedelta(hours=hours)
def __init__(self): self.token = ''.join( [choice(string.letters + string.digits) for x in range(30)]) self.created = utcnow() self.expires = self.created + timedelta(days=3)
def validate(self, value): if value != self.token: raise TokenValidationError("Token doesn't match.") if utcnow() > self.expires: raise TokenValidationError("Token expired.")
def valid(self): if self.expires is None: return True return self.expires > utcnow()