Files
kami-parse-server/src/Routers/PublicAPIRouter.js

325 lines
7.4 KiB
JavaScript

import PromiseRouter from '../PromiseRouter';
import Config from '../Config';
import express from 'express';
import path from 'path';
import fs from 'fs';
import qs from 'querystring';
import { Parse } from 'parse/node';
const public_html = path.resolve(__dirname, '../../public_html');
const views = path.resolve(__dirname, '../../views');
export class PublicAPIRouter extends PromiseRouter {
verifyEmail(req) {
const { username, token: rawToken } = req.query;
const token = rawToken && typeof rawToken !== 'string' ? rawToken.toString() : rawToken;
const appId = req.params.appId;
const config = Config.get(appId);
if (!config) {
this.invalidRequest();
}
if (!config.publicServerURL) {
return this.missingPublicServerURL();
}
if (!token || !username) {
return this.invalidLink(req);
}
const userController = config.userController;
return userController.verifyEmail(username, token).then(
() => {
const params = qs.stringify({ username });
return Promise.resolve({
status: 302,
location: `${config.verifyEmailSuccessURL}?${params}`,
});
},
() => {
return this.invalidVerificationLink(req);
}
);
}
resendVerificationEmail(req) {
const username = req.body.username;
const appId = req.params.appId;
const config = Config.get(appId);
if (!config) {
this.invalidRequest();
}
if (!config.publicServerURL) {
return this.missingPublicServerURL();
}
if (!username) {
return this.invalidLink(req);
}
const userController = config.userController;
return userController.resendVerificationEmail(username, req).then(
() => {
return Promise.resolve({
status: 302,
location: `${config.linkSendSuccessURL}`,
});
},
() => {
return Promise.resolve({
status: 302,
location: `${config.linkSendFailURL}`,
});
}
);
}
changePassword(req) {
return new Promise((resolve, reject) => {
const config = Config.get(req.query.id);
if (!config) {
this.invalidRequest();
}
if (!config.publicServerURL) {
return resolve({
status: 404,
text: 'Not found.',
});
}
// Should we keep the file in memory or leave like that?
fs.readFile(path.resolve(views, 'choose_password'), 'utf-8', (err, data) => {
if (err) {
return reject(err);
}
data = data.replace('PARSE_SERVER_URL', `'${config.publicServerURL}'`);
resolve({
text: data,
});
});
});
}
requestResetPassword(req) {
const config = req.config;
if (!config) {
this.invalidRequest();
}
if (!config.publicServerURL) {
return this.missingPublicServerURL();
}
const { username, token: rawToken } = req.query;
const token = rawToken && typeof rawToken !== 'string' ? rawToken.toString() : rawToken;
if (!username || !token) {
return this.invalidLink(req);
}
return config.userController.checkResetTokenValidity(username, token).then(
() => {
const params = qs.stringify({
token,
id: config.applicationId,
username,
app: config.appName,
});
return Promise.resolve({
status: 302,
location: `${config.choosePasswordURL}?${params}`,
});
},
() => {
return this.invalidLink(req);
}
);
}
resetPassword(req) {
const config = req.config;
if (!config) {
this.invalidRequest();
}
if (!config.publicServerURL) {
return this.missingPublicServerURL();
}
const { username, new_password, token: rawToken } = req.body;
const token = rawToken && typeof rawToken !== 'string' ? rawToken.toString() : rawToken;
if ((!username || !token || !new_password) && req.xhr === false) {
return this.invalidLink(req);
}
if (!username) {
throw new Parse.Error(Parse.Error.USERNAME_MISSING, 'Missing username');
}
if (!token) {
throw new Parse.Error(Parse.Error.OTHER_CAUSE, 'Missing token');
}
if (!new_password) {
throw new Parse.Error(Parse.Error.PASSWORD_MISSING, 'Missing password');
}
return config.userController
.updatePassword(username, token, new_password)
.then(
() => {
return Promise.resolve({
success: true,
});
},
err => {
return Promise.resolve({
success: false,
err,
});
}
)
.then(result => {
const params = qs.stringify({
username: username,
token: token,
id: config.applicationId,
error: result.err,
app: config.appName,
});
if (req.xhr) {
if (result.success) {
return Promise.resolve({
status: 200,
response: 'Password successfully reset',
});
}
if (result.err) {
throw new Parse.Error(Parse.Error.OTHER_CAUSE, `${result.err}`);
}
}
const encodedUsername = encodeURIComponent(username);
const location = result.success
? `${config.passwordResetSuccessURL}?username=${encodedUsername}`
: `${config.choosePasswordURL}?${params}`;
return Promise.resolve({
status: 302,
location,
});
});
}
invalidLink(req) {
return Promise.resolve({
status: 302,
location: req.config.invalidLinkURL,
});
}
invalidVerificationLink(req) {
const config = req.config;
if (req.query.username && req.params.appId) {
const params = qs.stringify({
username: req.query.username,
appId: req.params.appId,
});
return Promise.resolve({
status: 302,
location: `${config.invalidVerificationLinkURL}?${params}`,
});
} else {
return this.invalidLink(req);
}
}
missingPublicServerURL() {
return Promise.resolve({
text: 'Not found.',
status: 404,
});
}
invalidRequest() {
const error = new Error();
error.status = 403;
error.message = 'unauthorized';
throw error;
}
setConfig(req) {
req.config = Config.get(req.params.appId);
return Promise.resolve();
}
mountRoutes() {
this.route(
'GET',
'/apps/:appId/verify_email',
req => {
this.setConfig(req);
},
req => {
return this.verifyEmail(req);
}
);
this.route(
'POST',
'/apps/:appId/resend_verification_email',
req => {
this.setConfig(req);
},
req => {
return this.resendVerificationEmail(req);
}
);
this.route('GET', '/apps/choose_password', req => {
return this.changePassword(req);
});
this.route(
'POST',
'/apps/:appId/request_password_reset',
req => {
this.setConfig(req);
},
req => {
return this.resetPassword(req);
}
);
this.route(
'GET',
'/apps/:appId/request_password_reset',
req => {
this.setConfig(req);
},
req => {
return this.requestResetPassword(req);
}
);
}
expressRouter() {
const router = express.Router();
router.use('/apps', express.static(public_html));
router.use('/', super.expressRouter());
return router;
}
}
export default PublicAPIRouter;