write add user
This commit is contained in:
@ -9,4 +9,27 @@ class LoginForm(FlaskForm):
|
||||
password = PasswordField('Password', validators=[
|
||||
InputRequired(message='Password is required.'),
|
||||
Length(min=1, max=30, message='Password must be between 1 and 30 characters long.')
|
||||
])
|
||||
])
|
||||
|
||||
class AddUserForm(FlaskForm):
|
||||
username = StringField('Username', validators=[
|
||||
InputRequired(message='Username is required.'),
|
||||
Regexp(r'^[a-zA-Z][a-zA-Z0-9_]{0,19}$', message='Username must start with a letter and can only contain letters, numbers, and underscores (max 20 characters).')
|
||||
])
|
||||
password = PasswordField('Password', validators=[
|
||||
InputRequired(message='Password is required.'),
|
||||
Length(min=1, max=30, message='Password must be between 1 and 30 characters long.')
|
||||
])
|
||||
name = StringField('Name', validators=[
|
||||
InputRequired(message='Name is required.'),
|
||||
Regexp(r'^[\u4e00-\u9fa5]{2,5}$', message='Name must be 2-5 Chinese characters.')
|
||||
])
|
||||
mailAddr = StringField('Email', validators=[
|
||||
InputRequired(message='Email is required.'),
|
||||
Length(max=30, message='Email must be less than 30 characters long.'),
|
||||
Regexp(r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$', message='Invalid email format.')
|
||||
])
|
||||
privilege = StringField('Privilege', validators=[
|
||||
InputRequired(message='Privilege is required.'),
|
||||
Regexp(r'^[0-9]$|^10$', message='Privilege must be an integer between 0 and 10.')
|
||||
])
|
||||
|
29
UI/main.py
29
UI/main.py
@ -127,3 +127,32 @@ def logout():
|
||||
return redirect(url_for('home'))
|
||||
if __name__ == '__main__':
|
||||
app.run(debug=True)
|
||||
|
||||
@app.route('/admin/adduser', methods=['GET', 'POST'])
|
||||
def add_user():
|
||||
if 'username' not in session or utils.GetPrivilege(session['username'], ExecCommand) < 10:
|
||||
return redirect(url_for('login'))
|
||||
|
||||
form = AddUserForm()
|
||||
if form.validate_on_submit():
|
||||
cur_username = session['username']
|
||||
new_username = form.username.data
|
||||
password = form.password.data
|
||||
name = form.name.data
|
||||
mailAddr = form.mailAddr.data
|
||||
privilege = form.privilege.data
|
||||
|
||||
# 调用 ExecCommand 执行添加用户命令
|
||||
add_user_response = ExecCommand(f'add_user -c {cur_username} -u {new_username} -p {password} -n {name} -m {mailAddr} -g {privilege}')
|
||||
|
||||
if add_user_response.strip() == '0':
|
||||
flash('User added successfully.', 'success')
|
||||
return redirect(url_for('home'))
|
||||
elif add_user_response.strip() == '-1':
|
||||
error = 'Failed to add user.'
|
||||
else:
|
||||
error = 'An unknown error occurred.'
|
||||
|
||||
flash(error, 'danger')
|
||||
|
||||
return render_template('adduser.html', form=form)
|
||||
|
108
UI/templates/adduser.html
Normal file
108
UI/templates/adduser.html
Normal file
@ -0,0 +1,108 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block title %}Add User{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-6">
|
||||
<h2 class="text-center">Add User</h2>
|
||||
|
||||
<!-- Flash messages -->
|
||||
{% with messages = get_flashed_messages(with_categories=true) %}
|
||||
{% if messages %}
|
||||
{% for category, message in messages %}
|
||||
<div class="alert alert-{{ category }} alert-dismissible fade show" role="alert">
|
||||
{{ message }}
|
||||
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endwith %}
|
||||
|
||||
<form id="addUserForm" class="needs-validation" novalidate method="POST" action="/admin/adduser">
|
||||
{{ form.hidden_tag() }}
|
||||
<div class="form-group">
|
||||
<label for="username">Username</label>
|
||||
<input type="text" class="form-control" id="username" name="username" placeholder="Enter username" pattern="^[a-zA-Z][a-zA-Z0-9_]{0,19}$" required>
|
||||
<div class="invalid-feedback">
|
||||
Username must start with a letter and can only contain letters, numbers, and underscores (max 20 characters).
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="password">Password</label>
|
||||
<input type="password" class="form-control" id="password" name="password" minlength="1" maxlength="30" placeholder="Enter password" required>
|
||||
<div class="invalid-feedback">
|
||||
Password must be between 1 and 30 characters long.
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="name">Name</label>
|
||||
<input type="text" class="form-control" id="name" name="name" pattern="^[\u4e00-\u9fa5]{2,5}$" placeholder="Enter name" required>
|
||||
<div class="invalid-feedback">
|
||||
Name must be 2-5 Chinese characters.
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="mailAddr">Email</label>
|
||||
<input type="email" class="form-control" id="mailAddr" name="mailAddr" pattern="^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$" maxlength="30" placeholder="Enter email" required>
|
||||
<div class="invalid-feedback">
|
||||
Invalid email format.
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="privilege">Privilege</label>
|
||||
<input type="text" class="form-control" id="privilege" name="privilege" pattern="^[0-9]$|^10$" placeholder="Enter privilege" required>
|
||||
<div class="invalid-feedback">
|
||||
Privilege must be an integer between 0 and 10.
|
||||
</div>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary btn-block">Add User</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const addUserForm = document.getElementById('addUserForm');
|
||||
|
||||
// Utility function to toggle validation classes
|
||||
function validateInput(input) {
|
||||
if (input.checkValidity()) {
|
||||
input.classList.remove('is-invalid');
|
||||
input.classList.add('is-valid');
|
||||
} else {
|
||||
input.classList.remove('is-valid');
|
||||
input.classList.add('is-invalid');
|
||||
}
|
||||
}
|
||||
|
||||
// Attach input event listeners for real-time validation
|
||||
['username', 'password', 'name', 'mailAddr', 'privilege'].forEach(fieldId => {
|
||||
const input = document.getElementById(fieldId);
|
||||
input.addEventListener('input', () => validateInput(input));
|
||||
});
|
||||
|
||||
// Final form validation on submit
|
||||
addUserForm.addEventListener('submit', function(event) {
|
||||
let formValid = true;
|
||||
|
||||
['username', 'password', 'name', 'mailAddr', 'privilege'].forEach(fieldId => {
|
||||
const input = document.getElementById(fieldId);
|
||||
validateInput(input);
|
||||
if (!input.checkValidity()) {
|
||||
formValid = false;
|
||||
}
|
||||
});
|
||||
|
||||
if (!formValid) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
}
|
||||
|
||||
addUserForm.classList.add('was-validated');
|
||||
});
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
@ -22,22 +22,30 @@
|
||||
</li>
|
||||
</ul>
|
||||
<ul class="navbar-nav ml-auto">
|
||||
{% if session.get('username') %}
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
{{ session.get('username') }}
|
||||
</a>
|
||||
<div class="dropdown-menu dropdown-menu-right" aria-labelledby="navbarDropdown">
|
||||
<a class="dropdown-item" href="/profile">Profile</a>
|
||||
<a class="dropdown-item" href="/logout">Logout</a>
|
||||
</div>
|
||||
</li>
|
||||
{% else %}
|
||||
<li class="nav-item {% if request.endpoint == 'login' %}active{% endif %}">
|
||||
<a class="nav-link" href="/login">Login</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
{% if session.get('username') %}
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="#" id="adminDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
Admin
|
||||
</a>
|
||||
<div class="dropdown-menu dropdown-menu-right" aria-labelledby="adminDropdown">
|
||||
<a class="dropdown-item" href="/admin/adduser">AddUser</a>
|
||||
</div>
|
||||
</li>
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
{{ session.get('username') }}
|
||||
</a>
|
||||
<div class="dropdown-menu dropdown-menu-right" aria-labelledby="navbarDropdown">
|
||||
<a class="dropdown-item" href="/profile">Profile</a>
|
||||
<a class="dropdown-item" href="/logout">Logout</a>
|
||||
</div>
|
||||
</li>
|
||||
{% else %}
|
||||
<li class="nav-item {% if request.endpoint == 'login' %}active{% endif %}">
|
||||
<a class="nav-link" href="/login">Login</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
|
Reference in New Issue
Block a user