示例#1
0
文件: user.py 项目: agdsn/pycroft
 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
文件: traffic.py 项目: agdsn/pycroft
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
文件: __init__.py 项目: JuKu/pycroft
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
文件: test_i18n.py 项目: JuKu/pycroft
 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
文件: user.py 项目: JuKu/pycroft
 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
文件: user.py 项目: agdsn/pycroft
    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
文件: user.py 项目: FriwiDev/pycroft
    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
文件: user.py 项目: JuKu/pycroft
 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
文件: finance.py 项目: agdsn/pycroft
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
文件: user.py 项目: agdsn/pycroft
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
文件: finance.py 项目: agdsn/pycroft
 def __contains__(self, date):
     return date in closed(self.begins_on, self.ends_on)
示例#46
0
文件: user.py 项目: agdsn/pycroft
 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))]