1
1
import { Router } from 'express'
2
2
3
- import sql = require( '../lib/sql' )
4
- const { grants, roles } = sql
3
+ import SQL from 'sql-template-strings'
4
+ import sqlTemplates = require( '../lib/sql' )
5
+ const { grants, roles } = sqlTemplates
5
6
import { coalesceRowsToArray } from '../lib/helpers'
6
7
import { RunQuery } from '../lib/connectionPool'
7
8
import { DEFAULT_ROLES , DEFAULT_SYSTEM_SCHEMAS } from '../lib/constants'
@@ -37,13 +38,53 @@ router.get('/', async (req, res) => {
37
38
38
39
router . post ( '/' , async ( req , res ) => {
39
40
try {
40
- const sql = createRoleSqlize ( req . body )
41
- const { data } = await RunQuery ( req . headers . pg , sql )
42
- return res . status ( 200 ) . json ( data )
41
+ const query = createRoleSqlize ( req . body )
42
+ await RunQuery ( req . headers . pg , query )
43
+
44
+ const getRoleQuery = singleRoleByNameSqlize ( roles , req . body . name )
45
+ const role = ( await RunQuery ( req . headers . pg , getRoleQuery ) ) . data [ 0 ]
46
+
47
+ return res . status ( 200 ) . json ( role )
48
+ } catch ( error ) {
49
+ console . log ( 'throwing error' , error )
50
+ res . status ( 500 ) . json ( { error : 'Database error' , status : 500 } )
51
+ }
52
+ } )
53
+
54
+ router . patch ( '/:id' , async ( req , res ) => {
55
+ try {
56
+ const id = req . params . id
57
+ const getRoleQuery = singleRoleSqlize ( roles , id )
58
+ const role = ( await RunQuery ( req . headers . pg , getRoleQuery ) ) . data [ 0 ]
59
+ const { name : oldName } = role
60
+
61
+ const alterRoleArgs = req . body
62
+ alterRoleArgs . oldName = oldName
63
+ const query = alterRoleSqlize ( alterRoleArgs )
64
+ await RunQuery ( req . headers . pg , query )
65
+
66
+ const updated = ( await RunQuery ( req . headers . pg , getRoleQuery ) ) . data [ 0 ]
67
+ return res . status ( 200 ) . json ( updated )
68
+ } catch ( error ) {
69
+ console . log ( 'throwing error' , error )
70
+ res . status ( 500 ) . json ( { error : 'Database error' , status : 500 } )
71
+ }
72
+ } )
73
+
74
+ router . delete ( '/:id' , async ( req , res ) => {
75
+ try {
76
+ const id = req . params . id
77
+ const getRoleQuery = singleRoleSqlize ( roles , id )
78
+ const role = ( await RunQuery ( req . headers . pg , getRoleQuery ) ) . data [ 0 ]
79
+ const { name } = role
80
+
81
+ const query = dropRoleSqlize ( name )
82
+ await RunQuery ( req . headers . pg , query )
83
+
84
+ return res . status ( 200 ) . json ( role )
43
85
} catch ( error ) {
44
- // For this one, we always want to give back the error to the customer
45
- console . log ( 'Soft error!' , error )
46
- res . status ( 200 ) . json ( [ { error : error . toString ( ) } ] )
86
+ console . log ( 'throwing error' , error )
87
+ res . status ( 500 ) . json ( { error : 'Database error' , status : 500 } )
47
88
}
48
89
} )
49
90
@@ -103,7 +144,7 @@ const createRoleSqlize = ({
103
144
const adminsSql = admins === undefined ? '' : `ADMIN ${ admins . join ( ',' ) } `
104
145
105
146
return `
106
- CREATE ROLE ${ name }
147
+ CREATE ROLE " ${ name } "
107
148
WITH
108
149
${ isSuperuserSql }
109
150
${ canCreateDbSql }
@@ -119,6 +160,92 @@ WITH
119
160
${ membersSql }
120
161
${ adminsSql } `
121
162
}
163
+ const singleRoleSqlize = ( roles : string , id : string ) => {
164
+ return SQL `` . append ( roles ) . append ( SQL ` WHERE oid = ${ id } ` )
165
+ }
166
+ const singleRoleByNameSqlize = ( roles : string , name : string ) => {
167
+ return SQL `` . append ( roles ) . append ( SQL ` WHERE rolname = ${ name } ` )
168
+ }
169
+ const alterRoleSqlize = ( {
170
+ oldName,
171
+ name,
172
+ isSuperuser,
173
+ canCreateDb,
174
+ canCreateRole,
175
+ inheritRole,
176
+ canLogin,
177
+ isReplicationRole,
178
+ canBypassRls,
179
+ connectionLimit,
180
+ password,
181
+ validUntil,
182
+ } : {
183
+ oldName : string
184
+ name ?: string
185
+ isSuperuser ?: boolean
186
+ canCreateDb ?: boolean
187
+ canCreateRole ?: boolean
188
+ inheritRole ?: boolean
189
+ canLogin ?: boolean
190
+ isReplicationRole ?: boolean
191
+ canBypassRls ?: boolean
192
+ connectionLimit ?: number
193
+ password ?: string
194
+ validUntil ?: string
195
+ } ) => {
196
+ const nameSql = name === undefined ? '' : `ALTER ROLE "${ oldName } " RENAME TO "${ name } ";`
197
+ let isSuperuserSql = ''
198
+ if ( isSuperuser !== undefined ) {
199
+ isSuperuserSql = isSuperuser ? 'SUPERUSER' : 'NOSUPERUSER'
200
+ }
201
+ let canCreateDbSql = ''
202
+ if ( canCreateDb !== undefined ) {
203
+ canCreateDbSql = canCreateDb ? 'CREATEDB' : 'NOCREATEDB'
204
+ }
205
+ let canCreateRoleSql = ''
206
+ if ( canCreateRole !== undefined ) {
207
+ canCreateRoleSql = canCreateRole ? 'CREATEROLE' : 'NOCREATEROLE'
208
+ }
209
+ let inheritRoleSql = ''
210
+ if ( inheritRole !== undefined ) {
211
+ inheritRoleSql = inheritRole ? 'INHERIT' : 'NOINHERIT'
212
+ }
213
+ let canLoginSql = ''
214
+ if ( canLogin !== undefined ) {
215
+ canLoginSql = canLogin ? 'LOGIN' : 'NOLOGIN'
216
+ }
217
+ let isReplicationRoleSql = ''
218
+ if ( isReplicationRole !== undefined ) {
219
+ isReplicationRoleSql = isReplicationRole ? 'REPLICATION' : 'NOREPLICATION'
220
+ }
221
+ let canBypassRlsSql = ''
222
+ if ( canBypassRls !== undefined ) {
223
+ canBypassRlsSql = canBypassRls ? 'BYPASSRLS' : 'NOBYPASSRLS'
224
+ }
225
+ const connectionLimitSql =
226
+ connectionLimit === undefined ? '' : `CONNECTION LIMIT ${ connectionLimit } `
227
+ let passwordSql = password === undefined ? '' : `PASSWORD '${ password } '`
228
+ let validUntilSql = validUntil === undefined ? '' : `VALID UNTIL '${ validUntil } '`
229
+
230
+ return `
231
+ BEGIN;
232
+ ALTER ROLE "${ oldName } "
233
+ ${ isSuperuserSql }
234
+ ${ canCreateDbSql }
235
+ ${ canCreateRoleSql }
236
+ ${ inheritRoleSql }
237
+ ${ canLoginSql }
238
+ ${ isReplicationRoleSql }
239
+ ${ canBypassRlsSql }
240
+ ${ connectionLimitSql }
241
+ ${ passwordSql }
242
+ ${ validUntilSql } ;
243
+ ${ nameSql }
244
+ COMMIT;`
245
+ }
246
+ const dropRoleSqlize = ( name : string ) => {
247
+ return `DROP ROLE "${ name } "`
248
+ }
122
249
const removeSystemSchemas = ( data : Roles . Role [ ] ) => {
123
250
return data . map ( ( role ) => {
124
251
let grants = role . grants . filter ( ( x ) => ! DEFAULT_SYSTEM_SCHEMAS . includes ( x . schema ) )
0 commit comments