Skip to content

Commit c450b22

Browse files
committed
Support multiple users
1 parent bb62421 commit c450b22

File tree

14 files changed

+382
-50
lines changed

14 files changed

+382
-50
lines changed

assets/js/settings.js

Lines changed: 170 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ function buildSettingsHtml() {
66
jsCreateElement('div', {
77
attrs: {
88
class: 'tabButtons',
9-
style: 'display: grid ; grid-template-columns: 1fr 1fr 1fr 1fr; width: 600px; grid-gap: 30px; margin-bottom: 60px; height: 40px;'
9+
style: 'display: grid ; grid-template-columns: 1fr 1fr 1fr 1fr 1fr; width: 600px; grid-gap: 30px; margin-bottom: 60px; height: 40px;'
1010
},
1111
children: [
1212
jsCreateElement('button', {
@@ -36,6 +36,13 @@ function buildSettingsHtml() {
3636
onclick: 'showTab("webhooks")'
3737
},
3838
children: ['Webhooks']
39+
}),
40+
jsCreateElement('button', {
41+
attrs: {
42+
class: 'tabButton w100p',
43+
onclick: 'showTab("users")'
44+
},
45+
children: ['Users']
3946
})
4047
]
4148
}),
@@ -126,6 +133,33 @@ function showTab(tab) {
126133

127134
});
128135
}
136+
137+
if (tab == "users") {
138+
buildSettingsUsers().then((html) => {
139+
tabContent.appendChild(jsRender(jsCreateElement('div', { attrs: { style: "" }, children: html })));
140+
labelFloater();
141+
142+
var objTableUsers = new Tabulator("#usersTable", {
143+
height: '500px',
144+
layout:"fitColumns",
145+
ajaxURL:"/api/settings/users",
146+
progressiveLoad:"load",
147+
columns:[
148+
{ title: "ID", field: "id", visible: false },
149+
{ title: "Email", field: "email" },
150+
{ title: "Created At", field: "created_at" },
151+
{ title: "Delete", field: "delete", width: 40 }
152+
]
153+
});
154+
155+
objTableUsers.on("cellClick", function(e, cell){
156+
if (cell.getColumn().getField() == "delete") {
157+
deleteUser(cell.getData().id);
158+
}
159+
});
160+
});
161+
162+
}
129163
}
130164

131165
/*
@@ -681,3 +715,138 @@ function addWebhook() {
681715
window.location.reload();
682716
});
683717
}
718+
719+
720+
721+
/*
722+
723+
Users
724+
725+
*/
726+
727+
async function buildSettingsUsers() {
728+
729+
let html = [];
730+
731+
html.push(
732+
jsCreateElement('div', {
733+
attrs: {
734+
class: 'mb40'
735+
},
736+
children: [
737+
jsCreateElement('div', {
738+
attrs: {
739+
class: 'itemBlock mb20'
740+
},
741+
children: [
742+
jsCreateElement('label', {
743+
attrs: {
744+
class: 'forinput'
745+
},
746+
children: ["Email"]
747+
}),
748+
jsCreateElement('input', {
749+
attrs: {
750+
id: 'userEmail',
751+
value: '',
752+
placeholder: 'Enter email',
753+
class: ''
754+
}
755+
}),
756+
]
757+
}),
758+
jsCreateElement('div', {
759+
attrs: {
760+
class: 'itemBlock mb20'
761+
},
762+
children: [
763+
jsCreateElement('label', {
764+
attrs: {
765+
class: 'forinput'
766+
},
767+
children: ["Password"]
768+
}),
769+
jsCreateElement('input', {
770+
attrs: {
771+
id: 'userPassword',
772+
value: '',
773+
placeholder: 'Enter password',
774+
class: ''
775+
}
776+
}),
777+
]
778+
}),
779+
jsCreateElement('button', {
780+
attrs: {
781+
id: 'user_create',
782+
class: 'buttonIcon',
783+
onclick: 'createUser()'
784+
},
785+
rawHtml: [
786+
'<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-6"><path stroke-linecap="round" stroke-linejoin="round" d="M12 9v6m3-3H9m12 0a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z" /></svg><div class="ml10">Add new user</div>'
787+
]
788+
})
789+
]
790+
})
791+
);
792+
793+
html.push(
794+
jsCreateElement('div', {
795+
attrs: {
796+
id: 'usersTable'
797+
}
798+
})
799+
);
800+
801+
return html;
802+
}
803+
804+
function deleteUser(id) {
805+
const html = jsCreateElement('div', {
806+
attrs: {
807+
},
808+
children: [
809+
jsCreateElement('div', {
810+
attrs: {
811+
class: 'headingH3 mb20'
812+
},
813+
children: ["Delete user"]
814+
}),
815+
jsCreateElement('button', {
816+
attrs: {
817+
class: "buttonIcon",
818+
onclick: 'deleteUserDo("' + id + '")'
819+
},
820+
rawHtml: [
821+
'<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-6"><path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12" /></svg><div class="ml10">Delete</div>'
822+
]
823+
})
824+
]
825+
});
826+
827+
rawModalLoader(jsRender(html));
828+
}
829+
830+
function deleteUserDo(id) {
831+
fetch('/api/users/delete?userID=' + id, {
832+
method: 'DELETE'
833+
})
834+
.then(manageErrors)
835+
.then(() => {
836+
window.location.reload();
837+
});
838+
}
839+
840+
function createUser() {
841+
fetch('/api/users/create', {
842+
method: 'POST',
843+
body: new URLSearchParams({
844+
email: dqs("#userEmail").value,
845+
password: dqs("#userPassword").value
846+
})
847+
})
848+
.then(manageErrors)
849+
.then(() => {
850+
window.location.reload();
851+
});
852+
}

