// @ts-check
/**
* @import {treeAction} from './../../types.js'
*/
import { query, transaction, HEX2uuid } from '@commtool/sql-query'
import { personRebuildAccess } from '../rebuildList.js'
import { requalify } from '../../Router/job/utilities.js'
import { errorLoggerUpdate } from '../../utils/requestLogger.js'
/**
* Handles the `function` add action.
*
* Fired when a function template is created or modified with respect to its
* qualification requirements. Re-qualifies all jobs based on this template.
*
* @param {treeAction} action
* @returns {Promise<void>}
*/
export const addFunctionAction = async (action) => {
try {
requalify(HEX2uuid(action.UIDroot), action.UIDObjectID)
} catch (e) {
errorLoggerUpdate(e || new Error('treeAdd.functionActions.addFunctionAction: Unknown error occurred'))
}
}
/**
* Handles the `functionV` add action.
*
* Fired when a function template is modified with respect to its visibility or
* changeability requirements. Deletes and rebuilds all visibility/changeability
* filter entries for every job linked to this function template, then refreshes
* the holding person's access.
*
* @param {treeAction} action
* @returns {Promise<void>}
*/
export const addFunctionVAction = async (action) => {
try {
const jobs = await query(
`SELECT Jobs.UID AS UIDJob, Jobs.UIDBelongsTo AS UIDPerson, GLinks.UIDTarget AS UIDGroup
FROM ObjectBase AS Jobs
INNER JOIN Links AS FLinks ON (FLinks.UIDTarget=Jobs.UID AND FLinks.Type='function' AND Jobs.Type='job')
INNER JOIN Links AS GLinks ON (GLinks.UID=Jobs.UID AND GLinks.Type='memberA')
AND FLinks.UID=?`,
[action.UIDObjectID],
)
for await (const job of jobs) {
await transaction(
async (connection) => {
// delete all visibility and changeability filters for this job
await connection.query(
`DELETE ObjectBase,Links
FROM ObjectBase
INNER JOIN Links ON (ObjectBase.UID=Links.UID AND ObjectBase.Type IN ('visible','changeable') AND Links.Type='list')
WHERE Links.UIDTarget=?`,
[job.UIDJob],
)
const functionTemplate = await connection.query(
`SELECT ObjectBase.Data FROM ObjectBase WHERE UID=?`,
[action.UIDObjectID],
{ cast: ['json'] },
)
const functionData = functionTemplate[0].Data
if (functionTemplate.length > 0 && Object.keys(functionData.access).length > 0) {
// get the groups from the hierarchy of this job given by the access key
const hGroups = await connection.query(
`SELECT ObjectBase.UID,
JSON_VALUE(Member.Data,'$.hierarchie') AS Hierarchie,
JSON_VALUE(Member.Data,'$.gender') AS Gender,
ObjectBase.Title
FROM ObjectBase
INNER JOIN Member ON (Member.UID=ObjectBase.UID)
INNER JOIN Links ON (Links.UIDTarget=ObjectBase.UID)
WHERE (Links.UID=? OR ObjectBase.UID=?)
AND ObjectBase.Type='group'
AND JSON_VALUE(Member.Data,'$.hierarchie') IN (?)
GROUP BY ObjectBase.UID`,
[job.UIDGroup, job.UIDGroup, Object.keys(functionData.access)],
)
// add a visibility filter for each matching hierarchie group
if (hGroups.length > 0) {
for (const hGroup of hGroups) {
// add only filters to combined groups; skip if a combined group
// for the same hierarchie already exists
if (hGroup.Gender === 'C' || !hGroups.find(hg =>
hg.Hierarchie === hGroup.Hierarchie && hg.Gender === 'C',
)) {
const [{ UID: filterUID }] = await query(`SELECT UIDV1() AS UID`, [])
await connection.query(
`INSERT INTO ObjectBase
(UID, Type, UIDBelongsTo, Title, Display, SortName, FullTextIndex, dindex, Data)
VALUES (?, 'visible', ?, ?, ?, 'visible', '', 0, ?)`,
[
filterUID,
hGroup.UID,
functionData.name,
hGroup.Title,
JSON.stringify(functionData.access[hGroup.Hierarchie]),
],
)
await connection.query(
`INSERT IGNORE INTO Links (UID, Type, UIDTarget) VALUES (?, 'list', ?)`,
[filterUID, job.UIDJob],
)
}
}
}
// add changeability filter
if (functionData.writeAccess) {
const [{ UID: filterUID }] = await query(`SELECT UIDV1() AS UID`, [])
await connection.query(
`INSERT INTO ObjectBase
(UID, Type, UIDBelongsTo, Title, Display, SortName, FullTextIndex, dindex, Data)
VALUES (?, 'changeable', ?, ?, ?, 'changeable', '', 0, ?)`,
[
filterUID,
job.UIDGroup,
functionData.name,
'',
JSON.stringify(functionData.writeAccess),
],
)
await connection.query(
`INSERT IGNORE INTO Links (UID, Type, UIDTarget) VALUES (?, 'list', ?)`,
[filterUID, job.UIDJob],
)
}
}
},
{
beforeTransaction: async (connection) =>
await connection.query(`SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;`),
},
)
await personRebuildAccess(job.UIDPerson)
}
} catch (e) {
errorLoggerUpdate(e || new Error('treeAdd.functionActions.addFunctionVAction: Unknown error occurred'))
}
}