backend/app/controllers/api/v1/Misc.controller.js
garrettmills f58fcd85b1
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone Build is passing
Noded/frontend#75 - support searching file boxes and files from universal search
2021-02-04 20:41:03 -06:00

226 lines
8.0 KiB
JavaScript

const Controller = require('libflitter/controller/Controller')
const { ObjectId } = require("mongodb");
const Page = require("../../../models/api/Page.model")
/*
* Misc Controller
* -------------------------------------------------------------
* Put some description here!
*/
class Misc extends Controller {
#default_token_grants = ['database']
static get services() {
return [...super.services, 'models', 'injector']
}
async get_token(req, res, next) {
const Token = this.models.get('api:Token')
const token = await Token.for_user(req.user)
return res.api(token.token)
}
async get_search(req, res, next) {
if ( !req.query.query ) {
return res.status(400)
.message('Missing query.')
.api()
}
const query = String(req.query.query)
const snip_length = 100
const Page = this.models.get('api:Page')
const Node = this.models.get('api:Node')
const Codium = this.models.get('api:Codium')
const Database = this.models.get('api:db:Database')
const FileGroup = this.models.get('api:FileGroup')
const File = this.models.get('upload::File')
const FileBox = this.models.get('api:files:FileBox')
const all_user_page_ids = (await req.user.get_accessible_pages()).map(x => x.UUID)
const results = []
const matching_pages = await Page.find({
UUID: { $in: all_user_page_ids },
Active: true,
$text: { $search: query },
})
for ( const page of matching_pages ) {
results.push({
title: page.Name,
short_title: `${page.Name.replace(/(<([^>]+)>)/ig, '').slice(0, snip_length)}${page.Name.length > snip_length ? '...' : ''}`,
type: 'page',
id: page.UUID,
})
}
const matching_nodes = await Node.find({
PageId: { $in: all_user_page_ids },
'Value.Mode': { $in: ['norm', 'markdown'] },
$text: { $search: query }
})
for ( const node of matching_nodes ) {
const page = await node.page
results.push({
title: node.Value.Value,
short_title: `${node.Value.Value.replace(/(<([^>]+)>)/ig, '').slice(0, snip_length)}${node.Value.Value.length > snip_length ? '...' : ''}`,
type: node.Value.Mode === 'norm' ? 'node' : 'markdown',
id: node.UUID,
associated: {
title: page.Name,
short_title: `${page.Name.slice(0, snip_length)}${page.Name.length > snip_length ? '...' : ''}`,
type: 'page',
id: page.UUID,
}
})
}
const matching_codiums = await Codium.find({
Active: true,
PageId: { $in: all_user_page_ids },
$text: { $search: query },
});
for ( const codium of matching_codiums ) {
const page = await codium.page
results.push({
title: codium.code,
short_title: `${codium.code.replace(/(<([^>]+)>)/ig, '').slice(0, snip_length)}${codium.code.length > snip_length ? '...' : ''}`,
type: 'code',
id: codium.NodeId,
associated: {
title: page.Name,
short_title: `${page.Name.slice(0, snip_length)}${page.Name.length > snip_length ? '...' : ''}`,
type: 'page',
id: page.UUID,
}
})
}
const matching_dbs = await Database.find({
Active: true,
PageId: { $in: all_user_page_ids },
$text: { $search: query },
})
for ( const db of matching_dbs ) {
const page = await db.page
results.push({
title: db.Name,
short_title: `${db.Name.replace(/(<([^>]+)>)/ig, '').slice(0, snip_length)}${db.Name.length > snip_length ? '...' : ''}`,
type: 'db',
id: db.NodeId,
associated: {
title: page.Name,
short_title: `${page.Name.slice(0, snip_length)}${page.Name.length > snip_length ? '...' : ''}`,
type: 'page',
id: page.UUID,
}
})
}
const unique = (value, index, self) => {
return self.indexOf(value) === index
}
const matching_boxes = await FileBox.find({
active: true,
pageId: { $in: all_user_page_ids },
$text: { $search: query },
})
for ( const box of matching_boxes ) {
const page = await box.page()
results.push({
title: box.name,
short_title: `${box.name.replace(/(<([^>]+)>)/ig, '').slice(0, snip_length)}${box.name.length > snip_length ? '...' : ''}`,
type: 'file_box',
id: box.nodeId,
boxId: box.UUID,
associated: {
title: page.Name,
short_title: `${page.Name.slice(0, snip_length)}${page.Name.length > snip_length ? '...' : ''}`,
type: 'page',
id: page.UUID,
},
})
}
const all_boxes = await FileBox.find({
active: true,
pageId: { $in: all_user_page_ids },
})
const all_file_groups = await FileGroup.find({
PageId: { $in: all_user_page_ids },
})
let all_file_ids = []
const file_id_x_group = {}
const file_id_x_box = {}
for ( const group of all_file_groups ) {
group.FileIds.forEach(id => {
all_file_ids.push(id)
file_id_x_group[id] = group
})
}
for ( const box of all_boxes ) {
box.fileIds.forEach(id => {
all_file_ids.push(id)
file_id_x_box[id] = box
})
}
const unique_file_ids = all_file_ids.filter(unique).map(x => File.ObjectId(x))
const matching_files = await File.find({
_id: { $in: unique_file_ids },
$text: { $search: query },
})
for ( const file of matching_files ) {
const group = file_id_x_group[file.id]
const box = file_id_x_box[file.id]
if ( box ) {
const page = await box.page()
results.push({
title: file.original_name,
short_title: `${file.original_name.slice(0, snip_length)}${file.original_name.length > snip_length ? '...' : ''}`,
type: `file_box-${this.injector.get('controllers').get('api:v1:FileBox.get_file_category')(file.mime_type)}`,
id: box.nodeId,
boxId: box.UUID,
associated: {
title: page.Name,
short_title: `${page.Name.slice(0, snip_length)}${page.Name.length > snip_length ? '...' : ''}`,
type: 'page',
id: page.UUID,
},
})
} else if ( group ) {
const page = await group.page
results.push({
title: file.original_name,
short_title: `${file.original_name.slice(0, snip_length)}${file.original_name.length > snip_length ? '...' : ''}`,
type: 'files',
id: group.NodeId,
associated: {
title: page.Name,
short_title: `${page.Name.slice(0, snip_length)}${page.Name.length > snip_length ? '...' : ''}`,
type: 'page',
id: page.UUID,
},
})
}
}
return res.api({results})
}
}
module.exports = exports = Misc