@@ -32,11 +32,13 @@ export interface ConditionalStorage {
32
32
createCondition (
33
33
conditionalDecision : RoleConditionalPolicyDecision < PermissionInfo > ,
34
34
) : Promise < number > ;
35
- findUniqueCondition (
35
+ checkConflictedConditions (
36
36
roleEntityRef : string ,
37
37
resourceType : string ,
38
+ pluginId : string ,
38
39
queryPermissionNames : string [ ] ,
39
- ) : Promise < RoleConditionalPolicyDecision < PermissionInfo > | undefined > ;
40
+ idToExclude ?: number ,
41
+ ) : Promise < void > ;
40
42
getCondition (
41
43
id : number ,
42
44
) : Promise < RoleConditionalPolicyDecision < PermissionInfo > | undefined > ;
@@ -57,7 +59,7 @@ export class DataBaseConditionalStorage implements ConditionalStorage {
57
59
actions ?: PermissionAction [ ] ,
58
60
permissionNames ?: string [ ] ,
59
61
) : Promise < RoleConditionalPolicyDecision < PermissionInfo > [ ] > {
60
- const daoRaws = await this . knex ? .table ( CONDITIONAL_TABLE ) . where ( builder => {
62
+ const daoRaws = await this . knex . table ( CONDITIONAL_TABLE ) . where ( builder => {
61
63
if ( pluginId ) {
62
64
builder . where ( 'pluginId' , pluginId ) ;
63
65
}
@@ -100,22 +102,16 @@ export class DataBaseConditionalStorage implements ConditionalStorage {
100
102
async createCondition (
101
103
conditionalDecision : RoleConditionalPolicyDecision < PermissionInfo > ,
102
104
) : Promise < number > {
103
- const condition = await this . findUniqueCondition (
105
+ await this . checkConflictedConditions (
104
106
conditionalDecision . roleEntityRef ,
105
107
conditionalDecision . resourceType ,
106
- conditionalDecision . permissionMapping . map ( permInfo => permInfo . name ) ,
108
+ conditionalDecision . pluginId ,
109
+ conditionalDecision . permissionMapping . map ( permInfo => permInfo . action ) ,
107
110
) ;
108
- if ( condition ) {
109
- throw new ConflictError (
110
- `A condition with resource type '${ condition . resourceType } '` +
111
- ` and permission '${ JSON . stringify ( condition . permissionMapping ) } '` +
112
- ` has already been stored for role '${ conditionalDecision . roleEntityRef } '` ,
113
- ) ;
114
- }
115
111
116
112
const conditionRaw = this . toDAO ( conditionalDecision ) ;
117
113
const result = await this . knex
118
- ? .table ( CONDITIONAL_TABLE )
114
+ . table ( CONDITIONAL_TABLE )
119
115
. insert < ConditionalPolicyDecisionDAO > ( conditionRaw )
120
116
. returning ( 'id' ) ;
121
117
if ( result && result ?. length > 0 ) {
@@ -125,42 +121,53 @@ export class DataBaseConditionalStorage implements ConditionalStorage {
125
121
throw new Error ( `Failed to create the condition.` ) ;
126
122
}
127
123
128
- async findUniqueCondition (
124
+ async checkConflictedConditions (
129
125
roleEntityRef : string ,
130
126
resourceType : string ,
131
- queryPermissionNames : string [ ] ,
132
- ) : Promise < RoleConditionalPolicyDecision < PermissionInfo > | undefined > {
133
- const daoRaws = await this . knex
134
- ?. table ( CONDITIONAL_TABLE )
135
- . where ( 'roleEntityRef' , roleEntityRef )
136
- . where ( 'resourceType' , resourceType ) ;
127
+ pluginId : string ,
128
+ queryConditionActions : PermissionAction [ ] ,
129
+ idToExclude ?: number ,
130
+ ) : Promise < void > {
131
+ let conditionsForTheSameResource = await this . filterConditions (
132
+ roleEntityRef ,
133
+ pluginId ,
134
+ resourceType ,
135
+ ) ;
136
+ conditionsForTheSameResource = conditionsForTheSameResource . filter (
137
+ c => c . id !== idToExclude ,
138
+ ) ;
137
139
138
- if ( daoRaws ) {
139
- const conditions = daoRaws . map ( daoRaw =>
140
- this . daoToConditionalDecision ( daoRaw ) ,
140
+ if ( conditionsForTheSameResource ) {
141
+ const conflictedCondition = conditionsForTheSameResource . find (
142
+ condition => {
143
+ const conditionActions = condition . permissionMapping . map (
144
+ permInfo => permInfo . action ,
145
+ ) ;
146
+ return queryConditionActions . some ( action =>
147
+ conditionActions . includes ( action ) ,
148
+ ) ;
149
+ } ,
141
150
) ;
142
151
143
- return conditions . find ( condition => {
144
- const conditionPermissionNames = condition . permissionMapping . map (
145
- permInfo => permInfo . name ,
152
+ if ( conflictedCondition ) {
153
+ const conflictedActions = queryConditionActions . filter ( action =>
154
+ conflictedCondition . permissionMapping . some ( p => p . action === action ) ,
146
155
) ;
147
- const isContainTheSamePermissions = queryPermissionNames . every ( name =>
148
- conditionPermissionNames . includes ( name ) ,
156
+ throw new ConflictError (
157
+ `Found condition with conflicted permission action '${ JSON . stringify (
158
+ conflictedActions ,
159
+ ) } '. Role could have multiple ` +
160
+ `conditions for the same resource type '${ conflictedCondition . resourceType } ', but with different permission action sets.` ,
149
161
) ;
150
- return (
151
- isContainTheSamePermissions &&
152
- conditionPermissionNames . length === queryPermissionNames . length
153
- ) ;
154
- } ) ;
162
+ }
155
163
}
156
- return undefined ;
157
164
}
158
165
159
166
async getCondition (
160
167
id : number ,
161
168
) : Promise < RoleConditionalPolicyDecision < PermissionInfo > | undefined > {
162
169
const daoRaw = await this . knex
163
- ? .table ( CONDITIONAL_TABLE )
170
+ . table ( CONDITIONAL_TABLE )
164
171
. where ( 'id' , id )
165
172
. first ( ) ;
166
173
@@ -187,35 +194,18 @@ export class DataBaseConditionalStorage implements ConditionalStorage {
187
194
throw new NotFoundError ( `Condition with id ${ id } was not found` ) ;
188
195
}
189
196
190
- const conditionsForTheSameResource = await this . filterConditions (
197
+ await this . checkConflictedConditions (
191
198
conditionalDecision . roleEntityRef ,
192
- conditionalDecision . pluginId ,
193
199
conditionalDecision . resourceType ,
200
+ conditionalDecision . pluginId ,
201
+ conditionalDecision . permissionMapping . map ( perm => perm . action ) ,
202
+ id ,
194
203
) ;
195
204
196
- for ( const permission of conditionalDecision . permissionMapping ) {
197
- for ( const conditionToCompare of conditionsForTheSameResource ) {
198
- if ( conditionToCompare . id === id ) {
199
- continue ;
200
- }
201
- const conditionPermNames = conditionToCompare . permissionMapping . map (
202
- perm => perm . name ,
203
- ) ;
204
- if ( conditionPermNames . includes ( permission . name ) ) {
205
- throw new ConflictError (
206
- `Found condition with conflicted permission '${ JSON . stringify (
207
- permission ,
208
- ) } '. Role could have multiple ` +
209
- `conditions for the same resource type '${ conditionalDecision . resourceType } ', but with different permission name and action sets.` ,
210
- ) ;
211
- }
212
- }
213
- }
214
-
215
205
const conditionRaw = this . toDAO ( conditionalDecision ) ;
216
206
conditionRaw . id = id ;
217
207
const result = await this . knex
218
- ? .table ( CONDITIONAL_TABLE )
208
+ . table ( CONDITIONAL_TABLE )
219
209
. where ( 'id' , conditionRaw . id )
220
210
. update < ConditionalPolicyDecisionDAO > ( conditionRaw )
221
211
. returning ( 'id' ) ;
0 commit comments