From 820cc77a83f1f69011fb10a1ff4538f7bad907f5 Mon Sep 17 00:00:00 2001 From: NGPixel Date: Fri, 25 Oct 2019 23:02:33 -0400 Subject: [PATCH] fix: MSSQL - setup + pageTree + page delete --- server/db/migrations-sqlite/2.0.0-rc.2.js | 4 +-- server/db/migrations/2.0.0-rc.2.js | 44 +++++++++++++++++++---- server/jobs/rebuild-tree.js | 11 +----- server/models/pages.js | 6 ++-- server/setup.js | 24 ++++++------- 5 files changed, 53 insertions(+), 36 deletions(-) diff --git a/server/db/migrations-sqlite/2.0.0-rc.2.js b/server/db/migrations-sqlite/2.0.0-rc.2.js index b5df6e3f..4bfd5986 100644 --- a/server/db/migrations-sqlite/2.0.0-rc.2.js +++ b/server/db/migrations-sqlite/2.0.0-rc.2.js @@ -2,7 +2,7 @@ exports.up = knex => { return knex.schema .dropTable('pageTree') .createTable('pageTree', table => { - table.increments('id').primary() + table.integer('id').primary() table.string('path').notNullable() table.integer('depth').unsigned().notNullable() table.string('title').notNullable() @@ -20,7 +20,7 @@ exports.down = knex => { return knex.schema .dropTable('pageTree') .createTable('pageTree', table => { - table.increments('id').primary() + table.integer('id').primary() table.string('path').notNullable() table.integer('depth').unsigned().notNullable() table.string('title').notNullable() diff --git a/server/db/migrations/2.0.0-rc.2.js b/server/db/migrations/2.0.0-rc.2.js index 53e584b2..e2427ed9 100644 --- a/server/db/migrations/2.0.0-rc.2.js +++ b/server/db/migrations/2.0.0-rc.2.js @@ -1,23 +1,53 @@ +/* global WIKI */ + exports.up = knex => { + const dbCompat = { + charset: (WIKI.config.db.type === `mysql` || WIKI.config.db.type === `mariadb`), + selfCascadeDelete: WIKI.config.db.type !== 'mssql' + } return knex.schema - .table('pageTree', table => { - table.dropColumn('parent') - table.dropColumn('pageId') + .dropTable('pageTree') + .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') }) .table('pageTree', table => { - table.integer('parent').unsigned().references('id').inTable('pageTree').onDelete('CASCADE') + 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') }) } exports.down = knex => { + const dbCompat = { + charset: (WIKI.config.db.type === `mysql` || WIKI.config.db.type === `mariadb`), + selfCascadeDelete: WIKI.config.db.type !== 'mssql' + } return knex.schema - .table('pageTree', table => { - table.dropColumn('parent') - table.dropColumn('pageId') + .dropTable('pageTree') + .createTable('pageTree', table => { + if (dbCompat.charset) { table.charset('utf8mb4') } + 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('pageTree', table => { table.integer('parent').unsigned().references('id').inTable('pageTree') table.integer('pageId').unsigned().references('id').inTable('pages') + table.string('localeCode', 5).references('code').inTable('locales') }) } diff --git a/server/jobs/rebuild-tree.js b/server/jobs/rebuild-tree.js index 0ce0cb72..81e7ecf4 100644 --- a/server/jobs/rebuild-tree.js +++ b/server/jobs/rebuild-tree.js @@ -53,16 +53,7 @@ module.exports = async (pageId) => { await WIKI.models.knex.table('pageTree').truncate() if (tree.length > 0) { - const { bindings, sql } = WIKI.models.knex.table('pageTree').insert(tree).toSQL(); - if (WIKI.config.db.type === 'mssql') { - await WIKI.models.knex.raw(sql, bindings).wrap( - 'SET IDENTITY_INSERT pageTree ON;', - 'SET IDENTITY_INSERT pageTree OFF;', - ) - } else { - await WIKI.models.knex.raw(sql, bindings) - } - // await WIKI.models.knex.table('pageTree').insert(tree) + await WIKI.models.knex.table('pageTree').insert(tree) } await WIKI.models.knex.destroy() diff --git a/server/models/pages.js b/server/models/pages.js index 57800bde..24f0aa77 100644 --- a/server/models/pages.js +++ b/server/models/pages.js @@ -568,8 +568,8 @@ module.exports = class Page extends Model { } let affectedHashes = [] - // -> Perform replace and return affected page hashes (POSTGRES, MSSQL only) - if (WIKI.config.db.type === 'postgres' || WIKI.config.db.type === 'mssql') { + // -> Perform replace and return affected page hashes (POSTGRES only) + if (WIKI.config.db.type === 'postgres') { affectedHashes = await WIKI.models.pages.query() .returning('hash') .patch({ @@ -583,7 +583,7 @@ module.exports = class Page extends Model { }) .pluck('hash') } else { - // -> Perform replace, then query affected page hashes (MYSQL, MARIADB, SQLITE only) + // -> Perform replace, then query affected page hashes (MYSQL, MARIADB, MSSQL, SQLITE only) await WIKI.models.pages.query() .patch({ render: WIKI.models.knex.raw('REPLACE(??, ?, ?)', ['render', replaceArgs.from, replaceArgs.to]) diff --git a/server/setup.js b/server/setup.js index a7e561aa..2b254e86 100644 --- a/server/setup.js +++ b/server/setup.js @@ -9,7 +9,6 @@ const https = require('https') const Promise = require('bluebird') const fs = require('fs-extra') const _ = require('lodash') -const cfgHelper = require('./helpers/config') const crypto = Promise.promisifyAll(require('crypto')) const pem2jwk = require('pem-jwk').pem2jwk const semver = require('semver') @@ -203,14 +202,14 @@ module.exports = () => { WIKI.logger.info('Creating default groups...') const adminGroup = await WIKI.models.groups.query().insert({ - id: 1, + ...(WIKI.config.db.type !== `mssql` && { id: 1 }), name: 'Administrators', permissions: JSON.stringify(['manage:system']), pageRules: JSON.stringify([]), isSystem: true }) const guestGroup = await WIKI.models.groups.query().insert({ - id: 2, + ...(WIKI.config.db.type !== `mssql` && { id: 2 }), name: 'Guests', permissions: JSON.stringify(['read:pages', 'read:assets', 'read:comments']), pageRules: JSON.stringify([ @@ -218,6 +217,9 @@ module.exports = () => { ]), isSystem: true }) + if (adminGroup.id !== 1 || guestGroup.id !== 2) { + throw new Error('Incorrect groups auto-increment configuration! Should start at 0 and increment by 1. Contact your database administrator.') + } // Load authentication strategies + enable local await WIKI.models.authentication.refreshStrategiesFromDisk() @@ -244,12 +246,8 @@ module.exports = () => { // Create root administrator WIKI.logger.info('Creating root administrator...') - await WIKI.models.users.query().delete().where({ - providerKey: 'local', - email: req.body.adminEmail - }).orWhere('id', 1) const adminUser = await WIKI.models.users.query().insert({ - id: 1, + ...(WIKI.config.db.type !== `mssql` && { id: 1 }), email: req.body.adminEmail, provider: 'local', password: req.body.adminPassword, @@ -264,12 +262,8 @@ module.exports = () => { // Create Guest account WIKI.logger.info('Creating guest account...') - await WIKI.models.users.query().delete().where({ - providerKey: 'local', - email: 'guest@example.com' - }).orWhere('id', 2) const guestUser = await WIKI.models.users.query().insert({ - id: 2, + ...(WIKI.config.db.type !== `mssql` && { id: 2 }), provider: 'local', email: 'guest@example.com', name: 'Guest', @@ -282,11 +276,13 @@ module.exports = () => { isVerified: true }) await guestUser.$relatedQuery('groups').relate(guestGroup.id) + if (adminUser.id !== 1 || guestUser.id !== 2) { + throw new Error('Incorrect groups auto-increment configuration! Should start at 0 and increment by 1. Contact your database administrator.') + } // Create site nav WIKI.logger.info('Creating default site navigation') - await WIKI.models.navigation.query().delete().where({ key: 'site' }) await WIKI.models.navigation.query().insert({ key: 'site', config: [