* fix(layout): Fix Settings layout in firefox * chore(availableForHire): Remove available for hire setting * feat(helpers): Use helper components for Settings layout * fix(map): Fix undefined lang requested * feat(settings): Expand Settings page functionality * chore(pledge): Remove pledge from Settings * fix(about): Adjust AboutSettings layout * fix(portfolio): Improve PortfolioSettings layout * fix(email): Improve EmailSettings layout * fix(settings): Align save buttons with form fields * fix(AHP): Format AHP * fix(DangerZone): Adjust DangerZone layout * fix(projectSettings): Change Button Copy * fix(CertSettings): Fix certificate claim logic * chore(lint): Lint
216 lines
5.1 KiB
JavaScript
216 lines
5.1 KiB
JavaScript
import { check } from 'express-validator/check';
|
|
|
|
import {
|
|
ifNoUser401,
|
|
createValidatorErrorHandler
|
|
} from '../utils/middleware';
|
|
import supportedLanguages from '../../common/utils/supported-languages.js';
|
|
import { themes } from '../../common/utils/themes.js';
|
|
import { alertTypes } from '../../common/utils/flash.js';
|
|
|
|
export default function settingsController(app) {
|
|
const api = app.loopback.Router();
|
|
const toggleUserFlag = (flag, req, res, next) => {
|
|
const { user } = req;
|
|
const currentValue = user[ flag ];
|
|
return user
|
|
.update$({ [ flag ]: !currentValue })
|
|
.subscribe(
|
|
() => res.status(200).json({
|
|
flag,
|
|
value: !currentValue
|
|
}),
|
|
next
|
|
);
|
|
};
|
|
|
|
function refetchChallengeMap(req, res, next) {
|
|
const { user } = req;
|
|
return user.requestChallengeMap()
|
|
.subscribe(
|
|
challengeMap => res.json({ challengeMap }),
|
|
next
|
|
);
|
|
}
|
|
|
|
const updateMyEmailValidators = [
|
|
check('email')
|
|
.isEmail()
|
|
.withMessage('Email format is invalid.')
|
|
];
|
|
|
|
function updateMyEmail(req, res, next) {
|
|
const { user, body: { email } } = req;
|
|
return user.requestUpdateEmail(email)
|
|
.subscribe(
|
|
message => res.sendFlash(alertTypes.info, message),
|
|
next
|
|
);
|
|
}
|
|
|
|
function updateMyLang(req, res, next) {
|
|
const { user, body: { lang } = {} } = req;
|
|
const langName = supportedLanguages[lang];
|
|
const update = { languageTag: lang };
|
|
if (!supportedLanguages[lang]) {
|
|
return res.json({
|
|
message: `${lang} is currently unsupported`
|
|
});
|
|
}
|
|
if (user.languageTag === lang) {
|
|
return res.json({
|
|
message: `Your language is already set to ${langName}`
|
|
});
|
|
}
|
|
return user.update$(update)
|
|
.subscribe(
|
|
() => res.json({
|
|
message: `Your language has been updated to '${langName}'`
|
|
}),
|
|
next
|
|
);
|
|
}
|
|
|
|
const updateMyCurrentChallengeValidators = [
|
|
check('currentChallengeId')
|
|
.isMongoId()
|
|
.withMessage('currentChallengeId is not a valid challenge ID')
|
|
];
|
|
|
|
function updateMyCurrentChallenge(req, res, next) {
|
|
const { user, body: { currentChallengeId } } = req;
|
|
return user.update$({ currentChallengeId }).subscribe(
|
|
() => res.json({
|
|
message:
|
|
`your current challenge has been updated to ${currentChallengeId}`
|
|
}),
|
|
next
|
|
);
|
|
}
|
|
|
|
const updateMyThemeValidators = [
|
|
check('theme')
|
|
.isIn(Object.keys(themes))
|
|
.withMessage('Theme is invalid.')
|
|
];
|
|
|
|
function updateMyTheme(req, res, next) {
|
|
const { body: { theme } } = req;
|
|
if (req.user.theme === theme) {
|
|
return res.sendFlash(alertTypes.info, 'Theme already set');
|
|
}
|
|
return req.user.updateTheme(theme)
|
|
.then(
|
|
() => res.sendFlash(alertTypes.info, 'Your theme has been updated'),
|
|
next
|
|
);
|
|
}
|
|
|
|
function updateFlags(req, res, next) {
|
|
const { user, body: { values } } = req;
|
|
const keys = Object.keys(values);
|
|
if (
|
|
keys.length === 1 &&
|
|
typeof keys[0] === 'boolean'
|
|
) {
|
|
return toggleUserFlag(keys[0], req, res, next);
|
|
}
|
|
return user.requestUpdateFlags(values)
|
|
.subscribe(
|
|
message => res.json({ message }),
|
|
next
|
|
);
|
|
}
|
|
|
|
function updateMyPortfolio(req, res, next) {
|
|
const {
|
|
user,
|
|
body: { portfolio }
|
|
} = req;
|
|
// if we only have one key, it should be the id
|
|
// user cannot send only one key to this route
|
|
// other than to remove a portfolio item
|
|
const requestDelete = Object.keys(portfolio).length === 1;
|
|
return user.updateMyPortfolio(portfolio, requestDelete)
|
|
.subscribe(
|
|
message => res.json({ message }),
|
|
next
|
|
);
|
|
}
|
|
|
|
function updateMyProjects(req, res, next) {
|
|
const {
|
|
user,
|
|
body: { projects: project }
|
|
} = req;
|
|
return user.updateMyProjects(project)
|
|
.subscribe(
|
|
message => res.json({ message }),
|
|
next
|
|
);
|
|
}
|
|
|
|
function updateMyUsername(req, res, next) {
|
|
const { user, body: { username } } = req;
|
|
return user.updateMyUsername(username)
|
|
.subscribe(
|
|
message => res.json({ message }),
|
|
next
|
|
);
|
|
}
|
|
|
|
api.post(
|
|
'/refetch-user-challenge-map',
|
|
ifNoUser401,
|
|
refetchChallengeMap
|
|
);
|
|
api.post(
|
|
'/update-flags',
|
|
ifNoUser401,
|
|
updateFlags
|
|
);
|
|
api.post(
|
|
'/update-my-email',
|
|
ifNoUser401,
|
|
updateMyEmailValidators,
|
|
createValidatorErrorHandler(alertTypes.danger),
|
|
updateMyEmail
|
|
);
|
|
api.post(
|
|
'/update-my-current-challenge',
|
|
ifNoUser401,
|
|
updateMyCurrentChallengeValidators,
|
|
createValidatorErrorHandler(alertTypes.danger),
|
|
updateMyCurrentChallenge
|
|
);
|
|
api.post(
|
|
'/update-my-lang',
|
|
ifNoUser401,
|
|
updateMyLang
|
|
);
|
|
api.post(
|
|
'/update-my-portfolio',
|
|
ifNoUser401,
|
|
updateMyPortfolio
|
|
);
|
|
api.post(
|
|
'/update-my-projects',
|
|
ifNoUser401,
|
|
updateMyProjects
|
|
);
|
|
api.post(
|
|
'/update-my-theme',
|
|
ifNoUser401,
|
|
updateMyThemeValidators,
|
|
createValidatorErrorHandler(alertTypes.danger),
|
|
updateMyTheme
|
|
);
|
|
api.post(
|
|
'/update-my-username',
|
|
ifNoUser401,
|
|
updateMyUsername
|
|
);
|
|
|
|
app.use(api);
|
|
}
|