refactor: knex remaining models
This commit is contained in:
		@@ -3,7 +3,7 @@
 | 
				
			|||||||
    nav-header
 | 
					    nav-header
 | 
				
			||||||
      template(slot='actions')
 | 
					      template(slot='actions')
 | 
				
			||||||
        v-btn(outline, color='green', @click.native.stop='save')
 | 
					        v-btn(outline, color='green', @click.native.stop='save')
 | 
				
			||||||
          v-icon(color='green', left) save
 | 
					          v-icon(color='green', left) check
 | 
				
			||||||
          span.white--text Save
 | 
					          span.white--text Save
 | 
				
			||||||
        v-btn(icon): v-icon(color='red') close
 | 
					        v-btn(icon): v-icon(color='red') close
 | 
				
			||||||
        v-btn(icon, @click.native.stop='openModal(`properties`)'): v-icon(color='white') sort_by_alpha
 | 
					        v-btn(icon, @click.native.stop='openModal(`properties`)'): v-icon(color='white') sort_by_alpha
 | 
				
			||||||
@@ -11,12 +11,12 @@
 | 
				
			|||||||
    v-content
 | 
					    v-content
 | 
				
			||||||
      editor-code
 | 
					      editor-code
 | 
				
			||||||
      component(:is='currentModal')
 | 
					      component(:is='currentModal')
 | 
				
			||||||
      v-dialog(v-model='dialogProgress', persistent, max-width='300')
 | 
					      v-dialog(v-model='dialogProgress', persistent, max-width='350')
 | 
				
			||||||
        v-card
 | 
					        v-card(color='blue darken-3', dark)
 | 
				
			||||||
          v-progress-linear.my-0(indeterminate, color='primary', height='5')
 | 
					          v-card-text.text-xs-center.py-4
 | 
				
			||||||
          v-card-text.text-xs-center
 | 
					            v-progress-circular(indeterminate, color='white', width='1')
 | 
				
			||||||
            .headline Saving
 | 
					            .subheading Processing
 | 
				
			||||||
            .caption Please wait...
 | 
					            .caption.blue--text.text--lighten-3 Please wait...
 | 
				
			||||||
</template>
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<script>
 | 
					<script>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,73 +1,70 @@
 | 
				
			|||||||
<template lang='pug'>
 | 
					<template lang='pug'>
 | 
				
			||||||
  .editor-code
 | 
					  .editor-code
 | 
				
			||||||
    .editor-code-toolbar
 | 
					    v-toolbar.editor-code-toolbar.px-3(dense, color='primary', dark)
 | 
				
			||||||
      .editor-code-toolbar-group
 | 
					      v-btn(icon).mx-0
 | 
				
			||||||
        .editor-code-toolbar-item(@click='toggleAround("**", "**")')
 | 
					        svg.icons.is-18(role='img')
 | 
				
			||||||
 | 
					          title Bold
 | 
				
			||||||
 | 
					          use(xlink:href='#fa-bold')
 | 
				
			||||||
 | 
					      v-btn(icon).mx-0
 | 
				
			||||||
 | 
					        svg.icons.is-18(role='img')
 | 
				
			||||||
 | 
					          title Italic
 | 
				
			||||||
 | 
					          use(xlink:href='#fa-italic')
 | 
				
			||||||
 | 
					      v-btn(icon).mx-0
 | 
				
			||||||
 | 
					        svg.icons.is-18(role='img')
 | 
				
			||||||
 | 
					          title Strikethrough
 | 
				
			||||||
 | 
					          use(xlink:href='#fa-strikethrough')
 | 
				
			||||||
 | 
					      v-menu(offset-y, open-on-hover)
 | 
				
			||||||
 | 
					        v-btn(icon, slot='activator').mx-0
 | 
				
			||||||
          svg.icons.is-18(role='img')
 | 
					          svg.icons.is-18(role='img')
 | 
				
			||||||
            title Bold
 | 
					            title Heading
 | 
				
			||||||
            use(xlink:href='#fa-bold')
 | 
					            use(xlink:href='#fa-heading')
 | 
				
			||||||
        .editor-code-toolbar-item
 | 
					        v-list
 | 
				
			||||||
          svg.icons.is-18(role='img')
 | 
					          v-list-tile(v-for='(n, idx) in 6', @click='', :key='idx')
 | 
				
			||||||
            title Italic
 | 
					            v-list-tile-action
 | 
				
			||||||
            use(xlink:href='#fa-italic')
 | 
					              svg.icons.is-18(role='img')
 | 
				
			||||||
        .editor-code-toolbar-item
 | 
					                title Heading {{n}}
 | 
				
			||||||
          svg.icons.is-18(role='img')
 | 
					                use(xlink:href='#fa-heading')
 | 
				
			||||||
            title Strikethrough
 | 
					            v-list-tile-title Heading {{n}}
 | 
				
			||||||
            use(xlink:href='#fa-strikethrough')
 | 
					      v-btn(icon).mx-0
 | 
				
			||||||
      .editor-code-toolbar-group
 | 
					        svg.icons.is-18(role='img')
 | 
				
			||||||
        v-menu(offset-y, open-on-hover)
 | 
					          title Blockquote
 | 
				
			||||||
          .editor-code-toolbar-item.is-dropdown(slot='activator')
 | 
					          use(xlink:href='#fa-quote-left')
 | 
				
			||||||
            svg.icons.is-18(role='img')
 | 
					      v-btn(icon).mx-0
 | 
				
			||||||
              title Heading
 | 
					        svg.icons.is-18(role='img')
 | 
				
			||||||
              use(xlink:href='#fa-heading')
 | 
					          title Unordered List
 | 
				
			||||||
          v-list
 | 
					          use(xlink:href='#fa-list-ul')
 | 
				
			||||||
            v-list-tile(v-for='(n, idx) in 6', @click='', :key='idx')
 | 
					      v-btn(icon).mx-0
 | 
				
			||||||
              v-list-tile-action: v-icon format_size
 | 
					        svg.icons.is-18(role='img')
 | 
				
			||||||
              v-list-tile-title Heading {{n}}
 | 
					          title Ordered List
 | 
				
			||||||
        .editor-code-toolbar-item
 | 
					          use(xlink:href='#fa-list-ol')
 | 
				
			||||||
          svg.icons.is-18(role='img')
 | 
					      v-btn(icon).mx-0
 | 
				
			||||||
            title Blockquote
 | 
					        svg.icons.is-18(role='img')
 | 
				
			||||||
            use(xlink:href='#fa-quote-left')
 | 
					          title Link
 | 
				
			||||||
      .editor-code-toolbar-group
 | 
					          use(xlink:href='#fa-link')
 | 
				
			||||||
        .editor-code-toolbar-item
 | 
					      v-btn(icon).mx-0
 | 
				
			||||||
          svg.icons.is-18(role='img')
 | 
					        svg.icons.is-18(role='img')
 | 
				
			||||||
            title Unordered List
 | 
					          title Inline Code
 | 
				
			||||||
            use(xlink:href='#fa-list-ul')
 | 
					          use(xlink:href='#fa-terminal')
 | 
				
			||||||
        .editor-code-toolbar-item
 | 
					      v-btn(icon).mx-0
 | 
				
			||||||
          svg.icons.is-18(role='img')
 | 
					        svg.icons.is-18(role='img')
 | 
				
			||||||
            title Ordered List
 | 
					          title Code Block
 | 
				
			||||||
            use(xlink:href='#fa-list-ol')
 | 
					          use(xlink:href='#fa-code')
 | 
				
			||||||
      .editor-code-toolbar-group
 | 
					      v-btn(icon).mx-0
 | 
				
			||||||
        .editor-code-toolbar-item
 | 
					        svg.icons.is-18(role='img')
 | 
				
			||||||
          svg.icons.is-18(role='img')
 | 
					          title Horizontal Bar
 | 
				
			||||||
            title Link
 | 
					          use(xlink:href='#fa-minus')
 | 
				
			||||||
            use(xlink:href='#fa-link')
 | 
					 | 
				
			||||||
      .editor-code-toolbar-group
 | 
					 | 
				
			||||||
        .editor-code-toolbar-item
 | 
					 | 
				
			||||||
          svg.icons.is-18(role='img')
 | 
					 | 
				
			||||||
            title Inline Code
 | 
					 | 
				
			||||||
            use(xlink:href='#fa-terminal')
 | 
					 | 
				
			||||||
        .editor-code-toolbar-item
 | 
					 | 
				
			||||||
          svg.icons.is-18(role='img')
 | 
					 | 
				
			||||||
            title Code Block
 | 
					 | 
				
			||||||
            use(xlink:href='#fa-code')
 | 
					 | 
				
			||||||
      .editor-code-toolbar-group
 | 
					 | 
				
			||||||
        .editor-code-toolbar-item
 | 
					 | 
				
			||||||
          svg.icons.is-18(role='img')
 | 
					 | 
				
			||||||
            title Horizontal Bar
 | 
					 | 
				
			||||||
            use(xlink:href='#fa-minus')
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    .editor-code-main
 | 
					    .editor-code-main
 | 
				
			||||||
      .editor-code-editor
 | 
					      .editor-code-editor
 | 
				
			||||||
        .editor-code-editor-title(v-if='previewShown', @click='previewShown = false') Editor
 | 
					        .editor-code-editor-title(v-if='previewShown', @click='previewShown = false') Editor
 | 
				
			||||||
        .editor-code-editor-title(v-else='previewShown', @click='previewShown = true'): v-icon(dark) search
 | 
					        .editor-code-editor-title(v-else='previewShown', @click='previewShown = true'): v-icon(dark) drag_indicator
 | 
				
			||||||
        codemirror(ref='cm', v-model='code', :options='cmOptions', @ready='onCmReady', @input='onCmInput')
 | 
					        codemirror(ref='cm', v-model='code', :options='cmOptions', @ready='onCmReady', @input='onCmInput')
 | 
				
			||||||
      transition(name='editor-code-preview')
 | 
					      transition(name='editor-code-preview')
 | 
				
			||||||
        .editor-code-preview(v-if='previewShown')
 | 
					        .editor-code-preview(v-if='previewShown')
 | 
				
			||||||
          .editor-code-preview-title(@click='previewShown = false') Preview
 | 
					          .editor-code-preview-title(@click='previewShown = false') Preview
 | 
				
			||||||
          .editor-code-preview-content.markdown-content(ref='editorPreview', v-html='previewHTML')
 | 
					          .editor-code-preview-content.markdown-content(ref='editorPreview', v-html='previewHTML')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      v-speed-dial(v-model='fabInsertMenu', :open-on-hover='true', direction='top', transition='slide-y-reverse-transition', fixed, right, bottom)
 | 
					      v-speed-dial(v-model='fabInsertMenu', :open-on-hover='true', direction='top', transition='slide-y-reverse-transition', fixed, left, bottom)
 | 
				
			||||||
        v-btn(color='blue', fab, dark, v-model='fabInsertMenu', slot='activator')
 | 
					        v-btn(color='blue', fab, dark, v-model='fabInsertMenu', slot='activator')
 | 
				
			||||||
          v-icon add_circle
 | 
					          v-icon add_circle
 | 
				
			||||||
          v-icon close
 | 
					          v-icon close
 | 
				
			||||||
