refactor admin user settings away from standard user settings

It was possible for Users to grant themselves flags and permissions.
These operations now require Admin privileges, and are only implemented
by services.user.updateForAdmin. The services.user.update method no
longer has any logic to alter flags and/or permissions.
master
rob 3 years ago
parent 929a8875ef
commit 4f1c8cb245

@ -47,15 +47,23 @@ class UserController extends SiteController {
async postUpdateUser (req, res, next) {
const { user: userService } = this.dtp.services;
try {
await userService.update(res.locals.userAccount, req.body);
await userService.updateForAdmin(res.locals.userAccount, req.body);
res.redirect('/admin/user');
} catch (error) {
return next(error);
}
}
async getUserView (req, res) {
res.render('admin/user/form');
async getUserView (req, res, error) {
const { comment: commentService } = this.dtp.services;
try {
res.locals.pagination = this.getPaginationParameters(req, 20);
res.locals.recentComments = await commentService.getForAuthor(res.locals.userAccount, res.locals.pagination);
res.render('admin/user/form');
} catch (error) {
this.log.error('failed to produce user view', { error });
return next(error);
}
}
async getHomeView (req, res, next) {

@ -20,6 +20,8 @@ const UserPermissionsSchema = new Schema({
canChat: { type: Boolean, default: true, required: true },
canComment: { type: Boolean, default: true, required: true },
canReport: { type: Boolean, default: true, required: true },
canAuthorPages: { type: Boolean, default: false, required: true },
canAuthorPosts: { type: Boolean, default: false, required: true },
});
const UserSchema = new Schema({

@ -99,6 +99,8 @@ class UserService {
canChat: true,
canComment: true,
canReport: true,
canAuthorPages: false,
canAuthorPosts: false,
};
this.log.info('creating new user account', { email: userDefinition.email });
@ -112,6 +114,10 @@ class UserService {
}
async update (user, userDefinition) {
if (!user.flags.canLogin) {
throw SiteError(403, 'Invalid user account operation');
}
// strip characters we don't want to allow in username
userDefinition.username = striptags(userDefinition.username.trim().replace(/[^A-Za-z0-9\-_]/gi, ''));
const username_lc = userDefinition.username.toLowerCase();
@ -120,6 +126,28 @@ class UserService {
userDefinition.bio = striptags(userDefinition.bio.trim());
this.log.info('updating user', { userDefinition });
await User.updateOne(
{ _id: user._id },
{
$set: {
username: userDefinition.username,
username_lc,
displayName: userDefinition.displayName,
bio: userDefinition.bio,
},
},
);
}
async updateForAdmin (user, userDefinition) {
// strip characters we don't want to allow in username
userDefinition.username = striptags(userDefinition.username.trim().replace(/[^A-Za-z0-9\-_]/gi, ''));
const username_lc = userDefinition.username.toLowerCase();
userDefinition.displayName = striptags(userDefinition.displayName.trim());
userDefinition.bio = striptags(userDefinition.bio.trim());
this.log.info('updating user for admin', { userDefinition });
await User.updateOne(
{ _id: user._id },
{
@ -134,6 +162,8 @@ class UserService {
'permissions.canChat': userDefinition.canChat === 'on',
'permissions.canComment': userDefinition.canComment === 'on',
'permissions.canReport': userDefinition.canReport === 'on',
'permissions.canAuthorPages': userDefinition.canAuthorPages === 'on',
'permissions.canAuthorPosts': userDefinition.canAuthorPosts === 'on',
},
},
);

@ -1,43 +1,74 @@
extends ../layouts/main
block content
.uk-margin
.uk-text-large= userAccount.displayName || userAccount.email
div= userAccount.username
form(method="POST", action=`/admin/user/${userAccount._id}`).uk-form
input(type="hidden", name="username", value= userAccount.username)
input(type="hidden", name="displayName", value= userAccount.displayName)
.uk-margin
div(uk-grid)
div(class="uk-width-1-1 uk-width-1-2@m")
fieldset
legend Flags
include ../../comment/components/comment-review
div(uk-grid).uk-grid-small
div(class="uk-width-1-1 uk-width-2-3@l")
form(method="POST", action=`/admin/user/${userAccount._id}`).uk-form
input(type="hidden", name="username", value= userAccount.username)
input(type="hidden", name="displayName", value= userAccount.displayName)
.uk-card.uk-card-secondary.uk-card-small
.uk-card-header
if userAccount.displayName
.uk-text-large= userAccount.displayName
div
a(href=`mailto:${userAccount.email}`)= userAccount.email
div
a(href=`/user/${userAccount._id}`) @#{userAccount.username}
.uk-card-body
.uk-margin
div(uk-grid).uk-grid-small
label
input(id="is-admin", name="isAdmin", type="checkbox", checked= userAccount.flags.isAdmin)
| Admin
label
input(id="is-moderator", name="isModerator", type="checkbox", checked= userAccount.flags.isModerator)
| Moderator
div(class="uk-width-1-1 uk-width-1-2@m")
fieldset
legend Permissions
label(for="bio").uk-form-label.sr-only Bio
textarea(id="bio", name="bio", rows="4", placeholder= "Bio is empty", disabled= !userAccount.bio || (userAccount.bio.length === 0)).uk-textarea.uk-resize-vertical= userAccount.bio
.uk-margin
div(uk-grid).uk-grid-small
label
input(id="can-login", name="canLogin", type="checkbox", checked= userAccount.permissions.canLogin)
| Can Login
label
input(id="can-chat", name="canChat", type="checkbox", checked= userAccount.permissions.canChat)
| Can Chat
label
input(id="can-comment", name="canComment", type="checkbox", checked= userAccount.permissions.canComment)
| Can Comment
label
input(id="can-report", name="canReport", type="checkbox", checked= userAccount.permissions.canReport)
| Can Report
button(type="submit").uk-button.uk-button-primary Update User
div(uk-grid)
div(class="uk-width-1-1 uk-width-1-2@m")
fieldset
legend Flags
.uk-margin
div(uk-grid).uk-grid-small
label
input(id="is-admin", name="isAdmin", type="checkbox", checked= userAccount.flags.isAdmin)
| Admin
label
input(id="is-moderator", name="isModerator", type="checkbox", checked= userAccount.flags.isModerator)
| Moderator
div(class="uk-width-1-1 uk-width-1-2@m")
fieldset
legend Permissions
.uk-margin
div(uk-grid).uk-grid-small
label
input(id="can-login", name="canLogin", type="checkbox", checked= userAccount.permissions.canLogin)
| Can Login
label
input(id="can-chat", name="canChat", type="checkbox", checked= userAccount.permissions.canChat)
| Can Chat
label
input(id="can-comment", name="canComment", type="checkbox", checked= userAccount.permissions.canComment)
| Can Comment
label
input(id="can-report", name="canReport", type="checkbox", checked= userAccount.permissions.canReport)
| Can Report
label
input(id="can-author-pages", name="canAuthorPages", type="checkbox", checked= userAccount.permissions.canAuthorPages)
| Can Author Pages
label
input(id="can-author-posts", name="canAuthorPosts", type="checkbox", checked= userAccount.permissions.canAuthorPosts)
| Can Author Posts
button(type="submit").uk-button.dtp-button-primary.uk-display-block.uk-width-1-1 Update User
div(class="uk-width-1-1 uk-width-1-3@l")
.uk-card.uk-card-secondary.uk-card-small
.uk-card-header
h4.uk-card-title #{userAccount.displayName || userAccount.username}'s Comments
.uk-card-body
ul.uk-list.uk-list-divider
each comment in recentComments
li
+renderCommentReview(comment)

@ -20,13 +20,13 @@ block content
}
.uk-margin
+renderFileUploadImage(
`/user/${user._id}/header-image`,
'header-image-upload',
'header-image-file',
'header-image-picture',
`/img/default-header.png`,
user.header,
{ aspectRatio: 1400 / 400 },
`/user/${user._id}/profile-photo`,
'profile-picture-upload',
'profile-picture-file',
'site-profile-picture',
`/img/default-member.png`,
currentProfile,
{ aspectRatio: 1 },
)
div(class="uk-width-1-1 uk-width-expand@m")

Loading…
Cancel
Save