feat: Deprecation DEPPS11: Replace PublicAPIRouter with PagesRouter (#9974)
BREAKING CHANGE: This release replaces `PublicAPIRouter` with `PagesRouter` (Deprecation DEPPS11).
This commit is contained in:
@@ -828,10 +828,8 @@ export class Config {
|
||||
return this.masterKey;
|
||||
}
|
||||
|
||||
// TODO: Remove this function once PagesRouter replaces the PublicAPIRouter;
|
||||
// the (default) endpoint has to be defined in PagesRouter only.
|
||||
get pagesEndpoint() {
|
||||
return this.pages && this.pages.enableRouter && this.pages.pagesEndpoint
|
||||
return this.pages && this.pages.pagesEndpoint
|
||||
? this.pages.pagesEndpoint
|
||||
: 'apps';
|
||||
}
|
||||
|
||||
@@ -27,7 +27,6 @@ import { InstallationsRouter } from './Routers/InstallationsRouter';
|
||||
import { LogsRouter } from './Routers/LogsRouter';
|
||||
import { ParseLiveQueryServer } from './LiveQuery/ParseLiveQueryServer';
|
||||
import { PagesRouter } from './Routers/PagesRouter';
|
||||
import { PublicAPIRouter } from './Routers/PublicAPIRouter';
|
||||
import { PushRouter } from './Routers/PushRouter';
|
||||
import { CloudCodeRouter } from './Routers/CloudCodeRouter';
|
||||
import { RolesRouter } from './Routers/RolesRouter';
|
||||
@@ -330,9 +329,7 @@ class ParseServer {
|
||||
api.use(
|
||||
'/',
|
||||
express.urlencoded({ extended: false }),
|
||||
pages.enableRouter
|
||||
? new PagesRouter(pages).expressRouter()
|
||||
: new PublicAPIRouter().expressRouter()
|
||||
new PagesRouter(pages).expressRouter()
|
||||
);
|
||||
|
||||
api.use(express.json({ type: '*/*', limit: maxUploadSize }));
|
||||
|
||||
@@ -1,332 +0,0 @@
|
||||
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';
|
||||
import Deprecator from '../Deprecator/Deprecator';
|
||||
|
||||
const public_html = path.resolve(__dirname, '../../public_html');
|
||||
const views = path.resolve(__dirname, '../../views');
|
||||
|
||||
export class PublicAPIRouter extends PromiseRouter {
|
||||
constructor() {
|
||||
super();
|
||||
Deprecator.logRuntimeDeprecation({
|
||||
usage: 'PublicAPIRouter',
|
||||
solution: 'pages.enableRouter'
|
||||
});
|
||||
}
|
||||
verifyEmail(req) {
|
||||
const { 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) {
|
||||
return this.invalidLink(req);
|
||||
}
|
||||
|
||||
const userController = config.userController;
|
||||
return userController.verifyEmail(token).then(
|
||||
() => {
|
||||
return Promise.resolve({
|
||||
status: 302,
|
||||
location: `${config.verifyEmailSuccessURL}`,
|
||||
});
|
||||
},
|
||||
() => {
|
||||
return this.invalidVerificationLink(req, token);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
const token = req.body.token;
|
||||
|
||||
if (!username && !token) {
|
||||
return this.invalidLink(req);
|
||||
}
|
||||
|
||||
const userController = config.userController;
|
||||
|
||||
return userController.resendVerificationEmail(username, req, token).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 { token: rawToken } = req.query;
|
||||
const token = rawToken && typeof rawToken !== 'string' ? rawToken.toString() : rawToken;
|
||||
|
||||
if (!token) {
|
||||
return this.invalidLink(req);
|
||||
}
|
||||
|
||||
return config.userController.checkResetTokenValidity(token).then(
|
||||
() => {
|
||||
const params = qs.stringify({
|
||||
token,
|
||||
id: config.applicationId,
|
||||
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 { new_password, token: rawToken } = req.body || {};
|
||||
const token = rawToken && typeof rawToken !== 'string' ? rawToken.toString() : rawToken;
|
||||
|
||||
if ((!token || !new_password) && req.xhr === false) {
|
||||
return this.invalidLink(req);
|
||||
}
|
||||
|
||||
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(token, new_password)
|
||||
.then(
|
||||
() => {
|
||||
return Promise.resolve({
|
||||
success: true,
|
||||
});
|
||||
},
|
||||
err => {
|
||||
return Promise.resolve({
|
||||
success: false,
|
||||
err,
|
||||
});
|
||||
}
|
||||
)
|
||||
.then(result => {
|
||||
const queryString = {
|
||||
token: token,
|
||||
id: config.applicationId,
|
||||
error: result.err,
|
||||
app: config.appName,
|
||||
};
|
||||
|
||||
if (result?.err === 'The password reset link has expired') {
|
||||
delete queryString.token;
|
||||
queryString.token = token;
|
||||
}
|
||||
const params = qs.stringify(queryString);
|
||||
|
||||
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 location = result.success
|
||||
? `${config.passwordResetSuccessURL}`
|
||||
: `${config.choosePasswordURL}?${params}`;
|
||||
|
||||
return Promise.resolve({
|
||||
status: 302,
|
||||
location,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
invalidLink(req) {
|
||||
return Promise.resolve({
|
||||
status: 302,
|
||||
location: req.config.invalidLinkURL,
|
||||
});
|
||||
}
|
||||
|
||||
invalidVerificationLink(req, token) {
|
||||
const config = req.config;
|
||||
if (req.params.appId) {
|
||||
const params = qs.stringify({
|
||||
appId: req.params.appId,
|
||||
token,
|
||||
});
|
||||
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;
|
||||
Reference in New Issue
Block a user