Пример #1
0
 def property_intervals(self, name, when=UnboundedInterval):
     """
     Get the set of intervals in which the user was granted a given property
     :param str name:
     :param Interval when:
     :returns: The set of intervals in which the user was granted the
     property
     :rtype: IntervalSet
     """
     property_assignments = object_session(self).query(
         Property.granted,
         Membership.begins_at,
         Membership.ends_at
     ).filter(
         Property.name == name,
         Property.property_group_id == PropertyGroup.id,
         PropertyGroup.id == Membership.group_id,
         Membership.user_id == self.id
     ).all()
     granted_intervals = IntervalSet(
         closed(begins_at, ends_at)
         for granted, begins_at, ends_at in property_assignments
         if granted
     )
     denied_intervals = IntervalSet(
         closed(begins_at, ends_at)
         for granted, begins_at, ends_at in property_assignments
         if not granted
     )
     return (granted_intervals - denied_intervals).intersect(when)
Пример #2
0
def sync_exceeded_traffic_limits():
    """Adds and removes memberships of the 'traffic_limit_exceeded group.'

    """

    processor = User.q.get(0)

    # Add memberships
    users = User.q.join(User._current_traffic_balance) \
                  .filter(CurrentTrafficBalance.amount < 0) \
                  .except_(User.q.join(User.current_properties)\
                  .filter(or_(CurrentProperty.property_name == 'traffic_limit_disabled',\
                              CurrentProperty.property_name == 'traffic_limit_exceeded')))\
                  .all()

    for user in users:
        make_member_of(user, config.traffic_limit_exceeded_group,
                       processor, closed(session.utcnow(), None))
        print("Traffic-Limit exceeded: " + user.name)

    # End memberships
    users = User.q.join(User.current_properties) \
                  .filter(CurrentProperty.property_name == 'traffic_limit_exceeded') \
                  .join(User._current_traffic_balance) \
                  .filter(or_(CurrentTrafficBalance.amount >= 0,
                              CurrentProperty.property_name == 'traffic_limit_disabled')) \
                  .all()

    for user in users:
        remove_member_of(user, config.traffic_limit_exceeded_group,
                         processor, closed(session.utcnow(), None))
        print("Traffic-Limit no longer exceeded: " + user.name)
Пример #3
0
 def test_complement(self):
     self.assertIntervalSetOperationEquals(IntervalSet.complement, [
         ([[]], open(None, None)),
         ([[closed(0, 1), open(2, 3)]
           ], [open(None, 0),
               openclosed(1, 2),
               closedopen(3, None)]),
         ([[closed(None, 0), closed(1, None)]], ([open(0, 1)])),
     ])
Пример #4
0
 def test_length(self):
     self.assertIntervalSetMethodEquals(operator.attrgetter("length"), [
         ([[closed(0, 0)]], 0),
         ([[closed(0, 1)]], 1),
         ([[closed(0, 0), closed(1, 2),
            closed(3, 4)]], 2),
         ([[closed(0, 1), closed(2, None)]], None),
         ([[closed(None, 0), closed(1, 2)]], None),
         ([[closed(None, None)]], None),
     ])
Пример #5
0
 def test_intersect(self):
     self.assertIntervalSetOperationEquals(IntervalSet.intersect, [
         ([[open(None, None)],
           [openclosed(None, 0),
            closed(1, 2),
            closedopen(3, None)]
           ], [openclosed(None, 0),
               closed(1, 2),
               closedopen(3, None)]),
     ])
Пример #6
0
 def test_length(self):
     self.assertCallEquals(operator.attrgetter("length"), [
         ([open(0, 0)], 0),
         ([closed(0, 0)], 0),
         ([open(0, 1)], 1),
         ([closed(0, 1)], 1),
         ([closed(0, None)], None),
         ([closed(None, 0)], None),
         ([closed(None, None)], None),
     ])
Пример #7
0
    def test_join_overlapping_memberships(self):
        begins_at1 = session.utcnow()
        ends_at1 = begins_at1 + timedelta(hours=2)
        during1 = closed(begins_at1, ends_at1)
        begins_at2 = begins_at1 + timedelta(hours=1)
        ends_at2 = begins_at1 + timedelta(hours=3)
        during2 = closed(begins_at2, ends_at2)

        self.add_membership(during1)
        self.add_membership(during2)
        self.assertMembershipIntervalsEqual(IntervalSet(closed(begins_at1, ends_at2)))
