001package ca.cdr.api.model.enm;
002
003/*
004 * #%L
005 * Smile CDR - CDR
006 * %%
007 * Copyright (C) 2016 - 2025 Smile CDR, Inc.
008 * %%
009 * All rights reserved.
010 * #L%
011 */
012
013import ca.cdr.api.security.permission.PermissionArgumentFormat;
014import ca.cdr.api.security.permission.PermissionArgumentFormats;
015import jakarta.annotation.Nonnull;
016import org.apache.commons.text.StringTokenizer;
017
018import java.util.ArrayList;
019import java.util.Arrays;
020import java.util.Collection;
021import java.util.Collections;
022import java.util.EnumSet;
023import java.util.List;
024import java.util.Locale;
025import java.util.Optional;
026import java.util.Set;
027import java.util.stream.Collectors;
028
029import static org.apache.commons.lang3.StringUtils.isBlank;
030import static org.apache.commons.lang3.StringUtils.isNotBlank;
031import static org.apache.commons.lang3.StringUtils.trim;
032
033public enum PermissionEnum {
034
035        /*
036         * Sorting agnostic, but don't change which one is first because swagger uses it as an example.
037         */
038
039        /**
040         * User has permission to change password
041         */
042        CHANGE_OWN_PASSWORD(PermissionCategoryEnum.USER_MANAGER),
043
044        /**
045         * User can log in to EasyShare
046         */
047        ACCESS_EASYSHARE(PermissionCategoryEnum.EASYSHARE),
048
049        /**
050         * User can create a SMART Health Link using EasyShare
051         */
052        EASYSHARE_CREATE_SMART_HEALTH_LINK(PermissionCategoryEnum.EASYSHARE, PermissionEnum.ACCESS_EASYSHARE),
053
054        //      TODO: add this once this UI is created
055        //      /**
056        //       * User can manage SMART Health Links in EasyShare
057        //       */
058        //      EASYSHARE_MANAGE_ALL_SMART_HEALTH_LINKS(
059        //                      PermissionCategoryEnum.EASYSHARE, new PermissionEnum[] {PermissionEnum.ACCESS_EASYSHARE}),
060
061        /**
062         * User can update their own launch contexts
063         */
064        CHANGE_OWN_DEFAULT_LAUNCH_CONTEXTS(PermissionCategoryEnum.USER_MANAGER),
065
066        /**
067         * User can change their own TFA key
068         */
069        CHANGE_OWN_TFA_KEY(PermissionCategoryEnum.USER_MANAGER),
070
071        /**
072         * User is allowed to log into the web admin console
073         */
074        ACCESS_ADMIN_WEB(PermissionCategoryEnum.ADMIN, CHANGE_OWN_PASSWORD),
075
076        /**
077         * User is allowed to use the JSON Admin API services
078         */
079        ACCESS_ADMIN_JSON(PermissionCategoryEnum.ADMIN),
080
081        /**
082         * User is allowed to access FHIR services
083         */
084        ACCESS_FHIR_ENDPOINT(PermissionCategoryEnum.FHIR_CLIENT),
085
086        /**
087         * User has permission to log into the FHIRWeb console
088         */
089        ACCESS_FHIRWEB(PermissionCategoryEnum.ADMIN),
090
091        /**
092         * User can access internal metrics API, including thread dump API
093         */
094        VIEW_METRICS(PermissionCategoryEnum.ADMIN),
095
096        /**
097         * User can see (but not change) status information about modules. This includes running/stopped status, health checks, etc., but does not give access to more sensitive details such as logs.
098         */
099        VIEW_MODULE_STATUS(PermissionCategoryEnum.ADMIN),
100
101        /**
102         * User can see (but not change) module configuration information (not including database passwords)
103         */
104        VIEW_MODULE_CONFIG(PermissionCategoryEnum.ADMIN, VIEW_MODULE_STATUS),
105
106        /**
107         * User can archive module
108         */
109        ARCHIVE_MODULE(PermissionCategoryEnum.ADMIN, VIEW_MODULE_CONFIG),
110
111        /**
112         * User can reinstate module
113         */
114        REINSTATE_MODULE(PermissionCategoryEnum.ADMIN, VIEW_MODULE_CONFIG),
115
116        /**
117         * User is allowed to view existing OpenID Connect client list
118         */
119        OPENID_CONNECT_VIEW_CLIENT_LIST(PermissionCategoryEnum.ADMIN),
120
121        /**
122         * User is allowed to view existing OpenID Connect server list
123         */
124        OPENID_CONNECT_VIEW_SERVER_LIST(PermissionCategoryEnum.ADMIN),
125
126        /**
127         * User is allowed to create OpenID Connect clients
128         */
129        OPENID_CONNECT_ADD_CLIENT(PermissionCategoryEnum.ADMIN),
130
131        /**
132         * User is allowed to create OpenID Connect clients with pre-set permissions
133         */
134        OIDC_CLIENT_PRESET_PERMISSION(
135                        PermissionCategoryEnum.ADMIN,
136                        OPENID_CONNECT_ADD_CLIENT,
137                        TakesArgumentEnum.YES,
138                        PermissionArgumentFormats.NO_ARGUMENT_FORMAT),
139
140        /**
141         * User is allowed to add OpenID Connect servers
142         */
143        OPENID_CONNECT_ADD_SERVER(PermissionCategoryEnum.ADMIN),
144
145        /**
146         * User is allowed to edit OpenID Connect servers
147         */
148        OPENID_CONNECT_EDIT_SERVER(PermissionCategoryEnum.ADMIN),
149
150        /**
151         * User is allowed to edit existing OpenID Connect clients
152         */
153        OPENID_CONNECT_EDIT_CLIENT(PermissionCategoryEnum.ADMIN),
154
155        /**
156         * User is allows to manage other users' OIDC sessions (view active sessions and revoke them).
157         */
158        OPENID_CONNECT_MANAGE_GLOBAL_SESSIONS(PermissionCategoryEnum.ADMIN),
159
160        /**
161         * User is allowed to manage (view/create/update/delete) OIDC Keystore definitions
162         */
163        OPENID_CONNECT_MANAGE_KEYSTORES(PermissionCategoryEnum.ADMIN),
164
165        /**
166         * User can create other users
167         */
168        CREATE_USER(PermissionCategoryEnum.USER_MANAGER),
169
170        /**
171         * User can update existing users other than themself
172         */
173        UPDATE_USER(PermissionCategoryEnum.USER_MANAGER),
174
175        /**
176         * User can view list of users
177         */
178        VIEW_USERS(PermissionCategoryEnum.USER_MANAGER),
179
180        /**
181         * User can view, create, and update users
182         */
183        SAVE_USER(PermissionCategoryEnum.USER_MANAGER, CREATE_USER, UPDATE_USER, VIEW_USERS),
184
185        /**
186         * User is allowed to use a FHIR client
187         */
188        ROLE_FHIR_CLIENT(PermissionCategoryEnum.FHIR_CLIENT, ACCESS_FHIR_ENDPOINT),
189
190        /**
191         * Actions performed by the system itself.
192         * Implied permissions are populated internally and not explicitly defined in the constructor.
193         */
194        ROLE_SYSTEM(PermissionCategoryEnum.SYSTEM),
195
196        /**
197         * Actions performed by the system itself during initialization
198         */
199        ROLE_SYSTEM_INITIALIZATION(PermissionCategoryEnum.SYSTEM, ROLE_SYSTEM),
200
201        /**
202         * User is allowed to view the audit log
203         */
204        VIEW_AUDIT_LOG(PermissionCategoryEnum.ADMIN),
205
206        /**
207         * User is allowed to view the transaction log
208         */
209        VIEW_TRANSACTION_LOG(PermissionCategoryEnum.ADMIN),
210
211        /**
212         * User is allowed to view entries in the transaction log
213         */
214        VIEW_TRANSACTION_LOG_EVENT(PermissionCategoryEnum.ADMIN),
215
216        /**
217         * User is allows to modify a module's configuration
218         */
219        UPDATE_MODULE_CONFIG(PermissionCategoryEnum.ADMIN, VIEW_MODULE_CONFIG),
220
221        /**
222         * User is allowed to start/stop modules
223         */
224        START_STOP_MODULE(PermissionCategoryEnum.ADMIN),
225
226        /**
227         * User can start/stop/restart modules
228         */
229        CONTROL_MODULE(PermissionCategoryEnum.ADMIN, VIEW_MODULE_CONFIG, START_STOP_MODULE),
230
231        /**
232         * User is allowed to create new modules
233         */
234        CREATE_MODULE(PermissionCategoryEnum.ADMIN, VIEW_MODULE_CONFIG),
235
236        /**
237         * User is allowed to create, reconfigure and start/stop modules
238         */
239        MODULE_ADMIN(
240                        PermissionCategoryEnum.ADMIN,
241                        CREATE_MODULE,
242                        UPDATE_MODULE_CONFIG,
243                        CONTROL_MODULE,
244                        REINSTATE_MODULE,
245                        ARCHIVE_MODULE,
246                        START_STOP_MODULE,
247                        VIEW_MODULE_CONFIG),
248
249        /**
250         * User is allowed to access (includes both read and write operations) data in all
251         * partitions. Note that this permission does not actually authorize any specific read/write
252         * operations, it simply implies access to the partitions.
253         */
254        FHIR_ACCESS_PARTITION_ALL(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
255
256        /**
257         * User is allowed to access (includes both read and write operations) data in the given
258         * partition. Note that this permission does not actually authorize any specific read/write
259         * operations, it simply implies access to the given partition.
260         */
261        FHIR_ACCESS_PARTITION_NAME(
262                        PermissionCategoryEnum.FHIR_CLIENT,
263                        ROLE_FHIR_CLIENT,
264                        TakesArgumentEnum.YES,
265                        PermissionArgumentFormats.NO_ARGUMENT_FORMAT),
266
267        /**
268         * User is allowed to invoke the ConceptMap/$hapi.fhir.add-mapping and
269         * ConceptMap/$hapi.fhir.remove-mapping operations
270         */
271        FHIR_OP_ADD_AND_REMOVE_CONCEPT_MAPPING(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
272
273        /**
274         * User is allowed to invoke the $binary-access-XXX operation (note that the user
275         * will also need permission to read/write the individual resource that is
276         * actually being accessed)
277         */
278        FHIR_OP_BINARY_ACCESS_READ(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
279
280        /**
281         * User is allowed to invoke the $binary-access-XXX operation (note that the user
282         * will also need permission to read/write the individual resource that is
283         * actually being accessed)
284         */
285        FHIR_OP_BINARY_ACCESS_WRITE(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
286
287        /**
288         * User is allowed to invoke the $hapi.fhir.bulk-patch operation. This is a potentially destructive
289         * operation, so this permission should only be granted to trusted administrative
290         * users. The Bulk Patch operation must also be enabled in the FHIR Storage module
291         * configuration to use this operation.
292         */
293        FHIR_OP_BULK_PATCH(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
294
295        /**
296         * User is allowed to invoke the $hapi.fhir.bulk-patch-rewrite-history operation. This is a potentially destructive
297         * operation, so this permission should only be granted to trusted administrative
298         * users. The Bulk Patch operation must also be enabled in the FHIR Storage module
299         * configuration to use this operation.
300         */
301        FHIR_OP_BULK_PATCH_REWRITE_HISTORY(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
302
303        /**
304         * User is allowed to initiate a bulk data export using the $export operation
305         */
306        FHIR_OP_INITIATE_BULK_DATA_EXPORT(
307                        PermissionCategoryEnum.FHIR_CLIENT,
308                        ROLE_FHIR_CLIENT,
309                        TakesArgumentEnum.OPTIONAL,
310                        PermissionArgumentFormats.EXPORT_RESOURCE_TYPES_FORMAT),
311
312        /**
313         * User is allowed to initiate a bulk data import using the $import operation
314         */
315        FHIR_OP_INITIATE_BULK_DATA_IMPORT(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
316
317        /**
318         * Bulk export - group Level
319         */
320        FHIR_OP_INITIATE_BULK_DATA_EXPORT_GROUP(
321                        PermissionCategoryEnum.FHIR_CLIENT,
322                        ROLE_FHIR_CLIENT,
323                        TakesArgumentEnum.YES,
324                        PermissionArgumentFormats.COMPARTMENT_WITH_EXPORT_RESOURCE_TYPES_FORMAT),
325
326        /**
327         * Bulk export - Patient Level
328         *
329         * @deprecated In favour of FHIR_OP_INITIATE_BULK_DATA_EXPORT_PATIENTS and FHIR_OP_INITIATE_BULK_DATA_EXPORT_ALL_PATIENTS
330         */
331        @Deprecated
332        FHIR_OP_INITIATE_BULK_DATA_EXPORT_PATIENT(
333                        PermissionCategoryEnum.FHIR_CLIENT,
334                        ROLE_FHIR_CLIENT,
335                        TakesArgumentEnum.OPTIONAL,
336                        PermissionArgumentFormats.COMPARTMENT_WITH_EXPORT_RESOURCE_TYPES_FORMAT),
337
338        /**
339         * Bulk Export for a list of patient IDs and resource types
340         */
341        FHIR_OP_INITIATE_BULK_DATA_EXPORT_PATIENTS(
342                        PermissionCategoryEnum.FHIR_CLIENT,
343                        ROLE_FHIR_CLIENT,
344                        TakesArgumentEnum.OPTIONAL,
345                        PermissionArgumentFormats.COMPARTMENTS_WITH_EXPORT_RESOURCE_TYPES_FORMAT),
346
347        /**
348         * Bulk Export for all patients
349         */
350        FHIR_OP_INITIATE_BULK_DATA_EXPORT_ALL_PATIENTS(
351                        PermissionCategoryEnum.FHIR_CLIENT,
352                        ROLE_FHIR_CLIENT,
353                        TakesArgumentEnum.NO,
354                        PermissionArgumentFormats.OPTIONAL_FILTER_FORMAT),
355
356        /**
357         * Bulk export - System Level
358         */
359        FHIR_OP_INITIATE_BULK_DATA_EXPORT_SYSTEM(
360                        PermissionCategoryEnum.FHIR_CLIENT,
361                        ROLE_FHIR_CLIENT,
362                        TakesArgumentEnum.OPTIONAL,
363                        PermissionArgumentFormats.EXPORT_RESOURCE_TYPES_FORMAT),
364
365        /**
366         * User is allowed to invoke the server-level $reindex operation.
367         */
368        FHIR_OP_REINDEX(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
369
370        /**
371         * User is allowed to read search parameters
372         */
373        FHIR_READ_SEARCH_PARAMETERS(
374                        PermissionCategoryEnum.FHIR_CLIENT,
375                        new PermissionEnum[] {
376                                // does not imply FHIR_CLIENT since this can be used for JSON Admin functions too
377                        }),
378
379        /**
380         * User is allowed to create, update, and delete search parameters
381         */
382        FHIR_MODIFY_SEARCH_PARAMETERS(
383                        PermissionCategoryEnum.FHIR_CLIENT,
384                        new PermissionEnum[] {
385                                // does not imply FHIR_CLIENT since this can be used for JSON Admin functions too
386                        }),
387
388        /**
389         * User is allowed to read any resources in the given compartment
390         */
391        FHIR_READ_ALL_IN_COMPARTMENT(
392                        PermissionCategoryEnum.FHIR_CLIENT,
393                        ROLE_FHIR_CLIENT,
394                        TakesArgumentEnum.YES,
395                        PermissionArgumentFormats.COMPARTMENT_WITH_OPTIONAL_FILTER_FORMAT),
396
397        /**
398         * User is allowed to write any resources in the given compartment
399         */
400        FHIR_WRITE_ALL_IN_COMPARTMENT(
401                        PermissionCategoryEnum.FHIR_CLIENT,
402                        ROLE_FHIR_CLIENT,
403                        TakesArgumentEnum.YES,
404                        PermissionArgumentFormats.COMPARTMENT_WITH_OPTIONAL_FILTER_FORMAT),
405
406        /**
407         * User is allowed to read any resources of the given type in the given compartment
408         */
409        FHIR_READ_TYPE_IN_COMPARTMENT(
410                        PermissionCategoryEnum.FHIR_CLIENT,
411                        ROLE_FHIR_CLIENT,
412                        TakesArgumentEnum.YES,
413                        PermissionArgumentFormats.TYPE_IN_COMPARTMENT_WITH_OPTIONAL_FILTER_FORMAT),
414
415        /**
416         * User is allowed to write any resources of the given type in the given compartment
417         */
418        FHIR_WRITE_TYPE_IN_COMPARTMENT(
419                        PermissionCategoryEnum.FHIR_CLIENT,
420                        ROLE_FHIR_CLIENT,
421                        TakesArgumentEnum.YES,
422                        PermissionArgumentFormats.TYPE_IN_COMPARTMENT_WITH_OPTIONAL_FILTER_FORMAT),
423
424        /**
425         * User is allowed to read any resources of the given type
426         */
427        FHIR_READ_ALL_OF_TYPE(
428                        PermissionCategoryEnum.FHIR_CLIENT,
429                        ROLE_FHIR_CLIENT,
430                        TakesArgumentEnum.YES,
431                        PermissionArgumentFormats.RESOURCE_TYPE_OPTIONAL_FILTER_FORMAT),
432
433        /**
434         * User is allowed to write any resources of the given type
435         */
436        FHIR_WRITE_ALL_OF_TYPE(
437                        PermissionCategoryEnum.FHIR_CLIENT,
438                        ROLE_FHIR_CLIENT,
439                        TakesArgumentEnum.YES,
440                        PermissionArgumentFormats.RESOURCE_TYPE_OPTIONAL_FILTER_FORMAT),
441
442        /**
443         * User is allowed to read a specific resource instance by ID
444         */
445        FHIR_READ_INSTANCE(
446                        PermissionCategoryEnum.FHIR_CLIENT,
447                        ROLE_FHIR_CLIENT,
448                        TakesArgumentEnum.YES,
449                        PermissionArgumentFormats.INSTANCE_WITH_OPTIONAL_FILTER_FORMAT),
450
451        /**
452         * User is allowed to write a specific resource instance by ID
453         */
454        FHIR_WRITE_INSTANCE(
455                        PermissionCategoryEnum.FHIR_CLIENT,
456                        ROLE_FHIR_CLIENT,
457                        TakesArgumentEnum.YES,
458                        PermissionArgumentFormats.INSTANCE_WITH_OPTIONAL_FILTER_FORMAT),
459
460        /**
461         * User is allowed to access resources with a code
462         */
463        BLOCK_FHIR_READ_UNLESS_CODE_IN_VS(
464                        PermissionCategoryEnum.FHIR_CLIENT,
465                        TakesArgumentEnum.YES,
466                        true,
467                        PermissionArgumentFormats.CODE_IN_VALUE_SET_FILTER_FORMAT,
468                        new PermissionEnum[] {ROLE_FHIR_CLIENT}),
469
470        /**
471         * User is allowed to access resources with a code
472         */
473        BLOCK_FHIR_READ_UNLESS_CODE_NOT_IN_VS(
474                        PermissionCategoryEnum.FHIR_CLIENT,
475                        TakesArgumentEnum.YES,
476                        true,
477                        PermissionArgumentFormats.CODE_IN_VALUE_SET_FILTER_FORMAT,
478                        new PermissionEnum[] {ROLE_FHIR_CLIENT}),
479
480        /**
481         * User is permitted to invoke the $expunge operation with expungeDeletedResources=true
482         */
483        FHIR_EXPUNGE_DELETED(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
484
485        /**
486         * User is permitted to invoke the $expunge operation with expungePreviousVersions=true
487         */
488        FHIR_EXPUNGE_PREVIOUS_VERSIONS(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
489
490        /**
491         * User is permitted to invoke the $expunge operation with expungeEverything=true
492         */
493        FHIR_EXPUNGE_EVERYTHING(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
494
495        /**
496         * User is permitted to invoke the $delete-expunge operation
497         */
498        FHIR_DELETE_EXPUNGE(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
499
500        /**
501         * User is permitted to invoke the $livebundle-watchlist-add, $livebundle-watchlist-delete, $livebundle-watchlist, and $livebundle operations
502         */
503        FHIR_LIVEBUNDLE(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
504
505        /**
506         * User is permitted to invoke the operations
507         * $partition-management-create-partition,
508         * $partition-management-read-partition,
509         * $partition-management-update-partition,
510         * $partition-management-delete-partition,
511         * $partition-management-list-partitions,
512         */
513        FHIR_MANAGE_PARTITIONS(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
514
515        /**
516         * User is permitted to invoke the $meta, $meta-add, and $meta-delete operations on
517         * any resource.
518         */
519        FHIR_META_OPERATIONS_SUPERUSER(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
520
521        /**
522         * User may invoke any kind of operation
523         */
524        FHIR_EXTENDED_OPERATION_SUPERUSER(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
525
526        /**
527         * User may invoke operation with name specified by argument (e.g. $fooOperation)
528         */
529        FHIR_EXTENDED_OPERATION_ON_SERVER(
530                        PermissionCategoryEnum.FHIR_CLIENT,
531                        ROLE_FHIR_CLIENT,
532                        TakesArgumentEnum.YES,
533                        PermissionArgumentFormats.OPERATION_FORMAT),
534
535        /**
536         * User may invoke operation at the type level with type and name specified by argument (e.g. Patient/$fooOperation)
537         */
538        FHIR_EXTENDED_OPERATION_ON_TYPE(
539                        PermissionCategoryEnum.FHIR_CLIENT,
540                        ROLE_FHIR_CLIENT,
541                        TakesArgumentEnum.YES,
542                        PermissionArgumentFormats.OPERATION_ON_RESOURCE_TYPE_FORMAT),
543
544        /**
545         * User may invoke operation at the instance level for any type with name specified by argument (e.g. $fooOperation)
546         */
547        FHIR_EXTENDED_OPERATION_ON_ANY_INSTANCE(
548                        PermissionCategoryEnum.FHIR_CLIENT,
549                        ROLE_FHIR_CLIENT,
550                        TakesArgumentEnum.YES,
551                        PermissionArgumentFormats.OPERATION_FORMAT),
552
553        /**
554         * User may invoke operation at the instance level with type and name specified by argument (e.g. Patient/$fooOperation)
555         */
556        FHIR_EXTENDED_OPERATION_ON_ANY_INSTANCE_OF_TYPE(
557                        PermissionCategoryEnum.FHIR_CLIENT,
558                        ROLE_FHIR_CLIENT,
559                        TakesArgumentEnum.YES,
560                        PermissionArgumentFormats.OPERATION_ON_RESOURCE_TYPE_FORMAT),
561
562        /**
563         * User may invoke the MDM $match operation on a Patient
564         */
565        FHIR_OP_PATIENT_MATCH(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
566
567        /**
568         * User may invoke the $sdh.mdm-bundle-match operation on a Bundle
569         */
570        FHIR_OP_MDM_BUNDLE_MATCH(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
571
572        /**
573         * User may invoke the MDM $mdm-merge-golden-resources operation on Golden Resources
574         */
575        FHIR_OP_MDM_MERGE_GOLDEN_RESOURCES(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
576
577        /**
578         * User may invoke the MDM $mdm-update-link operation on a Golden Resource
579         */
580        FHIR_OP_MDM_UPDATE_LINK(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
581
582        /**
583         * User may invoke the MDM $mdm-create-link operation on a Golden Resource
584         */
585        FHIR_OP_MDM_CREATE_LINK(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
586
587        /**
588         * User may invoke the MDM $mdm-query-links operation
589         */
590        FHIR_OP_MDM_QUERY_LINKS(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
591
592        /**
593         * User may invoke the MDM $mdm-query-links operation
594         */
595        FHIR_OP_MDM_LINK_HISTORY(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
596
597        /**
598         * User may invoke the MDM $mdm-duplicate-golden-resources
599         */
600        FHIR_OP_MDM_DUPLICATE_GOLDEN_RESOURCES(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
601
602        /**
603         * User may invoke the MDM $mdm-not-duplicate
604         */
605        FHIR_OP_MDM_NOT_DUPLICATE(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
606
607        /**
608         * User may invoke the MDM $mdm-clear Operation
609         */
610        FHIR_OP_MDM_CLEAR(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
611
612        /**
613         * User may invoke the MDM $mdm-submit operation
614         */
615        FHIR_OP_MDM_SUBMIT(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
616
617        /**
618         * User may perform all MDM operations
619         */
620        FHIR_MDM_ADMIN(
621                        PermissionCategoryEnum.FHIR_CLIENT,
622                        FHIR_OP_MDM_SUBMIT,
623                        FHIR_OP_MDM_CLEAR,
624                        FHIR_OP_MDM_DUPLICATE_GOLDEN_RESOURCES,
625                        FHIR_OP_MDM_NOT_DUPLICATE,
626                        FHIR_OP_MDM_MERGE_GOLDEN_RESOURCES,
627                        FHIR_OP_MDM_QUERY_LINKS,
628                        FHIR_OP_MDM_LINK_HISTORY,
629                        FHIR_OP_MDM_UPDATE_LINK,
630                        FHIR_OP_MDM_CREATE_LINK),
631
632        /**
633         * Legacy permission for backward compatibility. Use corresponding MDM permission instead.
634         */
635        FHIR_OP_EMPI_MERGE_PERSONS(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
636
637        /**
638         * Legacy permission for backward compatibility. Use corresponding MDM permission instead.
639         */
640        FHIR_OP_EMPI_UPDATE_LINK(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
641
642        /**
643         * Legacy permission for backward compatibility. Use corresponding MDM permission instead.
644         */
645        FHIR_OP_EMPI_QUERY_LINKS(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
646
647        /**
648         * Legacy permission for backward compatibility. Use corresponding MDM permission instead.
649         */
650        FHIR_OP_EMPI_DUPLICATE_PERSONS(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
651
652        /**
653         * Legacy permission for backward compatibility. Use corresponding MDM permission instead.
654         */
655        FHIR_OP_EMPI_CLEAR(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
656
657        /**
658         * Legacy permission for backward compatibility. Use corresponding MDM permission instead.
659         */
660        FHIR_OP_EMPI_SUBMIT(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
661
662        /**
663         * Legacy permission for backward compatibility. Use corresponding MDM permission instead.
664         */
665        FHIR_EMPI_ADMIN(
666                        PermissionCategoryEnum.FHIR_CLIENT,
667                        FHIR_OP_EMPI_SUBMIT,
668                        FHIR_OP_EMPI_CLEAR,
669                        FHIR_OP_EMPI_DUPLICATE_PERSONS,
670                        FHIR_OP_EMPI_MERGE_PERSONS,
671                        FHIR_OP_EMPI_QUERY_LINKS,
672                        FHIR_OP_EMPI_UPDATE_LINK),
673
674        /**
675         * CQL Permission for evaluate-measure operation.
676         */
677        FHIR_OP_EVALUATE_MEASURE(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
678        /**
679         * Permission for submit-data operation.
680         */
681        FHIR_OP_SUBMIT_DATA(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
682        /**
683         * Permission for care-gaps operation.
684         */
685        FHIR_OP_CARE_GAPS(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
686        /**
687         * Permission for evaluate operation.
688         */
689        FHIR_OP_EVALUATE(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
690        /**
691         * Permission for $collect-data operation.
692         */
693        FHIR_OP_COLLECTDATA(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
694        /**
695         * Permission for $data-requirements operation.
696         */
697        FHIR_OP_DATAREQUIREMENTS(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
698        /**
699         * Permission for cql operation.
700         */
701        FHIR_OP_CQL(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
702        /**
703         * Permission for evaluate-measures operation.
704         */
705        FHIR_OP_EVALUATE_MEASURES(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
706        /**
707         * Permission for qpp-build operation.
708         */
709        DQM_QPP_BUILD(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
710        /**
711         * Permission for job-analytics operation
712         */
713        BATCH_JOB_ANALYTICS(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
714
715        /**
716         * User is permitted to call the $apply operation
717         */
718        FHIR_OP_APPLY(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
719
720        /**
721         * User is permitted to call the $prepopulate operation
722         */
723        FHIR_OP_PREPOPULATE(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
724
725        /**
726         * User is permitted to call the $populate operation
727         */
728        FHIR_OP_POPULATE(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
729
730        /**
731         * User is permitted to call the $extract operation
732         */
733        FHIR_OP_EXTRACT(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
734
735        /**
736         * User is permitted to call the $package operation
737         */
738        FHIR_OP_PACKAGE(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
739
740        /**
741         * User is permitted to call the $hapi.fhir.replace-references operation
742         */
743        FHIR_OP_REPLACE_REFERENCES(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
744
745        /**
746         * User is permitted to call the $merge operation
747         */
748        FHIR_OP_MERGE(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
749
750        /**
751         * User may perform all DTR operations
752         */
753        FHIR_DTR_USER(PermissionCategoryEnum.FHIR_CLIENT, FHIR_OP_PACKAGE, FHIR_OP_POPULATE),
754
755        /**
756         * User is allowed to perform any FHIR read/access-to-data operation, e.g. `read`, `search`, `history`, etc
757         */
758        FHIR_ALL_READ(
759                        PermissionCategoryEnum.FHIR_CLIENT,
760                        TakesArgumentEnum.NO,
761                        false,
762                        PermissionArgumentFormats.OPTIONAL_FILTER_FORMAT,
763                        new PermissionEnum[] {ROLE_FHIR_CLIENT, FHIR_READ_SEARCH_PARAMETERS}),
764
765        /**
766         * User is allowed to perform FHIR transactions
767         */
768        FHIR_TRANSACTION(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
769
770        /**
771         * User is allowed to perform FHIR GraphQL Operations
772         */
773        FHIR_GRAPHQL(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
774
775        /**
776         * User is allowed to perform FHIR transactions
777         */
778        FHIR_BATCH(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
779
780        /**
781         * User is allowed to perform FHIR PATCH operations
782         *
783         * @deprecated FHIR_PATCH will be removed:  Users should instead be granted more granular write permissions that cover PATCH operations.
784         */
785        @Deprecated
786        FHIR_PATCH(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
787
788        /**
789         * User is allowed to perform any FHIR write/modify operation, e.g. `create`, `update`, etc
790         */
791        FHIR_ALL_WRITE(
792                        PermissionCategoryEnum.FHIR_CLIENT,
793                        TakesArgumentEnum.NO,
794                        false,
795                        PermissionArgumentFormats.OPTIONAL_FILTER_FORMAT,
796                        new PermissionEnum[] {ROLE_FHIR_CLIENT, FHIR_MODIFY_SEARCH_PARAMETERS, FHIR_META_OPERATIONS_SUPERUSER}),
797
798        /**
799         * User is allowed to perform any FHIR delete operation
800         */
801        FHIR_ALL_DELETE(
802                        PermissionCategoryEnum.FHIR_CLIENT,
803                        TakesArgumentEnum.OPTIONAL,
804                        false,
805                        PermissionArgumentFormats.OPTIONAL_FILTER_FORMAT,
806                        new PermissionEnum[] {ROLE_FHIR_CLIENT}),
807
808        /**
809         * User is allowed to perform any FHIR delete operation on the given type
810         */
811        FHIR_DELETE_ALL_OF_TYPE(
812                        PermissionCategoryEnum.FHIR_CLIENT,
813                        ROLE_FHIR_CLIENT,
814                        TakesArgumentEnum.YES,
815                        PermissionArgumentFormats.RESOURCE_TYPE_OPTIONAL_FILTER_FORMAT),
816
817        /**
818         * User is allowed to perform any FHIR delete operation on a given compartment
819         */
820        FHIR_DELETE_ALL_IN_COMPARTMENT(
821                        PermissionCategoryEnum.FHIR_CLIENT,
822                        ROLE_FHIR_CLIENT,
823                        TakesArgumentEnum.YES,
824                        PermissionArgumentFormats.COMPARTMENT_WITH_OPTIONAL_FILTER_FORMAT),
825
826        /**
827         * User is allowed to perform any FHIR delete operation on a given compartment
828         */
829        FHIR_DELETE_TYPE_IN_COMPARTMENT(
830                        PermissionCategoryEnum.FHIR_CLIENT,
831                        ROLE_FHIR_CLIENT,
832                        TakesArgumentEnum.YES,
833                        PermissionArgumentFormats.TYPE_IN_COMPARTMENT_WITH_OPTIONAL_FILTER_FORMAT),
834
835        /**
836         * Any delete permissions granted to the user may be applied to cascaded deletes
837         * as well as normal deletes. Note that this permission allows cascaded deletes
838         * to occur, but does not actually grant any permission to delete resources in
839         * the first place. This permission must be combined with other permissions that
840         * grant the ability to cascade deletes.
841         */
842        FHIR_DELETE_CASCADE_ALLOWED(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
843
844        /**
845         * User is allowed to access the server capability statement
846         */
847        FHIR_CAPABILITIES(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
848
849        /**
850         * User is allowed to invoke the `$validate` operation to validate resources
851         */
852        FHIR_MANUAL_VALIDATION(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
853
854        /**
855         * User is allowed to invoke the `$semantic-uplift` operation to uplift resources
856         */
857        FHIR_SEMANTIC_UPLIFT(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
858
859        /**
860         * User is allowed to invoke the `$process-message` operation to accept a message
861         */
862        FHIR_PROCESS_MESSAGE(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
863
864        /**
865         * User is permitted to upload external code systems
866         */
867        FHIR_UPLOAD_EXTERNAL_TERMINOLOGY(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
868
869        /**
870         * User is permitted to call the $get-resource-counts operation
871         */
872        FHIR_GET_RESOURCE_COUNTS(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
873
874        /**
875         * User is allowed to invoke the $trigger-subscription operation
876         */
877        FHIR_TRIGGER_SUBSCRIPTION(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
878
879        /**
880         * User is permitted to call read-only terminology methods, such as
881         * $lookup, $validate-code
882         */
883        ROLE_FHIR_TERMINOLOGY_READ_CLIENT(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
884
885        /**
886         * User is allowed to perform the patient $everything operation
887         */
888        FHIR_OP_PATIENT_EVERYTHING(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
889
890        /**
891         * User is allowed to perform the patient $everything operation with `Access All` permission
892         */
893        FHIR_OP_PATIENT_EVERYTHING_ACCESS_ALL(
894                        PermissionCategoryEnum.FHIR_CLIENT,
895                        ROLE_FHIR_CLIENT,
896                        TakesArgumentEnum.YES,
897                        PermissionArgumentFormats.INSTANCE_WITH_OPTIONAL_FILTER_FORMAT),
898
899        /**
900         * User is allowed to perform the patient $summary operation
901         */
902        FHIR_OP_PATIENT_SUMMARY(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
903
904        /**
905         * User is allowed to perform the encounter $everything operation
906         */
907        FHIR_OP_ENCOUNTER_EVERYTHING(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
908
909        /**
910         * User is allowed to perform the $snapshot operation
911         */
912        FHIR_OP_STRUCTUREDEFINITION_SNAPSHOT(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
913
914        /**
915         * User is allowed to perform the $member-match operation
916         */
917        FHIR_OP_MEMBER_MATCH(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
918
919        /**
920         * User is allowed to execute HFQL queries
921         */
922        HFQL_EXECUTE(),
923
924        /**
925         * Any read functions
926         */
927        ROLE_FHIR_CLIENT_SUPERUSER_RO(
928                        PermissionCategoryEnum.FHIR_CLIENT,
929                        FHIR_CAPABILITIES,
930                        FHIR_ALL_READ,
931                        FHIR_TRANSACTION,
932                        FHIR_GRAPHQL,
933                        FHIR_BATCH,
934                        FHIR_OP_ENCOUNTER_EVERYTHING,
935                        FHIR_OP_PATIENT_EVERYTHING,
936                        FHIR_OP_PATIENT_SUMMARY,
937                        FHIR_OP_BINARY_ACCESS_READ,
938                        FHIR_GET_RESOURCE_COUNTS,
939                        ROLE_FHIR_TERMINOLOGY_READ_CLIENT,
940                        FHIR_OP_INITIATE_BULK_DATA_EXPORT),
941
942        /**
943         * User has permission to perform any standard FHIR client operation (does not imply superuser status for other parts of the CDR, e.g. user management, FHIR search parameter modification, etc)
944         * Implied permissions are populated internally and not explicitly defined in the constructor.
945         */
946        ROLE_FHIR_CLIENT_SUPERUSER(PermissionCategoryEnum.FHIR_CLIENT),
947
948        /**
949         * User has all permissions to do anything
950         * Implied permissions are populated internally and not explicitly defined in the constructor.
951         */
952        ROLE_SUPERUSER(PermissionCategoryEnum.ADMIN),
953
954        /**
955         * User is not logged in or has not supplied credentials
956         */
957        ROLE_ANONYMOUS(),
958
959        /**
960         * User is allowed to initiate processing an ETL job
961         */
962        ETL_IMPORT_PROCESS_FILE(),
963
964        /**
965         * User is allowed to view CDA Document Templates
966         */
967        VIEW_CDA_TEMPLATE(PermissionCategoryEnum.CDA),
968
969        /**
970         * User is allowed to create new CDA Document Templates
971         */
972        CREATE_CDA_TEMPLATE(PermissionCategoryEnum.CDA, PermissionEnum.VIEW_CDA_TEMPLATE),
973
974        /**
975         * User is allowed to delete CDA Document Templates
976         */
977        DELETE_CDA_TEMPLATE(PermissionCategoryEnum.CDA, PermissionEnum.VIEW_CDA_TEMPLATE),
978
979        /**
980         * User is allowed to use CDA Document Templates,
981         * potentially persisting a Composition, Bundle, and returning sensitive information in the resultant XML
982         */
983        USE_CDA_TEMPLATE(PermissionCategoryEnum.CDA, PermissionEnum.VIEW_CDA_TEMPLATE),
984
985        /**
986         * User can set/update MDM match rules
987         */
988        MDM_UPDATE_MATCH_RULES(PermissionCategoryEnum.MDM),
989
990        /**
991         * User can see MDM match rules
992         */
993        MDM_VIEW_MATCH_RULES(PermissionCategoryEnum.MDM),
994
995        /**
996         * User can perform any MDM operations
997         */
998        MDM_ADMIN(PermissionCategoryEnum.MDM, PermissionEnum.MDM_VIEW_MATCH_RULES, PermissionEnum.MDM_UPDATE_MATCH_RULES),
999
1000        /**
1001         * User will have MDM expansion performed automatically on all queries
1002         */
1003        FHIR_AUTO_MDM(PermissionCategoryEnum.MDM),
1004
1005        /**
1006         * Legacy permission for backward compatibility. Use corresponding MDM permission instead.
1007         */
1008        EMPI_UPDATE_MATCH_RULES(PermissionCategoryEnum.EMPI),
1009
1010        /**
1011         * Legacy permission for backward compatibility. Use corresponding MDM permission instead.
1012         */
1013        EMPI_VIEW_MATCH_RULES(PermissionCategoryEnum.EMPI),
1014
1015        /**
1016         * Legacy permission for backward compatibility. Use corresponding MDM permission instead.
1017         */
1018        EMPI_ADMIN(
1019                        PermissionCategoryEnum.EMPI, PermissionEnum.EMPI_VIEW_MATCH_RULES, PermissionEnum.EMPI_UPDATE_MATCH_RULES),
1020
1021        /**
1022         * User can perform read operations from the package registry
1023         */
1024        PACKAGE_REGISTRY_READ(PermissionCategoryEnum.PACKAGE_REGISTRY),
1025
1026        /**
1027         * User can perform read operations from the package registry
1028         */
1029        PACKAGE_REGISTRY_WRITE(PermissionCategoryEnum.PACKAGE_REGISTRY),
1030
1031        /**
1032         * User can call CDS Hooks
1033         */
1034        INVOKE_CDS_HOOKS(PermissionCategoryEnum.CDS_HOOKS),
1035
1036        /**
1037         * User can perform read operations from the appSphere Admin Console
1038         */
1039        AG_ADMIN_CONSOLE_READ(PermissionCategoryEnum.AG_ADMIN_CONSOLE),
1040
1041        /**
1042         * User can perform write operations from the appSphere Admin Console
1043         */
1044        AG_ADMIN_CONSOLE_WRITE(PermissionCategoryEnum.AG_ADMIN_CONSOLE),
1045
1046        /**
1047         * User can perform read operations from the appSphere Developer Portal
1048         */
1049        AG_DEV_PORTAL_READ(PermissionCategoryEnum.AG_DEV_PORTAL),
1050
1051        /**
1052         * User can perform write operations from the appSphere Developer Portal
1053         */
1054        AG_DEV_PORTAL_WRITE(PermissionCategoryEnum.AG_DEV_PORTAL),
1055
1056        /**
1057         * User has permission to view batch jobs
1058         */
1059        VIEW_BATCH_JOBS(PermissionCategoryEnum.ADMIN),
1060
1061        /**
1062         * User has permission to manage (modify) batch jobs
1063         */
1064        MANAGE_BATCH_JOBS(PermissionCategoryEnum.ADMIN),
1065
1066        /**
1067         * User can perform a docref operation
1068         */
1069        DOCREF(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
1070
1071        /**
1072         * User can perform a CDA Import operation
1073         */
1074        CDA_IMPORT(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
1075
1076        /**
1077         * User can perform the $sdh.cda-to-fhir operation
1078         */
1079        SDH_CDA_TO_FHIR(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
1080
1081        /**
1082         * User can perform the $sdh.generate-cda operation
1083         */
1084        SMILE_GENERATE_CDA(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
1085
1086        /**
1087         * User can perform an update on the historical version of a resource
1088         */
1089        FHIR_UPDATE_REWRITE_HISTORY(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
1090
1091        SUBMIT_ATTACHMENT(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
1092
1093        /**
1094         * User can see (but not change) module configuration information (not including database passwords)
1095         * for a specific module id for a node id
1096         */
1097        VIEW_MODULE_CONFIG_FOR_MODULE(
1098                        PermissionCategoryEnum.ADMIN,
1099                        TakesArgumentEnum.YES,
1100                        false,
1101                        PermissionArgumentFormats.NODE_AND_MODULE_ID_PERMISSION_ARGUMENT_FORMAT,
1102                        new PermissionEnum[] {}),
1103        /**
1104         * User is allowed to modify a specific module id's configuration for a node id
1105         */
1106        UPDATE_MODULE_CONFIG_FOR_MODULE(
1107                        PermissionCategoryEnum.ADMIN,
1108                        TakesArgumentEnum.YES,
1109                        false,
1110                        PermissionArgumentFormats.NODE_AND_MODULE_ID_PERMISSION_ARGUMENT_FORMAT,
1111                        new PermissionEnum[] {VIEW_MODULE_CONFIG_FOR_MODULE}),
1112        /**
1113         * User is allowed to start/stop a specific module id for a node id
1114         */
1115        START_STOP_MODULE_FOR_MODULE(
1116                        PermissionCategoryEnum.ADMIN,
1117                        TakesArgumentEnum.YES,
1118                        false,
1119                        PermissionArgumentFormats.NODE_AND_MODULE_ID_PERMISSION_ARGUMENT_FORMAT,
1120                        new PermissionEnum[] {}),
1121        /**
1122         * User can start/stop/restart a specific module id for a node id
1123         */
1124        CONTROL_MODULE_FOR_MODULE(
1125                        PermissionCategoryEnum.ADMIN,
1126                        TakesArgumentEnum.YES,
1127                        false,
1128                        PermissionArgumentFormats.NODE_AND_MODULE_ID_PERMISSION_ARGUMENT_FORMAT,
1129                        new PermissionEnum[] {VIEW_MODULE_CONFIG_FOR_MODULE, START_STOP_MODULE_FOR_MODULE}),
1130
1131        /**
1132         * User is allowed to reconfigure and start/stop a specific module id for a node id
1133         */
1134        MODULE_ADMIN_FOR_MODULE(
1135                        PermissionCategoryEnum.ADMIN,
1136                        TakesArgumentEnum.YES,
1137                        false,
1138                        PermissionArgumentFormats.NODE_AND_MODULE_ID_PERMISSION_ARGUMENT_FORMAT,
1139                        new PermissionEnum[] {
1140                                UPDATE_MODULE_CONFIG_FOR_MODULE,
1141                                CONTROL_MODULE_FOR_MODULE,
1142                                START_STOP_MODULE_FOR_MODULE,
1143                                VIEW_MODULE_CONFIG_FOR_MODULE
1144                        }),
1145        ROLE_MDMUI_DATASTEWARD_FHIR(
1146                        PermissionCategoryEnum.FHIR_CLIENT,
1147                        FHIR_ALL_READ,
1148                        FHIR_BATCH,
1149                        FHIR_TRANSACTION,
1150                        FHIR_OP_MDM_DUPLICATE_GOLDEN_RESOURCES,
1151                        FHIR_OP_MDM_LINK_HISTORY,
1152                        FHIR_OP_MDM_MERGE_GOLDEN_RESOURCES,
1153                        FHIR_OP_MDM_NOT_DUPLICATE,
1154                        FHIR_OP_MDM_QUERY_LINKS,
1155                        FHIR_OP_MDM_UPDATE_LINK,
1156                        ROLE_FHIR_TERMINOLOGY_READ_CLIENT),
1157        ROLE_MDMUI_ADMIN_FHIR(
1158                        PermissionCategoryEnum.FHIR_CLIENT, ROLE_MDMUI_DATASTEWARD_FHIR, FHIR_OP_MDM_CLEAR, FHIR_OP_MDM_SUBMIT),
1159
1160        /** User will be assigned roles by giving permission APP_ROLE/MDM_UI_DATA_STEWARD */
1161        APP_ROLE(
1162                        PermissionCategoryEnum.ROLE,
1163                        TakesArgumentEnum.YES,
1164                        false,
1165                        PermissionArgumentFormats.ROLE_NAME_FORMAT,
1166                        new PermissionEnum[] {}),
1167
1168        CUSTOM_ROLE(
1169                        PermissionCategoryEnum.ROLE,
1170                        TakesArgumentEnum.YES,
1171                        false,
1172                        PermissionArgumentFormats.ROLE_NAME_FORMAT,
1173                        new PermissionEnum[] {}),
1174
1175        FHIR_OP_UPDATE_TOKENIZATION(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
1176        ;
1177
1178        private static final Set<PermissionEnum> ROLES = getRoles();
1179
1180        static {
1181                ROLE_SYSTEM.myImplies = getAllPermissions();
1182                ROLE_SUPERUSER.myImplies = getAllSuperuserPermissions();
1183                ROLE_FHIR_CLIENT_SUPERUSER.myImplies = getAllFhirSuperuserPermissions();
1184
1185                /*
1186                 * Creating EnumSet with enum elements that have not been initialized fails (not a bug).
1187                 * Use a static block to replace Set with EnumSet once everything is initialized.
1188                 * {@link https://bugs.openjdk.org/browse/JDK-8211749}.
1189                 */
1190                for (PermissionEnum next : values()) {
1191                        next.myImplies = unmodifiableEnumSet(next.myImplies.toArray(new PermissionEnum[0]));
1192                }
1193        }
1194
1195        private final TakesArgumentEnum myTakesArgument;
1196        private final boolean myNegativePermission;
1197        private Set<PermissionEnum> myImplies;
1198        private final PermissionCategoryEnum myCategory;
1199        /**
1200         * The format for the argument - defaults to no argument
1201         */
1202        private final PermissionArgumentFormat<?> myFormat;
1203
1204        /**
1205         * Constructor for permissions with just a name
1206         */
1207        PermissionEnum() {
1208                this(null);
1209        }
1210
1211        /**
1212         * Constructor for permissions with an assigned category
1213         */
1214        PermissionEnum(PermissionCategoryEnum theCategory) {
1215                this(theCategory, new PermissionEnum[] {});
1216        }
1217
1218        /**
1219         * Constructor for permissions that have implied (underlying) permissions
1220         */
1221        PermissionEnum(PermissionCategoryEnum theCategory, PermissionEnum... theImplies) {
1222                this(theCategory, TakesArgumentEnum.NO, false, PermissionArgumentFormats.NO_ARGUMENT_FORMAT, theImplies);
1223        }
1224
1225        /**
1226         * Constructor for permissions with arguments.
1227         */
1228        PermissionEnum(
1229                        PermissionCategoryEnum theCategory,
1230                        PermissionEnum theImplied,
1231                        TakesArgumentEnum theTakesArgument,
1232                        PermissionArgumentFormat<?> theFormat) {
1233                this(theCategory, theTakesArgument, false, theFormat, new PermissionEnum[] {theImplied});
1234        }
1235
1236        /**
1237         * Constructor for permissions with implied (underlying) permissions and/or with arguments.
1238         */
1239        PermissionEnum(
1240                        PermissionCategoryEnum theCategory,
1241                        TakesArgumentEnum theTakesArgument,
1242                        boolean theNegativePermission,
1243                        PermissionArgumentFormat<?> theFormat,
1244                        PermissionEnum[] theImplies) {
1245                assert theTakesArgument != null;
1246                assert !theNegativePermission || name().startsWith("BLOCK_");
1247                myImplies = Set.of(theImplies);
1248                myCategory = theCategory;
1249                myTakesArgument = theTakesArgument;
1250                myNegativePermission = theNegativePermission;
1251                myFormat = theFormat;
1252                validateInheritedPermissionsFormat(theImplies, theFormat);
1253        }
1254
1255        public static void validateInheritedPermissionsFormat(
1256                        PermissionEnum[] theImplies, PermissionArgumentFormat<?> theFormat) {
1257                if (Arrays.stream(theImplies).anyMatch(x -> x.isRequiresArgument() && (x.getFormat() != theFormat))) {
1258                        throw new IllegalArgumentException(
1259                                        "Implied Permissions with arguments must accept the same argument format as Parent permission. "
1260                                                        + theFormat);
1261                }
1262        }
1263
1264        @Deprecated(since = "7.2.0")
1265        public Set<PermissionCategoryEnum> getCategories() {
1266                return Set.of(myCategory);
1267        }
1268
1269        public PermissionCategoryEnum getCategory() {
1270                return myCategory;
1271        }
1272
1273        public Set<PermissionEnum> getImplies() {
1274                return myImplies;
1275        }
1276
1277        public boolean isSystemPermission() {
1278                return this == ROLE_SYSTEM_INITIALIZATION || this == ROLE_SYSTEM;
1279        }
1280
1281        public boolean isTakesArgument() {
1282                return myTakesArgument != TakesArgumentEnum.NO;
1283        }
1284
1285        public boolean isRequiresArgument() {
1286                return myTakesArgument == TakesArgumentEnum.YES;
1287        }
1288
1289        public boolean isArgumentOptional() {
1290                return myTakesArgument == TakesArgumentEnum.OPTIONAL;
1291        }
1292
1293        public boolean isNegative() {
1294                return myNegativePermission;
1295        }
1296
1297        /**
1298         * The format for the argument - defaults to NoArgument format
1299         */
1300        public PermissionArgumentFormat<?> getFormat() {
1301                return myFormat;
1302        }
1303
1304        private enum TakesArgumentEnum {
1305                YES,
1306                NO,
1307                OPTIONAL
1308        }
1309
1310        @Nonnull
1311        public static Optional<PermissionEnum> find(String thePermission) {
1312                try {
1313                        return Optional.of(PermissionEnum.valueOf(thePermission.toUpperCase(Locale.ROOT)));
1314                } catch (NullPointerException | IllegalArgumentException e) {
1315                        return Optional.empty();
1316                }
1317        }
1318
1319        @Nonnull
1320        public static List<PermissionEnum> findAll(List<String> thePermissions) {
1321                return Optional.ofNullable(thePermissions).stream()
1322                                .flatMap(Collection::stream)
1323                                .map(PermissionEnum::find)
1324                                .filter(Optional::isPresent)
1325                                .map(Optional::get)
1326                                .collect(Collectors.toList());
1327        }
1328
1329        private static <T extends Enum<T>> Set<T> unmodifiableEnumSet(T[] theValues) {
1330                if (theValues.length == 0) {
1331                        return Collections.emptySet();
1332                }
1333                Set<T> set = EnumSet.of(theValues[0], theValues);
1334                return Collections.unmodifiableSet(set);
1335        }
1336
1337        @Deprecated(since = "7.2.0")
1338        public static Set<PermissionEnum> roles() {
1339                return ROLES;
1340        }
1341
1342        public static String extractFirstSpaceSeparatedArgument(String theArgument) {
1343                if (isNotBlank(theArgument)) {
1344                        int spaceIdx = theArgument.indexOf(' ');
1345                        if (spaceIdx != -1) {
1346                                return trim(theArgument.substring(0, spaceIdx));
1347                        } else {
1348                                return theArgument;
1349                        }
1350                }
1351                return null;
1352        }
1353
1354        public static Collection<String> extractSpaceSeparatedResourceTypesFromArgument(String theArgument) {
1355                return extractSpaceSeparatedResourceTypesFromArgument(theArgument, 0);
1356        }
1357
1358        public static Collection<String> extractSpaceSeparatedResourceTypesFromArgument(
1359                        String theArgument, int theFromOffsetIndex) {
1360                if (isBlank(theArgument)) {
1361                        return null;
1362                }
1363                StringTokenizer tok = new StringTokenizer(theArgument, " ");
1364                List<String> retVal = new ArrayList<>();
1365                while (tok.hasNext()) {
1366                        String next = tok.next();
1367                        next = trim(next);
1368                        if (isNotBlank(next)) {
1369                                if (theFromOffsetIndex > 0) {
1370                                        theFromOffsetIndex--;
1371                                        continue;
1372                                }
1373                                retVal.add(next);
1374                        }
1375                }
1376                return retVal;
1377        }
1378
1379        private static Set<PermissionEnum> getAllPermissions() {
1380                return Arrays.stream(values())
1381                                .filter(p -> !p.isRole())
1382                                .filter(p -> !p.isRequiresArgument())
1383                                .collect(Collectors.toSet());
1384        }
1385
1386        private static Set<PermissionEnum> getAllSuperuserPermissions() {
1387                return Arrays.stream(values())
1388                                .filter(p -> !p.isRole())
1389                                .filter(p -> !p.isExpungePermission())
1390                                .filter(p -> !p.isRequiresArgument())
1391                                .collect(Collectors.toSet());
1392        }
1393
1394        private static Set<PermissionEnum> getAllFhirSuperuserPermissions() {
1395                Set<PermissionEnum> permissions = getAllSuperuserPermissions().stream()
1396                                .filter(PermissionEnum::isFhirPermission)
1397                                .collect(Collectors.toSet());
1398                permissions.add(ACCESS_FHIRWEB);
1399                return permissions;
1400        }
1401
1402        private static Set<PermissionEnum> getRoles() {
1403                Set<PermissionEnum> roles = Arrays.stream(values())
1404                                .filter(PermissionEnum::isRole)
1405                                .collect(Collectors.toCollection(() -> EnumSet.noneOf(PermissionEnum.class)));
1406                return Collections.unmodifiableSet(roles);
1407        }
1408
1409        public boolean isRole() {
1410                // unlike other roles, the terminology role is involved in the logic that checks the access
1411                return name().startsWith("ROLE_") && this != ROLE_FHIR_TERMINOLOGY_READ_CLIENT;
1412        }
1413
1414        public boolean isExpungePermission() {
1415                return name().toLowerCase().contains("expunge");
1416        }
1417
1418        /**
1419         * Determines if this is a FHIR delete permission.
1420         *
1421         * @return true if FHIR delete, false otherwise
1422         */
1423        public boolean isSuperuser() {
1424                return name().toLowerCase().contains("superuser");
1425        }
1426
1427        /**
1428         * Determines if this is a FHIR related permission.
1429         *
1430         * @return true if FHIR permission, false otherwise
1431         */
1432        public boolean isFhirPermission() {
1433                return PermissionCategoryEnum.FHIR_CLIENT.equals(myCategory);
1434        }
1435}