mirror of
https://github.com/laurent22/joplin.git
synced 2024-12-24 10:27:10 +02:00
trying
This commit is contained in:
parent
58a464d040
commit
aeb3c4a98d
@ -274,4 +274,8 @@ export default class Application extends BaseApplication {
|
||||
return true;
|
||||
}
|
||||
|
||||
public async processSharedContentForSave(file:File):Promise<File> {
|
||||
// console.info('
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,11 +1,14 @@
|
||||
import routes from '../../../routes/routes';
|
||||
import Router from '../../../utils/Router';
|
||||
import { SubPath } from '../../../utils/routeUtils';
|
||||
import { execRequest, SubPath } from '../../../utils/routeUtils';
|
||||
import { AppContext } from '../../../utils/types';
|
||||
|
||||
const router = new Router();
|
||||
|
||||
router.get('notes/:id', async (_path: SubPath, _ctx: AppContext) => {
|
||||
return 'testing';
|
||||
router.get('notes/:id', async (path: SubPath, ctx: AppContext) => {
|
||||
// return execRequest(routes, ctx, 'api/files/root:/' + path.id);
|
||||
// return execRoute('GET', 'api/files/:id', path, ctx);
|
||||
//return ctx.routes['api/files'](path, ctx);
|
||||
});
|
||||
|
||||
export default router;
|
||||
|
@ -1,7 +1,6 @@
|
||||
import routes from '../routes/routes';
|
||||
import { ErrorForbidden, ErrorNotFound } from '../utils/errors';
|
||||
import { routeResponseFormat, findMatchingRoute, Response, RouteResponseFormat, MatchedRoute } from '../utils/routeUtils';
|
||||
import { AppContext, Env, HttpMethod } from '../utils/types';
|
||||
import { routeResponseFormat, Response, RouteResponseFormat, execRequest } from '../utils/routeUtils';
|
||||
import { AppContext, Env } from '../utils/types';
|
||||
import MustacheService, { isView, View } from '../services/MustacheService';
|
||||
import config from '../config';
|
||||
|
||||
@ -16,38 +15,21 @@ function mustache(): MustacheService {
|
||||
export default async function(ctx: AppContext) {
|
||||
ctx.appLogger().info(`${ctx.request.method} ${ctx.path}`);
|
||||
|
||||
const match: MatchedRoute = null;
|
||||
|
||||
try {
|
||||
const match = findMatchingRoute(ctx.path, routes);
|
||||
const responseObject = await execRequest(routes, ctx);
|
||||
|
||||
if (match) {
|
||||
let responseObject = null;
|
||||
|
||||
const routeHandler = match.route.findEndPoint(ctx.request.method as HttpMethod, match.subPath.schema);
|
||||
|
||||
// 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
|
||||
// might have additional permission checks depending on the action.
|
||||
if (!match.route.public && !ctx.owner) throw new ErrorForbidden();
|
||||
|
||||
responseObject = await routeHandler(match.subPath, ctx);
|
||||
|
||||
if (responseObject instanceof Response) {
|
||||
ctx.response = responseObject.response;
|
||||
} else if (isView(responseObject)) {
|
||||
ctx.response.status = 200;
|
||||
ctx.response.body = await mustache().renderView(responseObject, {
|
||||
notifications: ctx.notifications || [],
|
||||
hasNotifications: !!ctx.notifications && !!ctx.notifications.length,
|
||||
owner: ctx.owner,
|
||||
});
|
||||
} else {
|
||||
ctx.response.status = 200;
|
||||
ctx.response.body = responseObject;
|
||||
}
|
||||
if (responseObject instanceof Response) {
|
||||
ctx.response = responseObject.response;
|
||||
} else if (isView(responseObject)) {
|
||||
ctx.response.status = 200;
|
||||
ctx.response.body = await mustache().renderView(responseObject, {
|
||||
notifications: ctx.notifications || [],
|
||||
hasNotifications: !!ctx.notifications && !!ctx.notifications.length,
|
||||
owner: ctx.owner,
|
||||
});
|
||||
} else {
|
||||
throw new ErrorNotFound();
|
||||
ctx.response.status = 200;
|
||||
ctx.response.body = responseObject;
|
||||
}
|
||||
} catch (error) {
|
||||
if (error.httpCode >= 400 && error.httpCode < 500) {
|
||||
@ -58,7 +40,7 @@ export default async function(ctx: AppContext) {
|
||||
|
||||
ctx.response.status = error.httpCode ? error.httpCode : 500;
|
||||
|
||||
const responseFormat = routeResponseFormat(match, ctx);
|
||||
const responseFormat = routeResponseFormat(ctx);
|
||||
|
||||
if (responseFormat === RouteResponseFormat.Html) {
|
||||
ctx.response.set('Content-Type', 'text/html');
|
||||
|
@ -3,9 +3,11 @@ import TransactionHandler from '../utils/TransactionHandler';
|
||||
import uuidgen from '../utils/uuidgen';
|
||||
import { ErrorUnprocessableEntity, ErrorBadRequest } from '../utils/errors';
|
||||
import { Models } from './factory';
|
||||
import Applications from '../services/Applications';
|
||||
|
||||
export interface ModelOptions {
|
||||
userId?: string;
|
||||
apps?: Applications;
|
||||
}
|
||||
|
||||
export interface SaveOptions {
|
||||
@ -67,6 +69,10 @@ export default abstract class BaseModel<T> {
|
||||
return this.options.userId;
|
||||
}
|
||||
|
||||
protected get apps():Applications {
|
||||
return this.options.apps;
|
||||
}
|
||||
|
||||
protected get db(): DbConnection {
|
||||
if (this.transactionHandler_.activeTransaction) return this.transactionHandler_.activeTransaction;
|
||||
return this.db_;
|
||||
|
@ -302,6 +302,12 @@ export default class FileModel extends BaseModel<File> {
|
||||
}
|
||||
}
|
||||
|
||||
private async processSharedContentForSave(file:File):Promise<File> {
|
||||
if (!('source_file_id' in file)) throw new Error('source_file_id prop is required');
|
||||
if (!file.source_file_id) return file;
|
||||
return this.apps.processSharedContentForSave(file);
|
||||
}
|
||||
|
||||
public async createRootFile(): Promise<File> {
|
||||
const existingRootFile = await this.userRootFile();
|
||||
if (existingRootFile) throw new Error(`User ${this.userId} has already a root file`);
|
||||
@ -477,9 +483,12 @@ export default class FileModel extends BaseModel<File> {
|
||||
size: fileSize,
|
||||
source_file_id: '',
|
||||
};
|
||||
|
||||
sourceFile = await this.processSharedContentForSave(file);
|
||||
|
||||
delete file.content;
|
||||
} else {
|
||||
file.size = fileSize;
|
||||
file.size = file.content ? file.content.byteLength : 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -65,19 +65,22 @@ import ChangeModel from './ChangeModel';
|
||||
import NotificationModel from './NotificationModel';
|
||||
import ShareModel from './ShareModel';
|
||||
import ShareUserModel from './ShareUserModel';
|
||||
import Applications from '../services/Applications';
|
||||
|
||||
export class Models {
|
||||
|
||||
private db_: DbConnection;
|
||||
private baseUrl_: string;
|
||||
private apps_:Applications;
|
||||
|
||||
public constructor(db: DbConnection, baseUrl: string) {
|
||||
public constructor(db: DbConnection, baseUrl: string, apps:Applications) {
|
||||
this.db_ = db;
|
||||
this.baseUrl_ = baseUrl;
|
||||
this.apps_ = apps;
|
||||
}
|
||||
|
||||
public file(options: ModelOptions = null) {
|
||||
return new FileModel(this.db_, newModelFactory, this.baseUrl_, options);
|
||||
return new FileModel(this.db_, newModelFactory, this.baseUrl_, { ...options, apps: this.apps_ });
|
||||
}
|
||||
|
||||
public user(options: ModelOptions = null) {
|
||||
|
@ -1,5 +1,6 @@
|
||||
import ApplicationJoplin from '../apps/joplin/Application';
|
||||
import config from '../config';
|
||||
import { File } from '../db';
|
||||
import { Models } from '../models/factory';
|
||||
|
||||
export default class Applications {
|
||||
@ -21,6 +22,11 @@ export default class Applications {
|
||||
return this.joplin_;
|
||||
}
|
||||
|
||||
public async processSharedContentForSave(file:File):Promise<File> {
|
||||
const app = await this.joplin();
|
||||
return app.processSharedContentForSave(file);
|
||||
}
|
||||
|
||||
public async localFileFromUrl(url: string): Promise<string> {
|
||||
if (url.indexOf('apps/') !== 0) return null;
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { File, ItemAddressingType } from '../db';
|
||||
import { ErrorBadRequest } from './errors';
|
||||
import { ErrorBadRequest, ErrorForbidden, ErrorNotFound } from './errors';
|
||||
import Router from './Router';
|
||||
import { AppContext } from './types';
|
||||
import { AppContext, HttpMethod } from './types';
|
||||
|
||||
const { ltrimSlashes, rtrimSlashes } = require('@joplin/lib/path-utils');
|
||||
|
||||
@ -151,16 +151,33 @@ export function parseSubPath(basePath: string, p: string): SubPath {
|
||||
return output;
|
||||
}
|
||||
|
||||
export function routeResponseFormat(match: MatchedRoute, context: AppContext): RouteResponseFormat {
|
||||
const rawPath = context.path;
|
||||
if (match && match.route.responseFormat) return match.route.responseFormat;
|
||||
export function routeResponseFormat(context: AppContext): RouteResponseFormat {
|
||||
// const rawPath = context.path;
|
||||
// if (match && match.route.responseFormat) return match.route.responseFormat;
|
||||
|
||||
let path = rawPath;
|
||||
if (match) path = match.basePath ? match.basePath : match.subPath.raw;
|
||||
// let path = rawPath;
|
||||
// if (match) path = match.basePath ? match.basePath : match.subPath.raw;
|
||||
|
||||
const path = context.path;
|
||||
return path.indexOf('api') === 0 || path.indexOf('/api') === 0 ? RouteResponseFormat.Json : RouteResponseFormat.Html;
|
||||
}
|
||||
|
||||
export async function execRequest(routes:Routers, ctx:AppContext, path:string = null) {
|
||||
path = path || ctx.path;
|
||||
|
||||
const match = findMatchingRoute(ctx.path, routes);
|
||||
if (!match) throw new ErrorNotFound();
|
||||
|
||||
const routeHandler = match.route.findEndPoint(ctx.request.method as HttpMethod, match.subPath.schema);
|
||||
|
||||
// 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
|
||||
// might have additional permission checks depending on the action.
|
||||
if (!match.route.public && !ctx.owner) throw new ErrorForbidden();
|
||||
|
||||
return routeHandler(match.subPath, ctx);
|
||||
}
|
||||
|
||||
// In a path such as "/api/files/SOME_ID/content" we want to find:
|
||||
// - The base path: "api/files"
|
||||
// - The ID: "SOME_ID"
|
||||
|
@ -4,11 +4,13 @@ import { DbConnection } from '../db';
|
||||
import newModelFactory from '../models/factory';
|
||||
import Applications from '../services/Applications';
|
||||
import { AppContext, Env } from './types';
|
||||
import routes from '../routes/routes';
|
||||
|
||||
export default async function(appContext: AppContext, env: Env, dbConnection: DbConnection, appLogger: ()=> LoggerWrapper) {
|
||||
appContext.env = env;
|
||||
appContext.db = dbConnection;
|
||||
appContext.models = newModelFactory(appContext.db, config().baseUrl);
|
||||
appContext.apps = new Applications(appContext.models);
|
||||
appContext.models = newModelFactory(appContext.db, config().baseUrl, appContext.apps);
|
||||
appContext.appLogger = appLogger;
|
||||
appContext.routes = routes;
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ import * as Koa from 'koa';
|
||||
import { DbConnection, User, Uuid } from '../db';
|
||||
import { Models } from '../models/factory';
|
||||
import Applications from '../services/Applications';
|
||||
import { Routers } from './routeUtils';
|
||||
|
||||
export enum Env {
|
||||
Dev = 'dev',
|
||||
@ -25,6 +26,7 @@ export interface AppContext extends Koa.Context {
|
||||
notifications: NotificationView[];
|
||||
owner: User;
|
||||
apps: Applications;
|
||||
routes: Routers;
|
||||
}
|
||||
|
||||
export enum DatabaseConfigClient {
|
||||
|
Loading…
Reference in New Issue
Block a user