Пример #8
0
    def test_join_overlapping_memberships(self):
        begins_at1 = session.utcnow()
        ends_at1 = begins_at1 + timedelta(hours=2)
        during1 = closed(begins_at1, ends_at1)
        begins_at2 = begins_at1 + timedelta(hours=1)
        ends_at2 = begins_at1 + timedelta(hours=3)
        during2 = closed(begins_at2, ends_at2)

        self.add_membership(during1)
        self.add_membership(during2)
        self.assertMembershipIntervalsEqual(IntervalSet(closed(begins_at1, ends_at2)))
Пример #9
0
    def test_removing_all_memberships(self):
        begins_at1 = session.utcnow()
        ends_at1 = begins_at1 + timedelta(hours=1)
        during1 = closed(begins_at1, ends_at1)
        begins_at2 = begins_at1 + timedelta(hours=2)
        ends_at2 = begins_at1 + timedelta(hours=3)
        during2 = closed(begins_at2, ends_at2)

        self.add_membership(during1)
        self.add_membership(during2)
        self.remove_membership()
        self.assertMembershipIntervalsEqual(IntervalSet())
Пример #10
0
 def test_removing_memberships(self):
     t0 = session.utcnow()
     t1 = t0 + timedelta(hours=1)
     t2 = t0 + timedelta(hours=2)
     t3 = t0 + timedelta(hours=3)
     t4 = t0 + timedelta(hours=4)
     t5 = t0 + timedelta(hours=5)
     self.add_membership(closed(t0, t2))
     self.add_membership(closed(t3, t5))
     self.remove_membership(closed(t1, t4))
     self.assertMembershipIntervalsEqual(IntervalSet(
         (closed(t0, t1), closed(t4, t5))))
Пример #11
0
 def test_removing_memberships(self):
     t0 = session.utcnow()
     t1 = t0 + timedelta(hours=1)
     t2 = t0 + timedelta(hours=2)
     t3 = t0 + timedelta(hours=3)
     t4 = t0 + timedelta(hours=4)
     t5 = t0 + timedelta(hours=5)
     self.add_membership(closed(t0, t2))
     self.add_membership(closed(t3, t5))
     self.remove_membership(closed(t1, t4))
     self.assertMembershipIntervalsEqual(IntervalSet(
         (closed(t0, t1), closed(t4, t5))))
Пример #12
0
    def test_removing_all_memberships(self):
        begins_at1 = session.utcnow()
        ends_at1 = begins_at1 + timedelta(hours=1)
        during1 = closed(begins_at1, ends_at1)
        begins_at2 = begins_at1 + timedelta(hours=2)
        ends_at2 = begins_at1 + timedelta(hours=3)
        during2 = closed(begins_at2, ends_at2)

        self.add_membership(during1)
        self.add_membership(during2)
        self.remove_membership()
        self.assertMembershipIntervalsEqual(IntervalSet())
Пример #13
0
 def test_contains_operator(self):
     self.assertCallTrue(operator.contains, [
         (closed(0, 0), 0),
         (closed(0, 2), 1),
         (openclosed(None, 0), 0),
         (closedopen(0, None), 0),
         (open(None, None), 0),
     ])
     self.assertCallFalse(operator.contains, [
         (empty(0), 0),
         (closedopen(0, 1), 1),
         (openclosed(0, 1), 0),
         (open(0, 1), 1),
     ])
Пример #14
0
 def test_difference(self):
     self.assertIntervalSetOperationEquals(IntervalSet.difference, [
         ([[open(None, None)],
           [closed(0, 1),
            closedopen(2, 3),
            openclosed(4, 5),
            open(6, 7)]], [
                open(None, 0),
                open(1, 2),
                closed(3, 4),
                openclosed(5, 6),
                closedopen(7, None)
            ]),
     ])
Пример #15
0
 def test_empty(self):
     self.assertCallTrue(operator.attrgetter("empty"), [
         [empty(0)],
         [closedopen(0, 0)],
         [openclosed(0, 0)],
         [open(0, 0)],
     ])
     self.assertCallFalse(operator.attrgetter("empty"), [
         [single(0)],
         [closed(0, 0)],
         [closed(0, 1)],
         [closedopen(0, 1)],
         [openclosed(0, 1)],
         [open(0, 1)],
     ])
