mirror of
https://github.com/laurent22/joplin.git
synced 2024-12-24 10:27:10 +02:00
Merge branch 'dev' into release-2.0
This commit is contained in:
commit
f45e0d106f
@ -33,8 +33,7 @@ module.exports = {
|
||||
'<rootDir>/node_modules/',
|
||||
'<rootDir>/tests/support/',
|
||||
'<rootDir>/build/',
|
||||
'<rootDir>/tests/test-utils.js',
|
||||
'<rootDir>/tests/test-utils-synchronizer.js',
|
||||
'<rootDir>/tests/testUtils.js',
|
||||
'<rootDir>/tests/tmp/',
|
||||
'<rootDir>/tests/test data/',
|
||||
],
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { parseSubPath, splitItemPath } from './routeUtils';
|
||||
import { isValidOrigin, parseSubPath, splitItemPath } from './routeUtils';
|
||||
import { ItemAddressingType } from '../db';
|
||||
|
||||
describe('routeUtils', function() {
|
||||
@ -41,4 +41,46 @@ describe('routeUtils', function() {
|
||||
}
|
||||
});
|
||||
|
||||
it('should check the request origin', async function() {
|
||||
const testCases: any[] = [
|
||||
[
|
||||
'https://example.com', // Request origin
|
||||
'https://example.com', // Config base URL
|
||||
true,
|
||||
],
|
||||
[
|
||||
// Apache ProxyPreserveHost somehow converts https:// to http://
|
||||
// but in this context it's valid as only the domain matters.
|
||||
'http://example.com',
|
||||
'https://example.com',
|
||||
true,
|
||||
],
|
||||
[
|
||||
// With Apache ProxyPreserveHost, the request might be eg
|
||||
// https://example.com/joplin/api/ping but the origin part, as
|
||||
// forwarded by Apache will be https://example.com/api/ping
|
||||
// (without /joplin). In that case the request is valid anyway
|
||||
// since we only care about the domain.
|
||||
'https://example.com',
|
||||
'https://example.com/joplin',
|
||||
true,
|
||||
],
|
||||
[
|
||||
'https://bad.com',
|
||||
'https://example.com',
|
||||
false,
|
||||
],
|
||||
[
|
||||
'http://bad.com',
|
||||
'https://example.com',
|
||||
false,
|
||||
],
|
||||
];
|
||||
|
||||
for (const testCase of testCases) {
|
||||
const [requestOrigin, configBaseUrl, expected] = testCase;
|
||||
expect(isValidOrigin(requestOrigin, configBaseUrl)).toBe(expected);
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
|
@ -3,6 +3,7 @@ import { Item, ItemAddressingType } from '../db';
|
||||
import { ErrorBadRequest, ErrorForbidden, ErrorNotFound } from './errors';
|
||||
import Router from './Router';
|
||||
import { AppContext, HttpMethod } from './types';
|
||||
import { URL } from 'url';
|
||||
|
||||
const { ltrimSlashes, rtrimSlashes } = require('@joplin/lib/path-utils');
|
||||
|
||||
@ -152,6 +153,12 @@ export function parseSubPath(basePath: string, p: string, rawPath: string = null
|
||||
return output;
|
||||
}
|
||||
|
||||
export function isValidOrigin(requestOrigin: string, endPointBaseUrl: string): boolean {
|
||||
const host1 = (new URL(requestOrigin)).host;
|
||||
const host2 = (new URL(endPointBaseUrl)).host;
|
||||
return host1 === host2;
|
||||
}
|
||||
|
||||
export function routeResponseFormat(context: AppContext): RouteResponseFormat {
|
||||
// const rawPath = context.path;
|
||||
// if (match && match.route.responseFormat) return match.route.responseFormat;
|
||||
@ -168,7 +175,7 @@ export async function execRequest(routes: Routers, ctx: AppContext) {
|
||||
if (!match) throw new ErrorNotFound();
|
||||
|
||||
const endPoint = match.route.findEndPoint(ctx.request.method as HttpMethod, match.subPath.schema);
|
||||
if (ctx.URL && ctx.URL.origin !== baseUrl(endPoint.type)) throw new ErrorNotFound('Invalid origin', 'invalidOrigin');
|
||||
if (ctx.URL && !isValidOrigin(ctx.URL.origin, baseUrl(endPoint.type))) throw new ErrorNotFound('Invalid origin', 'invalidOrigin');
|
||||
|
||||
// This is a generic catch-all for all private end points - if we
|
||||
// couldn't get a valid session, we exit now. Individual end points
|
||||
|
Loading…
Reference in New Issue
Block a user