|
|
@ -18,6 +18,7 @@ class UserController extends SiteController { |
|
|
|
async start ( ) { |
|
|
|
const { dtp } = this; |
|
|
|
const { |
|
|
|
csrfToken: csrfTokenService, |
|
|
|
limiter: limiterService, |
|
|
|
otpAuth: otpAuthService, |
|
|
|
session: sessionService, |
|
|
@ -97,6 +98,7 @@ class UserController extends SiteController { |
|
|
|
router.post( |
|
|
|
'/', |
|
|
|
limiterService.createMiddleware(limiterService.config.user.postCreate), |
|
|
|
csrfTokenService.middleware({ name: 'user-create' }), |
|
|
|
this.postCreateUser.bind(this), |
|
|
|
); |
|
|
|
|
|
|
@ -155,7 +157,10 @@ class UserController extends SiteController { |
|
|
|
} |
|
|
|
|
|
|
|
async populateCoreUsername (req, res, next, coreUsername) { |
|
|
|
const { user: userService } = this.dtp.services; |
|
|
|
const { |
|
|
|
logan: loganService, |
|
|
|
user: userService, |
|
|
|
} = this.dtp.services; |
|
|
|
try { |
|
|
|
res.locals.username = userService.filterUsername(coreUsername); |
|
|
|
res.locals.userProfileId = await userService.getCoreUserId(res.locals.username); |
|
|
@ -166,12 +171,21 @@ class UserController extends SiteController { |
|
|
|
return this.populateCoreUserId(req, res, next, res.locals.userProfileId); |
|
|
|
} catch (error) { |
|
|
|
this.log.error('failed to populate core username', { coreUsername, error }); |
|
|
|
loganService.sendRequestEvent(module.exports, req, { |
|
|
|
level: 'error', |
|
|
|
event: 'populateCoreUsername', |
|
|
|
message: `failed to populate Core user: ${error.message}`, |
|
|
|
data: { coreUsername, error }, |
|
|
|
}); |
|
|
|
return next(error); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
async populateCoreUserId (req, res, next, coreUserId) { |
|
|
|
const { user: userService } = this.dtp.services; |
|
|
|
const { |
|
|
|
logan: loganService, |
|
|
|
user: userService, |
|
|
|
} = this.dtp.services; |
|
|
|
try { |
|
|
|
res.locals.userProfileId = mongoose.Types.ObjectId(coreUserId); |
|
|
|
|
|
|
@ -187,13 +201,21 @@ class UserController extends SiteController { |
|
|
|
|
|
|
|
return next(); |
|
|
|
} catch (error) { |
|
|
|
this.log.error('failed to populate core user id', { coreUserId, error }); |
|
|
|
loganService.sendRequestEvent(module.exports, req, { |
|
|
|
level: 'error', |
|
|
|
event: 'populateCoreUserId', |
|
|
|
message: `failed to populate core user: ${error.message}`, |
|
|
|
data: { coreUserId, error }, |
|
|
|
}); |
|
|
|
return next(error); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
async populateLocalUsername (req, res, next, username) { |
|
|
|
const { user: userService } = this.dtp.services; |
|
|
|
const { |
|
|
|
logan: loganService, |
|
|
|
user: userService, |
|
|
|
} = this.dtp.services; |
|
|
|
try { |
|
|
|
res.locals.username = userService.filterUsername(username); |
|
|
|
|
|
|
@ -210,12 +232,21 @@ class UserController extends SiteController { |
|
|
|
return next(); |
|
|
|
} catch (error) { |
|
|
|
this.log.error('failed to populate local username', { username, error }); |
|
|
|
loganService.sendRequestEvent(module.exports, req, { |
|
|
|
level: 'error', |
|
|
|
event: 'populateLocalUsername', |
|
|
|
message: `failed to populate local user: ${error.message}`, |
|
|
|
data: { username, error }, |
|
|
|
}); |
|
|
|
return next(error); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
async populateLocalUserId (req, res, next, userId) { |
|
|
|
const { user: userService } = this.dtp.services; |
|
|
|
const { |
|
|
|
logan: loganService, |
|
|
|
user: userService, |
|
|
|
} = this.dtp.services; |
|
|
|
try { |
|
|
|
res.locals.userProfileId = mongoose.Types.ObjectId(userId); |
|
|
|
|
|
|
@ -231,13 +262,21 @@ class UserController extends SiteController { |
|
|
|
|
|
|
|
return next(); |
|
|
|
} catch (error) { |
|
|
|
this.log.error('failed to populate local user id', { userId, error }); |
|
|
|
loganService.sendRequestEvent(module.exports, req, { |
|
|
|
level: 'error', |
|
|
|
event: 'populateLocalUserId', |
|
|
|
message: `failed to populate local user: ${error.message}`, |
|
|
|
data: { userId, error }, |
|
|
|
}); |
|
|
|
return next(error); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
async postCreateUser (req, res, next) { |
|
|
|
const { user: userService } = this.dtp.services; |
|
|
|
const { |
|
|
|
logan: loganService, |
|
|
|
user: userService, |
|
|
|
} = this.dtp.services; |
|
|
|
try { |
|
|
|
// verify that the request has submitted a captcha
|
|
|
|
if ((typeof req.body.captcha !== 'string') || req.body.captcha.length === 0) { |
|
|
@ -255,11 +294,42 @@ class UserController extends SiteController { |
|
|
|
// create the user account
|
|
|
|
res.locals.user = await userService.create(req.body); |
|
|
|
|
|
|
|
const form = Object.assign(req.body); |
|
|
|
if (form.password) { |
|
|
|
delete form.password; |
|
|
|
} |
|
|
|
if (form.passwordv) { |
|
|
|
delete form.passwordv; |
|
|
|
} |
|
|
|
|
|
|
|
loganService.sendRequestEvent(module.exports, req, { |
|
|
|
level: 'info', |
|
|
|
event: 'postCreateUser', |
|
|
|
data: { |
|
|
|
form, |
|
|
|
user: { |
|
|
|
_id: res.locals.user._id, |
|
|
|
username: res.locals.user.username, |
|
|
|
}, |
|
|
|
}, |
|
|
|
}); |
|
|
|
|
|
|
|
// log the user in
|
|
|
|
req.login(res.locals.user, (error) => { |
|
|
|
if (error) { |
|
|
|
loganService.sendRequestEvent(module.exports, req, { |
|
|
|
level: 'error', |
|
|
|
event: 'postCreateUser', |
|
|
|
message: `failed to start user session: ${error.message}`, |
|
|
|
data: { error }, |
|
|
|
}); |
|
|
|
return next(error); |
|
|
|
} |
|
|
|
loganService.sendRequestEvent(module.exports, req, { |
|
|
|
level: 'info', |
|
|
|
event: 'postCreateUser', |
|
|
|
message: 'user session started', |
|
|
|
}); |
|
|
|
res.redirect(`/user/${res.locals.user.username}`); |
|
|
|
}); |
|
|
|
} catch (error) { |
|
|
@ -269,7 +339,10 @@ class UserController extends SiteController { |
|
|
|
} |
|
|
|
|
|
|
|
async postProfilePhoto (req, res) { |
|
|
|
const { user: userService } = this.dtp.services; |
|
|
|
const { |
|
|
|
logan: loganService, |
|
|
|
user: userService, |
|
|
|
} = this.dtp.services; |
|
|
|
try { |
|
|
|
await userService.updatePhoto(req.user, req.file); |
|
|
|
|
|
|
@ -280,9 +353,21 @@ class UserController extends SiteController { |
|
|
|
'bottom-center', |
|
|
|
2000, |
|
|
|
); |
|
|
|
|
|
|
|
loganService.sendRequestEvent(module.exports, req, { |
|
|
|
level: 'info', |
|
|
|
event: 'postProfilePhoto', |
|
|
|
message: 'profile photo updated', |
|
|
|
}); |
|
|
|
|
|
|
|
res.status(200).json({ success: true, displayList }); |
|
|
|
} catch (error) { |
|
|
|
this.log.error('failed to update profile photo', { error }); |
|
|
|
loganService.sendRequestEvent(module.exports, req, { |
|
|
|
level: 'error', |
|
|
|
event: 'postProfilePhoto', |
|
|
|
message: `failed to update profile photo: ${error.message}`, |
|
|
|
data: { error }, |
|
|
|
}); |
|
|
|
return res.status(error.statusCode || 500).json({ |
|
|
|
success: false, |
|
|
|
message: error.message, |
|
|
@ -291,7 +376,10 @@ class UserController extends SiteController { |
|
|
|
} |
|
|
|
|
|
|
|
async postHeaderImage (req, res) { |
|
|
|
const { user: userService } = this.dtp.services; |
|
|
|
const { |
|
|
|
logan: loganService, |
|
|
|
user: userService, |
|
|
|
} = this.dtp.services; |
|
|
|
try { |
|
|
|
await userService.updateHeaderImage(req.user, req.file); |
|
|
|
|
|
|
@ -302,9 +390,21 @@ class UserController extends SiteController { |
|
|
|
'bottom-center', |
|
|
|
2000, |
|
|
|
); |
|
|
|
|
|
|
|
loganService.sendRequestEvent(module.exports, req, { |
|
|
|
level: 'info', |
|
|
|
event: 'postHeaderImage', |
|
|
|
message: 'header image updated', |
|
|
|
}); |
|
|
|
|
|
|
|
res.status(200).json({ success: true, displayList }); |
|
|
|
} catch (error) { |
|
|
|
this.log.error('failed to update header image', { error }); |
|
|
|
loganService.sendRequestEvent(module.exports, req, { |
|
|
|
level: 'error', |
|
|
|
event: 'postHeaderImage', |
|
|
|
message: `failed to update header image: ${error.message}`, |
|
|
|
data: { error }, |
|
|
|
}); |
|
|
|
return res.status(error.statusCode || 500).json({ |
|
|
|
success: false, |
|
|
|
message: error.message, |
|
|
@ -313,15 +413,30 @@ class UserController extends SiteController { |
|
|
|
} |
|
|
|
|
|
|
|
async postUpdateCoreSettings (req, res) { |
|
|
|
const { coreNode: coreNodeService } = this.dtp.services; |
|
|
|
const { |
|
|
|
coreNode: coreNodeService, |
|
|
|
logan: loganService, |
|
|
|
} = this.dtp.services; |
|
|
|
try { |
|
|
|
await coreNodeService.updateUserSettings(req.user, req.body); |
|
|
|
|
|
|
|
const displayList = this.createDisplayList('app-settings'); |
|
|
|
displayList.reload(); |
|
|
|
|
|
|
|
loganService.sendRequestEvent(module.exports, req, { |
|
|
|
level: 'info', |
|
|
|
event: 'postUpdateCoreSettings', |
|
|
|
message: 'CoreUser settings updated', |
|
|
|
}); |
|
|
|
|
|
|
|
res.status(200).json({ success: true, displayList }); |
|
|
|
} catch (error) { |
|
|
|
this.log.error('failed to update CoreUser settings', { error }); |
|
|
|
loganService.sendRequestEvent(module.exports, req, { |
|
|
|
level: 'error', |
|
|
|
event: 'postUpdateCoreSettings', |
|
|
|
message: `failed to update CoreUser settings: ${error.message}`, |
|
|
|
data: { error }, |
|
|
|
}); |
|
|
|
return res.status(error.statusCode || 500).json({ |
|
|
|
success: false, |
|
|
|
message: error.message, |
|
|
@ -330,16 +445,30 @@ class UserController extends SiteController { |
|
|
|
} |
|
|
|
|
|
|
|
async postUpdateSettings (req, res) { |
|
|
|
const { user: userService } = this.dtp.services; |
|
|
|
const { |
|
|
|
logan: loganService, |
|
|
|
user: userService, |
|
|
|
} = this.dtp.services; |
|
|
|
try { |
|
|
|
await userService.updateSettings(req.user, req.body); |
|
|
|
|
|
|
|
const displayList = this.createDisplayList('app-settings'); |
|
|
|
displayList.reload(); |
|
|
|
|
|
|
|
loganService.sendRequestEvent(module.exports, req, { |
|
|
|
level: 'info', |
|
|
|
event: 'postUpdateSettings', |
|
|
|
message: 'account settings updates', |
|
|
|
}); |
|
|
|
|
|
|
|
res.status(200).json({ success: true, displayList }); |
|
|
|
} catch (error) { |
|
|
|
this.log.error('failed to update account settings', { error }); |
|
|
|
loganService.sendRequestEvent(module.exports, req, { |
|
|
|
level: 'error', |
|
|
|
event: 'postUpdateSettings', |
|
|
|
message: `failed to update account settings: ${error.message}`, |
|
|
|
data: { error }, |
|
|
|
}); |
|
|
|
return res.status(error.statusCode || 500).json({ |
|
|
|
success: false, |
|
|
|
message: error.message, |
|
|
@ -352,13 +481,26 @@ class UserController extends SiteController { |
|
|
|
} |
|
|
|
|
|
|
|
async getOtpDisable (req, res) { |
|
|
|
const { otpAuth: otpAuthService } = this.dtp.services; |
|
|
|
const { |
|
|
|
logan: loganService, |
|
|
|
otpAuth: otpAuthService, |
|
|
|
} = this.dtp.services; |
|
|
|
try { |
|
|
|
await otpAuthService.destroyOtpSession(req, 'Account'); |
|
|
|
await otpAuthService.removeForUser(req.user, 'Account'); |
|
|
|
loganService.sendRequestEvent(module.exports, req, { |
|
|
|
level: 'info', |
|
|
|
event: 'getOtpDisable', |
|
|
|
message: 'one-time passwords disabled', |
|
|
|
}); |
|
|
|
res.render('user/otp-disabled'); |
|
|
|
} catch (error) { |
|
|
|
this.log.error('failed to disable OTP service for Account', { error }); |
|
|
|
loganService.sendRequestEvent(module.exports, req, { |
|
|
|
level: 'error', |
|
|
|
event: 'getOtpDisable', |
|
|
|
message: `failed to disable OTP: ${error.message}`, |
|
|
|
data: { error }, |
|
|
|
}); |
|
|
|
res.status(error.statusCode || 500).json({ |
|
|
|
success: false, |
|
|
|
message: error.message, |
|
|
@ -367,43 +509,70 @@ class UserController extends SiteController { |
|
|
|
} |
|
|
|
|
|
|
|
async getCoreUserSettingsView (req, res, next) { |
|
|
|
const { otpAuth: otpAuthService } = this.dtp.services; |
|
|
|
const { |
|
|
|
logan: loganService, |
|
|
|
otpAuth: otpAuthService, |
|
|
|
} = this.dtp.services; |
|
|
|
try { |
|
|
|
res.locals.hasOtpAccount = await otpAuthService.isUserProtected(req.user, 'Account'); |
|
|
|
res.locals.startTab = req.query.st || 'watch'; |
|
|
|
res.render('user/settings-core'); |
|
|
|
} catch (error) { |
|
|
|
this.log.error('failed to render CoreUser settings view', { error }); |
|
|
|
loganService.sendRequestEvent(module.exports, req, { |
|
|
|
level: 'error', |
|
|
|
event: 'getCoreUserSettingsView', |
|
|
|
message: `failed to render the view: ${error.message}`, |
|
|
|
data: { error }, |
|
|
|
}); |
|
|
|
return next(error); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
async getUserSettingsView (req, res, next) { |
|
|
|
const { otpAuth: otpAuthService } = this.dtp.services; |
|
|
|
const { |
|
|
|
logan: loganService, |
|
|
|
otpAuth: otpAuthService, |
|
|
|
} = this.dtp.services; |
|
|
|
try { |
|
|
|
res.locals.hasOtpAccount = await otpAuthService.isUserProtected(req.user, 'Account'); |
|
|
|
res.locals.startTab = req.query.st || 'watch'; |
|
|
|
res.render('user/settings'); |
|
|
|
} catch (error) { |
|
|
|
this.log.error('failed to render user settings view', { error }); |
|
|
|
loganService.sendRequestEvent(module.exports, req, { |
|
|
|
level: 'error', |
|
|
|
event: 'getUserSettingsView', |
|
|
|
message: `failed to render the view: ${error.message}`, |
|
|
|
data: { error }, |
|
|
|
}); |
|
|
|
return next(error); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
async getUserView (req, res, next) { |
|
|
|
const { comment: commentService } = this.dtp.services; |
|
|
|
const { |
|
|
|
comment: commentService, |
|
|
|
logan: loganService, |
|
|
|
} = this.dtp.services; |
|
|
|
try { |
|
|
|
res.locals.pagination = this.getPaginationParameters(req, 20); |
|
|
|
res.locals.commentHistory = await commentService.getForAuthor(req.user, res.locals.pagination); |
|
|
|
res.render('user/profile'); |
|
|
|
} catch (error) { |
|
|
|
this.log.error('failed to produce user profile view', { error }); |
|
|
|
loganService.sendRequestEvent(module.exports, req, { |
|
|
|
level: 'error', |
|
|
|
event: 'getUserView', |
|
|
|
message: `failed to render the view: ${error.message}`, |
|
|
|
data: { error }, |
|
|
|
}); |
|
|
|
return next(error); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
async deleteProfilePhoto (req, res) { |
|
|
|
const { user: userService } = this.dtp.services; |
|
|
|
const { |
|
|
|
logan: loganService, |
|
|
|
user: userService, |
|
|
|
} = this.dtp.services; |
|
|
|
try { |
|
|
|
const displayList = this.createDisplayList('app-settings'); |
|
|
|
await userService.removePhoto(req.user); |
|
|
@ -413,9 +582,19 @@ class UserController extends SiteController { |
|
|
|
'bottom-center', |
|
|
|
2000, |
|
|
|
); |
|
|
|
loganService.sendRequestEvent(module.exports, req, { |
|
|
|
level: 'info', |
|
|
|
event: 'deleteProfilePhoto', |
|
|
|
message: 'profile photo removed', |
|
|
|
}); |
|
|
|
res.status(200).json({ success: true, displayList }); |
|
|
|
} catch (error) { |
|
|
|
this.log.error('failed to remove profile photo', { error }); |
|
|
|
loganService.sendRequestEvent(module.exports, req, { |
|
|
|
level: 'error', |
|
|
|
event: 'deleteProfilePhoto', |
|
|
|
message: `failed to remove profile photo: ${error.message}`, |
|
|
|
data: { error }, |
|
|
|
}); |
|
|
|
return res.status(error.statusCode || 500).json({ |
|
|
|
success: false, |
|
|
|
message: error.message, |
|
|
@ -424,7 +603,10 @@ class UserController extends SiteController { |
|
|
|
} |
|
|
|
|
|
|
|
async deleteHeaderImage (req, res) { |
|
|
|
const { user: userService } = this.dtp.services; |
|
|
|
const { |
|
|
|
logan: loganService, |
|
|
|
user: userService, |
|
|
|
} = this.dtp.services; |
|
|
|
try { |
|
|
|
const displayList = this.createDisplayList('remove-header-image'); |
|
|
|
await userService.removeHeaderImage(req.user); |
|
|
@ -434,9 +616,19 @@ class UserController extends SiteController { |
|
|
|
'bottom-center', |
|
|
|
2000, |
|
|
|
); |
|
|
|
loganService.sendRequestEvent(module.exports, req, { |
|
|
|
level: 'info', |
|
|
|
event: 'deleteHeaderImage', |
|
|
|
message: 'profile header image removed', |
|
|
|
}); |
|
|
|
res.status(200).json({ success: true, displayList }); |
|
|
|
} catch (error) { |
|
|
|
this.log.error('failed to remove header image', { error }); |
|
|
|
loganService.sendRequestEvent(module.exports, req, { |
|
|
|
level: 'error', |
|
|
|
event: 'deleteHeaderImage', |
|
|
|
message: `failed to remove header image: ${error.message}`, |
|
|
|
data: { error }, |
|
|
|
}); |
|
|
|
return res.status(error.statusCode || 500).json({ |
|
|
|
success: false, |
|
|
|
message: error.message, |
|
|
@ -448,5 +640,6 @@ class UserController extends SiteController { |
|
|
|
module.exports = { |
|
|
|
slug: 'user', |
|
|
|
name: 'user', |
|
|
|
className: 'UserController', |
|
|
|
create: async (dtp) => { return new UserController(dtp); }, |
|
|
|
}; |
|
|
|