Пример #16
0
    def test_adding_single_membership(self):
        begins_at = session.utcnow()
        ends_at = begins_at + timedelta(hours=1)
        during = closed(begins_at, ends_at)

        self.add_membership(during)
        self.assertMembershipIntervalsEqual(IntervalSet(during))
Пример #17
0
def make_member_of(user, group, processor, during=UnboundedInterval):
    """
    Makes a user member of a group in a given interval. If the given interval
    overlaps with an existing membership, this method will join the overlapping
    intervals together, so that there will be at most one membership for
    particular user in particular group at any given point in time.

    :param User user: the user
    :param Group group: the group
    :param User processor: User issuing the addition
    :param Interval during:
    """
    memberships = session.session.query(Membership).filter(
        Membership.user == user, Membership.group == group,
        Membership.active(during)).all()
    intervals = IntervalSet(
        closed(m.begins_at, m.ends_at) for m in memberships).union(during)
    for m in memberships:
        session.session.delete(m)
    session.session.add_all(
        Membership(begins_at=i.begin, ends_at=i.end, user=user, group=group)
        for i in intervals)
    message = deferred_gettext(u"Added to group {group} during {during}.")
    log_user_event(message=message.format(group=group.name,
                                          during=during).to_json(),
                   user=user,
                   author=processor)
Пример #18
0
def remove_member_of(user, group, processor, during=UnboundedInterval):
    """Remove a user from a group in a given interval.

    The interval defaults to the unbounded interval, so that the user
    will be removed from the group at any point in time, **removing
    all memberships** in this group retroactively.

    However, a common use case is terminating a membership by setting
    ``during=closedopen(now, None)``.

    :param User user: the user
    :param Group group: the group
    :param User processor: User issuing the removal
    :param Interval during:
    """
    memberships = session.session.query(Membership).filter(
        Membership.user == user, Membership.group == group,
        Membership.active(during)).all()
    intervals = IntervalSet(
        closed(m.begins_at, m.ends_at) for m in memberships
    ).difference(during)
    for m in memberships:
        session.session.delete(m)
    session.session.add_all(
        Membership(begins_at=i.begin, ends_at=i.end, user=user, group=group)
        for i in intervals)
    message = deferred_gettext(u"Removed from group {group} during {during}.")
    log_user_event(message=message.format(group=group.name,
                                          during=during).to_json(),
                   user=user, author=processor)
Пример #19
0
def make_member_of(user, group, processor, during=UnboundedInterval):
    """
    Makes a user member of a group in a given interval. If the given interval
    overlaps with an existing membership, this method will join the overlapping
    intervals together, so that there will be at most one membership for
    particular user in particular group at any given point in time.

    :param User user: the user
    :param Group group: the group
    :param User processor: User issuing the addition
    :param Interval during:
    """
    memberships = session.session.query(Membership).filter(
        Membership.user == user, Membership.group == group,
        Membership.active(during)).all()
    intervals = IntervalSet(
        closed(m.begins_at, m.ends_at) for m in memberships
    ).union(during)
    for m in memberships:
        session.session.delete(m)
    session.session.add_all(
        Membership(begins_at=i.begin, ends_at=i.end, user=user, group=group)
        for i in intervals)
    message = deferred_gettext(u"Added to group {group} during {during}.")
    log_user_event(message=message.format(group=group.name,
                                          during=during).to_json(),
                   user=user, author=processor)
Пример #20
0
def add_membership(user_id):
    user = get_user_or_404(user_id)
    form = UserAddGroupMembership()

    if form.validate_on_submit():
        if form.begins_at.data is not None:
            begins_at = datetime.combine(form.begins_at.data, utc.time_min())
        else:
            begins_at = session.utcnow()
        if not form.ends_at.unlimited.data:
            ends_at = datetime.combine(form.ends_at.date.data, utc.time_min())
        else:
            ends_at = None
        make_member_of(user, form.group.data, current_user,
                       closed(begins_at, ends_at))
        message = u"Nutzer zur Gruppe '{}' hinzugefügt.".format(form.group.data.name)
        lib.logging.log_user_event(message, current_user, user)
        session.session.commit()
        flash(u'Nutzer wurde der Gruppe hinzugefügt.', 'success')

        return redirect(url_for(".user_show",
                                user_id=user_id,
                                _anchor='groups'))

    return render_template('user/add_membership.html',
        page_title=u"Neue Gruppenmitgliedschaft für Nutzer {}".format(user_id),
        user_id=user_id, form=form)
