def route_modify(user_id): """ Change details about the current user """ # only accept form data if request.method != 'POST': return redirect(url_for('main.route_profile')) # security check if g.user.user_id != user_id: flash('Unable to modify a different user', 'danger') return redirect(url_for('main.route_dashboard')) if g.user.auth_type == 'local+locked': flash('Unable to change user as account locked', 'danger') return redirect(url_for('main.route_dashboard')) if g.user.auth_type == 'oauth': flash('Unable to change OAuth-only user', 'danger') return redirect(url_for('main.route_dashboard')) user = db.session.query(User).filter(User.user_id == user_id).first() # verify name if 'display_name' in request.form: display_name = request.form['display_name'] if len(display_name) < 3: flash('Failed to modify profile: Name invalid', 'warning') return redirect(url_for('main.route_profile'), 302) user.display_name = display_name # get the new human_user_id if specified if 'human_user' in request.form and request.form['human_user']: username = request.form['human_user'] human_user = db.session.query(User).\ filter(User.username == username).first() if not human_user: flash( 'Failed to modify profile: Human user %s not found' % username, 'warning') return redirect(url_for('main.route_profile'), 302) user.human_user_id = human_user.user_id # unchecked checkbuttons are not included in the form data for key in [ 'notify-demote-failures', 'notify-promote', 'notify-upload-vendor', 'notify-upload-affiliate', 'notify-non-public', 'notify-server-error' ]: if key in request.form: if not user.get_action(key): user.actions.append(UserAction(value=key)) else: action = user.get_action(key) if action: user.actions.remove(action) # save to database user.mtime = datetime.datetime.utcnow() db.session.commit() flash('Updated profile', 'info') return redirect(url_for('main.route_profile'))
def route_modify_by_admin(user_id): """ Change details about the any user """ # check exists user = db.session.query(User).filter(User.user_id == user_id).first() if not user: flash('No user matched!', 'danger') return redirect(url_for('main.route_dashboard'), 422) # security check if not user.vendor.check_acl('@manage-users'): flash('Permission denied: Unable to modify user as non-admin', 'danger') return redirect(url_for('main.route_dashboard')) if not g.user.check_acl('@admin') and 'vendor_id' in request.form: flash('Permission denied: Unable to modify group for user as non-admin', 'danger') return redirect(url_for('main.route_dashboard')) # user is being promoted, so check the manager already has this attribute if not user.check_acl('@vendor-manager') and 'vendor-manager' in request.form: if not g.user.check_acl('@add-action-vendor-manager'): flash('Permission denied: Unable to promote user to manager', 'danger') return redirect(url_for('main.route_dashboard')) if not user.check_acl('@researcher') and 'researcher' in request.form: if not g.user.check_acl('@add-action-researcher'): flash('Permission denied: Unable to promote user to researcher', 'danger') return redirect(url_for('main.route_dashboard')) if not user.check_acl('@analyst') and 'analyst' in request.form: if not g.user.check_acl('@add-action-analyst'): flash('Permission denied: Unable to promote user to analyst', 'danger') return redirect(url_for('main.route_dashboard')) if not user.check_acl('@qa') and 'qa' in request.form: if not g.user.check_acl('@add-action-qa'): flash('Permission denied: Unable to promote user to QA', 'danger') return redirect(url_for('main.route_dashboard')) if not user.check_acl('@approved-public') and 'approved-public' in request.form: if not g.user.check_acl('@add-action-approved-public'): flash('Permission denied: Unable to promote user to approved public', 'danger') return redirect(url_for('main.route_dashboard')) if not user.check_acl('@robot') and 'robot' in request.form: if not g.user.check_acl('@add-action-robot'): flash('Permission denied: Unable to mark user as robot', 'danger') return redirect(url_for('main.route_dashboard')) if not user.check_acl('@admin') and 'admin' in request.form: if not g.user.check_acl('@add-action-admin'): flash('Permission denied: Unable to mark user as admin', 'danger') return redirect(url_for('main.route_dashboard')) if not user.check_acl('@admin') and 'partner' in request.form: if not g.user.check_acl('@add-action-partner'): flash('Permission denied: Unable to mark user as partner', 'danger') return redirect(url_for('main.route_dashboard')) # set each optional thing in turn old_vendor = user.vendor for key in ['display_name', 'username', 'auth_type', 'vendor_id', 'auth_warning']: if key in request.form: value = request.form[key] if value == '': value = None setattr(user, key, value) # get the new human_user_id if specified if 'human_user' in request.form: username = request.form['human_user'] if username: human_user = db.session.query(User).\ filter(User.username == username).first() if not human_user: flash('Failed to modify profile: Human user %s not found' % username, 'warning') return redirect(url_for('main.route_profile'), 302) user.human_user_id = human_user.user_id else: user.human_user_id = None # unchecked checkbuttons are not included in the form data for key in ['is_otp_enabled']: setattr(user, key, bool(key in request.form)) for key in ['qa', 'analyst', 'vendor-manager', 'researcher', 'approved-public', 'robot', 'admin', 'partner']: if key in request.form: if not user.get_action(key): user.actions.append(UserAction(value=key)) else: action = user.get_action(key) if action: user.actions.remove(action) # password is optional, and hashed if 'password' in request.form and request.form['password']: user.password = request.form['password'] # was disabled? if user.auth_type == 'disabled': if not user.dtime: user.dtime = datetime.datetime.utcnow() else: user.dtime = None user.mtime = datetime.datetime.utcnow() db.session.commit() # reparent any uploaded firmware is_dirty = False reparent = bool('reparent' in request.form) if old_vendor.vendor_id != user.vendor_id and reparent: for fw in db.session.query(Firmware).\ filter(Firmware.user_id == user.user_id): fw.vendor_id = user.vendor_id if fw.remote.name.startswith('embargo'): is_dirty = True fw.remote_id = user.vendor.remote.remote_id for ev in db.session.query(FirmwareEvent).\ filter(FirmwareEvent.user_id == user.user_id): ev.remote_id = user.vendor.remote.remote_id # fix event log if old_vendor.vendor_id != user.vendor_id: for ev in db.session.query(Event).\ filter(Event.user_id == user.user_id): ev.vendor_id = user.vendor_id # mark both remotes as dirty if is_dirty: user.vendor.remote.is_dirty = True old_vendor.remote.is_dirty = True db.session.commit() # send email if 'send_email' in request.form: if old_vendor.vendor_id != user.vendor_id: send_email("[LVFS] Your account has been moved", user.email_address, render_template('email-moved.txt', user=user, old_vendor=old_vendor, reparent=reparent)) else: if user.auth_type == 'disabled': send_email("[LVFS] Your account has been disabled", user.email_address, render_template('email-disabled.txt', user=user)) else: send_email("[LVFS] Your account has been updated", user.email_address, render_template('email-modify.txt', user=user)) flash('Updated profile and sent a notification email to the user', 'info') else: flash('Updated profile', 'info') return redirect(url_for('users.route_admin', user_id=user_id))
def upgrade(): op.create_table('user_actions', sa.Column('user_action_id', sa.Integer(), nullable=False), sa.Column('user_id', sa.Integer(), nullable=False), sa.Column('ctime', sa.DateTime(), nullable=False), sa.Column('value', sa.Text(), nullable=True), sa.ForeignKeyConstraint( ['user_id'], ['users.user_id'], ), sa.PrimaryKeyConstraint('user_action_id'), sa.UniqueConstraint('user_action_id'), mysql_character_set='utf8mb4') for user in db.session.query(User): if user.unused_is_qa: user.actions.append(UserAction(value='qa')) if user.unused_is_robot: user.actions.append(UserAction(value='robot')) if user.unused_is_analyst: user.actions.append(UserAction(value='analyst')) if user.unused_is_vendor_manager: user.actions.append(UserAction(value='vendor-manager')) if user.unused_is_approved_public: user.actions.append(UserAction(value='approved-public')) if user.unused_is_admin: user.actions.append(UserAction(value='admin')) if user.unused_is_researcher: user.actions.append(UserAction(value='researcher')) if user.unused_notify_demote_failures: user.actions.append(UserAction(value='notify-demote-failures')) if user.unused_notify_server_error: user.actions.append(UserAction(value='notify-server-error')) if user.unused_notify_upload_vendor: user.actions.append(UserAction(value='notify-upload-vendor')) if user.unused_notify_upload_affiliate: user.actions.append(UserAction(value='notify-upload-affiliate')) if user.unused_notify_promote: user.actions.append(UserAction(value='notify-promote')) db.session.commit()