nimletter.nim

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ import
3939
./src/routes/routes_profile,
4040
./src/routes/routes_settings,
4141
./src/routes/routes_subscriptions,
42+
./src/routes/routes_users,
4243
./src/routes/routes_webhooks_sns
4344

4445
var
@@ -64,6 +65,9 @@ for r in analyticsRouter.routes:
6465
for r in assetRouter.routes:
6566
routerMain.routes.add(r)
6667

68+
for r in contactsRouter.routes:
69+
routerMain.routes.add(r)
70+
6771
for r in eventRouter.routes:
6872
routerMain.routes.add(r)
6973

@@ -95,6 +99,7 @@ for r in webhooksSnsRouter.routes:
9599
routerMain.routes.add(r)
96100

97101

102+
98103
proc scheduleStart() {.thread.} =
99104
echo "Starting thread: scheduling"
100105
{.gcsafe.}:

nimletter.nimble

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Package
22

3-
version = "0.4.4"
3+
version = "0.4.5"
44
author = "ThomasTJdev"
55
description = "Newsletter"
66
license = "AGPL v3"

src/database/database_testdata.nim

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -127,9 +127,10 @@ proc insertTestData*() =
127127
data = [
128128
"email",
129129
"password",
130-
"salt"
130+
"salt",
131+
"rank"
131132
]
132-
), adminEmail, passwordCreated, salt)
133+
), adminEmail, passwordCreated, salt, "admin")
133134

134135

135136

src/database/db_schema.sql

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,7 @@ CREATE TABLE IF NOT EXISTS users (
206206
yubikey_public TEXT,
207207
yubikey_clientid TEXT,
208208
twofa_app_secret TEXT,
209+
rank TEXT DEFAULT 'user',
209210
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
210211
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
211212
);

src/html/dash.nimf

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
#
33
#
44
#
5-
#proc nimfMain(page = ""): string =
5+
#proc nimfMain(c: UserData, page = ""): string =
66
<html>
77
<head>
88
<title>Nimletter</title>
@@ -35,7 +35,7 @@
3535
</head>
3636
<body class="mainbody ${page}">
3737
<main>
38-
${nimfSidebar()}
38+
${nimfSidebar(c)}
3939
<div class="content">
4040
<h1 id="heading">Nimletter, drip it!</h1>
4141
<div id="work">
@@ -48,7 +48,7 @@
4848
#
4949
#
5050
#
51-
#proc nimfEvent(page = ""): string =
51+
#proc nimfEvent(c: UserData, page = ""): string =
5252
<html>
5353
<head>
5454
<title>Nimletter</title>
@@ -74,7 +74,7 @@
7474
</head>
7575
<body class="mainbody ${page}">
7676
<main>
77-
${nimfSidebar()}
77+
${nimfSidebar(c)}
7878
<div class="content">
7979
<h1 id="heading">Events</h1>
8080
<div id="work">

src/html/profile.nimf

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
#
33
#
44
#
5-
#proc nimfProfile(): string =
5+
#proc nimfProfile(c: UserData): string =
66
<html>
77
<head>
88
<title>Nimletter</title>
@@ -18,7 +18,7 @@
1818
</head>
1919
<body class="mainbody">
2020
<main>
21-
${nimfSidebar()}
21+
${nimfSidebar(c)}
2222
<div class="content">
2323
<h1 id="heading">Nimletter, drip it!</h1>
2424
<div id="work">

