const Controller = require('libflitter/controller/Controller') const Page = require('../../../models/api/Page.model') const Node = require('../../../models/api/Node.model') const Database = require('../../../models/api/db/Database.model') const ColumnDef = require('../../../models/api/db/ColumnDef.model') const DBEntry = require('../../../models/api/db/DBEntry.model') /* * Database Controller * ------------------------------------------------------------- * Put some description here! */ class FormDatabase extends Controller { async create_new(req, res) { const PageId = req.params.PageId let page = await Page.findOne({UUID: PageId}) if ( !page ) return res.status(404).message('Page not found with that ID.').api({}) if ( !(await page.is_accessible_by(req.user, 'update')) ) return req.security.deny() const NodeId = req.params.NodeId let node = await Node.findOne({UUID: NodeId}) if ( !node ) return res.status(404).message('Node not found with that ID.').api({}) const db = new Database({ Name: req.body.name || req.body.Name || 'New Database', NodeId: node.UUID, PageId: page.UUID, }) if ( req.body.UUID ) { const existingUUID = await Database.findOne({ UUID: req.body.UUID }) if ( !existingUUID ) { db.UUID = req.body.UUID } } await db.version_save(`Added to page "${page.Name}"`, req.user.id) req.user.allow(`database:${db.UUID}`); await req.user.save() return res.api(db) } async get_config(req, res) { const PageId = req.params.PageId let page = await Page.findOne({UUID: PageId}) if ( !page ) return res.status(404).message('Page not found with that ID.').api({}) if ( !(await page.is_accessible_by(req.user)) ) return req.security.deny() const NodeId = req.params.NodeId let node = await Node.findOne({UUID: NodeId}) if ( !node ) return res.status(404).message('Node not found with that ID.').api({}) const DatabaseId = req.params.DatabaseId const db = await Database.findOne({UUID: DatabaseId}) if ( !db ) return res.status(404).message('Database not found with that ID.').api({}) // if ( !db.accessible_by(req.user) ) return req.security.deny() return res.api(db) } async get_columns(req, res) { const PageId = req.params.PageId let page = await Page.findOne({UUID: PageId}) if ( !page ) return res.status(404).message('Page not found with that ID.').api({}) if ( !(await page.is_accessible_by(req.user)) ) return req.security.deny() const NodeId = req.params.NodeId let node = await Node.findOne({UUID: NodeId}) if ( !node ) return res.status(404).message('Node not found with that ID.').api({}) const DatabaseId = req.params.DatabaseId const db = await Database.findOne({UUID: DatabaseId}) if ( !db ) return res.status(404).message('Database not found with that ID.').api({}) const columns = [] for ( const col_id of db.ColumnIds ) { const rec = await ColumnDef.findOne({UUID: col_id}) if ( rec ) { rec.additionalData = rec.data() columns.push(rec) } } // Fallback for backwards compat if ( columns.length < 1 ) { return res.api((await ColumnDef.find({DatabaseId: db.UUID})).map(x => { x.additionalData = x.data() return x })) } return res.api(columns) } async set_name(req, res) { if ( !req.body.Name ) { return res.status(400) .message('Missing required field: Name') .api() } const PageId = req.params.PageId let page = await Page.findOne({UUID: PageId}) if ( !page ) return res.status(404).message('Page not found with that ID.').api({}) if ( !(await page.is_accessible_by(req.user, 'update')) ) return req.security.deny() const NodeId = req.params.NodeId let node = await Node.findOne({UUID: NodeId}) if ( !node ) return res.status(404).message('Node not found with that ID.').api({}) const DatabaseId = req.params.DatabaseId const db = await Database.findOne({UUID: DatabaseId}) if ( !db ) return res.status(404).message('Database not found with that ID.').api({}) // if ( !db.accessible_by(req.user, 'update') ) return req.security.deny() if ( req.body.Name !== db.Name ) { db.Name = req.body.Name await db.version_save(`Changed database name to "${req.body.Name}"`, req.user.id) } else { await db.save() } return res.api(db) } async set_columns(req, res) { const PageId = req.params.PageId let page = await Page.findOne({UUID: PageId}) if ( !page ) return res.status(404).message('Page not found with that ID.').api({}) if ( !(await page.is_accessible_by(req.user, 'update')) ) return req.security.deny() const NodeId = req.params.NodeId let node = await Node.findOne({UUID: NodeId}) if ( !node ) return res.status(404).message('Node not found with that ID.').api({}) const DatabaseId = req.params.DatabaseId const db = await Database.findOne({UUID: DatabaseId}) if ( !db ) return res.status(404).message('Database not found with that ID.').api({}) // if ( !db.accessible_by(req.user, 'update') ) return req.security.deny() const existing_columns = await ColumnDef.find({ DatabaseId: db.UUID }) const assoc_columns = [] existing_columns.forEach(col => assoc_columns[col.UUID] = col) const update_columns = [] for ( const col of req.body.columns ) { if ( col.UUID && assoc_columns[col.UUID] ) { assoc_columns[col.UUID].headerName = col.headerName assoc_columns[col.UUID].field = col.field assoc_columns[col.UUID].DatabaseId = db.UUID assoc_columns[col.UUID].Type = col.Type assoc_columns[col.UUID].additionalData = JSON.stringify(col.additionalData) await assoc_columns[col.UUID].version_save(`Updated in page "${page.Name}"`, req.user.id) update_columns.push(assoc_columns[col.UUID]) } else { const new_col = new ColumnDef({ headerName: col.headerName, field: col.field, DatabaseId: db.UUID, Type: col.Type, additionalData: JSON.stringify(col.additionalData), }) if ( col.UUID ) { const existingUUID = await ColumnDef.findOne({ UUID: col.UUID }) if ( !existingUUID ) { new_col.UUID = col.UUID } } await new_col.version_save(`Added to database`, req.user.id) update_columns.push(new_col) } } for ( const col of existing_columns ) { if ( !update_columns.includes(col) ) { await col.delete() } } const new_cols = update_columns.map(x => x.UUID) const no_updates = (new_cols.length === db.ColumnIds.length) && (new_cols.every(val => db.ColumnIds.includes(val))); if ( !no_updates ) { db.ColumnIds = new_cols await db.version_save('Updated columns', req.user.id) } else { await db.save() } return res.api(update_columns) } async get_data(req, res) { const PageId = req.params.PageId let page = await Page.findOne({UUID: PageId}) if ( !page ) return res.status(404).message('Page not found with that ID.').api({}) if ( !(await page.is_accessible_by(req.user)) ) return req.security.deny() const NodeId = req.params.NodeId let node = await Node.findOne({UUID: NodeId}) if ( !node ) return res.status(404).message('Node not found with that ID.').api({}) const DatabaseId = req.params.DatabaseId const db = await Database.findOne({UUID: DatabaseId}) if ( !db ) return res.status(404).message('Database not found with that ID.').api({}) // if ( !db.accessible_by(req.user) ) return req.security.deny() const entries = await DBEntry.find({DatabaseId: db.UUID}) entries.forEach(entry => entry.RowData.UUID = entry.UUID) return res.api(entries) } async set_data(req, res) { const PageId = req.params.PageId let page = await Page.findOne({UUID: PageId}) if ( !page ) return res.status(404).message('Page not found with that ID.').api({}) if ( !(await page.is_accessible_by(req.user, 'update')) ) return req.security.deny() const NodeId = req.params.NodeId let node = await Node.findOne({UUID: NodeId}) if ( !node ) return res.status(404).message('Node not found with that ID.').api({}) const DatabaseId = req.params.DatabaseId const db = await Database.findOne({UUID: DatabaseId}) if ( !db ) return res.status(404).message('Database not found with that ID.').api({}) // if ( !db.accessible_by(req.user) ) return req.security.deny() await DBEntry.deleteMany({DatabaseId: db.UUID}) const new_recs = [] for ( const rec of req.body ) { const data = {DatabaseId: db.UUID} if ( rec.UUID ) data.UUID = rec.UUID delete rec.UUID data.RowData = rec const dbe = new DBEntry(data) await dbe.save() dbe.RowData.UUID = dbe.UUID new_recs.push(dbe) } await db.version_save('Updated data', req.user.id) return res.api(await this._set_indices(db, new_recs)) } async drop_database(req, res) { const PageId = req.params.PageId let page = await Page.findOne({UUID: PageId}) if ( !page ) return res.status(404).message('Page not found with that ID.').api({}) if ( !(await page.is_accessible_by(req.user, 'update')) ) return req.security.deny() const NodeId = req.params.NodeId let node = await Node.findOne({UUID: NodeId}) if ( !node ) return res.status(404).message('Node not found with that ID.').api({}) const DatabaseId = req.params.DatabaseId const db = await Database.findOne({UUID: DatabaseId}) if ( !db ) return res.status(404).message('Database not found with that ID.').api({}) // if ( !db.accessible_by(req.user) ) return req.security.deny() await DBEntry.deleteMany({DatabaseId: db.UUID}) await db.version_save('Deleted', req.user.id) await db.delete() return res.api({}) } async _set_indices(db, data) { const index_columns = await ColumnDef.find({DatabaseId: db.UUID, Type: 'index'}) for ( const col of index_columns ) { let max_val = 0 data.forEach(row => { const val = row.RowData[col.field] if ( val && val > max_val ) max_val = val }); let next_val = max_val + 1 for ( const row of data ) { if ( !row.RowData[col.field] ) { row.RowData[col.field] = next_val next_val += 1 await row.save() } } } return data } } module.exports = exports = FormDatabase