mirror of https://github.com/Requarks/wiki.git
10 changed files with 438 additions and 47 deletions
Unified View
Diff Options
-
4CHANGELOG.md
-
1dev/docker-sqlite/Dockerfile
-
12server/core/kernel.js
-
317server/db/migrations-sqlite/2.0.0-beta.1.js
-
51server/db/migrations-sqlite/2.0.0-beta.11.js
-
15server/db/migrations-sqlite/2.0.0-beta.38.js
-
9server/db/migrator-source.js
-
1server/models/pages.js
-
38server/modules/authentication/local/authentication.js
-
37wiki.js
@ -0,0 +1,317 @@ |
|||||
|
exports.up = knex => { |
||||
|
const dbCompat = { |
||||
|
charset: (WIKI.config.db.type === `mysql` || WIKI.config.db.type === `mariadb`), |
||||
|
noForeign: WIKI.config.db.type === 'sqlite' |
||||
|
} |
||||
|
return knex.schema |
||||
|
// =====================================
|
||||
|
// MODEL TABLES
|
||||
|
// =====================================
|
||||
|
// ASSETS ------------------------------
|
||||
|
.createTable('assets', table => { |
||||
|
if (dbCompat.charset) { table.charset('utf8mb4') } |
||||
|
table.increments('id').primary() |
||||
|
table.string('filename').notNullable() |
||||
|
table.string('basename').notNullable() |
||||
|
table.string('ext').notNullable() |
||||
|
table.enum('kind', ['binary', 'image']).notNullable().defaultTo('binary') |
||||
|
table.string('mime').notNullable().defaultTo('application/octet-stream') |
||||
|
table.integer('fileSize').unsigned().comment('In kilobytes') |
||||
|
table.json('metadata') |
||||
|
table.string('createdAt').notNullable() |
||||
|
table.string('updatedAt').notNullable() |
||||
|
|
||||
|
table.integer('folderId').unsigned().references('id').inTable('assetFolders') |
||||
|
table.integer('authorId').unsigned().references('id').inTable('users') |
||||
|
}) |
||||
|
// ASSET FOLDERS -----------------------
|
||||
|
.createTable('assetFolders', table => { |
||||
|
if (dbCompat.charset) { table.charset('utf8mb4') } |
||||
|
table.increments('id').primary() |
||||
|
table.string('name').notNullable() |
||||
|
table.string('slug').notNullable() |
||||
|
table.integer('parentId').unsigned().references('id').inTable('assetFolders') |
||||
|
}) |
||||
|
// AUTHENTICATION ----------------------
|
||||
|
.createTable('authentication', table => { |
||||
|
if (dbCompat.charset) { table.charset('utf8mb4') } |
||||
|
table.string('key').notNullable().primary() |
||||
|
table.boolean('isEnabled').notNullable().defaultTo(false) |
||||
|
table.json('config').notNullable() |
||||
|
table.boolean('selfRegistration').notNullable().defaultTo(false) |
||||
|
table.json('domainWhitelist').notNullable() |
||||
|
table.json('autoEnrollGroups').notNullable() |
||||
|
}) |
||||
|
// COMMENTS ----------------------------
|
||||
|
.createTable('comments', table => { |
||||
|
if (dbCompat.charset) { table.charset('utf8mb4') } |
||||
|
table.increments('id').primary() |
||||
|
table.text('content').notNullable() |
||||
|
table.string('createdAt').notNullable() |
||||
|
table.string('updatedAt').notNullable() |
||||
|
|
||||
|
table.integer('pageId').unsigned().references('id').inTable('pages') |
||||
|
table.integer('authorId').unsigned().references('id').inTable('users') |
||||
|
}) |
||||
|
// EDITORS -----------------------------
|
||||
|
.createTable('editors', table => { |
||||
|
if (dbCompat.charset) { table.charset('utf8mb4') } |
||||
|
table.string('key').notNullable().primary() |
||||
|
table.boolean('isEnabled').notNullable().defaultTo(false) |
||||
|
table.json('config').notNullable() |
||||
|
}) |
||||
|
// GROUPS ------------------------------
|
||||
|
.createTable('groups', table => { |
||||
|
if (dbCompat.charset) { table.charset('utf8mb4') } |
||||
|
table.increments('id').primary() |
||||
|
table.string('name').notNullable() |
||||
|
table.json('permissions').notNullable() |
||||
|
table.json('pageRules').notNullable() |
||||
|
table.boolean('isSystem').notNullable().defaultTo(false) |
||||
|
table.string('createdAt').notNullable() |
||||
|
table.string('updatedAt').notNullable() |
||||
|
}) |
||||
|
// LOCALES -----------------------------
|
||||
|
.createTable('locales', table => { |
||||
|
if (dbCompat.charset) { table.charset('utf8mb4') } |
||||
|
table.string('code', 2).notNullable().primary() |
||||
|
table.json('strings') |
||||
|
table.boolean('isRTL').notNullable().defaultTo(false) |
||||
|
table.string('name').notNullable() |
||||
|
table.string('nativeName').notNullable() |
||||
|
table.string('createdAt').notNullable() |
||||
|
table.string('updatedAt').notNullable() |
||||
|
}) |
||||
|
// LOGGING ----------------------------
|
||||
|
.createTable('loggers', table => { |
||||
|
if (dbCompat.charset) { table.charset('utf8mb4') } |
||||
|
table.string('key').notNullable().primary() |
||||
|
table.boolean('isEnabled').notNullable().defaultTo(false) |
||||
|
table.string('level').notNullable().defaultTo('warn') |
||||
|
table.json('config') |
||||
|
}) |
||||
|
// NAVIGATION ----------------------------
|
||||
|
.createTable('navigation', table => { |
||||
|
if (dbCompat.charset) { table.charset('utf8mb4') } |
||||
|
table.string('key').notNullable().primary() |
||||
|
table.json('config') |
||||
|
}) |
||||
|
// PAGE HISTORY ------------------------
|
||||
|
.createTable('pageHistory', table => { |
||||
|
if (dbCompat.charset) { table.charset('utf8mb4') } |
||||
|
table.increments('id').primary() |
||||
|
table.string('path').notNullable() |
||||
|
table.string('hash').notNullable() |
||||
|
table.string('title').notNullable() |
||||
|
table.string('description') |
||||
|
table.boolean('isPrivate').notNullable().defaultTo(false) |
||||
|
table.boolean('isPublished').notNullable().defaultTo(false) |
||||
|
table.string('publishStartDate') |
||||
|
table.string('publishEndDate') |
||||
|
table.text('content') |
||||
|
table.string('contentType').notNullable() |
||||
|
table.string('createdAt').notNullable() |
||||
|
|
||||
|
table.integer('pageId').unsigned().references('id').inTable('pages') |
||||
|
table.string('editorKey').references('key').inTable('editors') |
||||
|
table.string('localeCode', 2).references('code').inTable('locales') |
||||
|
table.integer('authorId').unsigned().references('id').inTable('users') |
||||
|
}) |
||||
|
// PAGES -------------------------------
|
||||
|
.createTable('pages', table => { |
||||
|
if (dbCompat.charset) { table.charset('utf8mb4') } |
||||
|
table.increments('id').primary() |
||||
|
table.string('path').notNullable() |
||||
|
table.string('hash').notNullable() |
||||
|
table.string('title').notNullable() |
||||
|
table.string('description') |
||||
|
table.boolean('isPrivate').notNullable().defaultTo(false) |
||||
|
table.boolean('isPublished').notNullable().defaultTo(false) |
||||
|
table.string('privateNS') |
||||
|
table.string('publishStartDate') |
||||
|
table.string('publishEndDate') |
||||
|
table.text('content') |
||||
|
table.text('render') |
||||
|
table.json('toc') |
||||
|
table.string('contentType').notNullable() |
||||
|
table.string('createdAt').notNullable() |
||||
|
table.string('updatedAt').notNullable() |
||||
|
|
||||
|
table.string('editorKey').references('key').inTable('editors') |
||||
|
table.string('localeCode', 2).references('code').inTable('locales') |
||||
|
table.integer('authorId').unsigned().references('id').inTable('users') |
||||
|
table.integer('creatorId').unsigned().references('id').inTable('users') |
||||
|
}) |
||||
|
// PAGE TREE ---------------------------
|
||||
|
.createTable('pageTree', table => { |
||||
|
if (dbCompat.charset) { table.charset('utf8mb4') } |
||||
|
table.increments('id').primary() |
||||
|
table.string('path').notNullable() |
||||
|
table.integer('depth').unsigned().notNullable() |
||||
|
table.string('title').notNullable() |
||||
|
table.boolean('isPrivate').notNullable().defaultTo(false) |
||||
|
table.boolean('isFolder').notNullable().defaultTo(false) |
||||
|
table.string('privateNS') |
||||
|
|
||||
|
table.integer('parent').unsigned().references('id').inTable('pageTree') |
||||
|
table.integer('pageId').unsigned().references('id').inTable('pages') |
||||
|
table.string('localeCode', 2).references('code').inTable('locales') |
||||
|
}) |
||||
|
// RENDERERS ---------------------------
|
||||
|
.createTable('renderers', table => { |
||||
|
if (dbCompat.charset) { table.charset('utf8mb4') } |
||||
|
table.string('key').notNullable().primary() |
||||
|
table.boolean('isEnabled').notNullable().defaultTo(false) |
||||
|
table.json('config') |
||||
|
}) |
||||
|
// SEARCH ------------------------------
|
||||
|
.createTable('searchEngines', table => { |
||||
|
if (dbCompat.charset) { table.charset('utf8mb4') } |
||||
|
table.string('key').notNullable().primary() |
||||
|
table.boolean('isEnabled').notNullable().defaultTo(false) |
||||
|
table.json('config') |
||||
|
}) |
||||
|
// SETTINGS ----------------------------
|
||||
|
.createTable('settings', table => { |
||||
|
if (dbCompat.charset) { table.charset('utf8mb4') } |
||||
|
table.string('key').notNullable().primary() |
||||
|
table.json('value') |
||||
|
table.string('updatedAt').notNullable() |
||||
|
}) |
||||
|
// STORAGE -----------------------------
|
||||
|
.createTable('storage', table => { |
||||
|
if (dbCompat.charset) { table.charset('utf8mb4') } |
||||
|
table.string('key').notNullable().primary() |
||||
|
table.boolean('isEnabled').notNullable().defaultTo(false) |
||||
|
table.string('mode', ['sync', 'push', 'pull']).notNullable().defaultTo('push') |
||||
|
table.json('config') |
||||
|
}) |
||||
|
// TAGS --------------------------------
|
||||
|
.createTable('tags', table => { |
||||
|
if (dbCompat.charset) { table.charset('utf8mb4') } |
||||
|
table.increments('id').primary() |
||||
|
table.string('tag').notNullable().unique() |
||||
|
table.string('title') |
||||
|
table.string('createdAt').notNullable() |
||||
|
table.string('updatedAt').notNullable() |
||||
|
}) |
||||
|
// USER KEYS ---------------------------
|
||||
|
.createTable('userKeys', table => { |
||||
|
if (dbCompat.charset) { table.charset('utf8mb4') } |
||||
|
table.increments('id').primary() |
||||
|
table.string('kind').notNullable() |
||||
|
table.string('token').notNullable() |
||||
|
table.string('createdAt').notNullable() |
||||
|
table.string('validUntil').notNullable() |
||||
|
|
||||
|
table.integer('userId').unsigned().references('id').inTable('users') |
||||
|
}) |
||||
|
// USERS -------------------------------
|
||||
|
.createTable('users', table => { |
||||
|
if (dbCompat.charset) { table.charset('utf8mb4') } |
||||
|
table.increments('id').primary() |
||||
|
table.string('email').notNullable() |
||||
|
table.string('name').notNullable() |
||||
|
table.string('providerId') |
||||
|
table.string('password') |
||||
|
table.boolean('tfaIsActive').notNullable().defaultTo(false) |
||||
|
table.string('tfaSecret') |
||||
|
table.string('jobTitle').defaultTo('') |
||||
|
table.string('location').defaultTo('') |
||||
|
table.string('pictureUrl') |
||||
|
table.string('timezone').notNullable().defaultTo('America/New_York') |
||||
|
table.boolean('isSystem').notNullable().defaultTo(false) |
||||
|
table.boolean('isActive').notNullable().defaultTo(false) |
||||
|
table.boolean('isVerified').notNullable().defaultTo(false) |
||||
|
table.string('createdAt').notNullable() |
||||
|
table.string('updatedAt').notNullable() |
||||
|
|
||||
|
table.string('providerKey').references('key').inTable('authentication').notNullable().defaultTo('local') |
||||
|
table.string('localeCode', 2).references('code').inTable('locales').notNullable().defaultTo('en') |
||||
|
table.string('defaultEditor').references('key').inTable('editors').notNullable().defaultTo('markdown') |
||||
|
}) |
||||
|
// =====================================
|
||||
|
// RELATION TABLES
|
||||
|
// =====================================
|
||||
|
// PAGE HISTORY TAGS ---------------------------
|
||||
|
.createTable('pageHistoryTags', table => { |
||||
|
if (dbCompat.charset) { table.charset('utf8mb4') } |
||||
|
table.increments('id').primary() |
||||
|
table.integer('pageId').unsigned().references('id').inTable('pageHistory').onDelete('CASCADE') |
||||
|
table.integer('tagId').unsigned().references('id').inTable('tags').onDelete('CASCADE') |
||||
|
}) |
||||
|
// PAGE TAGS ---------------------------
|
||||
|
.createTable('pageTags', table => { |
||||
|
if (dbCompat.charset) { table.charset('utf8mb4') } |
||||
|
table.increments('id').primary() |
||||
|
table.integer('pageId').unsigned().references('id').inTable('pages').onDelete('CASCADE') |
||||
|
table.integer('tagId').unsigned().references('id').inTable('tags').onDelete('CASCADE') |
||||
|
}) |
||||
|
// USER GROUPS -------------------------
|
||||
|
.createTable('userGroups', table => { |
||||
|
if (dbCompat.charset) { table.charset('utf8mb4') } |
||||
|
table.increments('id').primary() |
||||
|
table.integer('userId').unsigned().references('id').inTable('users').onDelete('CASCADE') |
||||
|
table.integer('groupId').unsigned().references('id').inTable('groups').onDelete('CASCADE') |
||||
|
}) |
||||
|
// =====================================
|
||||
|
// REFERENCES
|
||||
|
// =====================================
|
||||
|
// .table('assets', table => {
|
||||
|
// dbCompat.noForeign ? table.integer('folderId').unsigned() : table.integer('folderId').unsigned().references('id').inTable('assetFolders')
|
||||
|
// dbCompat.noForeign ? table.integer('authorId').unsigned() : table.integer('authorId').unsigned().references('id').inTable('users')
|
||||
|
// })
|
||||
|
// .table('comments', table => {
|
||||
|
// dbCompat.noForeign ? table.integer('pageId').unsigned() : table.integer('pageId').unsigned().references('id').inTable('pages')
|
||||
|
// dbCompat.noForeign ? table.integer('authorId').unsigned() : table.integer('authorId').unsigned().references('id').inTable('users')
|
||||
|
// })
|
||||
|
// .table('pageHistory', table => {
|
||||
|
// dbCompat.noForeign ? table.integer('pageId').unsigned() : table.integer('pageId').unsigned().references('id').inTable('pages')
|
||||
|
// dbCompat.noForeign ? table.string('editorKey') : table.string('editorKey').references('key').inTable('editors')
|
||||
|
// dbCompat.noForeign ? table.string('localeCode', 2) : table.string('localeCode', 2).references('code').inTable('locales')
|
||||
|
// dbCompat.noForeign ? table.integer('authorId').unsigned() : table.integer('authorId').unsigned().references('id').inTable('users')
|
||||
|
// })
|
||||
|
// .table('pages', table => {
|
||||
|
// dbCompat.noForeign ? table.string('editorKey') : table.string('editorKey').references('key').inTable('editors')
|
||||
|
// dbCompat.noForeign ? table.string('localeCode', 2) : table.string('localeCode', 2).references('code').inTable('locales')
|
||||
|
// dbCompat.noForeign ? table.integer('authorId').unsigned() : table.integer('authorId').unsigned().references('id').inTable('users')
|
||||
|
// dbCompat.noForeign ? table.integer('creatorId').unsigned() : table.integer('creatorId').unsigned().references('id').inTable('users')
|
||||
|
// })
|
||||
|
// .table('pageTree', table => {
|
||||
|
// dbCompat.noForeign ? table.integer('parent').unsigned() : table.integer('parent').unsigned().references('id').inTable('pageTree')
|
||||
|
// dbCompat.noForeign ? table.integer('pageId').unsigned() : table.integer('pageId').unsigned().references('id').inTable('pages')
|
||||
|
// dbCompat.noForeign ? table.string('localeCode', 2) : table.string('localeCode', 2).references('code').inTable('locales')
|
||||
|
// })
|
||||
|
// .table('userKeys', table => {
|
||||
|
// dbCompat.noForeign ? table.integer('userId').unsigned() : table.integer('userId').unsigned().references('id').inTable('users')
|
||||
|
// })
|
||||
|
.table('users', table => { |
||||
|
// dbCompat.noForeign ? table.string('providerKey') : table.string('providerKey').references('key').inTable('authentication').notNullable().defaultTo('local')
|
||||
|
// dbCompat.noForeign ? table.string('localeCode', 2) : table.string('localeCode', 2).references('code').inTable('locales').notNullable().defaultTo('en')
|
||||
|
// dbCompat.noForeign ? table.string('defaultEditor') : table.string('defaultEditor').references('key').inTable('editors').notNullable().defaultTo('markdown')
|
||||
|
|
||||
|
table.unique(['providerKey', 'email']) |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
exports.down = knex => { |
||||
|
return knex.schema |
||||
|
.dropTableIfExists('userGroups') |
||||
|
.dropTableIfExists('pageHistoryTags') |
||||
|
.dropTableIfExists('pageHistory') |
||||
|
.dropTableIfExists('pageTags') |
||||
|
.dropTableIfExists('assets') |
||||
|
.dropTableIfExists('assetFolders') |
||||
|
.dropTableIfExists('comments') |
||||
|
.dropTableIfExists('editors') |
||||
|
.dropTableIfExists('groups') |
||||
|
.dropTableIfExists('locales') |
||||
|
.dropTableIfExists('navigation') |
||||
|
.dropTableIfExists('pages') |
||||
|
.dropTableIfExists('renderers') |
||||
|
.dropTableIfExists('settings') |
||||
|
.dropTableIfExists('storage') |
||||
|
.dropTableIfExists('tags') |
||||
|
.dropTableIfExists('userKeys') |
||||
|
.dropTableIfExists('users') |
||||
|
} |
@ -0,0 +1,51 @@ |
|||||
|
exports.up = knex => { |
||||
|
return knex.schema |
||||
|
.renameTable('pageHistory', 'pageHistory_old') |
||||
|
.createTable('pageHistory', table => { |
||||
|
table.increments('id').primary() |
||||
|
table.string('path').notNullable() |
||||
|
table.string('hash').notNullable() |
||||
|
table.string('title').notNullable() |
||||
|
table.string('description') |
||||
|
table.boolean('isPrivate').notNullable().defaultTo(false) |
||||
|
table.boolean('isPublished').notNullable().defaultTo(false) |
||||
|
table.string('publishStartDate') |
||||
|
table.string('publishEndDate') |
||||
|
table.text('content') |
||||
|
table.string('contentType').notNullable() |
||||
|
table.string('createdAt').notNullable() |
||||
|
table.string('action').defaultTo('updated') |
||||
|
|
||||
|
table.string('editorKey').references('key').inTable('editors') |
||||
|
table.string('localeCode', 2).references('code').inTable('locales') |
||||
|
table.integer('authorId').unsigned().references('id').inTable('users') |
||||
|
}) |
||||
|
.raw(`INSERT INTO pageHistory SELECT id,path,hash,title,description,isPrivate,isPublished,publishStartDate,publishEndDate,content,contentType,createdAt,'updated' AS action,editorKey,localeCode,authorId FROM pageHistory_old;`) |
||||
|
.dropTable('pageHistory_old') |
||||
|
} |
||||
|
|
||||
|
exports.down = knex => { |
||||
|
return knex.schema |
||||
|
.renameTable('pageHistory', 'pageHistory_old') |
||||
|
.createTable('pageHistory', table => { |
||||
|
table.increments('id').primary() |
||||
|
table.string('path').notNullable() |
||||
|
table.string('hash').notNullable() |
||||
|
table.string('title').notNullable() |
||||
|
table.string('description') |
||||
|
table.boolean('isPrivate').notNullable().defaultTo(false) |
||||
|
table.boolean('isPublished').notNullable().defaultTo(false) |
||||
|
table.string('publishStartDate') |
||||
|
table.string('publishEndDate') |
||||
|
table.text('content') |
||||
|
table.string('contentType').notNullable() |
||||
|
table.string('createdAt').notNullable() |
||||
|
|
||||
|
table.integer('pageId').unsigned().references('id').inTable('pages') |
||||
|
table.string('editorKey').references('key').inTable('editors') |
||||
|
table.string('localeCode', 2).references('code').inTable('locales') |
||||
|
table.integer('authorId').unsigned().references('id').inTable('users') |
||||
|
}) |
||||
|
.raw('INSERT INTO pageHistory SELECT id,path,hash,title,description,isPrivate,isPublished,publishStartDate,publishEndDate,content,contentType,createdAt,NULL as pageId,editorKey,localeCode,authorId FROM pageHistory_old;') |
||||
|
.dropTable('pageHistory_old') |
||||
|
} |
@ -0,0 +1,15 @@ |
|||||
|
exports.up = knex => { |
||||
|
return knex.schema |
||||
|
.table('storage', table => { |
||||
|
table.string('syncInterval') |
||||
|
table.json('state') |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
exports.down = knex => { |
||||
|
return knex.schema |
||||
|
.table('storage', table => { |
||||
|
table.dropColumn('syncInterval') |
||||
|
table.dropColumn('state') |
||||
|
}) |
||||
|
} |
Write
Preview
Loading…
Cancel
Save