diff --git a/eveai_app/models/user.py b/eveai_app/models/user.py index 8e50acd..7d2b0bc 100644 --- a/eveai_app/models/user.py +++ b/eveai_app/models/user.py @@ -81,3 +81,4 @@ class User(db.Model, UserMixin): def __repr__(self): return '' % self.name() + diff --git a/eveai_app/templates/user/edit_user.html b/eveai_app/templates/user/edit_user.html index 74b47f1..1e74521 100644 --- a/eveai_app/templates/user/edit_user.html +++ b/eveai_app/templates/user/edit_user.html @@ -8,8 +8,8 @@ {% block content %}
{{ form.hidden_tag() }} - {% set disabled_fields = ['email', 'user_name'] %} - {% set exclude_fields = ['password', 'confirm_password'] %} + {% set disabled_fields = ['email', 'user_name', 'tenant_id'] %} + {% set exclude_fields = [] %} {% for field in form %} {{ render_field(field, disabled_fields, exclude_fields) }} {% endfor %} diff --git a/eveai_app/views/user_forms.py b/eveai_app/views/user_forms.py index a5c22ea..fed343a 100644 --- a/eveai_app/views/user_forms.py +++ b/eveai_app/views/user_forms.py @@ -1,6 +1,8 @@ from flask_wtf import FlaskForm -from wtforms import StringField, PasswordField, BooleanField, SubmitField, EmailField, IntegerField, DateField +from wtforms import (StringField, PasswordField, BooleanField, SubmitField, EmailField, IntegerField, DateField, + SelectMultipleField, FieldList, FormField) from wtforms.validators import DataRequired, Length, Email, NumberRange +from ..models.user import User, Role class TenantForm(FlaskForm): @@ -12,16 +14,38 @@ class TenantForm(FlaskForm): submit = SubmitField('Submit') -class UserForm(FlaskForm): +class BaseUserForm(FlaskForm): user_name = StringField('Name', validators=[DataRequired(), Length(max=80)]) email = EmailField('Email', validators=[DataRequired(), Email()]) - password = PasswordField('Password', validators=[DataRequired(), Length(min=8)]) - confirm_password = PasswordField('Confirm Password', validators=[DataRequired(), Length(min=8)]) first_name = StringField('First Name', validators=[DataRequired(), Length(max=80)]) last_name = StringField('Last Name', validators=[DataRequired(), Length(max=80)]) is_active = BooleanField('Is Active', id='flexSwitchCheckDefault') valid_to = DateField('Valid to', id='datepicker') tenant_id = IntegerField('Tenant ID', validators=[NumberRange(min=0)]) - submit = SubmitField('Submit') + roles = SelectMultipleField('Roles', coerce=int) + + def __init__(self, *args, **kwargs): + super(BaseUserForm, self).__init__(*args, **kwargs) + self.roles.choices = [(role.id, role.name) for role in Role.query.all()] +class CreateUserForm(BaseUserForm): + password = PasswordField('Password', validators=[DataRequired(), Length(min=8)]) + confirm_password = PasswordField('Confirm Password', validators=[DataRequired(), Length(min=8)]) + submit = SubmitField('Create User') + + +class EditUserForm(BaseUserForm): + submit = SubmitField('Save User') + + +class RoleForm(FlaskForm): + # This subform will represent a single checkbox for each role + role_id = StringField('Role ID') + checked = BooleanField('Assigned') + + +class UserRoleForm(FlaskForm): + email = EmailField('Email', validators=[DataRequired(), Email()]) + roles = FieldList(FormField(RoleForm), min_entries=1) + submit = SubmitField('Update Roles') diff --git a/eveai_app/views/user_views.py b/eveai_app/views/user_views.py index d6532f1..29a3b04 100644 --- a/eveai_app/views/user_views.py +++ b/eveai_app/views/user_views.py @@ -4,9 +4,9 @@ from datetime import datetime as dt, timezone as tz from flask import request, redirect, url_for, flash, render_template, Blueprint, session from flask_security import hash_password -from ..models.user import User, Tenant +from ..models.user import User, Tenant, Role, RolesUsers from ..extensions import db -from .user_forms import TenantForm, UserForm +from .user_forms import TenantForm, CreateUserForm, EditUserForm from ..utils.database import Database user_bp = Blueprint('user_bp', __name__, url_prefix='/user') @@ -78,9 +78,10 @@ def edit_tenant(tenant_id): return render_template('user/edit_tenant.html', form=form, tenant_id=tenant_id) + @user_bp.route('/user', methods=['GET', 'POST']) def user(): - form = UserForm() + form = CreateUserForm() if form.validate_on_submit(): if form.password.data != form.confirm_password.data: flash('Passwords do not match.') @@ -108,6 +109,11 @@ def user(): the_tenant = Tenant.query.get(tenant_id) new_user.tenant = the_tenant + # Add roles + for role_id in form.roles.data: + the_role = Role.query.get(role_id) + new_user.roles.append(the_role) + # Add the new user to the database and commit the changes try: @@ -125,13 +131,34 @@ def user(): @user_bp.route('/user/', methods=['GET', 'POST']) def edit_user(user_id): user = User.query.get_or_404(user_id) # This will return a 404 if no user is found - form = UserForm(obj=user) + form = EditUserForm(obj=user) if request.method == 'POST' and form.validate_on_submit(): # Populate the user with form data - form.populate_obj(user) + user.first_name = form.first_name.data + user.last_name = form.last_name.data + user.is_active = form.is_active.data + user.valid_to = form.valid_to.data + user.updated_at = dt.now(tz.utc) + + # Update roles + current_roles = set(role.id for role in user.roles) + selected_roles = set(form.roles.data) + # Add new roles + for role_id in selected_roles - current_roles: + role = Role.query.get(role_id) + if role: + user.roles.append(role) + # Remove unselected roles + for role_id in current_roles - selected_roles: + role = Role.query.get(role_id) + if role: + user.roles.remove(role) + db.session.commit() flash('User updated successfully.', 'success') - return redirect(url_for('user_bp.user_profile', user_id=user.id)) # Assuming there's a user profile view to redirect to + return redirect( + url_for('user_bp.edit_user', user_id=user.id)) # Assuming there's a user profile view to redirect to + form.roles.data = [role.id for role in user.roles] return render_template('user/edit_user.html', form=form, user_id=user_id)