src/html/sidebar.nimf

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
#
33
#
44
#
5-
#proc nimfSidebar(): string =
5+
#proc nimfSidebar(c: UserData): string =
66
<div class="sidebar">
77
<div class="sidebarArea">
88
<div class="heading">Nimletter</div>
@@ -30,14 +30,6 @@
3030
Lists
3131
</div>
3232
</a>
33-
<a href="/mails" class="mails">
34-
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor" className="size-6">
35-
<path strokeLinecap="round" strokeLinejoin="round" d="M21.75 6.75v10.5a2.25 2.25 0 0 1-2.25 2.25h-15a2.25 2.25 0 0 1-2.25-2.25V6.75m19.5 0A2.25 2.25 0 0 0 19.5 4.5h-15a2.25 2.25 0 0 0-2.25 2.25m19.5 0v.243a2.25 2.25 0 0 1-1.07 1.916l-7.5 4.615a2.25 2.25 0 0 1-2.36 0L3.32 8.91a2.25 2.25 0 0 1-1.07-1.916V6.75" />
36-
</svg>
37-
<div>
38-
Mails
39-
</div>
40-
</a>
4133
<a href="/flows" class="flows">
4234
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-6">
4335
<path stroke-linecap="round" stroke-linejoin="round" d="M3 8.689c0-.864.933-1.406 1.683-.977l7.108 4.061a1.125 1.125 0 0 1 0 1.954l-7.108 4.061A1.125 1.125 0 0 1 3 16.811V8.69ZM12.75 8.689c0-.864.933-1.406 1.683-.977l7.108 4.061a1.125 1.125 0 0 1 0 1.954l-7.108 4.061a1.125 1.125 0 0 1-1.683-.977V8.69Z" />
@@ -46,6 +38,14 @@
4638
Flows
4739
</div>
4840
</a>
41+
<a href="/mails" class="mails">
42+
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor" className="size-6">
43+
<path strokeLinecap="round" strokeLinejoin="round" d="M21.75 6.75v10.5a2.25 2.25 0 0 1-2.25 2.25h-15a2.25 2.25 0 0 1-2.25-2.25V6.75m19.5 0A2.25 2.25 0 0 0 19.5 4.5h-15a2.25 2.25 0 0 0-2.25 2.25m19.5 0v.243a2.25 2.25 0 0 1-1.07 1.916l-7.5 4.615a2.25 2.25 0 0 1-2.36 0L3.32 8.91a2.25 2.25 0 0 1-1.07-1.916V6.75" />
44+
</svg>
45+
<div>
46+
Mails
47+
</div>
48+
</a>
4949
<a href="/events" class="events">
5050
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-6">
5151
<path stroke-linecap="round" stroke-linejoin="round" d="M6 12 3.269 3.125A59.769 59.769 0 0 1 21.485 12 59.768 59.768 0 0 1 3.27 20.875L5.999 12Zm0 0h7.5" />
@@ -63,6 +63,7 @@
6363
</div>
6464
</a>
6565
<div style=" width: 100%; height: 1px; border-top: 1px solid var(--colorN30); margin: 20px 0; "></div>
66+
# if c.rank == "admin":
6667
<a href="/settings" class="settings">
6768
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-6">
6869
<path stroke-linecap="round" stroke-linejoin="round" d="M9.594 3.94c.09-.542.56-.94 1.11-.94h2.593c.55 0 1.02.398 1.11.94l.213 1.281c.063.374.313.686.645.87.074.04.147.083.22.127.325.196.72.257 1.075.124l1.217-.456a1.125 1.125 0 0 1 1.37.49l1.296 2.247a1.125 1.125 0 0 1-.26 1.431l-1.003.827c-.293.241-.438.613-.43.992a7.723 7.723 0 0 1 0 .255c-.008.378.137.75.43.991l1.004.827c.424.35.534.955.26 1.43l-1.298 2.247a1.125 1.125 0 0 1-1.369.491l-1.217-.456c-.355-.133-.75-.072-1.076.124a6.47 6.47 0 0 1-.22.128c-.331.183-.581.495-.644.869l-.213 1.281c-.09.543-.56.94-1.11.94h-2.594c-.55 0-1.019-.398-1.11-.94l-.213-1.281c-.062-.374-.312-.686-.644-.87a6.52 6.52 0 0 1-.22-.127c-.325-.196-.72-.257-1.076-.124l-1.217.456a1.125 1.125 0 0 1-1.369-.49l-1.297-2.247a1.125 1.125 0 0 1 .26-1.431l1.004-.827c.292-.24.437-.613.43-.991a6.932 6.932 0 0 1 0-.255c.007-.38-.138-.751-.43-.992l-1.004-.827a1.125 1.125 0 0 1-.26-1.43l1.297-2.247a1.125 1.125 0 0 1 1.37-.491l1.216.456c.356.133.751.072 1.076-.124.072-.044.146-.086.22-.128.332-.183.582-.495.644-.869l.214-1.28Z" />
@@ -72,6 +73,7 @@
7273
Settings
7374
</div>
7475
</a>
76+
# end if
7577
<a href="/profile" class="profile">
7678
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-6">
7779
<path stroke-linecap="round" stroke-linejoin="round" d="M17.982 18.725A7.488 7.488 0 0 0 12 15.75a7.488 7.488 0 0 0-5.982 2.975m11.963 0a9 9 0 1 0-11.963 0m11.963 0A8.966 8.966 0 0 1 12 21a8.966 8.966 0 0 1-5.982-2.275M15 9.75a3 3 0 1 1-6 0 3 3 0 0 1 6 0Z" />

0 commit comments

Comments
 (0)