Пример #21
0
 def assertMembershipIntervalsEqual(self, expected):
     memberships = session.session.query(Membership).filter_by(
         user=self.user, group=self.group)
     got = IntervalSet(closed(m.begins_at, m.ends_at) for m in memberships)
     assert expected == got, "IntervalSets differ: " \
                             "expected {0!r}" \
                             "got      {1!r}".format(expected, got)
Пример #22
0
 def assertMembershipIntervalsEqual(self, expected):
     memberships = session.session.query(Membership).filter_by(
         user=self.user, group=self.group)
     got = IntervalSet(closed(m.begins_at, m.ends_at) for m in memberships)
     assert expected == got, "IntervalSets differ: " \
                             "expected {0!r}" \
                             "got      {1!r}".format(expected, got)
Пример #23
0
def remove_member_of(user, group, processor, during=UnboundedInterval):
    """Remove a user from a group in a given interval.

    The interval defaults to the unbounded interval, so that the user
    will be removed from the group at any point in time, **removing
    all memberships** in this group retroactively.

    However, a common use case is terminating a membership by setting
    ``during=closedopen(now, None)``.

    :param User user: the user
    :param Group group: the group
    :param User processor: User issuing the removal
    :param Interval during:
    """
    memberships = session.session.query(Membership).filter(
        Membership.user == user, Membership.group == group,
        Membership.active(during)).all()
    intervals = IntervalSet(
        closed(m.begins_at, m.ends_at) for m in memberships).difference(during)
    for m in memberships:
        session.session.delete(m)
    session.session.add_all(
        Membership(begins_at=i.begin, ends_at=i.end, user=user, group=group)
        for i in intervals)
    message = deferred_gettext(u"Removed from group {group} during {during}.")
    log_user_event(message=message.format(group=group.name,
                                          during=during).to_json(),
                   user=user,
                   author=processor)
Пример #24
0
    def test_adding_single_membership(self):
        begins_at = session.utcnow()
        ends_at = begins_at + timedelta(hours=1)
        during = closed(begins_at, ends_at)

        self.add_membership(during)
        self.assertMembershipIntervalsEqual(IntervalSet(during))
Пример #25
0
 def test_positive_test_interval(self):
     interval = closed(self.membership.begins_at, self.membership.ends_at)
     self.assertTrue(self.user.has_property(self.GRANTED_NAME, interval))
     self.assertIsNotNone(
         user.User.q.filter(
             user.User.login == self.user.login,
             user.User.has_property(self.GRANTED_NAME, interval)).first())
Пример #26
0
 def test_serialize_interval(self):
     self.assertValidSerialization(UnboundedInterval)
     now = datetime.datetime.utcnow()
     then = now + datetime.timedelta(1)
     self.assertValidSerialization(closed(now, then))
     self.assertValidSerialization(closedopen(now, then))
     self.assertValidSerialization(openclosed(now, then))
     self.assertValidSerialization(open(now, then))
Пример #27
0
 def test_negative_test_interval(self):
     interval = closed(self.membership.ends_at + timedelta(1),
                       self.membership.ends_at + timedelta(2))
     self.assertFalse(self.user.has_property(self.GRANTED_NAME, interval))
     self.assertIsNone(
         user.User.q.filter(
             user.User.login == self.user.login,
             user.User.has_property(self.GRANTED_NAME, interval)).first())
Пример #28
0
 def test_serialize_interval(self):
     self.assertValidSerialization(UnboundedInterval)
     now = datetime.datetime.utcnow()
     then = now + datetime.timedelta(1)
     self.assertValidSerialization(closed(now, then))
     self.assertValidSerialization(closedopen(now, then))
     self.assertValidSerialization(openclosed(now, then))
     self.assertValidSerialization(open(now, then))
Пример #29
0
 def active_memberships(self, when=None):
     if when is None:
         now = session.utcnow()
         when = single(now)
     return [
         m for m in self.memberships
         if when.overlaps(closed(m.begins_at, m.ends_at))
     ]
