write add user

This commit is contained in:
2024-06-22 05:01:32 +00:00
parent 2d407a53f0
commit c6df6a9a28
4 changed files with 185 additions and 17 deletions

View File

@ -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.')
])

View File

@ -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
View 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">&times;</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 %}

View File

@ -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>