Example #1
0
def delete_inactive_users():
    user_auto_delete = docassemble.base.config.daconfig.get('user auto delete', {})
    if not isinstance(user_auto_delete, dict):
        sys.stderr.write("Error in configuration for user auto delete\n")
        return
    if not user_auto_delete.get('enable', True):
        return
    try:
        cutoff_days = int(user_auto_delete.get('inactive days', 0))
        assert cutoff_days >= 0
    except:
        sys.stderr.write("Error in configuration for user auto delete\n")
        return
    if cutoff_days == 0:
        return
    delete_shared = bool(user_auto_delete.get('delete shared', False))
    role_ids = {}
    for item in Role.query.all():
        role_ids[item.name] = item.id
    roles = user_auto_delete.get('privileges', ['user'])
    if isinstance(roles, str):
        roles = [roles]
    if not isinstance(roles, list):
        sys.stderr.write("Error in configuration for user auto delete\n")
        return
    search_roles = set()
    for item in roles:
        if not isinstance(item, str):
            sys.stderr.write("Error in configuration for user auto delete: invalid privilege\n")
            return
        if item not in role_ids:
            sys.stderr.write("Error in configuration for user auto delete: unknown privilege" + repr(item) + "\n")
            return
        if item == 'cron':
            sys.stderr.write("Error in configuration for user auto delete: invalid privilege\n")
            return
        search_roles.add(role_ids[item])
    filters = []
    for item in search_roles:
        filters.append(UserRoles.role_id == item)
    cutoff_date = datetime.datetime.utcnow() - dateutil.relativedelta.relativedelta(days=cutoff_days)
    default_date = datetime.datetime(2020, 2, 24, 0, 0)
    candidates = []
    for item in db.session.execute(select(UserModel.id, UserModel.last_login).join(UserRoles, UserModel.id == UserRoles.user_id).where(or_(*filters))).all():
        if item.last_login is None:
            the_date = default_date
        else:
            the_date = item.last_login
        if the_date < cutoff_date:
            candidates.append(item.id)
    for user_id in candidates:
        last_interview = db.session.execute(select(UserDictKeys.user_id, db.func.max(UserDict.modtime).label('last_activity')).join(UserDict, and_(UserDictKeys.filename == UserDict.filename, UserDictKeys.key == UserDict.key)).where(UserDictKeys.user_id == user_id).group_by(UserDictKeys.user_id)).first()
        if last_interview is not None and last_interview.last_activity > cutoff_date:
            continue
        sys.stderr.write("delete_inactive_users: deleting %d\n" % (user_id,))
        user_interviews(user_id=user_id, secret=None, exclude_invalid=False, action='delete_all', delete_shared=delete_shared, admin=True)
        docassemble.webapp.backend.delete_user_data(user_id, r, r_user)
Example #2
0
def edit_user_profile_page(id):
    user = UserModel.query.options(
        db.joinedload('roles')).filter_by(id=id).first()
    the_tz = user.timezone if user.timezone else get_default_timezone()
    if user is None or user.social_id.startswith('disabled$'):
        abort(404)
    if 'disable_mfa' in request.args and int(request.args['disable_mfa']) == 1:
        user.otp_secret = None
        db.session.commit()
        #docassemble.webapp.daredis.clear_user_cache()
        return redirect(url_for('edit_user_profile_page', id=id))
    if 'reset_email_confirmation' in request.args and int(
            request.args['reset_email_confirmation']) == 1:
        user.confirmed_at = None
        db.session.commit()
        #docassemble.webapp.daredis.clear_user_cache()
        return redirect(url_for('edit_user_profile_page', id=id))
    if daconfig.get('admin can delete account',
                    True) and user.id != current_user.id:
        if 'delete_account' in request.args and int(
                request.args['delete_account']) == 1:
            from docassemble.webapp.server import user_interviews, r, r_user
            from docassemble.webapp.backend import delete_user_data
            user_interviews(user_id=id,
                            secret=None,
                            exclude_invalid=False,
                            action='delete_all',
                            delete_shared=False)
            delete_user_data(id, r, r_user)
            db.session.commit()
            flash(word('The user account was deleted.'), 'success')
            return redirect(url_for('user_list'))
        if 'delete_account_complete' in request.args and int(
                request.args['delete_account_complete']) == 1:
            from docassemble.webapp.server import user_interviews, r, r_user
            from docassemble.webapp.backend import delete_user_data
            user_interviews(user_id=id,
                            secret=None,
                            exclude_invalid=False,
                            action='delete_all',
                            delete_shared=True)
            delete_user_data(id, r, r_user)
            db.session.commit()
            flash(word('The user account was deleted.'), 'success')
            return redirect(url_for('user_list'))
    the_role_id = list()
    for role in user.roles:
        the_role_id.append(text_type(role.id))
    if len(the_role_id) == 0:
        the_role_id = [text_type(Role.query.filter_by(name='user').first().id)]
    form = EditUserProfileForm(request.form, obj=user, role_id=the_role_id)
    if request.method == 'POST' and form.cancel.data:
        flash(word('The user profile was not changed.'), 'success')
        return redirect(url_for('user_list'))
    if user.social_id.startswith('local$'):
        form.role_id.choices = [(r.id, r.name)
                                for r in db.session.query(Role).filter(
                                    Role.name != 'cron').order_by('name')]
        privileges_note = None
    else:
        form.role_id.choices = [(r.id, r.name) for r in db.session.query(
            Role).filter(and_(Role.name != 'cron',
                              Role.name != 'admin')).order_by('name')]
        privileges_note = word(
            "Note: only users with e-mail/password accounts can be given admin privileges."
        )
    form.timezone.choices = [
        (x, x) for x in sorted([tz for tz in pytz.all_timezones])
    ]
    form.timezone.default = the_tz
    if text_type(form.timezone.data) == 'None' or text_type(
            form.timezone.data) == '':
        form.timezone.data = the_tz
    if user.otp_secret is None:
        form.uses_mfa.data = False
    else:
        form.uses_mfa.data = True
    admin_id = Role.query.filter_by(name='admin').first().id
    if request.method == 'POST' and form.validate(user.id, admin_id):
        form.populate_obj(user)
        roles_to_remove = list()
        the_role_id = list()
        for role in user.roles:
            roles_to_remove.append(role)
        for role in roles_to_remove:
            user.roles.remove(role)
        for role in Role.query.order_by('id'):
            if role.id in form.role_id.data:
                user.roles.append(role)
                the_role_id.append(role.id)
        db.session.commit()
        #docassemble.webapp.daredis.clear_user_cache()
        flash(word('The information was saved.'), 'success')
        return redirect(url_for('user_list'))
    form.role_id.default = the_role_id
    confirmation_feature = True if user.id > 2 else False
    script = """
    <script>
      $(".dadeleteaccount").click(function(event){
        if (!confirm(""" + json.dumps(
        word("Are you sure you want to permanently delete this user's account?"
             )) + """)){
          event.preventDefault();
          return false;
        }
      });
    </script>"""
    response = make_response(
        render_template('users/edit_user_profile_page.html',
                        version_warning=None,
                        page_title=word('Edit User Profile'),
                        tab_title=word('Edit User Profile'),
                        form=form,
                        confirmation_feature=confirmation_feature,
                        privileges_note=privileges_note,
                        is_self=(user.id == current_user.id),
                        extra_js=Markup(script)), 200)
    response.headers[
        'Cache-Control'] = 'no-store, no-cache, must-revalidate, post-check=0, pre-check=0, max-age=0'
    return response