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>/node_modules/',
|
||||||
'<rootDir>/tests/support/',
|
'<rootDir>/tests/support/',
|
||||||
'<rootDir>/build/',
|
'<rootDir>/build/',
|
||||||
'<rootDir>/tests/test-utils.js',
|
'<rootDir>/tests/testUtils.js',
|
||||||
'<rootDir>/tests/test-utils-synchronizer.js',
|
|
||||||
'<rootDir>/tests/tmp/',
|
'<rootDir>/tests/tmp/',
|
||||||
'<rootDir>/tests/test data/',
|
'<rootDir>/tests/test data/',
|
||||||
],
|
],
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { parseSubPath, splitItemPath } from './routeUtils';
|
import { isValidOrigin, parseSubPath, splitItemPath } from './routeUtils';
|
||||||
import { ItemAddressingType } from '../db';
|
import { ItemAddressingType } from '../db';
|
||||||
|
|
||||||
describe('routeUtils', function() {
|
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 { ErrorBadRequest, ErrorForbidden, ErrorNotFound } from './errors';
|
||||||
import Router from './Router';
|
import Router from './Router';
|
||||||
import { AppContext, HttpMethod } from './types';
|
import { AppContext, HttpMethod } from './types';
|
||||||
|
import { URL } from 'url';
|
||||||
|
|
||||||
const { ltrimSlashes, rtrimSlashes } = require('@joplin/lib/path-utils');
|
const { ltrimSlashes, rtrimSlashes } = require('@joplin/lib/path-utils');
|
||||||
|
|
||||||
@ -152,6 +153,12 @@ export function parseSubPath(basePath: string, p: string, rawPath: string = null
|
|||||||
return output;
|
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 {
|
export function routeResponseFormat(context: AppContext): RouteResponseFormat {
|
||||||
// const rawPath = context.path;
|
// const rawPath = context.path;
|
||||||
// if (match && match.route.responseFormat) return match.route.responseFormat;
|
// 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();
|
if (!match) throw new ErrorNotFound();
|
||||||
|
|
||||||
const endPoint = match.route.findEndPoint(ctx.request.method as HttpMethod, match.subPath.schema);
|
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
|
// 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
|
// couldn't get a valid session, we exit now. Individual end points
|
||||||
|
Loading…
Reference in New Issue
Block a user