Пример #30
0
def edit_membership(user_id, membership_id):
    membership = Membership.q.get(membership_id)

    if membership is None:
        flash(
            u"Gruppenmitgliedschaft mit ID {} existiert nicht!".format(
                membership_id), 'error')
        abort(404)

    if membership.group.permission_level > current_user.permission_level:
        flash(
            "Eine Bearbeitung von Gruppenmitgliedschaften für Gruppen mit "
            "höherem Berechtigungslevel ist nicht möglich.", 'error')
        abort(403)

    membership_data = {}
    if request.method == 'GET':
        membership_data = {
            "begins_at":
            None
            if membership.begins_at is None else membership.begins_at.date(),
            "ends_at": {
                "unlimited": membership.ends_at is None,
                "date": membership.ends_at and membership.ends_at.date()
            }
        }

    form = UserEditGroupMembership(**membership_data)

    if form.validate_on_submit():
        membership.begins_at = datetime.combine(form.begins_at.data,
                                                utc.time_min())
        if form.ends_at.unlimited.data:
            membership.ends_at = None
        else:
            membership.ends_at = datetime.combine(form.ends_at.date.data,
                                                  utc.time_min())

        message = (
            u"Edited the membership of group '{group}'. During: {during}".
            format(group=membership.group.name,
                   during=closed(membership.begins_at, membership.ends_at)))
        lib.logging.log_user_event(message, current_user, membership.user)
        session.session.commit()
        flash(u'Gruppenmitgliedschaft bearbeitet', 'success')
        return redirect(
            url_for('.user_show', user_id=membership.user_id,
                    _anchor='groups'))

    return render_template('user/user_edit_membership.html',
                           page_title=(u"Mitgliedschaft {} für "
                                       u"{} bearbeiten".format(
                                           membership.group.name,
                                           membership.user.name)),
                           membership_id=membership_id,
                           user=membership.user,
                           form=form)
Пример #31
0
 def test_union(self):
     self.assertIntervalSetOperationEquals(IntervalSet.union, [
         ([[], [closed(0, 1), open(1, 2)]], [closed(0, 1),
                                             open(1, 2)]),
         ([[closed(0, 1), open(1, 2)], []], [closed(0, 1),
                                             open(1, 2)]),
         ([[closed(None, 1), closed(3, 4),
            open(7, 8)],
           [open(0, 5), closed(6, 7),
            closedopen(8, None)]], [open(None, 5),
                                    closed(6, None)]),
     ])
Пример #32
0
 def active_memberships(self,
                        when: Optional[Interval] = None
                        ) -> List[Membership]:
     if when is None:
         now = session.utcnow()
         when = single(now)
     return [
         m for m in self.memberships
         if when.overlaps(closed(m.begins_at, m.ends_at))
     ]
Пример #33
0
 def test_positive_test_interval(self):
     interval = closed(MembershipData.dummy_membership.begins_at,
                       MembershipData.dummy_membership.ends_at)
     self.assertTrue(
         self.user.has_property(PropertyData.granted.name, interval))
     self.assertIsNotNone(
         user.User.q.filter(
             user.User.login == self.user.login,
             user.User.has_property(PropertyData.granted.name,
                                    interval)).first())
Пример #34
0
 def test_positive_test_interval(self):
     interval = closed(MembershipData.dummy_membership.begins_at,
                       MembershipData.dummy_membership.ends_at)
     self.assertTrue(
         self.user.has_property(PropertyData.granted.name, interval)
     )
     self.assertIsNotNone(
         user.User.q.filter(
             user.User.login == self.user.login,
             user.User.has_property(PropertyData.granted.name, interval)
         ).first())
Пример #35
0
 def test_negative_test_interval(self):
     interval = closed(
         MembershipData.dummy_membership.ends_at + timedelta(1),
         MembershipData.dummy_membership.ends_at + timedelta(2))
     self.assertFalse(
         self.user.has_property(PropertyData.granted.name, interval))
     self.assertIsNone(
         user.User.q.filter(
             user.User.login == self.user.login,
             user.User.has_property(PropertyData.granted.name,
                                    interval)).first())
Пример #36
0
    def active(self, when=None):
        """
        Tests if the membership overlaps with a given interval. If no interval
        is given, it tests if the membership is active right now.
        :param Interval when: interval in which the membership
        :rtype: bool
        """
        if when is None:
            now = object_session(self).query(func.current_timestamp()).scalar()
            when = single(now)

        return when.overlaps(closed(self.begins_at, self.ends_at))
