From b73fdece9543be43415ff4e2a7aacd179e039d25 Mon Sep 17 00:00:00 2001 From: Izalia Mae Date: Mon, 4 Mar 2024 01:40:51 -0500 Subject: [PATCH] create admin users page --- relay/frontend/base.haml | 1 + relay/frontend/page/admin-users.haml | 44 +++++++++++++++++++++++ relay/frontend/style/users.css | 25 +++++++++++++ relay/views/frontend.py | 54 ++++++++++++++++++++++++++++ 4 files changed, 124 insertions(+) create mode 100644 relay/frontend/page/admin-users.haml create mode 100644 relay/frontend/style/users.css diff --git a/relay/frontend/base.haml b/relay/frontend/base.haml index aa118bd..7de72ce 100644 --- a/relay/frontend/base.haml +++ b/relay/frontend/base.haml @@ -27,6 +27,7 @@ {{menu_item("Whitelist", "/admin/whitelist")}} {{menu_item("Domain Bans", "/admin/domain_bans")}} {{menu_item("Software Bans", "/admin/software_bans")}} + {{menu_item("Users", "/admin/users")}} {{menu_item("Config", "/admin/config")}} {{menu_item("Logout", "/logout")}} diff --git a/relay/frontend/page/admin-users.haml b/relay/frontend/page/admin-users.haml new file mode 100644 index 0000000..aff5ee7 --- /dev/null +++ b/relay/frontend/page/admin-users.haml @@ -0,0 +1,44 @@ +-extends "base.haml" +-set page="Users" +-block content + %details.section + %summary << Add User + %form(target="/admin/users", method="POST") + #add-user + %label(for="username") << Username + %input(id="username" name="username" placeholder="Username") + + %label(for="password") << Password + %input(type="password" id="password" name="password" placeholder="Password") + + %label(for="password2") << Password Again + %input(type="password" id="password2" name="password2" placeholder="Password Again") + + %label(for="handle") << Handle + %input(type="email" name="handle" id="handle" placeholder="handle") + + %input(type="submit" value="Add User") + + #users.section + %table + %thead + %tr + %td.username << Username + %td.handle << Handle + %td.date << Joined + %td.remove + + %tbody + -for user in users + %tr + %td.username + =user.username + + %td.handle + =user.handle or "n/a" + + %td.date + =user.created.strftime("%Y-%m-%d") + + %td.remove + %a(href="/admin/users/delete/{{user.username}}" title="Remove User") << ✖ diff --git a/relay/frontend/style/users.css b/relay/frontend/style/users.css new file mode 100644 index 0000000..c7fe20a --- /dev/null +++ b/relay/frontend/style/users.css @@ -0,0 +1,25 @@ +form input[type="submit"] { + display: block; + margin: 0 auto; +} + +#users .username { + width: 100%; +} + +#users .handle { + text-align: center; +} + +#users .date { + width: max-content; + text-align: right; +} + +#add-user { + display: grid; + grid-template-columns: max-content auto; + grid-gap: var(--spacing); + margin-top: var(--spacing); + margin-bottom: var(--spacing); +} diff --git a/relay/views/frontend.py b/relay/views/frontend.py index 550528c..20c3ddb 100644 --- a/relay/views/frontend.py +++ b/relay/views/frontend.py @@ -350,6 +350,60 @@ class AdminSoftwareBansDelete(View): return await AdminSoftwareBans.run("GET", request, message = 'Unbanned software') +@register_route('/admin/users') +class AdminUsers(View): + async def get(self, + request: Request, + error: str | None = None, + message: str | None = None) -> Response: + + with self.database.session() as conn: + context = { + 'users': tuple(conn.execute('SELECT * FROM users').all()) + } + + if error: + context['error'] = error + + if message: + context['message'] = message + + data = self.template.render('page/admin-users.haml', self, **context) + return Response.new(data, ctype = 'html') + + + async def post(self, request: Request) -> Response: + data = await request.post() + required_fields = {'username', 'password', 'password2'} + print(data) + + if not all(map(data.get, required_fields)): + return await self.get(request, error = 'Missing username and/or password') + + if data['password'] != data['password2']: + return await self.get(request, error = 'Passwords do not match') + + with self.database.session(True) as conn: + if conn.get_user(data['username']): + return await self.get(request, message = "User already exists") + + conn.put_user(data['username'], data['password'], data['handle']) + + return await self.get(request, message = "Added user") + + +@register_route('/admin/users/delete/{name}') +class AdminUsersDelete(View): + async def get(self, request: Request, name: str) -> Response: + with self.database.session() as conn: + if not (conn.get_user(name)): + return await AdminUsers.run("GET", request, message = 'User not found') + + conn.del_user(name) + + return await AdminUsers.run("GET", request, message = 'User deleted') + + @register_route('/admin/config') class AdminConfig(View): async def get(self, request: Request, message: str | None = None) -> Response: