Skip to content

Commit ec94e47

Browse files
committed
feat: add kyc, max quota and smtp limit to user admin page
1 parent 8cd4ba1 commit ec94e47

File tree

2 files changed

+111
-8
lines changed

2 files changed

+111
-8
lines changed

app/controllers/web/admin/users.js

Lines changed: 48 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
*/
55

66
const Boom = require('@hapi/boom');
7+
const RE2 = require('re2');
8+
const bytes = require('@forwardemail/bytes');
79
const isSANB = require('is-string-and-not-blank');
810
const paginate = require('koa-ctx-paginate');
911
const parser = require('mongodb-query-parser');
@@ -13,6 +15,8 @@ const _ = require('#helpers/lodash');
1315
const { Users } = require('#models');
1416
const config = require('#config');
1517

18+
const REGEX_BYTES = new RE2(/^((-|\+)?(\d+(?:\.\d+)?)) *(kb|mb|gb|tb|pb)$/i);
19+
1620
const USER_SEARCH_PATHS = [
1721
'email',
1822
config.passport.fields.givenName,
@@ -91,18 +95,54 @@ async function update(ctx) {
9195
if (!user) throw Boom.notFound(ctx.translateError('INVALID_USER'));
9296
const { body } = ctx.request;
9397

94-
user[config.passport.fields.givenName] =
95-
body[config.passport.fields.givenName];
96-
user[config.passport.fields.familyName] =
97-
body[config.passport.fields.familyName];
98-
user[config.passport.fields.otpEnabled] =
99-
body[config.passport.fields.otpEnabled];
100-
user.email = body.email;
101-
user.group = body.group;
98+
if (body[config.passport.fields.givenName])
99+
user[config.passport.fields.givenName] =
100+
body[config.passport.fields.givenName];
101+
102+
if (body[config.passport.fields.familyName])
103+
user[config.passport.fields.familyName] =
104+
body[config.passport.fields.familyName];
105+
106+
if (body[config.passport.fields.otpEnabled])
107+
user[config.passport.fields.otpEnabled] =
108+
body[config.passport.fields.otpEnabled];
102109

103110
if (boolean(!body[config.passport.fields.otpEnabled]))
104111
user[config.userFields.pendingRecovery] = false;
105112

113+
if (body.email) user.email = body.email;
114+
115+
if (body.group) user.group = body.group;
116+
117+
if (isSANB(body.has_passed_kyc))
118+
user.has_passed_kyc = boolean(body.has_passed_kyc);
119+
120+
if (body.max_quota_per_alias_per_alias) {
121+
// validate `body.max_quota_per_alias_per_alias` if a value was passed
122+
if (
123+
typeof body.max_quota_per_alias_per_alias !== 'undefined' &&
124+
typeof body.max_quota_per_alias_per_alias !== 'string'
125+
)
126+
throw Boom.badRequest(ctx.translateError('INVALID_BYTES'));
127+
128+
// indicates reset of the value
129+
if (body.max_quota_per_alias === '') {
130+
body.max_quota_per_alias = Number.isFinite(
131+
ctx.state.domain.max_quota_per_alias
132+
)
133+
? ctx.state.domain.max_quota_per_alias
134+
: config.maxQuotaPerAlias;
135+
} else if (typeof body.max_quota_per_alias === 'string') {
136+
// test against bytes regex
137+
if (!REGEX_BYTES.test(body.max_quota_per_alias))
138+
throw Boom.badRequest(ctx.translateError('INVALID_BYTES'));
139+
// otherwise convert the value
140+
body.max_quota_per_alias = bytes(body.max_quota_per_alias);
141+
}
142+
}
143+
144+
if (body.smtp_limit) user.smtp_limit = body.smtp_limit;
145+
106146
await user.save();
107147

108148
if (user.id === ctx.state.user.id) await ctx.login(user);

app/views/admin/users/_table.pug

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,12 @@ include ../../_pagination
1919
+sortHeader('plan', null, '#table-users')
2020
th(scope="col")
2121
+sortHeader('group', null, '#table-users')
22+
th(scope="col")
23+
+sortHeader('has_passed_kyc', 'Passed KYC', '#table-users')
24+
th(scope="col")
25+
+sortHeader('max_quota_per_alias', 'Max Qouta', '#table-users')
26+
th(scope="col")
27+
+sortHeader('smtp_limit', 'SMTP Limit', '#table-users')
2228
th(scope="col")
2329
+sortHeader('created_at', 'Created', '#table-users')
2430
th(scope="col")
@@ -51,6 +57,63 @@ include ../../_pagination
5157
td.align-middle= user.alias_count
5258
td.align-middle= titleize(humanize(user.plan))
5359
td.align-middle= titleize(humanize(user.group))
60+
td.align-middle.text-center
61+
form.ajax-form.confirm-prompt.d-inline-block(
62+
action=l(`/admin/users/${user.id}`),
63+
method="POST"
64+
)
65+
input(type="hidden", name="_method", value="PUT")
66+
input(
67+
type="hidden",
68+
name="has_passed_kyc",
69+
value=(!user.has_passed_kyc).toString()
70+
)
71+
button.btn.btn-sm(
72+
type="submit",
73+
class=user.has_passed_kyc ? "btn-danger" : "btn-success"
74+
)
75+
if user.has_passed_kyc
76+
= "Missing KYC"
77+
else
78+
= "Passed KYC"
79+
td.align-middle.text-center
80+
form.ajax-form.confirm-prompt.d-inline-block(
81+
action=l(`/admin/users/${user.id}`),
82+
method="PUT"
83+
)
84+
input(type="hidden", name="_method", value="PUT")
85+
.input-group
86+
input.form-control(
87+
type="string",
88+
name="max_quota_per_alias",
89+
value=alias && Number.isFinite(user.max_quota_per_alias) ? bytes(user.max_quota_per_alias) : ""
90+
)
91+
.input-group-append
92+
button.btn.btn-sm.btn-dark(
93+
type="submit",
94+
data-toggle="tooltip",
95+
data-title=t("Update")
96+
): i.fa.fa-fw.fa-save
97+
td.align-middle.text-center
98+
form.ajax-form.confirm-prompt.d-inline-block(
99+
action=l(`/admin/users/${user.id}`),
100+
method="PUT"
101+
)
102+
input(type="hidden", name="_method", value="PUT")
103+
.input-group
104+
input.form-control(
105+
type="number",
106+
min=300,
107+
step=100,
108+
name="smtp_limit",
109+
value=user.smtp_limit
110+
)
111+
.input-group-append
112+
button.btn.btn-sm.btn-dark(
113+
type="submit",
114+
data-toggle="tooltip",
115+
data-title=t("Update")
116+
): i.fa.fa-fw.fa-save
54117
td.align-middle.dayjs(
55118
data-time=new Date(user.created_at).getTime()
56119
)= dayjs(user.created_at).tz(user.timezone === 'Etc/Unknown' ? 'UTC' : user.timezone).format("M/D/YY h:mm A z")

0 commit comments

Comments
 (0)