-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathcrossSearch.ts
130 lines (114 loc) · 4.43 KB
/
crossSearch.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
import { User, CrossSearch, Role, CrossSearchRouteParameters } from '../../../frontend/src/shared/types'
import { getCrossSearchFields, getFieldsOfTables, nowDb } from '../utils/db'
import { ColumnFilter, SortingState, generateCrossSearchSql } from './queries/crossSearchQuery'
import { ValidationObject } from '../../../frontend/src/shared/validators/validator'
import { validateCrossSearchRouteParams } from '../../../frontend/src/shared/validators/crossSearch'
const getAllowedLocalities = async (user: User) => {
const usersProjects = await nowDb.now_proj_people.findMany({
where: { initials: user.initials },
select: { pid: true },
})
const projectsSet = new Set(usersProjects.map(({ pid }) => pid))
const projectIDs = Array.from(projectsSet)
const localities = await nowDb.now_plr.findMany({
where: { pid: { in: projectIDs } },
select: { lid: true },
})
const localitiesSet = new Set(localities.map(({ lid }) => lid))
const localityIDs = Array.from(localitiesSet)
return localityIDs
}
const convertFilterIdToFieldName = (id: string) => {
const aliasToFieldName: { [key: string]: string } = {
species_id_com_species: 'com_species.species_id',
body_mass_com_species: 'com_species.body_mass',
microwear_com_species: 'com_species.microwear',
mesowear_com_species: 'com_species.mesowear',
mw_or_high_com_species: 'com_species.mw_or_high',
mw_or_low_com_species: 'com_species.mw_or_low',
mw_cs_sharp_com_species: 'com_species.mw_cs_sharp',
mw_cs_round_com_species: 'com_species.mw_cs_round',
mw_cs_blunt_com_species: 'com_species.mw_cs_blunt',
mw_scale_min_com_species: 'com_species.mw_scale_min',
mw_scale_max_com_species: 'com_species.mw_scale_max',
mw_value_com_species: 'com_species.mw_value',
lid_now_loc: 'now_loc.lid',
species_id_now_ls: 'now_ls.species_id',
microwear_now_ls: 'now_ls.microwear',
body_mass_now_ls: 'now_ls.body_mass',
mesowear_now_ls: 'now_ls.mesowear',
mw_or_high_now_ls: 'now_ls.mw_or_high',
mw_or_low_now_ls: 'now_ls.mw_or_low',
mw_cs_sharp_now_ls: 'now_ls.mw_cs_sharp',
mw_cs_round_now_ls: 'now_ls.mw_cs_round',
mw_cs_blunt_now_ls: 'now_ls.mw_cs_blunt',
mw_scale_min_now_ls: 'now_ls.mw_scale_min',
mw_scale_max_now_ls: 'now_ls.mw_scale_max',
mw_value_now_ls: 'now_ls.mw_value',
}
if (Object.keys(aliasToFieldName).includes(id)) {
return aliasToFieldName[id]
}
if (getFieldsOfTables(['com_species']).includes(id)) {
return `com_species.${id}`
}
if (getFieldsOfTables(['now_ls']).includes(id)) {
return `now_ls.${id}`
}
if (getFieldsOfTables(['now_loc']).includes(id)) {
return `now_loc.${id}`
}
return id
}
export const getCrossSearchRawSql = async (
user: User | undefined,
limit?: number,
offset?: number,
columnFilters?: ColumnFilter[],
sorting?: SortingState[]
) => {
let orderBy: string | undefined
let descendingOrder: boolean = false
if (!sorting || sorting.length === 0) {
orderBy = undefined
} else {
orderBy = sorting[0].id
descendingOrder = sorting[0].desc
}
let convertedOrderBy = undefined
if (orderBy) {
convertedOrderBy = convertFilterIdToFieldName(orderBy)
if (!getCrossSearchFields().includes(convertedOrderBy)) throw new Error('orderBy was not a valid column id.')
}
const convertedColumnFilters = []
if (columnFilters) {
const allowedColumns = getCrossSearchFields()
for (const filter of columnFilters) {
const convertedId = convertFilterIdToFieldName(filter.id)
if (!allowedColumns.includes(convertedId)) throw new Error('columnFilters has an invalid column id.')
convertedColumnFilters.push({ id: convertedId, value: filter.value })
}
}
const showAll = user ? [Role.Admin, Role.EditUnrestricted].includes(user.role) : false
const allowedLocalities = user ? await getAllowedLocalities(user) : []
const sql = generateCrossSearchSql(
showAll,
allowedLocalities,
limit,
offset,
convertedColumnFilters,
convertedOrderBy,
descendingOrder
)
const result: Partial<CrossSearch>[] = await nowDb.$queryRaw(sql)
return result
}
export const validateCrossSearchRouteParameters = (parameters: CrossSearchRouteParameters) => {
const keys = Object.keys(parameters)
const errors: ValidationObject[] = []
for (const key of keys) {
const error = validateCrossSearchRouteParams(parameters, key as keyof CrossSearchRouteParameters)
if (error.error) errors.push(error)
}
return errors
}