Пример #37
0
    def active(self, when=None):
        """
        Tests if the membership overlaps with a given interval. If no interval
        is given, it tests if the membership is active right now.
        :param Interval when: interval in which the membership
        :rtype: bool
        """
        if when is None:
            now = object_session(self).query(func.current_timestamp()).scalar()
            when = single(now)

        return when.overlaps(closed(self.begins_at, self.ends_at))
Пример #38
0
 def test_negative_test_interval(self):
     interval = closed(
         MembershipData.dummy_membership.ends_at + timedelta(1),
         MembershipData.dummy_membership.ends_at + timedelta(2)
     )
     self.assertFalse(
         self.user.has_property(PropertyData.granted.name, interval)
     )
     self.assertIsNone(
         user.User.q.filter(
             user.User.login == self.user.login,
             user.User.has_property(PropertyData.granted.name, interval)
         ).first())
Пример #39
0
 def property_intervals(self, name, when=UnboundedInterval):
     """
     Get the set of intervals in which the user was granted a given property
     :param str name:
     :param Interval when:
     :returns: The set of intervals in which the user was granted the
     property
     :rtype: IntervalSet
     """
     property_assignments = object_session(self).query(
         Property.granted, Membership.begins_at, Membership.ends_at).filter(
             Property.name == name,
             Property.property_group_id == PropertyGroup.id,
             PropertyGroup.id == Membership.group_id,
             Membership.user_id == self.id).all()
     granted_intervals = IntervalSet(
         closed(begins_at, ends_at)
         for granted, begins_at, ends_at in property_assignments if granted)
     denied_intervals = IntervalSet(
         closed(begins_at, ends_at)
         for granted, begins_at, ends_at in property_assignments
         if not granted)
     return (granted_intervals - denied_intervals).intersect(when)
Пример #40
0
def handle_payments_in_default():
    processor = User.q.get(0)

    # Add memberships and end "member" membership if threshold met
    users = User.q.join(User.current_properties)\
                  .filter(CurrentProperty.property_name == 'membership_fee') \
                  .join(Account).filter(Account.balance > 0).all()

    users_pid_membership = []
    users_membership_terminated = []

    ts_now = session.utcnow()
    for user in users:
        last_pid_membership = Membership.q.filter(Membership.user_id == user.id) \
            .filter(Membership.group_id == config.payment_in_default_group.id) \
            .order_by(Membership.ends_at.desc()) \
            .first()

        if last_pid_membership is not None:
            if last_pid_membership.ends_at is not None and \
               last_pid_membership.ends_at >= ts_now - timedelta(days=7):
                continue

        in_default_days = user.account.in_default_days

        try:
            fee = get_membership_fee_for_date(
                date.today() - timedelta(days=in_default_days))
        except NoResultFound:
            fee = get_last_applied_membership_fee()

        if not fee:
            return [], []

        if not user.has_property('payment_in_default'):
            if in_default_days >= fee.payment_deadline.days:
                make_member_of(user, config.payment_in_default_group,
                               processor, closed(ts_now, None))
                users_pid_membership.append(user)

        if in_default_days >= fee.payment_deadline_final.days:
            remove_member_of(user, config.member_group, processor,
                             closedopen(ts_now, None))
            log_user_event("Mitgliedschaftsende wegen Zahlungsrückstand ({})"
                           .format(fee.name),
                           processor, user)
            users_membership_terminated.append(user)

    return users_pid_membership, users_membership_terminated
Пример #41
0
def handle_payments_in_default():
    processor = User.q.get(0)

    # Add memberships and end "member" membership if threshold met
    users = User.q.join(User.current_properties)\
                  .filter(CurrentProperty.property_name == 'membership_fee') \
                  .join(Account).filter(Account.balance > 0).all()

    users_pid_membership = []
    users_membership_terminated = []

    ts_now = session.utcnow()
    for user in users:
        last_pid_membership = Membership.q.filter(Membership.user_id == user.id) \
            .filter(Membership.group_id == config.payment_in_default_group.id) \
            .order_by(Membership.ends_at.desc()) \
            .first()

        if last_pid_membership is not None:
            if last_pid_membership.ends_at is not None and \
               last_pid_membership.ends_at >= ts_now - timedelta(days=7):
                continue

        in_default_days = user.account.in_default_days

        try:
            fee = get_membership_fee_for_date(date.today() -
                                              timedelta(days=in_default_days))
        except NoResultFound:
            fee = get_last_applied_membership_fee()

        if not fee:
            return [], []

        if not user.has_property('payment_in_default'):
            if in_default_days >= fee.payment_deadline.days:
                make_member_of(user, config.payment_in_default_group,
                               processor, closed(ts_now, None))
                users_pid_membership.append(user)

        if in_default_days >= fee.payment_deadline_final.days:
            remove_member_of(user, config.member_group, processor,
                             closedopen(ts_now, None))
            log_user_event(
                "Mitgliedschaftsende wegen Zahlungsrückstand ({})".format(
                    fee.name), processor, user)
            users_membership_terminated.append(user)

    return users_pid_membership, users_membership_terminated