@@ -276,7 +273,7 @@ export default {
 | 
				
			|||||||
    background-color: darken(mc('grey', '900'), 4.5%);
 | 
					    background-color: darken(mc('grey', '900'), 4.5%);
 | 
				
			||||||
    flex: 1 1 50%;
 | 
					    flex: 1 1 50%;
 | 
				
			||||||
    display: block;
 | 
					    display: block;
 | 
				
			||||||
    height: calc(100vh - 100px);
 | 
					    height: calc(100vh - 96px);
 | 
				
			||||||
    position: relative;
 | 
					    position: relative;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    &-title {
 | 
					    &-title {
 | 
				
			||||||
@@ -361,48 +358,12 @@ export default {
 | 
				
			|||||||
  &-toolbar {
 | 
					  &-toolbar {
 | 
				
			||||||
    background-color: mc('blue', '700');
 | 
					    background-color: mc('blue', '700');
 | 
				
			||||||
    background-image: linear-gradient(to bottom, mc('blue', '700') 0%, mc('blue','800') 100%);
 | 
					    background-image: linear-gradient(to bottom, mc('blue', '700') 0%, mc('blue','800') 100%);
 | 
				
			||||||
    height: 50px;
 | 
					 | 
				
			||||||
    color: #FFF;
 | 
					    color: #FFF;
 | 
				
			||||||
    display: flex;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @include until($tablet) {
 | 
					    @include until($tablet) {
 | 
				
			||||||
      justify-content: center;
 | 
					      justify-content: center;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    &-group {
 | 
					 | 
				
			||||||
      display: flex;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      + .editor-code-toolbar-group {
 | 
					 | 
				
			||||||
        border-left: 1px solid rgba(mc('blue', '600'), .5);
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    &-item {
 | 
					 | 
				
			||||||
      width: 40px;
 | 
					 | 
				
			||||||
      height: 50px;
 | 
					 | 
				
			||||||
      display: flex;
 | 
					 | 
				
			||||||
      justify-content: center;
 | 
					 | 
				
			||||||
      align-items: center;
 | 
					 | 
				
			||||||
      transition: all .4s ease;
 | 
					 | 
				
			||||||
      cursor: pointer;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      &:first-child {
 | 
					 | 
				
			||||||
        padding-left: .5rem;
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      &:last-child {
 | 
					 | 
				
			||||||
        padding-right: .5rem;
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      &:hover {
 | 
					 | 
				
			||||||
        background-color: mc('blue', '600');
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      @include until($tablet) {
 | 
					 | 
				
			||||||
        width: 35px;
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    svg {
 | 
					    svg {
 | 
				
			||||||
      use {
 | 
					      use {
 | 
				
			||||||
        color: #FFF;
 | 
					        color: #FFF;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -31,10 +31,7 @@
 | 
				
			|||||||
        v-subheader Assets
 | 
					        v-subheader Assets
 | 
				
			||||||
        v-list-tile(avatar, @click='')
 | 
					        v-list-tile(avatar, @click='')
 | 
				
			||||||
          v-list-tile-avatar: v-icon(color='blue-grey') burst_mode
 | 
					          v-list-tile-avatar: v-icon(color='blue-grey') burst_mode
 | 
				
			||||||
          v-list-tile-content Images
 | 
					          v-list-tile-content Images & Files
 | 
				
			||||||
        v-list-tile(avatar, @click='')
 | 
					 | 
				
			||||||
          v-list-tile-avatar: v-icon(color='blue-grey') description
 | 
					 | 
				
			||||||
          v-list-tile-content Files
 | 
					 | 
				
			||||||
    v-toolbar-title
 | 
					    v-toolbar-title
 | 
				
			||||||
      span.subheading Wiki.js
 | 
					      span.subheading Wiki.js
 | 
				
			||||||
    v-spacer
 | 
					    v-spacer
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,46 +1,85 @@
 | 
				
			|||||||
exports.up = knex => {
 | 
					exports.up = knex => {
 | 
				
			||||||
  return knex.schema
 | 
					  return knex.schema
 | 
				
			||||||
    // -------------------------------------
 | 
					    // =====================================
 | 
				
			||||||
    // GROUPS
 | 
					    // MODEL TABLES
 | 
				
			||||||
    // -------------------------------------
 | 
					    // =====================================
 | 
				
			||||||
 | 
					    // ASSETS ------------------------------
 | 
				
			||||||
 | 
					    .createTable('assets', table => {
 | 
				
			||||||
 | 
					      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.jsonb('metadata')
 | 
				
			||||||
 | 
					      table.string('createdAt').notNullable()
 | 
				
			||||||
 | 
					      table.string('updatedAt').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')
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
 | 
					    // COMMENTS ----------------------------
 | 
				
			||||||
 | 
					    .createTable('comments', table => {
 | 
				
			||||||
 | 
					      table.increments('id').primary()
 | 
				
			||||||
 | 
					      table.text('content').notNullable()
 | 
				
			||||||
 | 
					      table.string('createdAt').notNullable()
 | 
				
			||||||
 | 
					      table.string('updatedAt').notNullable()
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
 | 
					    // GROUPS ------------------------------
 | 
				
			||||||
    .createTable('groups', table => {
 | 
					    .createTable('groups', table => {
 | 
				
			||||||
      table.increments('id').primary()
 | 
					      table.increments('id').primary()
 | 
				
			||||||
 | 
					 | 
				
			||||||
      table.string('name').notNullable()
 | 
					      table.string('name').notNullable()
 | 
				
			||||||
      table.string('createdAt').notNullable()
 | 
					      table.string('createdAt').notNullable()
 | 
				
			||||||
      table.string('updatedAt').notNullable()
 | 
					      table.string('updatedAt').notNullable()
 | 
				
			||||||
    })
 | 
					    })
 | 
				
			||||||
    // -------------------------------------
 | 
					    // LOCALES -----------------------------
 | 
				
			||||||
    // LOCALES
 | 
					 | 
				
			||||||
    // -------------------------------------
 | 
					 | 
				
			||||||
    .createTable('locales', table => {
 | 
					    .createTable('locales', table => {
 | 
				
			||||||
      table.increments('id').primary()
 | 
					      table.increments('id').primary()
 | 
				
			||||||
 | 
					 | 
				
			||||||
      table.string('code', 2).notNullable().unique()
 | 
					      table.string('code', 2).notNullable().unique()
 | 
				
			||||||
      table.json('strings')
 | 
					      table.jsonb('strings')
 | 
				
			||||||
      table.boolean('isRTL').notNullable().defaultTo(false)
 | 
					      table.boolean('isRTL').notNullable().defaultTo(false)
 | 
				
			||||||
      table.string('name').notNullable()
 | 
					      table.string('name').notNullable()
 | 
				
			||||||
      table.string('nativeName').notNullable()
 | 
					      table.string('nativeName').notNullable()
 | 
				
			||||||
      table.string('createdAt').notNullable()
 | 
					      table.string('createdAt').notNullable()
 | 
				
			||||||
      table.string('updatedAt').notNullable()
 | 
					      table.string('updatedAt').notNullable()
 | 
				
			||||||
    })
 | 
					    })
 | 
				
			||||||
    // -------------------------------------
 | 
					    // PAGES -------------------------------
 | 
				
			||||||
    // SETTINGS
 | 
					    .createTable('pages', table => {
 | 
				
			||||||
    // -------------------------------------
 | 
					 | 
				
			||||||
    .createTable('settings', table => {
 | 
					 | 
				
			||||||
      table.increments('id').primary()
 | 
					      table.increments('id').primary()
 | 
				
			||||||
 | 
					      table.string('path').notNullable()
 | 
				
			||||||
      table.string('key').notNullable().unique()
 | 
					      table.string('title').notNullable()
 | 
				
			||||||
      table.json('value')
 | 
					      table.string('description')
 | 
				
			||||||
 | 
					      table.boolean('isPublished').notNullable().defaultTo(false)
 | 
				
			||||||
 | 
					      table.string('publishStartDate')
 | 
				
			||||||
 | 
					      table.string('publishEndDate')
 | 
				
			||||||
 | 
					      table.text('content')
 | 
				
			||||||
      table.string('createdAt').notNullable()
 | 
					      table.string('createdAt').notNullable()
 | 
				
			||||||
      table.string('updatedAt').notNullable()
 | 
					      table.string('updatedAt').notNullable()
 | 
				
			||||||
    })
 | 
					    })
 | 
				
			||||||
    // -------------------------------------
 | 
					    // SETTINGS ----------------------------
 | 
				
			||||||
    // USERS
 | 
					    .createTable('settings', table => {
 | 
				
			||||||
    // -------------------------------------
 | 
					      table.increments('id').primary()
 | 
				
			||||||
 | 
					      table.string('key').notNullable().unique()
 | 
				
			||||||
 | 
					      table.jsonb('value')
 | 
				
			||||||
 | 
					      table.string('createdAt').notNullable()
 | 
				
			||||||
 | 
					      table.string('updatedAt').notNullable()
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
 | 
					    // TAGS --------------------------------
 | 
				
			||||||
 | 
					    .createTable('tags', table => {
 | 
				
			||||||
 | 
					      table.increments('id').primary()
 | 
				
			||||||
 | 
					      table.string('tag').notNullable().unique()
 | 
				
			||||||
 | 
					      table.string('title')
 | 
				
			||||||
 | 
					      table.string('createdAt').notNullable()
 | 
				
			||||||
 | 
					      table.string('updatedAt').notNullable()
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
 | 
					    // USERS -------------------------------
 | 
				
			||||||
    .createTable('users', table => {
 | 
					    .createTable('users', table => {
 | 
				
			||||||
      table.increments('id').primary()
 | 
					      table.increments('id').primary()
 | 
				
			||||||
 | 
					 | 
				
			||||||
      table.string('email').notNullable()
 | 
					      table.string('email').notNullable()
 | 
				
			||||||
      table.string('name').notNullable()
 | 
					      table.string('name').notNullable()
 | 
				
			||||||
      table.string('provider').notNullable().defaultTo('local')
 | 
					      table.string('provider').notNullable().defaultTo('local')
 | 
				
			||||||
@@ -54,22 +93,52 @@ exports.up = knex => {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
      table.unique(['provider', 'email'])
 | 
					      table.unique(['provider', 'email'])
 | 
				
			||||||
    })
 | 
					    })
 | 
				
			||||||
    // -------------------------------------
 | 
					    // =====================================
 | 
				
			||||||
    // USER GROUPS
 | 
					    // RELATION TABLES
 | 
				
			||||||
    // -------------------------------------
 | 
					    // =====================================
 | 
				
			||||||
 | 
					    // PAGE TAGS ---------------------------
 | 
				
			||||||
 | 
					    .createTable('pageTags', table => {
 | 
				
			||||||
 | 
					      table.increments('id').primary()
 | 
				
			||||||
 | 
					      table.integer('pageId').unsigned().references('id').inTable('pages')
 | 
				
			||||||
 | 
					      table.integer('tagId').unsigned().references('id').inTable('tags')
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
 | 
					    // USER GROUPS -------------------------
 | 
				
			||||||
    .createTable('userGroups', table => {
 | 
					    .createTable('userGroups', table => {
 | 
				
			||||||
      table.increments('id').primary()
 | 
					      table.increments('id').primary()
 | 
				
			||||||
 | 
					 | 
				
			||||||
      table.integer('userId').unsigned().references('id').inTable('users')
 | 
					      table.integer('userId').unsigned().references('id').inTable('users')
 | 
				
			||||||
      table.integer('groupId').unsigned().references('id').inTable('groups')
 | 
					      table.integer('groupId').unsigned().references('id').inTable('groups')
 | 
				
			||||||
    })
 | 
					    })
 | 
				
			||||||
 | 
					    // =====================================
 | 
				
			||||||
 | 
					    // 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('pages', table => {
 | 
				
			||||||
 | 
					      table.string('locale', 2).references('code').inTable('locales')
 | 
				
			||||||
 | 
					      table.integer('authorId').unsigned().references('id').inTable('users')
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
 | 
					    .table('users', table => {
 | 
				
			||||||
 | 
					      table.string('locale', 2).references('code').inTable('locales')
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
exports.down = knex => {
 | 
					exports.down = knex => {
 | 
				
			||||||
  return knex.schema
 | 
					  return knex.schema
 | 
				
			||||||
    .dropTableIfExists('userGroups')
 | 
					    .dropTableIfExists('userGroups')
 | 
				
			||||||
 | 
					    .dropTableIfExists('pageTags')
 | 
				
			||||||
 | 
					    .dropTableIfExists('assets')
 | 
				
			||||||
 | 
					    .dropTableIfExists('assetFolders')
 | 
				
			||||||
 | 
					    .dropTableIfExists('comments')
 | 
				
			||||||
    .dropTableIfExists('groups')
 | 
					    .dropTableIfExists('groups')
 | 
				
			||||||
    .dropTableIfExists('locales')
 | 
					    .dropTableIfExists('locales')
 | 
				
			||||||
 | 
					    .dropTableIfExists('pages')
 | 
				
			||||||
    .dropTableIfExists('settings')
 | 
					    .dropTableIfExists('settings')
 | 
				
			||||||
 | 
					    .dropTableIfExists('tags')
 | 
				
			||||||
    .dropTableIfExists('users')
 | 
					    .dropTableIfExists('users')
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,7 +1,7 @@
 | 
				
			|||||||
const Model = require('objection').Model
 | 
					const Model = require('objection').Model
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Settings model
 | 
					 * Groups model
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
module.exports = class Group extends Model {
 | 
					module.exports = class Group extends Model {
 | 
				
			||||||
  static get tableName() { return 'groups' }
 | 
					  static get tableName() { return 'groups' }
 | 
				
			||||||
@@ -21,11 +21,10 @@ module.exports = class Group extends Model {
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  static get relationMappings() {
 | 
					  static get relationMappings() {
 | 
				
			||||||
    const User = require('./users')
 | 
					 | 
				
			||||||
    return {
 | 
					    return {
 | 
				
			||||||
      users: {
 | 
					      users: {
 | 
				
			||||||
        relation: Model.ManyToManyRelation,
 | 
					        relation: Model.ManyToManyRelation,
 | 
				
			||||||
        modelClass: User,
 | 
					        modelClass: require('./users'),
 | 
				
			||||||
        join: {
 | 
					        join: {
 | 
				
			||||||
          from: 'groups.id',
 | 
					          from: 'groups.id',
 | 
				
			||||||
          through: {
 | 
					          through: {
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										70
									
								
								server/db/models/pages.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										70
									
								
								server/db/models/pages.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,70 @@
 | 
				
			|||||||
 | 
					const Model = require('objection').Model
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Pages model
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					module.exports = class Page extends Model {
 | 
				
			||||||
 | 
					  static get tableName() { return 'pages' }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  static get jsonSchema () {
 | 
				
			||||||
 | 
					    return {
 | 
				
			||||||
 | 
					      type: 'object',
 | 
				
			||||||
 | 
					      required: ['path', 'title'],
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      properties: {
 | 
				
			||||||
 | 
					        id: {type: 'integer'},
 | 
				
			||||||
 | 
					        path: {type: 'string'},
 | 
				
			||||||
 | 
					        title: {type: 'string'},
 | 
				
			||||||
 | 
					        description: {type: 'string'},
 | 
				
			||||||
 | 
					        isPublished: {type: 'boolean'},
 | 
				
			||||||
 | 
					        publishStartDate: {type: 'string'},
 | 
				
			||||||
 | 
					        publishEndDate: {type: 'string'},
 | 
				
			||||||
 | 
					        content: {type: 'string'},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        createdAt: {type: 'string'},
 | 
				
			||||||
 | 
					        updatedAt: {type: 'string'}
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  static get relationMappings() {
 | 
				
			||||||
 | 
					    return {
 | 
				
			||||||
 | 
					      tags: {
 | 
				
			||||||
 | 
					        relation: Model.ManyToManyRelation,
 | 
				
			||||||
 | 
					        modelClass: require('./tags'),
 | 
				
			||||||
 | 
					        join: {
 | 
				
			||||||
 | 
					          from: 'pages.id',
 | 
				
			||||||
 | 
					          through: {
 | 
				
			||||||
 | 
					            from: 'pageTags.pageId',
 | 
				
			||||||
 | 
					            to: 'pageTags.tagId'
 | 
				
			||||||
 | 
					          },
 | 
				
			||||||
 | 
					          to: 'tags.id'
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      author: {
 | 
				
			||||||
 | 
					        relation: Model.BelongsToOneRelation,
 | 
				
			||||||
 | 
					        modelClass: require('./users'),
 | 
				
			||||||
 | 
					        join: {
 | 
				
			||||||
 | 
					          from: 'pages.authorId',
 | 
				
			||||||
 | 
					          to: 'users.id'
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      locale: {
 | 
				
			||||||
 | 
					        relation: Model.BelongsToOneRelation,
 | 
				
			||||||
 | 
					        modelClass: require('./locales'),
 | 
				
			||||||
 | 
					        join: {
 | 
				
			||||||
 | 
					          from: 'users.locale',
 | 
				
			||||||
 | 
					          to: 'locales.code'
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  $beforeUpdate() {
 | 
				
			||||||
 | 
					    this.updatedAt = new Date().toISOString()
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  $beforeInsert() {
 | 
				
			||||||
 | 
					    this.createdAt = new Date().toISOString()
 | 
				
			||||||
 | 
					    this.updatedAt = new Date().toISOString()
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										49
									
								
								server/db/models/tags.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								server/db/models/tags.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,49 @@
 | 
				
			|||||||
 | 
					const Model = require('objection').Model
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Tags model
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					module.exports = class Tag extends Model {
 | 
				
			||||||
 | 
					  static get tableName() { return 'tags' }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  static get jsonSchema () {
 | 
				
			||||||
 | 
					    return {
 | 
				
			||||||
 | 
					      type: 'object',
 | 
				
			||||||
 | 
					      required: ['tag'],
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      properties: {
 | 
				
			||||||
 | 
					        id: {type: 'integer'},
 | 
				
			||||||
 | 
					        tag: {type: 'string'},
 | 
				
			||||||
 | 
					        title: {type: 'string'},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        createdAt: {type: 'string'},
 | 
				
			||||||
 | 
					        updatedAt: {type: 'string'}
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  static get relationMappings() {
 | 
				
			||||||
 | 
					    return {
 | 
				
			||||||
 | 
					      pages: {
 | 
				
			||||||
 | 
					        relation: Model.ManyToManyRelation,
 | 
				
			||||||
 | 
					        modelClass: require('./pages'),
 | 
				
			||||||
 | 
					        join: {
 | 
				
			||||||
 | 
					          from: 'tags.id',
 | 
				
			||||||
 | 
					          through: {
 | 
				
			||||||
 | 
					            from: 'pageTags.tagId',
 | 
				
			||||||
 | 
					            to: 'pageTags.pageId'
 | 
				
			||||||
 | 
					          },
 | 
				
			||||||
 | 
					          to: 'pages.id'
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  $beforeUpdate() {
 | 
				
			||||||
 | 
					    this.updatedAt = new Date().toISOString()
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  $beforeInsert() {
 | 
				
			||||||
 | 
					    this.createdAt = new Date().toISOString()
 | 
				
			||||||
 | 
					    this.updatedAt = new Date().toISOString()
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -29,6 +29,7 @@ module.exports = class User extends Model {
 | 
				
			|||||||
        role: {type: 'string', enum: ['admin', 'guest', 'user']},
 | 
					        role: {type: 'string', enum: ['admin', 'guest', 'user']},
 | 
				
			||||||
        tfaIsActive: {type: 'boolean', default: false},
 | 
					        tfaIsActive: {type: 'boolean', default: false},
 | 
				
			||||||
        tfaSecret: {type: 'string'},
 | 
					        tfaSecret: {type: 'string'},
 | 
				
			||||||
 | 
					        locale: {type: 'string'},
 | 
				
			||||||
        createdAt: {type: 'string'},
 | 
					        createdAt: {type: 'string'},
 | 
				
			||||||
        updatedAt: {type: 'string'}
 | 
					        updatedAt: {type: 'string'}
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
@@ -36,11 +37,10 @@ module.exports = class User extends Model {
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  static get relationMappings() {
 | 
					  static get relationMappings() {
 | 
				
			||||||
    const Group = require('./groups')
 | 
					 | 
				
			||||||
    return {
 | 
					    return {
 | 
				
			||||||
      groups: {
 | 
					      groups: {
 | 
				
			||||||
        relation: Model.ManyToManyRelation,
 | 
					        relation: Model.ManyToManyRelation,
 | 
				
			||||||
        modelClass: Group,
 | 
					        modelClass: require('./groups'),
 | 
				
			||||||
        join: {
 | 
					        join: {
 | 
				
			||||||
          from: 'users.id',
 | 
					          from: 'users.id',
 | 
				
			||||||
          through: {
 | 
					          through: {
 | 
				
			||||||
@@ -79,7 +79,7 @@ module.exports = class User extends Model {
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  async verifyPassword(pwd) {
 | 
					  async verifyPassword(pwd) {
 | 
				
			||||||
    if (await bcrypt.compare(this.password, pwd) === true) {
 | 
					    if (await bcrypt.compare(pwd, this.password) === true) {
 | 
				
			||||||
      return true
 | 
					      return true
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
      throw new WIKI.Error.AuthLoginFailed()
 | 
					      throw new WIKI.Error.AuthLoginFailed()
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										51
									
								
								server/graph/resolvers/page.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								server/graph/resolvers/page.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,51 @@
 | 
				
			|||||||
 | 
					const graphHelper = require('../../helpers/graph')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* global WIKI */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					module.exports = {
 | 
				
			||||||
 | 
					  Query: {
 | 
				
			||||||
 | 
					    async pages() { return {} }
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  Mutation: {
 | 
				
			||||||
 | 
					    async pages() { return {} }
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  PageQuery: {
 | 
				
			||||||
 | 
					    async list(obj, args, context, info) {
 | 
				
			||||||
 | 
					      return WIKI.db.groups.query().select(
 | 
				
			||||||
 | 
					        'groups.*',
 | 
				
			||||||
 | 
					        WIKI.db.groups.relatedQuery('users').count().as('userCount')
 | 
				
			||||||
 | 
					      )
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    async single(obj, args, context, info) {
 | 
				
			||||||
 | 
					      return WIKI.db.groups.query().findById(args.id)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  PageMutation: {
 | 
				
			||||||
 | 
					    async create(obj, args) {
 | 
				
			||||||
 | 
					      const group = await WIKI.db.pages.query().insertAndFetch({
 | 
				
			||||||
 | 
					        name: args.name
 | 
				
			||||||
 | 
					      })
 | 
				
			||||||
 | 
					      return {
 | 
				
			||||||
 | 
					        responseResult: graphHelper.generateSuccess('Group created successfully.'),
 | 
				
			||||||
 | 
					        group
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    async delete(obj, args) {
 | 
				
			||||||
 | 
					      await WIKI.db.groups.query().deleteById(args.id)
 | 
				
			||||||
 | 
					      return {
 | 
				
			||||||
 | 
					        responseResult: graphHelper.generateSuccess('Group has been deleted.')
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    async update(obj, args) {
 | 
				
			||||||
 | 
					      await WIKI.db.groups.query().patch({ name: args.name }).where('id', args.id)
 | 
				
			||||||
 | 
					      return {
 | 
				
			||||||
 | 
					        responseResult: graphHelper.generateSuccess('Group has been updated.')
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  Page: {
 | 
				
			||||||
 | 
					    // comments(pg) {
 | 
				
			||||||
 | 
					    //   return pg.$relatedQuery('comments')
 | 
				
			||||||
 | 
					    // }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										78
									
								
								server/graph/schemas/page.graphql
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										78
									
								
								server/graph/schemas/page.graphql
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,78 @@
 | 
				
			|||||||
 | 
					# ===============================================
 | 
				
			||||||
 | 
					# PAGES
 | 
				
			||||||
 | 
					# ===============================================
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extend type Query {
 | 
				
			||||||
 | 
					  pages: PageQuery
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extend type Mutation {
 | 
				
			||||||
 | 
					  pages: PageMutation
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# -----------------------------------------------
 | 
				
			||||||
 | 
					# QUERIES
 | 
				
			||||||
 | 
					# -----------------------------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type PageQuery {
 | 
				
			||||||
 | 
					  list(
 | 
				
			||||||
 | 
					    filter: String
 | 
				
			||||||
 | 
					    orderBy: String
 | 
				
			||||||
 | 
					  ): [PageMinimal]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  single(
 | 
				
			||||||
 | 
					    id: Int!
 | 
				
			||||||
 | 
					  ): Page
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# -----------------------------------------------
 | 
				
			||||||
 | 
					# MUTATIONS
 | 
				
			||||||
 | 
					# -----------------------------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type PageMutation {
 | 
				
			||||||
 | 
					  create(
 | 
				
			||||||
 | 
					    description: String
 | 
				
			||||||
 | 
					    isPublished: Boolean
 | 
				
			||||||
 | 
					    locale: String
 | 
				
			||||||
 | 
					    path: String!
 | 
				
			||||||
 | 
					    publishEndDate: Date
 | 
				
			||||||
 | 
					    publishStartDate: Date
 | 
				
			||||||
 | 
					    tags: [String]
 | 
				
			||||||
 | 
					    title: String!
 | 
				
			||||||
 | 
					  ): PageResponse
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  update(
 | 
				
			||||||
 | 
					    id: Int!
 | 
				
			||||||
 | 
					    name: String!
 | 
				
			||||||
 | 
					  ): DefaultResponse
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  delete(
 | 
				
			||||||
 | 
					    id: Int!
 | 
				
			||||||
 | 
					  ): DefaultResponse
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# -----------------------------------------------
 | 
				
			||||||
 | 
					# TYPES
 | 
				
			||||||
 | 
					# -----------------------------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type PageResponse {
 | 
				
			||||||
 | 
					  responseResult: ResponseStatus!
 | 
				
			||||||
 | 
					  page: Page
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type PageMinimal {
 | 
				
			||||||
 | 
					  id: Int!
 | 
				
			||||||
 | 
					  name: String!
 | 
				
			||||||
 | 
					  userCount: Int
 | 
				
			||||||
 | 
					  createdAt: Date!
 | 
				
			||||||
 | 
					  updatedAt: Date!
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Page {
 | 
				
			||||||
 | 
					  id: Int!
 | 
				
			||||||
 | 
					  name: String!
 | 
				
			||||||
 | 
					  rights: [Right]
 | 
				
			||||||
 | 
					  users: [User]
 | 
				
			||||||
 | 
					  createdAt: Date!
 | 
				
			||||||
 | 
					  updatedAt: Date!
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -1,16 +0,0 @@
 | 
				
			|||||||
/**
 | 
					 | 
				
			||||||
 * Associate DB Model relations
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
module.exports = db => {
 | 
					 | 
				
			||||||
  db.User.belongsToMany(db.Group, { through: 'userGroups' })
 | 
					 | 
				
			||||||
  db.Group.belongsToMany(db.User, { through: 'userGroups' })
 | 
					 | 
				
			||||||
  db.Group.hasMany(db.Right)
 | 
					 | 
				
			||||||
  db.Right.belongsTo(db.Group)
 | 
					 | 
				
			||||||
  db.Document.belongsToMany(db.Tag, { through: 'documentTags' })
 | 
					 | 
				
			||||||
  db.Document.hasMany(db.Comment)
 | 
					 | 
				
			||||||
  db.Tag.belongsToMany(db.Document, { through: 'documentTags' })
 | 
					 | 
				
			||||||
  db.File.belongsTo(db.Folder)
 | 
					 | 
				
			||||||
  db.Folder.hasMany(db.File)
 | 
					 | 
				
			||||||
  db.Comment.belongsTo(db.Document)
 | 
					 | 
				
			||||||
  db.Comment.belongsTo(db.User, { as: 'author' })
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,16 +0,0 @@
 | 
				
			|||||||
/**
 | 
					 | 
				
			||||||
 * Comment schema
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
module.exports = (sequelize, DataTypes) => {
 | 
					 | 
				
			||||||
  let commentSchema = sequelize.define('comment', {
 | 
					 | 
				
			||||||
    content: {
 | 
					 | 
				
			||||||
      type: DataTypes.STRING,
 | 
					 | 
				
			||||||
      allowNull: false
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }, {
 | 
					 | 
				
			||||||
    timestamps: true,
 | 
					 | 
				
			||||||
    version: true
 | 
					 | 
				
			||||||
  })
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  return commentSchema
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,64 +0,0 @@
 | 
				
			|||||||
/**
 | 
					 | 
				
			||||||
 * Document schema
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
module.exports = (sequelize, DataTypes) => {
 | 
					 | 
				
			||||||
  let documentSchema = sequelize.define('setting', {
 | 
					 | 
				
			||||||
    path: {
 | 
					 | 
				
			||||||
      type: DataTypes.STRING,
 | 
					 | 
				
			||||||
      allowNull: false
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    title: {
 | 
					 | 
				
			||||||
      type: DataTypes.STRING,
 | 
					 | 
				
			||||||
      allowNull: false,
 | 
					 | 
				
			||||||
      validate: {
 | 
					 | 
				
			||||||
        len: [2, 255]
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    subtitle: {
 | 
					 | 
				
			||||||
      type: DataTypes.STRING,
 | 
					 | 
				
			||||||
      allowNull: true,
 | 
					 | 
				
			||||||
      defaultValue: ''
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    parentPath: {
 | 
					 | 
				
			||||||
      type: DataTypes.STRING,
 | 
					 | 
				
			||||||
      allowNull: true,
 | 
					 | 
				
			||||||
      defaultValue: ''
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    parentTitle: {
 | 
					 | 
				
			||||||
      type: DataTypes.STRING,
 | 
					 | 
				
			||||||
      allowNull: true,
 | 
					 | 
				
			||||||
      defaultValue: ''
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    isDirectory: {
 | 
					 | 
				
			||||||
      type: DataTypes.BOOLEAN,
 | 
					 | 
				
			||||||
      allowNull: false,
 | 
					 | 
				
			||||||
      defaultValue: false
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    isEntry: {
 | 
					 | 
				
			||||||
      type: DataTypes.BOOLEAN,
 | 
					 | 
				
			||||||
      allowNull: false,
 | 
					 | 
				
			||||||
      defaultValue: false
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    isDraft: {
 | 
					 | 
				
			||||||
      type: DataTypes.BOOLEAN,
 | 
					 | 
				
			||||||
      allowNull: false,
 | 
					 | 
				
			||||||
      defaultValue: false
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    searchContent: {
 | 
					 | 
				
			||||||
      type: DataTypes.TEXT,
 | 
					 | 
				
			||||||
      allowNull: true,
 | 
					 | 
				
			||||||
      defaultValue: ''
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }, {
 | 
					 | 
				
			||||||
    timestamps: true,
 | 
					 | 
				
			||||||
    version: true,
 | 
					 | 
				
			||||||
    indexes: [
 | 
					 | 
				
			||||||
      {
 | 
					 | 
				
			||||||
        unique: true,
 | 
					 | 
				
			||||||
        fields: ['path']
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    ]
 | 
					 | 
				
			||||||
  })
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  return documentSchema
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,42 +0,0 @@
 | 
				
			|||||||
/**
 | 
					 | 
				
			||||||
 * File schema
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
module.exports = (sequelize, DataTypes) => {
 | 
					 | 
				
			||||||
  let fileSchema = sequelize.define('file', {
 | 
					 | 
				
			||||||
    category: {
 | 
					 | 
				
			||||||
      type: DataTypes.ENUM('binary', 'image'),
 | 
					 | 
				
			||||||
      allowNull: false,
 | 
					 | 
				
			||||||
      defaultValue: 'binary'
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    mime: {
 | 
					 | 
				
			||||||
      type: DataTypes.STRING,
 | 
					 | 
				
			||||||
      allowNull: false,
 | 
					 | 
				
			||||||
      defaultValue: 'application/octet-stream'
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    extra: {
 | 
					 | 
				
			||||||
      type: DataTypes.JSON,
 | 
					 | 
				
			||||||
      allowNull: true
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    filename: {
 | 
					 | 
				
			||||||
      type: DataTypes.STRING,
 | 
					 | 
				
			||||||
      allowNull: false
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    basename: {
 | 
					 | 
				
			||||||
      type: DataTypes.STRING,
 | 
					 | 
				
			||||||
      allowNull: false
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    filesize: {
 | 
					 | 
				
			||||||
      type: DataTypes.INTEGER,
 | 
					 | 
				
			||||||
      allowNull: false,
 | 
					 | 
				
			||||||
      validate: {
 | 
					 | 
				
			||||||
        isInt: true,
 | 
					 | 
				
			||||||
        min: 0
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }, {
 | 
					 | 
				
			||||||
    timestamps: true,
 | 
					 | 
				
			||||||
    version: true
 | 
					 | 
				
			||||||
  })
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  return fileSchema
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,22 +0,0 @@
 | 
				
			|||||||
/**
 | 
					 | 
				
			||||||
 * Folder schema
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
module.exports = (sequelize, DataTypes) => {
 | 
					 | 
				
			||||||
  let folderSchema = sequelize.define('folder', {
 | 
					 | 
				
			||||||
    name: {
 | 
					 | 
				
			||||||
      type: DataTypes.STRING,
 | 
					 | 
				
			||||||
      allowNull: false
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }, {
 | 
					 | 
				
			||||||
    timestamps: true,
 | 
					 | 
				
			||||||
    version: true,
 | 
					 | 
				
			||||||
    indexes: [
 | 
					 | 
				
			||||||
      {
 | 
					 | 
				
			||||||
        unique: true,
 | 
					 | 
				
			||||||
        fields: ['name']
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    ]
 | 
					 | 
				
			||||||
  })
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  return folderSchema
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,16 +0,0 @@
 | 
				
			|||||||
/**
 | 
					 | 
				
			||||||
 * Group schema
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
module.exports = (sequelize, DataTypes) => {
 | 
					 | 
				
			||||||
  let groupSchema = sequelize.define('group', {
 | 
					 | 
				
			||||||
    name: {
 | 
					 | 
				
			||||||
      type: DataTypes.STRING,
 | 
					 | 
				
			||||||
      allowNull: false
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }, {
 | 
					 | 
				
			||||||
    timestamps: true,
 | 
					 | 
				
			||||||
    version: true
 | 
					 | 
				
			||||||
  })
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  return groupSchema
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,39 +0,0 @@
 | 
				
			|||||||
/**
 | 
					 | 
				
			||||||
 * Locale schema
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
module.exports = (sequelize, DataTypes) => {
 | 
					 | 
				
			||||||
  let localeSchema = sequelize.define('locale', {
 | 
					 | 
				
			||||||
    code: {
 | 
					 | 
				
			||||||
      type: DataTypes.STRING,
 | 
					 | 
				
			||||||
      allowNull: false
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    strings: {
 | 
					 | 
				
			||||||
      type: DataTypes.JSON,
 | 
					 | 
				
			||||||
      allowNull: true
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    isRTL: {
 | 
					 | 
				
			||||||
      type: DataTypes.BOOLEAN,
 | 
					 | 
				
			||||||
      allowNull: false,
 | 
					 | 
				
			||||||
      defaultValue: false
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    name: {
 | 
					 | 
				
			||||||
      type: DataTypes.STRING,
 | 
					 | 
				
			||||||
      allowNull: false
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    nativeName: {
 | 
					 | 
				
			||||||
      type: DataTypes.STRING,
 | 
					 | 
				
			||||||
      allowNull: false
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }, {
 | 
					 | 
				
			||||||
    timestamps: true,
 | 
					 | 
				
			||||||
    version: true,
 | 
					 | 
				
			||||||
    indexes: [
 | 
					 | 
				
			||||||
      {
 | 
					 | 
				
			||||||
        unique: true,
 | 
					 | 
				
			||||||
        fields: ['code']
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    ]
 | 
					 | 
				
			||||||
  })
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  return localeSchema
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,36 +0,0 @@
 | 
				
			|||||||
/**
 | 
					 | 
				
			||||||
 * Right schema
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
module.exports = (sequelize, DataTypes) => {
 | 
					 | 
				
			||||||
  let rightSchema = sequelize.define('right', {
 | 
					 | 
				
			||||||
    path: {
 | 
					 | 
				
			||||||
      type: DataTypes.STRING,
 | 
					 | 
				
			||||||
      allowNull: false
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    role: {
 | 
					 | 
				
			||||||
      type: DataTypes.ENUM('read', 'write', 'manage'),
 | 
					 | 
				
			||||||
      allowNull: false,
 | 
					 | 
				
			||||||
      defaultValue: 'read'
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    exact: {
 | 
					 | 
				
			||||||
      type: DataTypes.BOOLEAN,
 | 
					 | 
				
			||||||
      allowNull: false,
 | 
					 | 
				
			||||||
      defaultValue: false
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    allow: {
 | 
					 | 
				
			||||||
      type: DataTypes.BOOLEAN,
 | 
					 | 
				
			||||||
      allowNull: false,
 | 
					 | 
				
			||||||
      defaultValue: false
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }, {
 | 
					 | 
				
			||||||
    timestamps: true,
 | 
					 | 
				
			||||||
    version: true,
 | 
					 | 
				
			||||||
    indexes: [
 | 
					 | 
				
			||||||
      {
 | 
					 | 
				
			||||||
        fields: ['path']
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    ]
 | 
					 | 
				
			||||||
  })
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  return rightSchema
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,26 +0,0 @@
 | 
				
			|||||||
/**
 | 
					 | 
				
			||||||
 * Settings schema
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
module.exports = (sequelize, DataTypes) => {
 | 
					 | 
				
			||||||
  let settingSchema = sequelize.define('setting', {
 | 
					 | 
				
			||||||
    key: {
 | 
					 | 
				
			||||||
      type: DataTypes.STRING,
 | 
					 | 
				
			||||||
      allowNull: false
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    config: {
 | 
					 | 
				
			||||||
      type: DataTypes.JSON,
 | 
					 | 
				
			||||||
      allowNull: false
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }, {
 | 
					 | 
				
			||||||
    timestamps: true,
 | 
					 | 
				
			||||||
    version: true,
 | 
					 | 
				
			||||||
    indexes: [
 | 
					 | 
				
			||||||
      {
 | 
					 | 
				
			||||||
        unique: true,
 | 
					 | 
				
			||||||
        fields: ['key']
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    ]
 | 
					 | 
				
			||||||
  })
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  return settingSchema
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,22 +0,0 @@
 | 
				
			|||||||
/**
 | 
					 | 
				
			||||||
 * Tags schema
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
module.exports = (sequelize, DataTypes) => {
 | 
					 | 
				
			||||||
  let tagSchema = sequelize.define('tag', {
 | 
					 | 
				
			||||||
    key: {
 | 
					 | 
				
			||||||
      type: DataTypes.STRING,
 | 
					 | 
				
			||||||
      allowNull: false
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }, {
 | 
					 | 
				
			||||||
    timestamps: true,
 | 
					 | 
				
			||||||
    version: true,
 | 
					 | 
				
			||||||
    indexes: [
 | 
					 | 
				
			||||||
      {
 | 
					 | 
				
			||||||
        unique: true,
 | 
					 | 
				
			||||||
        fields: ['key']
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    ]
 | 
					 | 
				
			||||||
  })
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  return tagSchema
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -23,12 +23,12 @@ module.exports = {
 | 
				
			|||||||
        }).then((user) => {
 | 
					        }).then((user) => {
 | 
				
			||||||
          if (user) {
 | 
					          if (user) {
 | 
				
			||||||
            return user.verifyPassword(uPassword).then(() => {
 | 
					            return user.verifyPassword(uPassword).then(() => {
 | 
				
			||||||
              return done(null, user) || true
 | 
					              done(null, user)
 | 
				
			||||||
            }).catch((err) => {
 | 
					            }).catch((err) => {
 | 
				
			||||||
              return done(err, null)
 | 
					              done(err, null)
 | 
				
			||||||
            })
 | 
					            })
 | 
				
			||||||
          } else {
 | 
					          } else {
 | 
				
			||||||
            return done(new WIKI.Error.AuthLoginFailed(), null)
 | 
					            done(new WIKI.Error.AuthLoginFailed(), null)
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
        }).catch((err) => {
 | 
					        }).catch((err) => {
 | 
				
			||||||
          done(err, null)
 | 
					          done(err, null)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -250,6 +250,8 @@ module.exports = () => {
 | 
				
			|||||||
  app.post('/finalize', async (req, res) => {
 | 
					  app.post('/finalize', async (req, res) => {
 | 
				
			||||||
    WIKI.telemetry.sendEvent('setup', 'finalize')
 | 
					    WIKI.telemetry.sendEvent('setup', 'finalize')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    console.error('DUDE')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    try {
 | 
					    try {
 | 
				
			||||||
      // Upgrade from WIKI.js 1.x?
 | 
					      // Upgrade from WIKI.js 1.x?
 | 
				
			||||||
      if (req.body.upgrade) {
 | 
					      if (req.body.upgrade) {
 | 
				
			||||||
@@ -307,6 +309,16 @@ module.exports = () => {
 | 
				
			|||||||
        { key: 'uploads', value: WIKI.config.uploads }
 | 
					        { key: 'uploads', value: WIKI.config.uploads }
 | 
				
			||||||
      ])
 | 
					      ])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      // Create default locale
 | 
				
			||||||
 | 
					      WIKI.logger.info('Installing default locale...')
 | 
				
			||||||
 | 
					      await WIKI.db.locales.query().insert({
 | 
				
			||||||
 | 
					        code: 'en',
 | 
				
			||||||
 | 
					        strings: require('./locales/default.json'),
 | 
				
			||||||
 | 
					        isRTL: false,
 | 
				
			||||||
 | 
					        name: 'English',
 | 
				
			||||||
 | 
					        nativeName: 'English'
 | 
				
			||||||
 | 
					      })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      // Create root administrator
 | 
					      // Create root administrator
 | 
				
			||||||
      WIKI.logger.info('Creating root administrator...')
 | 
					      WIKI.logger.info('Creating root administrator...')
 | 
				
			||||||
      await WIKI.db.users.query().insert({
 | 
					      await WIKI.db.users.query().insert({
 | 
				
			||||||
@@ -315,6 +327,7 @@ module.exports = () => {
 | 
				
			|||||||
        password: req.body.adminPassword,
 | 
					        password: req.body.adminPassword,
 | 
				
			||||||
        name: 'Administrator',
 | 
					        name: 'Administrator',
 | 
				
			||||||
        role: 'admin',
 | 
					        role: 'admin',
 | 
				
			||||||
 | 
					        locale: 'en',
 | 
				
			||||||
        tfaIsActive: false
 | 
					        tfaIsActive: false
 | 
				
			||||||
      })
 | 
					      })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -331,20 +344,11 @@ module.exports = () => {
 | 
				
			|||||||
          name: 'Guest',
 | 
					          name: 'Guest',
 | 
				
			||||||
          password: '',
 | 
					          password: '',
 | 
				
			||||||
          role: 'guest',
 | 
					          role: 'guest',
 | 
				
			||||||
 | 
					          locale: 'en',
 | 
				
			||||||
          tfaIsActive: false
 | 
					          tfaIsActive: false
 | 
				
			||||||
        })
 | 
					        })
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      // Create default locale
 | 
					 | 
				
			||||||
      WIKI.logger.info('Installing default locale...')
 | 
					 | 
				
			||||||
      await WIKI.db.locales.query().insert({
 | 
					 | 
				
			||||||
        code: 'en',
 | 
					 | 
				
			||||||
        strings: require('./locales/default.json'),
 | 
					 | 
				
			||||||
        isRTL: false,
 | 
					 | 
				
			||||||
        name: 'English',
 | 
					 | 
				
			||||||
        nativeName: 'English'
 | 
					 | 
				
			||||||
      })
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      WIKI.logger.info('Setup is complete!')
 | 
					      WIKI.logger.info('Setup is complete!')
 | 
				
			||||||
      res.json({
 | 
					      res.json({
 | 
				
			||||||
        ok: true,
 | 
					        ok: true,
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user