mirror of
https://github.com/laurent22/joplin.git
synced 2025-01-17 18:44:45 +02:00
Merge branch 'dev' into release-2.6
This commit is contained in:
commit
b903542aed
@ -38,8 +38,9 @@ export async function getDeviceTimeDrift(): Promise<number> {
|
||||
break;
|
||||
} catch (error) {
|
||||
if (tryCount >= maxTries) {
|
||||
error.message = `Cannot retrieve the network time: ${error.message}`;
|
||||
throw error;
|
||||
const newError = typeof error === 'string' ? new Error(error) : error;
|
||||
newError.message = `Cannot retrieve the network time from ${server.domain}:${server.port}: ${newError.message}`;
|
||||
throw newError;
|
||||
} else {
|
||||
await time.msleep(tryCount * 1000);
|
||||
}
|
||||
|
@ -23,6 +23,7 @@ import setupCommands from './utils/setupCommands';
|
||||
import { RouteResponseFormat, routeResponseFormat } from './utils/routeUtils';
|
||||
import { parseEnv } from './env';
|
||||
import storageConnectionCheck from './utils/storageConnectionCheck';
|
||||
import { setLocale } from '@joplin/lib/locale';
|
||||
|
||||
interface Argv {
|
||||
env?: Env;
|
||||
@ -254,11 +255,15 @@ async function main() {
|
||||
if (config().maxTimeDrift) {
|
||||
const timeDrift = await getDeviceTimeDrift();
|
||||
if (Math.abs(timeDrift) > config().maxTimeDrift) {
|
||||
throw new Error(`The device time drift is ${timeDrift}ms (Max allowed: ${config().maxTimeDrift}ms) - cannot continue as it could cause data loss and conflicts on the sync clients. You may increase env var MAX_TIME_DRIFT to pass the check.`);
|
||||
throw new Error(`The device time drift is ${timeDrift}ms (Max allowed: ${config().maxTimeDrift}ms) - cannot continue as it could cause data loss and conflicts on the sync clients. You may increase env var MAX_TIME_DRIFT to pass the check, or set to 0 to disabled the check.`);
|
||||
}
|
||||
appLogger().info(`NTP time offset: ${timeDrift}ms`);
|
||||
} else {
|
||||
appLogger().info('Skipping NTP time check because MAX_TIME_DRIFT is 0.');
|
||||
}
|
||||
|
||||
setLocale('en_GB');
|
||||
|
||||
appLogger().info('Running in Docker:', runningInDocker());
|
||||
appLogger().info('Public base URL:', config().baseUrl);
|
||||
appLogger().info('API base URL:', config().apiBaseUrl);
|
||||
|
@ -16,7 +16,7 @@ describe('index_changes', function() {
|
||||
});
|
||||
|
||||
test('should list changes', async function() {
|
||||
const { user: user1, session: session1 } = await createUserAndSession(1);
|
||||
const { user: user1, session: session1 } = await createUserAndSession(1, true);
|
||||
|
||||
const items: any = {};
|
||||
for (let i = 1; i <= 150; i++) {
|
||||
|
@ -9,10 +9,13 @@ import defaultView from '../../utils/defaultView';
|
||||
import { View } from '../../services/MustacheService';
|
||||
import { makeTablePagination, Table, Row, makeTableView } from '../../utils/views/table';
|
||||
import config, { showItemUrls } from '../../config';
|
||||
import { ErrorForbidden } from '../../utils/errors';
|
||||
|
||||
const router = new Router(RouteType.Web);
|
||||
|
||||
router.get('changes', async (_path: SubPath, ctx: AppContext) => {
|
||||
if (!ctx.joplin.owner.is_admin) throw new ErrorForbidden();
|
||||
|
||||
const pagination = makeTablePagination(ctx.query, 'updated_time', PaginationOrderDir.DESC);
|
||||
const paginatedChanges = await ctx.joplin.models.change().allByUser(ctx.joplin.owner.id, pagination);
|
||||
const items = await ctx.joplin.models.item().loadByIds(paginatedChanges.items.map(i => i.item_id), { fields: ['id'] });
|
||||
|
@ -16,7 +16,7 @@ describe('index_items', function() {
|
||||
});
|
||||
|
||||
test('should list the user items', async function() {
|
||||
const { user: user1, session: session1 } = await createUserAndSession(1);
|
||||
const { user: user1, session: session1 } = await createUserAndSession(1, true);
|
||||
|
||||
const items: any = {};
|
||||
for (let i = 1; i <= 150; i++) {
|
||||
|
@ -2,7 +2,7 @@ import { SubPath, respondWithItemContent } from '../../utils/routeUtils';
|
||||
import Router from '../../utils/Router';
|
||||
import { RouteType } from '../../utils/types';
|
||||
import { AppContext } from '../../utils/types';
|
||||
import { ErrorNotFound } from '../../utils/errors';
|
||||
import { ErrorForbidden, ErrorNotFound } from '../../utils/errors';
|
||||
import config, { showItemUrls } from '../../config';
|
||||
import { formatDateTime } from '../../utils/time';
|
||||
import defaultView from '../../utils/defaultView';
|
||||
@ -14,6 +14,8 @@ import { formatBytes } from '../../utils/bytes';
|
||||
const router = new Router(RouteType.Web);
|
||||
|
||||
router.get('items', async (_path: SubPath, ctx: AppContext) => {
|
||||
if (!ctx.joplin.owner.is_admin) throw new ErrorForbidden();
|
||||
|
||||
const pagination = makeTablePagination(ctx.query, 'name', PaginationOrderDir.ASC);
|
||||
const paginatedItems = await ctx.joplin.models.item().children(ctx.joplin.owner.id, '', pagination, { fields: ['id', 'name', 'updated_time', 'mime_type', 'content_size'] });
|
||||
|
||||
|
@ -8,6 +8,7 @@ import { User } from '../services/database/types';
|
||||
import { makeUrl, UrlType } from '../utils/routeUtils';
|
||||
import MarkdownIt = require('markdown-it');
|
||||
import { headerAnchor } from '@joplin/renderer';
|
||||
import { _ } from '@joplin/lib/locale';
|
||||
|
||||
export interface RenderOptions {
|
||||
partials?: any;
|
||||
@ -191,6 +192,15 @@ export default class MustacheService {
|
||||
|
||||
const layoutView: any = {
|
||||
global: globalParams,
|
||||
s: {
|
||||
home: _('Home'),
|
||||
users: _('Users'),
|
||||
items: _('Items'),
|
||||
log: _('Log'),
|
||||
tasks: _('Tasks'),
|
||||
help: _('Help'),
|
||||
logout: _('Logout'),
|
||||
},
|
||||
pageName: view.name,
|
||||
pageTitle: view.titleOverride ? view.title : `${config().appName} - ${view.title}`,
|
||||
contentHtml: contentHtml,
|
||||
|
@ -5,6 +5,6 @@ const generate = require('nanoid/generate');
|
||||
// > On the other hand, 128 bits (between 21 and 22 characters
|
||||
// > alphanumeric) is beyond the reach of brute-force attacks pretty much
|
||||
// > indefinitely
|
||||
export default function uuidgen(length: number = 32): string {
|
||||
export default function uuidgen(length: number = 22): string {
|
||||
return generate('0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz', length);
|
||||
}
|
||||
|
@ -10,23 +10,27 @@
|
||||
{{#global.owner}}
|
||||
<div class="navbar-menu is-active">
|
||||
<div class="navbar-start">
|
||||
<a class="navbar-item" href="{{{global.baseUrl}}}/home">Home</a>
|
||||
<a class="navbar-item" href="{{{global.baseUrl}}}/home">{{s.home}}</a>
|
||||
{{#global.owner.is_admin}}
|
||||
<a class="navbar-item" href="{{{global.baseUrl}}}/users">Users</a>
|
||||
<a class="navbar-item" href="{{{global.baseUrl}}}/users">{{s.users}}</a>
|
||||
{{/global.owner.is_admin}}
|
||||
<a class="navbar-item" href="{{{global.baseUrl}}}/items">Items</a>
|
||||
<a class="navbar-item" href="{{{global.baseUrl}}}/changes">Log</a>
|
||||
{{#global.owner.is_admin}}
|
||||
<a class="navbar-item" href="{{{global.baseUrl}}}/tasks">Tasks</a>
|
||||
<a class="navbar-item" href="{{{global.baseUrl}}}/items">{{s.items}}</a>
|
||||
{{/global.owner.is_admin}}
|
||||
{{#global.owner.is_admin}}
|
||||
<a class="navbar-item" href="{{{global.baseUrl}}}/changes">{{s.log}}</a>
|
||||
{{/global.owner.is_admin}}
|
||||
{{#global.owner.is_admin}}
|
||||
<a class="navbar-item" href="{{{global.baseUrl}}}/tasks">{{s.tasks}}</a>
|
||||
{{/global.owner.is_admin}}
|
||||
</div>
|
||||
<div class="navbar-end">
|
||||
{{#global.isJoplinCloud}}
|
||||
<a class="navbar-item" href="{{{global.baseUrl}}}/help">Help</a>
|
||||
<a class="navbar-item" href="{{{global.baseUrl}}}/help">{{s.help}}</a>
|
||||
{{/global.isJoplinCloud}}
|
||||
<div class="navbar-item">
|
||||
<form method="post" action="{{{global.baseUrl}}}/logout">
|
||||
<button class="button is-dark">Logout</button>
|
||||
<button class="button is-dark">{{s.logout}}</button>
|
||||
</form>
|
||||
</div>
|
||||
<div class="navbar-item">
|
||||
|
Loading…
Reference in New Issue
Block a user