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)
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)
def block(user, reason, processor, during=None, violation=True): """Suspend a user during a given interval. The user is added to violation_group or blocked_group in a given interval. A reason needs to be provided. :param User user: The user to be suspended. :param unicode reason: The reason for suspending. :param User processor: The admin who suspended the user. :param Interval|None during: The interval in which the user is suspended. If None the user will be suspendeded from now on without an upper bound. :param Boolean violation: If the user should be added to the violation group :return: The suspended user. """ if during is None: during = closedopen(session.utcnow(), None) if violation: make_member_of(user, config.violation_group, processor, during) else: make_member_of(user, config.blocked_group, processor, during) message = deferred_gettext(u"Suspended during {during}. Reason: {reason}.") log_user_event(message=message.format(during=during, reason=reason) .to_json(), author=processor, user=user) return user
def post(self, user_id): parser = reqparse.RequestParser() parser.add_argument('use_cache', dest='use_cache', type=inputs.boolean, required=True) args = parser.parse_args() user = get_user_or_404(user_id) if args.use_cache != user.member_of(config.cache_group): if args.use_cache: make_member_of(user, config.cache_group, user) else: remove_member_of(user, config.cache_group, user) session.session.commit() return "Cache usage has been changed."
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
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
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
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
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)
def setup_traffic_group(user, processor, custom_group_id=None, terminate_other=False): """Add a user to a default or custom traffic group If neither a custom group is given, nor the corresponding building has a default traffic group, no membership is added. Group removal is executed independent of the latter. :param User user: the user :param User processor: the processor :param int custom_group_id: the id of a custom traffic group. if ``None``, the traffic group of the building is used. :param bool terminate_other: Whether to terminate current :py:cls:`TrafficGroup` memberships. Defaults to ``False`` """ now = session.utcnow() if terminate_other: for group in user.traffic_groups: remove_member_of(user, group, processor, closedopen(now, None)) traffic_group = determine_traffic_group(user, custom_group_id) if traffic_group is not None: make_member_of(user, traffic_group, processor, closedopen(now, None))
def move_in(user, building_id, level, room_number, mac, processor, birthdate=None, host_annex=False, begin_membership=True, when=None): """Move in a user in a given room and do some initialization. The user is given a new Host with an interface of the given mac, a UnixAccount, a finance Account, and is made member of important groups. Networking is set up. :param User user: The user to move in :param int building_id: :param int level: :param str room_number: :param str mac: The mac address of the users pc. :param User processor: :param Date birthdate: Date of birth` :param bool host_annex: when true: if MAC already in use, annex host to new user :param bool begin_membership: Starts a membership if true :param datetime when: The date at which the user should be moved in :return: The user object. """ if when and when > session.utcnow(): return schedule_user_task(task_type=TaskType.USER_MOVE_IN, due=when, user=user, parameters={'building_id': building_id, 'level': level, 'room_number': room_number, 'mac': mac, 'birthdate': birthdate, 'host_annex': host_annex, 'begin_membership': begin_membership}, processor=processor) else: room = get_room(building_id, level, room_number) if birthdate: user.birthdate = birthdate if begin_membership: if user.member_of(config.external_group): remove_member_of(user, config.external_group, processor, closedopen(session.utcnow(), None)) for group in {config.member_group, config.network_access_group}: if not user.member_of(group): make_member_of(user, group, processor, closed(session.utcnow(), None)) if room: user.room = room user.address = room.address if mac and user.birthdate: interface_existing = Interface.q.filter_by(mac=mac).first() if interface_existing is not None: if host_annex: host_existing = interface_existing.host host_existing.owner_id = user.id session.session.add(host_existing) migrate_user_host(host_existing, user.room, processor) else: raise MacExistsException else: new_host = Host(owner=user, room=room) session.session.add(new_host) session.session.add(Interface(mac=mac, host=new_host)) setup_ipv4_networking(new_host) msg = deferred_gettext(u"Moved in: {room}") log_user_event(author=processor, message=msg.format(room=room.short_name).to_json(), user=user) return user
def create_user(name, login, email, birthdate, groups, processor, address, passwd_hash=None, send_confirm_mail: bool = False): """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 Optional[User] processor: The processor :param Address address: Where the user lives. May or may not come from a room. :param passwd_hash: Use password hash instead of generating a new password :param send_confirm_mail: If a confirmation mail should be send to the user :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, wifi_password=generate_wifi_password(), birthdate=birthdate, address=address) processor = processor if processor is not None else new_user if passwd_hash: new_user.passwd_hash = passwd_hash plain_password = None 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) user_send_mail(new_user, UserCreatedTemplate(), True) if email is not None and send_confirm_mail: send_confirmation_email(new_user) return new_user, plain_password
def merge_member_request(user: User, prm: PreMember, merge_name: bool, merge_email: bool, merge_person_id: bool, merge_room: bool, merge_password: bool, merge_birthdate: bool, processor: User): if prm.move_in_date is not None and prm.move_in_date < session.utcnow( ).date(): prm.move_in_date = session.utcnow().date() if merge_name: user = edit_name(user, prm.name, processor) if merge_email: user = edit_email(user, prm.email, user.email_forwarded, processor, is_confirmed=prm.email_confirmed) if merge_person_id: user = edit_person_id(user, prm.swdd_person_id, processor) move_in_datetime = datetime.combine(prm.move_in_date, utc.time_min()) if merge_room: if prm.room: if user.room: move(user, prm.room.building_id, prm.room.level, prm.room.number, processor=processor, when=move_in_datetime) else: move_in(user, prm.room.building_id, prm.room.level, prm.room.number, mac=None, processor=processor, when=move_in_datetime) if not user.member_of(config.member_group): make_member_of(user, config.member_group, processor, closed(move_in_datetime, None)) if merge_birthdate: user = edit_birthdate(user, prm.birthdate, processor) log_msg = "Merged information from registration {}." if merge_password: user.passwd_hash = prm.passwd_hash log_msg += " Password overridden." else: log_msg += " Kept old password." log_user_event( deferred_gettext(log_msg).format(encode_type2_user_id( prm.id)).to_json(), processor, user) session.session.delete(prm)
def move_in(user: User, building_id: int, level: int, room_number: str, mac: str | None, processor: User | None = None, birthdate: date = None, host_annex: bool = False, begin_membership: bool = True, when: datetime | None = None): """Move in a user in a given room and do some initialization. The user is given a new Host with an interface of the given mac, a UnixAccount, a finance Account, and is made member of important groups. Networking is set up. :param User user: The user to move in :param building_id: :param level: :param room_number: :param mac: The mac address of the users pc. :param processor: :param birthdate: Date of birth` :param host_annex: when true: if MAC already in use, annex host to new user :param begin_membership: Starts a membership if true :param when: The date at which the user should be moved in :return: The user object. """ if when and when > session.utcnow(): task_params = UserMoveInParams(building_id=building_id, level=level, room_number=room_number, mac=mac, birthdate=birthdate, host_annex=host_annex, begin_membership=begin_membership) return schedule_user_task(task_type=TaskType.USER_MOVE_IN, due=when, user=user, parameters=task_params, processor=processor) if user.room is not None: raise ValueError("user is already living in a room.") room = get_room(building_id, level, room_number) if birthdate: user.birthdate = birthdate if begin_membership: for group in {config.external_group, config.pre_member_group}: if user.member_of(group): remove_member_of(user, group, processor, closedopen(session.utcnow(), None)) for group in {config.member_group, config.network_access_group}: if not user.member_of(group): make_member_of(user, group, processor, closed(session.utcnow(), None)) if room: user.room = room user.address = room.address if mac and user.birthdate: interface_existing = Interface.q.filter_by(mac=mac).first() if interface_existing is not None: if host_annex: host_existing = interface_existing.host host_existing.owner_id = user.id session.session.add(host_existing) migrate_user_host(host_existing, user.room, processor) else: raise MacExistsException else: new_host = Host(owner=user, room=room) session.session.add(new_host) session.session.add(Interface(mac=mac, host=new_host)) setup_ipv4_networking(new_host) user_send_mail(user, UserMovedInTemplate(), True) msg = deferred_gettext("Moved in: {room}") log_user_event(author=processor if processor is not None else user, message=msg.format(room=room.short_name).to_json(), user=user) return user
def move_in(user, building, level, room_number, mac, processor, birthdate=None, traffic_group_id=None, host_annex=False, begin_membership=True): """Create a new user in a given room and do some initialization. The user is given a new Host with an interface of the given mac, a UnixAccount, a finance Account, and is made member of important groups. Networking is set up. :param User user: The user to move in :param Building building: See :py:func:`create_member` :param int level: See :py:func:`create_member` :param str room_number: See :py:func:`create_member` :param str mac: The mac address of the users pc. :param User processor: See :py:func:`create_member :param Date birthdate: Date of birth` :param int traffic_group_id: the id of the chosen traffic group to be used instead of the building's default one. :param bool host_annex: when true: if MAC already in use, annex host to new user :param bool begin_membership: Starts a membership if true :return: The user object. """ room = Room.q.filter_by(number=room_number, level=level, building=building).one() user.room = room if birthdate: user.birthdate = birthdate if begin_membership: if user.member_of(config.external_group): remove_member_of(user, config.external_group, processor, closedopen(session.utcnow(), None)) for group in {config.member_group, config.network_access_group}: if not user.member_of(group): make_member_of(user, group, processor, closed(session.utcnow(), None)) interface_existing = Interface.q.filter_by(mac=mac).first() if interface_existing is not None: if host_annex: host_existing = interface_existing.host host_existing.owner_id = user.id session.session.add(host_existing) migrate_user_host(host_existing, user.room, processor) else: raise MacExistsException else: new_host = Host(owner=user, room=room) session.session.add(new_host) session.session.add(Interface(mac=mac, host=new_host)) setup_ipv4_networking(new_host) setup_traffic_group(user, processor, traffic_group_id) try: grant_initial_credit(user) except NoTrafficGroup as e: raise ValueError("User {} could not be assigned a traffic group. " "Please specify one manually.".format(user)) from e msg = deferred_gettext(u"Moved in: {dorm} {level}-{room}") log_user_event(author=processor, message=msg.format(dorm=building.short_name, level=level, room=room_number).to_json(), user=user) return user
def add_membership(self, during): make_member_of(self.user, self.group, self.processor, during) session.session.commit()
def add_membership(self, during): make_member_of(self.user, self.group, self.processor, during) session.session.commit()