mirror of
https://github.com/laurent22/joplin.git
synced 2025-02-04 19:16:07 +02:00
Merge branch 'master' of github.com:laurent22/joplin
This commit is contained in:
commit
c19cc1b39a
@ -6,7 +6,7 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: Joplin-CLI 1.0.0\n"
|
"Project-Id-Version: Joplin-CLI 1.0.0\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"Last-Translator: yaozeye <yaozeye@outlook.com>\n"
|
"Last-Translator: WhiredPlanck <fungdaat31@outlook.com>\n"
|
||||||
"Language-Team: zh_CN <yaozeye@yaozeye.onmicrosoft.com>\n"
|
"Language-Team: zh_CN <yaozeye@yaozeye.onmicrosoft.com>\n"
|
||||||
"Language: zh_CN\n"
|
"Language: zh_CN\n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
@ -14,6 +14,8 @@ msgstr ""
|
|||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"X-Generator: Poedit 2.3.1\n"
|
"X-Generator: Poedit 2.3.1\n"
|
||||||
"Plural-Forms: nplurals=1; plural=0;\n"
|
"Plural-Forms: nplurals=1; plural=0;\n"
|
||||||
|
"POT-Creation-Date: \n"
|
||||||
|
"PO-Revision-Date: \n"
|
||||||
|
|
||||||
#: CliClient/app/command-cp.js:13
|
#: CliClient/app/command-cp.js:13
|
||||||
msgid ""
|
msgid ""
|
||||||
@ -2140,7 +2142,7 @@ msgstr "未知级别 ID: %s"
|
|||||||
|
|
||||||
#: ReactNativeClient/lib/SyncTargetAmazonS3.js:28
|
#: ReactNativeClient/lib/SyncTargetAmazonS3.js:28
|
||||||
msgid "AWS S3"
|
msgid "AWS S3"
|
||||||
msgstr ""
|
msgstr "AWS S3"
|
||||||
|
|
||||||
#: ReactNativeClient/lib/SyncTargetDropbox.js:25
|
#: ReactNativeClient/lib/SyncTargetDropbox.js:25
|
||||||
msgid "Dropbox"
|
msgid "Dropbox"
|
||||||
@ -2280,15 +2282,15 @@ msgstr "WebDAV 密码"
|
|||||||
|
|
||||||
#: ReactNativeClient/lib/models/Setting.js:189
|
#: ReactNativeClient/lib/models/Setting.js:189
|
||||||
msgid "AWS S3 bucket"
|
msgid "AWS S3 bucket"
|
||||||
msgstr ""
|
msgstr "AWS S3 存储桶"
|
||||||
|
|
||||||
#: ReactNativeClient/lib/models/Setting.js:200
|
#: ReactNativeClient/lib/models/Setting.js:200
|
||||||
msgid "AWS key"
|
msgid "AWS key"
|
||||||
msgstr ""
|
msgstr "AWS Access Key ID"
|
||||||
|
|
||||||
#: ReactNativeClient/lib/models/Setting.js:210
|
#: ReactNativeClient/lib/models/Setting.js:210
|
||||||
msgid "AWS secret"
|
msgid "AWS secret"
|
||||||
msgstr ""
|
msgstr "AWS Secret Access Key"
|
||||||
|
|
||||||
#: ReactNativeClient/lib/models/Setting.js:224
|
#: ReactNativeClient/lib/models/Setting.js:224
|
||||||
msgid "Attachment download behaviour"
|
msgid "Attachment download behaviour"
|
||||||
|
@ -157,6 +157,7 @@ class BaseModel {
|
|||||||
}
|
}
|
||||||
if (!('isNew' in options)) options.isNew = 'auto';
|
if (!('isNew' in options)) options.isNew = 'auto';
|
||||||
if (!('autoTimestamp' in options)) options.autoTimestamp = true;
|
if (!('autoTimestamp' in options)) options.autoTimestamp = true;
|
||||||
|
if (!('userSideValidation' in options)) options.userSideValidation = false;
|
||||||
return options;
|
return options;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -444,6 +445,17 @@ class BaseModel {
|
|||||||
return query;
|
return query;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static userSideValidation(o) {
|
||||||
|
if (('id' in o) && !o.id.match(/^[a-f0-9]{32}$/)) {
|
||||||
|
throw new Error('Validation error: ID must a 32-characters lowercase hexadecimal string');
|
||||||
|
}
|
||||||
|
|
||||||
|
const timestamps = ['user_updated_time', 'user_created_time'];
|
||||||
|
for (const k of timestamps) {
|
||||||
|
if ((k in o) && (typeof o[k] !== 'number' || isNaN(o[k]) || o[k] < 0)) throw new Error('Validation error: user_updated_time and user_created_time must be numbers greater than 0');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static async save(o, options = null) {
|
static async save(o, options = null) {
|
||||||
// When saving, there's a mutex per model ID. This is because the model returned from this function
|
// When saving, there's a mutex per model ID. This is because the model returned from this function
|
||||||
// is basically its input `o` (instead of being read from the database, for performance reasons).
|
// is basically its input `o` (instead of being read from the database, for performance reasons).
|
||||||
@ -471,6 +483,10 @@ class BaseModel {
|
|||||||
|
|
||||||
o = this.filter(o);
|
o = this.filter(o);
|
||||||
|
|
||||||
|
if (options.userSideValidation) {
|
||||||
|
this.userSideValidation(o);
|
||||||
|
}
|
||||||
|
|
||||||
let queries = [];
|
let queries = [];
|
||||||
const saveQuery = this.saveQuery(o, options);
|
const saveQuery = this.saveQuery(o, options);
|
||||||
const modelId = saveQuery.id;
|
const modelId = saveQuery.id;
|
||||||
@ -487,15 +503,10 @@ class BaseModel {
|
|||||||
await this.db().transactionExecBatch(queries);
|
await this.db().transactionExecBatch(queries);
|
||||||
|
|
||||||
o = Object.assign({}, o);
|
o = Object.assign({}, o);
|
||||||
// eslint-disable-next-line require-atomic-updates
|
|
||||||
if (modelId) o.id = modelId;
|
if (modelId) o.id = modelId;
|
||||||
// eslint-disable-next-line require-atomic-updates
|
|
||||||
if ('updated_time' in saveQuery.modObject) o.updated_time = saveQuery.modObject.updated_time;
|
if ('updated_time' in saveQuery.modObject) o.updated_time = saveQuery.modObject.updated_time;
|
||||||
// eslint-disable-next-line require-atomic-updates
|
|
||||||
if ('created_time' in saveQuery.modObject) o.created_time = saveQuery.modObject.created_time;
|
if ('created_time' in saveQuery.modObject) o.created_time = saveQuery.modObject.created_time;
|
||||||
// eslint-disable-next-line require-atomic-updates
|
|
||||||
if ('user_updated_time' in saveQuery.modObject) o.user_updated_time = saveQuery.modObject.user_updated_time;
|
if ('user_updated_time' in saveQuery.modObject) o.user_updated_time = saveQuery.modObject.user_updated_time;
|
||||||
// eslint-disable-next-line require-atomic-updates
|
|
||||||
if ('user_created_time' in saveQuery.modObject) o.user_created_time = saveQuery.modObject.user_created_time;
|
if ('user_created_time' in saveQuery.modObject) o.user_created_time = saveQuery.modObject.user_created_time;
|
||||||
o = this.addModelMd(o);
|
o = this.addModelMd(o);
|
||||||
|
|
||||||
|
@ -382,7 +382,7 @@ class Api {
|
|||||||
if (!request.files.length) throw new ErrorBadRequest('Resource cannot be created without a file');
|
if (!request.files.length) throw new ErrorBadRequest('Resource cannot be created without a file');
|
||||||
const filePath = request.files[0].path;
|
const filePath = request.files[0].path;
|
||||||
const defaultProps = request.bodyJson(this.readonlyProperties('POST'));
|
const defaultProps = request.bodyJson(this.readonlyProperties('POST'));
|
||||||
return shim.createResourceFromPath(filePath, defaultProps);
|
return shim.createResourceFromPath(filePath, defaultProps, { userSideValidation: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.defaultAction_(BaseModel.TYPE_RESOURCE, request, id, link);
|
return this.defaultAction_(BaseModel.TYPE_RESOURCE, request, id, link);
|
||||||
|
@ -145,6 +145,7 @@ function shimInit() {
|
|||||||
shim.createResourceFromPath = async function(filePath, defaultProps = null, options = null) {
|
shim.createResourceFromPath = async function(filePath, defaultProps = null, options = null) {
|
||||||
options = Object.assign({
|
options = Object.assign({
|
||||||
resizeLargeImages: 'always', // 'always', 'ask' or 'never'
|
resizeLargeImages: 'always', // 'always', 'ask' or 'never'
|
||||||
|
userSideValidation: false,
|
||||||
}, options);
|
}, options);
|
||||||
|
|
||||||
const readChunk = require('read-chunk');
|
const readChunk = require('read-chunk');
|
||||||
@ -159,7 +160,7 @@ function shimInit() {
|
|||||||
|
|
||||||
const resourceId = defaultProps.id ? defaultProps.id : uuid.create();
|
const resourceId = defaultProps.id ? defaultProps.id : uuid.create();
|
||||||
|
|
||||||
let resource = Resource.new();
|
const resource = Resource.new();
|
||||||
resource.id = resourceId;
|
resource.id = resourceId;
|
||||||
resource.mime = mimeUtils.fromFilename(filePath);
|
resource.mime = mimeUtils.fromFilename(filePath);
|
||||||
resource.title = basename(filePath);
|
resource.title = basename(filePath);
|
||||||
@ -186,15 +187,13 @@ function shimInit() {
|
|||||||
const ok = await handleResizeImage_(filePath, targetPath, resource.mime, options.resizeLargeImages);
|
const ok = await handleResizeImage_(filePath, targetPath, resource.mime, options.resizeLargeImages);
|
||||||
if (!ok) return null;
|
if (!ok) return null;
|
||||||
} else {
|
} else {
|
||||||
// const stat = await shim.fsDriver().stat(filePath);
|
|
||||||
// if (stat.size >= 10000000) throw new Error('Resources larger than 10 MB are not currently supported as they may crash the mobile applications. The issue is being investigated and will be fixed at a later time.');
|
|
||||||
|
|
||||||
await fs.copy(filePath, targetPath, { overwrite: true });
|
await fs.copy(filePath, targetPath, { overwrite: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (defaultProps) {
|
// While a whole object can be passed as defaultProps, we only just
|
||||||
resource = Object.assign({}, resource, defaultProps);
|
// support the title and ID (used above). Any other prop should be
|
||||||
}
|
// derived from the provided file.
|
||||||
|
if ('title' in defaultProps) resource.title = defaultProps.title;
|
||||||
|
|
||||||
const itDoes = await shim.fsDriver().waitTillExists(targetPath);
|
const itDoes = await shim.fsDriver().waitTillExists(targetPath);
|
||||||
if (!itDoes) throw new Error(`Resource file was not created: ${targetPath}`);
|
if (!itDoes) throw new Error(`Resource file was not created: ${targetPath}`);
|
||||||
@ -202,7 +201,9 @@ function shimInit() {
|
|||||||
const fileStat = await shim.fsDriver().stat(targetPath);
|
const fileStat = await shim.fsDriver().stat(targetPath);
|
||||||
resource.size = fileStat.size;
|
resource.size = fileStat.size;
|
||||||
|
|
||||||
return Resource.save(resource, { isNew: true });
|
const saveOptions = { isNew: true };
|
||||||
|
if (options.userSideValidation) saveOptions.userSideValidation = true;
|
||||||
|
return Resource.save(resource, saveOptions);
|
||||||
};
|
};
|
||||||
|
|
||||||
shim.attachFileToNoteBody = async function(noteBody, filePath, position = null, options = null) {
|
shim.attachFileToNoteBody = async function(noteBody, filePath, position = null, options = null) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user