1
0
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:
Laurent Cozic 2021-05-25 20:05:29 +02:00
commit f45e0d106f
3 changed files with 52 additions and 4 deletions

View File

@ -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/',
], ],

View File

@ -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);
}
});
}); });

View File

@ -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