mirror of https://github.com/Requarks/wiki.git
27 changed files with 750 additions and 15 deletions
Split View
Diff Options
-
22server/core/db.js
-
115server/db/beta/index.js
-
0server/db/beta/migrations-sqlite/2.0.0-beta.1.js
-
0server/db/beta/migrations-sqlite/2.0.0-beta.11.js
-
0server/db/beta/migrations-sqlite/2.0.0-beta.127.js
-
0server/db/beta/migrations-sqlite/2.0.0-beta.205.js
-
0server/db/beta/migrations-sqlite/2.0.0-beta.217.js
-
0server/db/beta/migrations-sqlite/2.0.0-beta.242.js
-
0server/db/beta/migrations-sqlite/2.0.0-beta.293.js
-
0server/db/beta/migrations-sqlite/2.0.0-beta.38.js
-
0server/db/beta/migrations-sqlite/2.0.0-beta.99.js
-
0server/db/beta/migrations-sqlite/2.0.0-rc.2.js
-
10server/db/beta/migrations/2.0.0-beta.1.js
-
0server/db/beta/migrations/2.0.0-beta.11.js
-
0server/db/beta/migrations/2.0.0-beta.127.js
-
0server/db/beta/migrations/2.0.0-beta.148.js
-
0server/db/beta/migrations/2.0.0-beta.205.js
-
0server/db/beta/migrations/2.0.0-beta.217.js
-
0server/db/beta/migrations/2.0.0-beta.242.js
-
0server/db/beta/migrations/2.0.0-beta.293.js
-
0server/db/beta/migrations/2.0.0-beta.38.js
-
0server/db/beta/migrations/2.0.0-beta.99.js
-
3server/db/beta/migrations/2.0.0-rc.2.js
-
20server/db/beta/migrations/2.0.0-rc.29.js
-
268server/db/migrations-sqlite/2.0.0.js
-
325server/db/migrations/2.0.0.js
-
2server/models/pages.js
@ -0,0 +1,115 @@ |
|||
const _ = require('lodash') |
|||
const path = require('path') |
|||
const fs = require('fs-extra') |
|||
const semver = require('semver') |
|||
|
|||
/* global WIKI */ |
|||
|
|||
module.exports = { |
|||
async migrate (knex) { |
|||
const migrationsTableExists = await knex.schema.hasTable('migrations') |
|||
if (!migrationsTableExists) { |
|||
return |
|||
} |
|||
|
|||
const dbCompat = { |
|||
charset: (WIKI.config.db.type === `mysql` || WIKI.config.db.type === `mariadb`) |
|||
} |
|||
|
|||
const migrations = await knex('migrations') |
|||
if (_.some(migrations, m => m.name.indexOf('2.0.0-beta') >= 0)) { |
|||
// -> Pre-beta.241 locale field length fix
|
|||
const localeColnInfo = await knex('pages').columnInfo('localeCode') |
|||
if (WIKI.config.db.type !== 'sqlite' && localeColnInfo.maxLength === 2) { |
|||
// -> Load locales
|
|||
const locales = await knex('locales') |
|||
await knex.schema |
|||
// -> Remove constraints
|
|||
.table('users', table => { |
|||
table.dropForeign('localeCode') |
|||
}) |
|||
.table('pages', table => { |
|||
table.dropForeign('localeCode') |
|||
}) |
|||
.table('pageHistory', table => { |
|||
table.dropForeign('localeCode') |
|||
}) |
|||
.table('pageTree', table => { |
|||
table.dropForeign('localeCode') |
|||
}) |
|||
// -> Recreate locales table
|
|||
.dropTable('locales') |
|||
.createTable('locales', table => { |
|||
if (dbCompat.charset) { table.charset('utf8mb4') } |
|||
table.string('code', 5).notNullable().primary() |
|||
table.json('strings') |
|||
table.boolean('isRTL').notNullable().defaultTo(false) |
|||
table.string('name').notNullable() |
|||
table.string('nativeName').notNullable() |
|||
table.integer('availability').notNullable().defaultTo(0) |
|||
table.string('createdAt').notNullable() |
|||
table.string('updatedAt').notNullable() |
|||
}) |
|||
await knex('locales').insert(locales) |
|||
// -> Alter columns length
|
|||
await knex.schema |
|||
.table('users', table => { |
|||
table.string('localeCode', 5).notNullable().defaultTo('en').alter() |
|||
}) |
|||
.table('pages', table => { |
|||
table.string('localeCode', 5).alter() |
|||
}) |
|||
.table('pageHistory', table => { |
|||
table.string('localeCode', 5).alter() |
|||
}) |
|||
.table('pageTree', table => { |
|||
table.string('localeCode', 5).alter() |
|||
}) |
|||
// -> Restore restraints
|
|||
.table('users', table => { |
|||
table.foreign('localeCode').references('code').inTable('locales') |
|||
}) |
|||
.table('pages', table => { |
|||
table.foreign('localeCode').references('code').inTable('locales') |
|||
}) |
|||
.table('pageHistory', table => { |
|||
table.foreign('localeCode').references('code').inTable('locales') |
|||
}) |
|||
.table('pageTree', table => { |
|||
table.foreign('localeCode').references('code').inTable('locales') |
|||
}) |
|||
} |
|||
|
|||
// -> Advance to latest beta/rc migration state
|
|||
const baseMigrationPath = path.join(WIKI.SERVERPATH, (WIKI.config.db.type !== 'sqlite') ? 'db/beta/migrations' : 'db/beta/migrations-sqlite') |
|||
await knex.migrate.latest({ |
|||
tableName: 'migrations', |
|||
migrationSource: { |
|||
async getMigrations() { |
|||
const migrationFiles = await fs.readdir(baseMigrationPath) |
|||
return migrationFiles.sort(semver.compare).map(m => ({ |
|||
file: m, |
|||
directory: baseMigrationPath |
|||
})) |
|||
}, |
|||
getMigrationName(migration) { |
|||
return migration.file |
|||
}, |
|||
getMigration(migration) { |
|||
return require(path.join(baseMigrationPath, migration.file)) |
|||
} |
|||
} |
|||
}) |
|||
|
|||
// -> Cleanup migration table
|
|||
await knex('migrations').truncate() |
|||
|
|||
// -> Advance to stable 2.0 migration state
|
|||
await knex('migrations').insert({ |
|||
name: '2.0.0.js', |
|||
batch: 1, |
|||
migration_time: knex.fn.now() |
|||
}) |
|||
} |
|||
} |
|||
} |
@ -1,10 +1,11 @@ |
|||
/* global WIKI */ |
|||
|
|||
exports.up = knex => { |
|||
exports.up = async knex => { |
|||
const dbCompat = { |
|||
charset: (WIKI.config.db.type === `mysql` || WIKI.config.db.type === `mariadb`), |
|||
selfCascadeDelete: WIKI.config.db.type !== 'mssql' |
|||
} |
|||
|
|||
return knex.schema |
|||
.dropTable('pageTree') |
|||
.createTable('pageTree', table => { |
@ -0,0 +1,20 @@ |
|||
/* global WIKI */ |
|||
|
|||
exports.up = knex => { |
|||
return knex.schema |
|||
.table('pages', table => { |
|||
switch (WIKI.config.db.type) { |
|||
case 'mariadb': |
|||
case 'mysql': |
|||
table.specificType('content', 'LONGTEXT').alter() |
|||
table.specificType('render', 'LONGTEXT').alter() |
|||
break |
|||
case 'mssql': |
|||
table.specificType('content', 'VARCHAR(max)').alter() |
|||
table.specificType('render', 'VARCHAR(max)').alter() |
|||
break |
|||
} |
|||
}) |
|||
} |
|||
|
|||
exports.down = knex => { } |
@ -0,0 +1,268 @@ |
|||
exports.up = knex => { |
|||
return knex.schema |
|||
// =====================================
|
|||
// MODEL TABLES
|
|||
// =====================================
|
|||
// ANALYTICS ---------------------------
|
|||
.createTable('analytics', table => { |
|||
table.string('key').notNullable().primary() |
|||
table.boolean('isEnabled').notNullable().defaultTo(false) |
|||
table.json('config').notNullable() |
|||
}) |
|||
// ASSETS ------------------------------
|
|||
.createTable('assets', table => { |
|||
table.increments('id').primary() |
|||
table.string('filename').notNullable() |
|||
table.string('hash').notNullable().defaultTo('') |
|||
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 DATA --------------------------
|
|||
.createTable('assetData', table => { |
|||
table.integer('id').primary() |
|||
table.binary('data').notNullable() |
|||
}) |
|||
// ASSET FOLDERS -----------------------
|
|||
.createTable('assetFolders', table => { |
|||
table.increments('id').primary() |
|||
table.string('name').notNullable() |
|||
table.string('slug').notNullable() |
|||
table.integer('parentId').unsigned().references('id').inTable('assetFolders') |
|||
}) |
|||
// AUTHENTICATION ----------------------
|
|||
.createTable('authentication', table => { |
|||
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 => { |
|||
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 => { |
|||
table.string('key').notNullable().primary() |
|||
table.boolean('isEnabled').notNullable().defaultTo(false) |
|||
table.json('config').notNullable() |
|||
}) |
|||
// GROUPS ------------------------------
|
|||
.createTable('groups', table => { |
|||
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 => { |
|||
table.string('code', 5).notNullable().primary() |
|||
table.json('strings') |
|||
table.boolean('isRTL').notNullable().defaultTo(false) |
|||
table.string('name').notNullable() |
|||
table.string('nativeName').notNullable() |
|||
table.integer('availability').notNullable().defaultTo(0) |
|||
table.string('createdAt').notNullable() |
|||
table.string('updatedAt').notNullable() |
|||
}) |
|||
// LOGGING ----------------------------
|
|||
.createTable('loggers', table => { |
|||
table.string('key').notNullable().primary() |
|||
table.boolean('isEnabled').notNullable().defaultTo(false) |
|||
table.string('level').notNullable().defaultTo('warn') |
|||
table.json('config') |
|||
}) |
|||
// NAVIGATION ----------------------------
|
|||
.createTable('navigation', table => { |
|||
table.string('key').notNullable().primary() |
|||
table.json('config') |
|||
}) |
|||
// PAGE HISTORY ------------------------
|
|||
.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.integer('pageId').unsigned() |
|||
table.string('editorKey').references('key').inTable('editors') |
|||
table.string('localeCode', 5).references('code').inTable('locales') |
|||
table.integer('authorId').unsigned().references('id').inTable('users') |
|||
}) |
|||
// PAGE LINKS --------------------------
|
|||
.createTable('pageLinks', table => { |
|||
table.increments('id').primary() |
|||
table.integer('pageId').unsigned().references('id').inTable('pages').onDelete('CASCADE') |
|||
table.string('path').notNullable() |
|||
table.string('localeCode', 5).notNullable() |
|||
}) |
|||
// PAGES -------------------------------
|
|||
.createTable('pages', 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('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', 5).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 => { |
|||
table.integer('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').onDelete('CASCADE') |
|||
table.integer('pageId').unsigned().references('id').inTable('pages').onDelete('CASCADE') |
|||
table.string('localeCode', 5).references('code').inTable('locales') |
|||
}) |
|||
// RENDERERS ---------------------------
|
|||
.createTable('renderers', table => { |
|||
table.string('key').notNullable().primary() |
|||
table.boolean('isEnabled').notNullable().defaultTo(false) |
|||
table.json('config') |
|||
}) |
|||
// SEARCH ------------------------------
|
|||
.createTable('searchEngines', table => { |
|||
table.string('key').notNullable().primary() |
|||
table.boolean('isEnabled').notNullable().defaultTo(false) |
|||
table.json('config') |
|||
}) |
|||
// SETTINGS ----------------------------
|
|||
.createTable('settings', table => { |
|||
table.string('key').notNullable().primary() |
|||
table.json('value') |
|||
table.string('updatedAt').notNullable() |
|||
}) |
|||
// STORAGE -----------------------------
|
|||
.createTable('storage', table => { |
|||
table.string('key').notNullable().primary() |
|||
table.boolean('isEnabled').notNullable().defaultTo(false) |
|||
table.string('mode', ['sync', 'push', 'pull']).notNullable().defaultTo('push') |
|||
table.json('config') |
|||
table.string('syncInterval') |
|||
table.json('state') |
|||
}) |
|||
// TAGS --------------------------------
|
|||
.createTable('tags', table => { |
|||
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 => { |
|||
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 => { |
|||
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.boolean('mustChangePwd').notNullable().defaultTo(false) |
|||
table.string('createdAt').notNullable() |
|||
table.string('updatedAt').notNullable() |
|||
|
|||
table.string('providerKey').references('key').inTable('authentication').notNullable().defaultTo('local') |
|||
table.string('localeCode', 5).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 => { |
|||
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 => { |
|||
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 => { |
|||
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('users', table => { |
|||
table.unique(['providerKey', 'email']) |
|||
}) |
|||
// =====================================
|
|||
// INDEXES
|
|||
// =====================================
|
|||
.table('pageLinks', table => { |
|||
table.index(['path', 'localeCode']) |
|||
}) |
|||
} |
|||
|
|||
exports.down = knex => { } |
@ -0,0 +1,325 @@ |
|||
/* global WIKI */ |
|||
|
|||
exports.up = knex => { |
|||
const dbCompat = { |
|||
blobLength: (WIKI.config.db.type === `mysql` || WIKI.config.db.type === `mariadb`), |
|||
charset: (WIKI.config.db.type === `mysql` || WIKI.config.db.type === `mariadb`), |
|||
selfCascadeDelete: WIKI.config.db.type !== 'mssql' |
|||
} |
|||
return knex.schema |
|||
// =====================================
|
|||
// MODEL TABLES
|
|||
// =====================================
|
|||
// ANALYTICS ---------------------------
|
|||
.createTable('analytics', table => { |
|||
if (dbCompat.charset) { table.charset('utf8mb4') } |
|||
table.string('key').notNullable().primary() |
|||
table.boolean('isEnabled').notNullable().defaultTo(false) |
|||
table.json('config').notNullable() |
|||
}) |
|||
// ASSETS ------------------------------
|
|||
.createTable('assets', table => { |
|||
if (dbCompat.charset) { table.charset('utf8mb4') } |
|||
table.increments('id').primary() |
|||
table.string('filename').notNullable() |
|||
table.string('hash').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() |
|||
}) |
|||
// ASSET DATA --------------------------
|
|||
.createTable('assetData', table => { |
|||
if (dbCompat.charset) { table.charset('utf8mb4') } |
|||
table.integer('id').primary() |
|||
if (dbCompat.blobLength) { |
|||
table.specificType('data', 'LONGBLOB').notNullable() |
|||
} else { |
|||
table.binary('data').notNullable() |
|||
} |
|||
}) |
|||
// 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() |
|||
}) |
|||
// 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', 5).notNullable().primary() |
|||
table.json('strings') |
|||
table.boolean('isRTL').notNullable().defaultTo(false) |
|||
table.string('name').notNullable() |
|||
table.string('nativeName').notNullable() |
|||
table.integer('availability').notNullable().defaultTo(0) |
|||
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.string('action').defaultTo('updated') |
|||
table.integer('pageId').unsigned() |
|||
table.text('content') |
|||
table.string('contentType').notNullable() |
|||
table.string('createdAt').notNullable() |
|||
}) |
|||
// PAGE LINKS --------------------------
|
|||
.createTable('pageLinks', table => { |
|||
if (dbCompat.charset) { table.charset('utf8mb4') } |
|||
table.increments('id').primary() |
|||
table.string('path').notNullable() |
|||
table.string('localeCode', 5).notNullable() |
|||
}) |
|||
// 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') |
|||
switch (WIKI.config.db.type) { |
|||
case 'postgres': |
|||
case 'sqlite': |
|||
table.text('content') |
|||
table.text('render') |
|||
break |
|||
case 'mariadb': |
|||
case 'mysql': |
|||
table.specificType('content', 'LONGTEXT') |
|||
table.specificType('render', 'LONGTEXT') |
|||
break |
|||
case 'mssql': |
|||
table.specificType('content', 'VARCHAR(max)') |
|||
table.specificType('render', 'VARCHAR(max)') |
|||
break |
|||
} |
|||
table.json('toc') |
|||
table.string('contentType').notNullable() |
|||
table.string('createdAt').notNullable() |
|||
table.string('updatedAt').notNullable() |
|||
}) |
|||
// PAGE TREE ---------------------------
|
|||
.createTable('pageTree', table => { |
|||
if (dbCompat.charset) { table.charset('utf8mb4') } |
|||
table.integer('id').unsigned().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') |
|||
}) |
|||
// 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') |
|||
table.string('syncInterval') |
|||
table.json('state') |
|||
}) |
|||
// 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() |
|||
}) |
|||
// 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.boolean('mustChangePwd').notNullable().defaultTo(false) |
|||
table.string('createdAt').notNullable() |
|||
table.string('updatedAt').notNullable() |
|||
}) |
|||
// =====================================
|
|||
// 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 => { |
|||
table.integer('folderId').unsigned().references('id').inTable('assetFolders') |
|||
table.integer('authorId').unsigned().references('id').inTable('users') |
|||
}) |
|||
.table('comments', table => { |
|||
table.integer('pageId').unsigned().references('id').inTable('pages') |
|||
table.integer('authorId').unsigned().references('id').inTable('users') |
|||
}) |
|||
.table('pageHistory', table => { |
|||
table.string('editorKey').references('key').inTable('editors') |
|||
table.string('localeCode', 5).references('code').inTable('locales') |
|||
table.integer('authorId').unsigned().references('id').inTable('users') |
|||
}) |
|||
.table('pageLinks', table => { |
|||
table.integer('pageId').unsigned().references('id').inTable('pages').onDelete('CASCADE') |
|||
table.index(['path', 'localeCode']) |
|||
}) |
|||
.table('pages', table => { |
|||
table.string('editorKey').references('key').inTable('editors') |
|||
table.string('localeCode', 5).references('code').inTable('locales') |
|||
table.integer('authorId').unsigned().references('id').inTable('users') |
|||
table.integer('creatorId').unsigned().references('id').inTable('users') |
|||
}) |
|||
.table('pageTree', table => { |
|||
if (dbCompat.selfCascadeDelete) { |
|||
table.integer('parent').unsigned().references('id').inTable('pageTree').onDelete('CASCADE') |
|||
} else { |
|||
table.integer('parent').unsigned() |
|||
} |
|||
table.integer('pageId').unsigned().references('id').inTable('pages').onDelete('CASCADE') |
|||
table.string('localeCode', 5).references('code').inTable('locales') |
|||
}) |
|||
.table('userKeys', table => { |
|||
table.integer('userId').unsigned().references('id').inTable('users') |
|||
}) |
|||
.table('users', table => { |
|||
table.string('providerKey').references('key').inTable('authentication').notNullable().defaultTo('local') |
|||
table.string('localeCode', 5).references('code').inTable('locales').notNullable().defaultTo('en') |
|||
table.string('defaultEditor').references('key').inTable('editors').notNullable().defaultTo('markdown') |
|||
|
|||
table.unique(['providerKey', 'email']) |
|||
}) |
|||
} |
|||
|
|||
exports.down = knex => { } |
Write
Preview
Loading…
Cancel
Save