| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531 | const _ = require('lodash')const graphHelper = require('../../helpers/graph')/* global WIKI */module.exports = {  Query: {    async pages() { return {} }  },  Mutation: {    async pages() { return {} }  },  PageQuery: {    /**     * PAGE HISTORY     */    async history(obj, args, context, info) {      const page = await WIKI.models.pages.query().select('path', 'localeCode').findById(args.id)      if (WIKI.auth.checkAccess(context.req.user, ['read:history'], {        path: page.path,        locale: page.localeCode      })) {        return WIKI.models.pageHistory.getHistory({          pageId: args.id,          offsetPage: args.offsetPage || 0,          offsetSize: args.offsetSize || 100        })      } else {        throw new WIKI.Error.PageHistoryForbidden()      }    },    /**     * PAGE VERSION     */    async version(obj, args, context, info) {      const page = await WIKI.models.pages.query().select('path', 'localeCode').findById(args.pageId)      if (WIKI.auth.checkAccess(context.req.user, ['read:history'], {        path: page.path,        locale: page.localeCode      })) {        return WIKI.models.pageHistory.getVersion({          pageId: args.pageId,          versionId: args.versionId        })      } else {        throw new WIKI.Error.PageHistoryForbidden()      }    },    /**     * SEARCH PAGES     */    async search (obj, args, context) {      if (WIKI.data.searchEngine) {        const resp = await WIKI.data.searchEngine.query(args.query, args)        return {          ...resp,          results: _.filter(resp.results, r => {            return WIKI.auth.checkAccess(context.req.user, ['read:pages'], {              path: r.path,              locale: r.locale            })          })        }      } else {        return {          results: [],          suggestions: [],          totalHits: 0        }      }    },    /**     * LIST PAGES     */    async list (obj, args, context, info) {      let results = await WIKI.models.pages.query().column([        'pages.id',        'path',        { locale: 'localeCode' },        'title',        'description',        'isPublished',        'isPrivate',        'privateNS',        'contentType',        'createdAt',        'updatedAt'      ])        .withGraphJoined('tags')        .modifyGraph('tags', builder => {          builder.select('tag')        })        .modify(queryBuilder => {          if (args.limit) {            queryBuilder.limit(args.limit)          }          if (args.locale) {            queryBuilder.where('localeCode', args.locale)          }          if (args.creatorId && args.authorId && args.creatorId > 0 && args.authorId > 0) {            queryBuilder.where(function () {              this.where('creatorId', args.creatorId).orWhere('authorId', args.authorId)            })          } else {            if (args.creatorId && args.creatorId > 0) {              queryBuilder.where('creatorId', args.creatorId)            }            if (args.authorId && args.authorId > 0) {              queryBuilder.where('authorId', args.authorId)            }          }          if (args.tags && args.tags.length > 0) {            queryBuilder.whereIn('tags.tag', args.tags.map(t => _.trim(t).toLowerCase()))          }          const orderDir = args.orderByDirection === 'DESC' ? 'desc' : 'asc'          switch (args.orderBy) {            case 'CREATED':              queryBuilder.orderBy('createdAt', orderDir)              break            case 'PATH':              queryBuilder.orderBy('path', orderDir)              break            case 'TITLE':              queryBuilder.orderBy('title', orderDir)              break            case 'UPDATED':              queryBuilder.orderBy('updatedAt', orderDir)              break            default:              queryBuilder.orderBy('pages.id', orderDir)              break          }        })      results = _.filter(results, r => {        return WIKI.auth.checkAccess(context.req.user, ['read:pages'], {          path: r.path,          locale: r.locale        })      }).map(r => ({        ...r,        tags: _.map(r.tags, 'tag')      }))      if (args.tags && args.tags.length > 0) {        results = _.filter(results, r => _.every(args.tags, t => _.includes(r.tags, t)))      }      return results    },    /**     * FETCH SINGLE PAGE     */    async single (obj, args, context, info) {      let page = await WIKI.models.pages.getPageFromDb(args.id)      if (page) {        if (WIKI.auth.checkAccess(context.req.user, ['manage:pages', 'delete:pages'], {          path: page.path,          locale: page.localeCode        })) {          return {            ...page,            locale: page.localeCode,            editor: page.editorKey          }        } else {          throw new WIKI.Error.PageViewForbidden()        }      } else {        throw new WIKI.Error.PageNotFound()      }    },    /**     * FETCH TAGS     */    async tags (obj, args, context, info) {      return WIKI.models.tags.query().orderBy('tag', 'asc')    },    /**     * SEARCH TAGS     */    async searchTags (obj, args, context, info) {      const query = _.trim(args.query)      const results = await WIKI.models.tags.query()        .column('tag')        .where(builder => {          builder.andWhere(builderSub => {            if (WIKI.config.db.type === 'postgres') {              builderSub.where('tag', 'ILIKE', `%${query}%`)            } else {              builderSub.where('tag', 'LIKE', `%${query}%`)            }          })        })        .limit(5)      return results.map(r => r.tag)    },    /**     * FETCH PAGE TREE     */    async tree (obj, args, context, info) {      let curPage = null      if (!args.locale) { args.locale = WIKI.config.lang.code }      if (args.path && !args.parent) {        curPage = await WIKI.models.knex('pageTree').first('parent', 'ancestors').where({          path: args.path,          localeCode: args.locale        })        if (curPage) {          args.parent = curPage.parent || 0        } else {          return []        }      }      const results = await WIKI.models.knex('pageTree').where(builder => {        builder.where('localeCode', args.locale)        switch (args.mode) {          case 'FOLDERS':            builder.andWhere('isFolder', true)            break          case 'PAGES':            builder.andWhereNotNull('pageId')            break        }        if (!args.parent || args.parent < 1) {          builder.whereNull('parent')        } else {          builder.where('parent', args.parent)          if (args.includeAncestors && curPage && curPage.ancestors.length > 0) {            builder.orWhereIn('id', _.isString(curPage.ancestors) ? JSON.parse(curPage.ancestors) : curPage.ancestors)          }        }      }).orderBy([{ column: 'isFolder', order: 'desc' }, 'title'])      return results.filter(r => {        return WIKI.auth.checkAccess(context.req.user, ['read:pages'], {          path: r.path,          locale: r.localeCode        })      }).map(r => ({        ...r,        parent: r.parent || 0,        locale: r.localeCode      }))    },    /**     * FETCH PAGE LINKS     */    async links (obj, args, context, info) {      let results = []      results = await WIKI.models.knex('pages')        .column({ id: 'pages.id' }, { path: 'pages.path' }, 'title', { link: 'pageLinks.path' }, { locale: 'pageLinks.localeCode' })        .fullOuterJoin('pageLinks', 'pages.id', 'pageLinks.pageId')        .where({          'pages.localeCode': args.locale        })      return _.reduce(results, (result, val) => {        // -> Check if user has access to source and linked page        if (          !WIKI.auth.checkAccess(context.req.user, ['read:pages'], { path: val.path, locale: args.locale }) ||          !WIKI.auth.checkAccess(context.req.user, ['read:pages'], { path: val.link, locale: val.locale })        ) {          return result        }        const existingEntry = _.findIndex(result, ['id', val.id])        if (existingEntry >= 0) {          if (val.link) {            result[existingEntry].links.push(`${val.locale}/${val.link}`)          }        } else {          result.push({            id: val.id,            title: val.title,            path: `${args.locale}/${val.path}`,            links: val.link ? [`${val.locale}/${val.link}`] : []          })        }        return result      }, [])    },    /**     * CHECK FOR EDITING CONFLICT     */    async checkConflicts (obj, args, context, info) {      let page = await WIKI.models.pages.query().select('path', 'localeCode', 'updatedAt').findById(args.id)      if (page) {        if (WIKI.auth.checkAccess(context.req.user, ['write:pages', 'manage:pages'], {          path: page.path,          locale: page.localeCode        })) {          return page.updatedAt > args.checkoutDate        } else {          throw new WIKI.Error.PageUpdateForbidden()        }      } else {        throw new WIKI.Error.PageNotFound()      }    },    /**     * FETCH LATEST VERSION FOR CONFLICT COMPARISON     */    async conflictLatest (obj, args, context, info) {      let page = await WIKI.models.pages.getPageFromDb(args.id)      if (page) {        if (WIKI.auth.checkAccess(context.req.user, ['write:pages', 'manage:pages'], {          path: page.path,          locale: page.localeCode        })) {          return {            ...page,            tags: page.tags.map(t => t.tag),            locale: page.localeCode          }        } else {          throw new WIKI.Error.PageViewForbidden()        }      } else {        throw new WIKI.Error.PageNotFound()      }    }  },  PageMutation: {    /**     * CREATE PAGE     */    async create(obj, args, context) {      try {        const page = await WIKI.models.pages.createPage({          ...args,          user: context.req.user        })        return {          responseResult: graphHelper.generateSuccess('Page created successfully.'),          page        }      } catch (err) {        return graphHelper.generateError(err)      }    },    /**     * UPDATE PAGE     */    async update(obj, args, context) {      try {        const page = await WIKI.models.pages.updatePage({          ...args,          user: context.req.user        })        return {          responseResult: graphHelper.generateSuccess('Page has been updated.'),          page        }      } catch (err) {        return graphHelper.generateError(err)      }    },    /**     * MOVE PAGE     */    async move(obj, args, context) {      try {        await WIKI.models.pages.movePage({          ...args,          user: context.req.user        })        return {          responseResult: graphHelper.generateSuccess('Page has been moved.')        }      } catch (err) {        return graphHelper.generateError(err)      }    },    /**     * DELETE PAGE     */    async delete(obj, args, context) {      try {        await WIKI.models.pages.deletePage({          ...args,          user: context.req.user        })        return {          responseResult: graphHelper.generateSuccess('Page has been deleted.')        }      } catch (err) {        return graphHelper.generateError(err)      }    },    /**     * DELETE TAG     */    async deleteTag (obj, args, context) {      try {        const tagToDel = await WIKI.models.tags.query().findById(args.id)        if (tagToDel) {          await tagToDel.$relatedQuery('pages').unrelate()          await WIKI.models.tags.query().deleteById(args.id)        } else {          throw new Error('This tag does not exist.')        }        return {          responseResult: graphHelper.generateSuccess('Tag has been deleted.')        }      } catch (err) {        return graphHelper.generateError(err)      }    },    /**     * UPDATE TAG     */    async updateTag (obj, args, context) {      try {        const affectedRows = await WIKI.models.tags.query()          .findById(args.id)          .patch({            tag: _.trim(args.tag).toLowerCase(),            title: _.trim(args.title)          })        if (affectedRows < 1) {          throw new Error('This tag does not exist.')        }        return {          responseResult: graphHelper.generateSuccess('Tag has been updated successfully.')        }      } catch (err) {        return graphHelper.generateError(err)      }    },    /**     * FLUSH PAGE CACHE     */    async flushCache(obj, args, context) {      try {        await WIKI.models.pages.flushCache()        WIKI.events.outbound.emit('flushCache')        return {          responseResult: graphHelper.generateSuccess('Pages Cache has been flushed successfully.')        }      } catch (err) {        return graphHelper.generateError(err)      }    },    /**     * MIGRATE ALL PAGES FROM SOURCE LOCALE TO TARGET LOCALE     */    async migrateToLocale(obj, args, context) {      try {        const count = await WIKI.models.pages.migrateToLocale(args)        return {          responseResult: graphHelper.generateSuccess('Migrated content to target locale successfully.'),          count        }      } catch (err) {        return graphHelper.generateError(err)      }    },    /**     * REBUILD TREE     */    async rebuildTree(obj, args, context) {      try {        await WIKI.models.pages.rebuildTree()        return {          responseResult: graphHelper.generateSuccess('Page tree rebuilt successfully.')        }      } catch (err) {        return graphHelper.generateError(err)      }    },    /**     * RENDER PAGE     */    async render (obj, args, context) {      try {        const page = await WIKI.models.pages.query().findById(args.id)        if (!page) {          throw new WIKI.Error.PageNotFound()        }        await WIKI.models.pages.renderPage(page)        return {          responseResult: graphHelper.generateSuccess('Page rendered successfully.')        }      } catch (err) {        return graphHelper.generateError(err)      }    },    /**     * RESTORE PAGE VERSION     */    async restore (obj, args, context) {      try {        const page = await WIKI.models.pages.query().select('path', 'localeCode').findById(args.pageId)        if (!page) {          throw new WIKI.Error.PageNotFound()        }        if (!WIKI.auth.checkAccess(context.req.user, ['write:pages'], {          path: page.path,          locale: page.localeCode        })) {          throw new WIKI.Error.PageRestoreForbidden()        }        const targetVersion = await WIKI.models.pageHistory.getVersion({ pageId: args.pageId, versionId: args.versionId })        if (!targetVersion) {          throw new WIKI.Error.PageNotFound()        }        await WIKI.models.pages.updatePage({          ...targetVersion,          id: targetVersion.pageId,          user: context.req.user,          action: 'restored'        })        return {          responseResult: graphHelper.generateSuccess('Page version restored successfully.')        }      } catch (err) {        return graphHelper.generateError(err)      }    }  },  Page: {    // comments(pg) {    //   return pg.$relatedQuery('comments')    // }  }}
 |