Better contact form
This commit is contained in:
Binary file not shown.
Binary file not shown.
9
forms.py
9
forms.py
@@ -1,5 +1,5 @@
|
||||
from flask_wtf import FlaskForm
|
||||
from wtforms import StringField, TextAreaField, BooleanField, SubmitField, PasswordField, SelectMultipleField
|
||||
from wtforms import StringField, TextAreaField, BooleanField, SubmitField, PasswordField, SelectMultipleField, SelectField
|
||||
from wtforms.validators import DataRequired, Email, Length, Optional, ValidationError
|
||||
from models import User
|
||||
from flask_login import current_user
|
||||
@@ -13,8 +13,11 @@ class UserForm(FlaskForm):
|
||||
company = StringField('Company (Optional)', validators=[Optional(), Length(max=100)])
|
||||
position = StringField('Position (Optional)', validators=[Optional(), Length(max=100)])
|
||||
notes = TextAreaField('Notes (Optional)', validators=[Optional()])
|
||||
is_admin = BooleanField('Admin Role', default=False)
|
||||
is_manager = BooleanField('Manager Role', default=False)
|
||||
role = SelectField('Role', choices=[
|
||||
('user', 'Standard User'),
|
||||
('manager', 'Manager'),
|
||||
('admin', 'Administrator')
|
||||
], validators=[DataRequired()])
|
||||
new_password = PasswordField('New Password (Optional)')
|
||||
confirm_password = PasswordField('Confirm Password (Optional)')
|
||||
profile_picture = FileField('Profile Picture (Optional)', validators=[FileAllowed(['jpg', 'jpeg', 'png', 'gif'], 'Images only!')])
|
||||
|
||||
Binary file not shown.
@@ -98,14 +98,8 @@ def new_contact():
|
||||
form = UserForm()
|
||||
total_admins = User.query.filter_by(is_admin=True).count()
|
||||
if request.method == 'GET':
|
||||
form.is_admin.data = False # Ensure admin role is unchecked by default
|
||||
form.is_manager.data = False # Ensure manager role is unchecked by default
|
||||
form.role.data = 'user' # Default to standard user
|
||||
elif request.method == 'POST':
|
||||
if 'is_admin' not in request.form:
|
||||
form.is_admin.data = False
|
||||
if 'is_manager' not in request.form:
|
||||
form.is_manager.data = False
|
||||
|
||||
if form.validate_on_submit():
|
||||
# Check if a user with this email already exists
|
||||
existing_user = User.query.filter_by(email=form.email.data).first()
|
||||
@@ -126,7 +120,7 @@ def new_contact():
|
||||
alphabet = string.ascii_letters + string.digits + string.punctuation
|
||||
random_password = ''.join(secrets.choice(alphabet) for _ in range(32))
|
||||
|
||||
# Create new user account
|
||||
# Create new user
|
||||
user = User(
|
||||
username=form.first_name.data,
|
||||
last_name=form.last_name.data,
|
||||
@@ -135,39 +129,12 @@ def new_contact():
|
||||
company=form.company.data,
|
||||
position=form.position.data,
|
||||
notes=form.notes.data,
|
||||
is_active=True, # Set default value
|
||||
is_admin=form.is_admin.data,
|
||||
is_manager=form.is_manager.data,
|
||||
is_admin=(form.role.data == 'admin'),
|
||||
is_manager=(form.role.data == 'manager'),
|
||||
profile_picture=profile_picture
|
||||
)
|
||||
user.set_password(random_password)
|
||||
db.session.add(user)
|
||||
db.session.commit()
|
||||
|
||||
# Create password setup token
|
||||
token = secrets.token_urlsafe(32)
|
||||
setup_token = PasswordSetupToken(
|
||||
user_id=user.id,
|
||||
token=token,
|
||||
expires_at=datetime.utcnow() + timedelta(hours=24)
|
||||
)
|
||||
db.session.add(setup_token)
|
||||
db.session.commit()
|
||||
|
||||
# Create notification for the new user
|
||||
create_notification(
|
||||
notif_type='account_created',
|
||||
user_id=user.id,
|
||||
sender_id=current_user.id, # Admin who created the account
|
||||
details={
|
||||
'message': 'Your DocuPulse account has been created by an administrator.',
|
||||
'username': user.username,
|
||||
'email': user.email,
|
||||
'created_by': f"{current_user.username} {current_user.last_name}",
|
||||
'timestamp': datetime.utcnow().isoformat(),
|
||||
'setup_link': url_for('auth.setup_password', token=token, _external=True)
|
||||
}
|
||||
)
|
||||
|
||||
# Log user creation event
|
||||
log_event(
|
||||
@@ -178,8 +145,7 @@ def new_contact():
|
||||
'user_id': user.id,
|
||||
'user_name': f"{user.username} {user.last_name}",
|
||||
'email': user.email,
|
||||
'is_admin': user.is_admin,
|
||||
'is_manager': user.is_manager,
|
||||
'role': form.role.data,
|
||||
'method': 'admin_creation'
|
||||
}
|
||||
)
|
||||
@@ -287,7 +253,13 @@ def edit_contact(id):
|
||||
form.company.data = user.company
|
||||
form.position.data = user.position
|
||||
form.notes.data = user.notes
|
||||
form.is_admin.data = user.is_admin
|
||||
# Set role based on current permissions
|
||||
if user.is_admin:
|
||||
form.role.data = 'admin'
|
||||
elif user.is_manager:
|
||||
form.role.data = 'manager'
|
||||
else:
|
||||
form.role.data = 'user'
|
||||
if form.validate_on_submit():
|
||||
# Handle profile picture removal
|
||||
if 'remove_picture' in request.form:
|
||||
@@ -315,9 +287,10 @@ def edit_contact(id):
|
||||
user.profile_picture = filename
|
||||
|
||||
# Prevent removing admin from the last admin
|
||||
if not form.is_admin.data and user.is_admin and total_admins <= 1:
|
||||
if form.role.data != 'admin' and user.is_admin and total_admins <= 1:
|
||||
flash('There must be at least one admin user in the system.', 'error')
|
||||
return render_template('contacts/form.html', form=form, title='Edit User', total_admins=total_admins, user=user)
|
||||
|
||||
# Check if the new email is already used by another user
|
||||
if form.email.data != user.email:
|
||||
existing_user = User.query.filter_by(email=form.email.data).first()
|
||||
@@ -332,7 +305,7 @@ def edit_contact(id):
|
||||
'phone': user.phone,
|
||||
'company': user.company,
|
||||
'position': user.position,
|
||||
'is_admin': user.is_admin
|
||||
'role': 'admin' if user.is_admin else 'manager' if user.is_manager else 'user'
|
||||
}
|
||||
|
||||
user.username = form.first_name.data
|
||||
@@ -342,7 +315,8 @@ def edit_contact(id):
|
||||
user.company = form.company.data
|
||||
user.position = form.position.data
|
||||
user.notes = form.notes.data
|
||||
user.is_admin = form.is_admin.data
|
||||
user.is_admin = (form.role.data == 'admin')
|
||||
user.is_manager = (form.role.data == 'manager')
|
||||
|
||||
# Set password if provided
|
||||
password_changed = False
|
||||
@@ -366,6 +340,7 @@ def edit_contact(id):
|
||||
'phone': user.phone,
|
||||
'company': user.company,
|
||||
'position': user.position,
|
||||
'role': form.role.data,
|
||||
'password_changed': password_changed
|
||||
},
|
||||
'timestamp': datetime.utcnow().isoformat()
|
||||
@@ -387,7 +362,7 @@ def edit_contact(id):
|
||||
'phone': user.phone,
|
||||
'company': user.company,
|
||||
'position': user.position,
|
||||
'is_admin': user.is_admin
|
||||
'role': form.role.data
|
||||
},
|
||||
'password_changed': password_changed,
|
||||
'method': 'admin_update'
|
||||
|
||||
@@ -113,37 +113,45 @@
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<div class="flex flex-col space-y-4">
|
||||
<div class="flex items-center space-x-4">
|
||||
<div class="flex items-center relative group">
|
||||
{% set is_last_admin = current_user.is_admin and total_admins <= 1 %}
|
||||
{{ form.is_admin(
|
||||
class="h-4 w-4 focus:ring-blue-500 border-gray-300 rounded",
|
||||
style="accent-color: #16767b;",
|
||||
disabled=is_last_admin and form.is_admin.data
|
||||
) }}
|
||||
{{ form.is_admin.label(class="ml-2 block text-sm text-gray-900") }}
|
||||
{% if is_last_admin and form.is_admin.data %}
|
||||
<input type="hidden" name="is_admin" value="y">
|
||||
<!-- Role Selection Section -->
|
||||
<div class="bg-gray-50 p-4 rounded-lg border border-gray-200">
|
||||
<h4 class="text-lg font-medium text-gray-900 mb-4">Role Selection</h4>
|
||||
<div class="space-y-3">
|
||||
{% for value, label in form.role.choices %}
|
||||
<div class="flex items-center">
|
||||
<input type="radio"
|
||||
name="{{ form.role.name }}"
|
||||
value="{{ value }}"
|
||||
id="role_{{ value }}"
|
||||
class="h-4 w-4 text-primary-600 focus:ring-primary-500 border-gray-300"
|
||||
{% if form.role.data == value %}checked{% endif %}
|
||||
{% if value == 'admin' and current_user.is_admin and total_admins <= 1 and form.role.data == 'admin' %}disabled{% endif %}>
|
||||
<label for="role_{{ value }}" class="ml-3 block text-sm font-medium text-gray-700">
|
||||
{{ label }}
|
||||
<span class="text-gray-500 text-xs block mt-0.5">
|
||||
{% if value == 'admin' %}
|
||||
Full access to all contacts, rooms and conversations. Can manage system settings and website customization.
|
||||
{% elif value == 'manager' %}
|
||||
Can create and manage rooms and conversations. Can view all contacts. Only limited access to system settings.
|
||||
{% else %}
|
||||
Basic user access.
|
||||
{% endif %}
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% if form.role.errors %}
|
||||
{% for error in form.role.errors %}
|
||||
<p class="mt-1 text-sm text-red-600">{{ error }}</p>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
<div class="absolute left-0 bottom-full mb-2 hidden group-hover:block bg-gray-800 text-white text-xs rounded py-1 px-2 w-48">
|
||||
Admin users have full access to manage contacts and system settings.
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex items-center relative group">
|
||||
{{ form.is_manager(
|
||||
class="h-4 w-4 focus:ring-blue-500 border-gray-300 rounded",
|
||||
style="accent-color: #16767b;"
|
||||
) }}
|
||||
{{ form.is_manager.label(class="ml-2 block text-sm text-gray-900") }}
|
||||
<div class="absolute left-0 bottom-full mb-2 hidden group-hover:block bg-gray-800 text-white text-xs rounded py-1 px-2 w-48">
|
||||
Manager users have similar permissions to admins but with some restrictions.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% if form.is_admin.errors %}
|
||||
|
||||
<div class="flex flex-col space-y-4">
|
||||
{% if form.role.errors %}
|
||||
<div class="p-3 bg-red-50 border border-red-200 rounded-lg">
|
||||
{% for error in form.is_admin.errors %}
|
||||
{% for error in form.role.errors %}
|
||||
<p class="text-sm text-red-700">{{ error }}</p>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user