Пример #42
0
def finish_member_request(prm: PreMember,
                          processor: User | None,
                          ignore_similar_name: bool = False):
    if prm.room is None:
        raise ValueError("Room is None")

    if prm.move_in_date is not None and prm.move_in_date < session.utcnow(
    ).date():
        prm.move_in_date = session.utcnow().date()

    check_new_user_data(prm.login, prm.email, prm.name, prm.swdd_person_id,
                        prm.room, prm.move_in_date, ignore_similar_name)

    user, _ = create_user(prm.name,
                          prm.login,
                          prm.email,
                          prm.birthdate,
                          groups=[],
                          processor=processor,
                          address=prm.room.address,
                          passwd_hash=prm.passwd_hash)

    processor = processor if processor is not None else user

    user.swdd_person_id = prm.swdd_person_id
    user.email_confirmed = prm.email_confirmed

    move_in_datetime = utc.with_min_time(prm.move_in_date)

    move_in(user,
            prm.room.building_id,
            prm.room.level,
            prm.room.number,
            None,
            processor if processor is not None else user,
            when=move_in_datetime)

    message = deferred_gettext("Created from registration {}.").format(
        str(prm.id)).to_json()
    log_user_event(message, processor, user)

    if move_in_datetime > session.utcnow():
        make_member_of(user, config.pre_member_group, processor,
                       closed(session.utcnow(), None))

    session.session.delete(prm)

    return user
Пример #43
0
def create_user(name, login, email, birthdate, groups, processor, address):
    """Create a new member

    Create a new user with a generated password, finance- and unix account, and make him member
    of the `config.member_group` and `config.network_access_group`.

    :param str name: The full name of the user (e.g. Max Mustermann)
    :param str login: The unix login for the user
    :param str email: E-Mail address of the user
    :param Date birthdate: Date of birth
    :param PropertyGroup groups: The initial groups of the new user
    :param User processor: The processor
    :param Address address: Where the user lives. May or may not come from a room.
    :return:
    """

    now = session.utcnow()
    plain_password = user_helper.generate_password(12)
    # create a new user
    new_user = User(
        login=login,
        name=name,
        email=email,
        registered_at=now,
        account=Account(name="", type="USER_ASSET"),
        password=plain_password,
        birthdate=birthdate,
        address=address
    )

    account = UnixAccount(home_directory="/home/{}".format(login))
    new_user.unix_account = account

    with session.session.begin(subtransactions=True):
        session.session.add(new_user)
        session.session.add(account)
    new_user.account.name = deferred_gettext(u"User {id}").format(
        id=new_user.id).to_json()

    for group in groups:
        make_member_of(new_user, group, processor, closed(now, None))

    log_user_event(author=processor,
                   message=deferred_gettext(u"User created.").to_json(),
                   user=new_user)

    return new_user, plain_password
Пример #44
0
def take_actions_for_payment_in_default_users(users_pid_membership,
                                              users_membership_terminated,
                                              processor):
    ts_now = session.utcnow()

    for user in users_pid_membership:
        if not user.member_of(config.payment_in_default_group):
            make_member_of(user, config.payment_in_default_group,
                           processor, closed(ts_now, None))

    from pycroft.lib.user import move_out

    for user in users_membership_terminated:
        if user.member_of(config.member_group):
            move_out(user, "Zahlungsrückstand", processor, ts_now - timedelta(seconds=1), True)

            log_user_event("Mitgliedschaftsende wegen Zahlungsrückstand.",
                           processor, user)
Пример #45
0
 def __contains__(self, date):
     return date in closed(self.begins_on, self.ends_on)
Пример #46
0
 def active_memberships(self, when=None):
     if when is None:
         now = session.utcnow()
         when = single(now)
     return [m for m in self.memberships
             if when.overlaps(closed(m.begins_at, m.ends_at))]