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 read search parameters
367         */
368        FHIR_READ_SEARCH_PARAMETERS(
369                        PermissionCategoryEnum.FHIR_CLIENT,
370                        new PermissionEnum[] {
371                                // does not imply FHIR_CLIENT since this can be used for JSON Admin functions too
372                        }),
373
374        /**
375         * User is allowed to create, update, and delete search parameters
376         */
377        FHIR_MODIFY_SEARCH_PARAMETERS(
378                        PermissionCategoryEnum.FHIR_CLIENT,
379                        new PermissionEnum[] {
380                                // does not imply FHIR_CLIENT since this can be used for JSON Admin functions too
381                        }),
382
383        /**
384         * User is allowed to read any resources in the given compartment
385         */
386        FHIR_READ_ALL_IN_COMPARTMENT(
387                        PermissionCategoryEnum.FHIR_CLIENT,
388                        ROLE_FHIR_CLIENT,
389                        TakesArgumentEnum.YES,
390                        PermissionArgumentFormats.COMPARTMENT_WITH_OPTIONAL_FILTER_FORMAT),
391
392        /**
393         * User is allowed to write any resources in the given compartment
394         */
395        FHIR_WRITE_ALL_IN_COMPARTMENT(
396                        PermissionCategoryEnum.FHIR_CLIENT,
397                        ROLE_FHIR_CLIENT,
398                        TakesArgumentEnum.YES,
399                        PermissionArgumentFormats.COMPARTMENT_WITH_OPTIONAL_FILTER_FORMAT),
400
401        /**
402         * User is allowed to read any resources of the given type in the given compartment
403         */
404        FHIR_READ_TYPE_IN_COMPARTMENT(
405                        PermissionCategoryEnum.FHIR_CLIENT,
406                        ROLE_FHIR_CLIENT,
407                        TakesArgumentEnum.YES,
408                        PermissionArgumentFormats.TYPE_IN_COMPARTMENT_WITH_OPTIONAL_FILTER_FORMAT),
409
410        /**
411         * User is allowed to write any resources of the given type in the given compartment
412         */
413        FHIR_WRITE_TYPE_IN_COMPARTMENT(
414                        PermissionCategoryEnum.FHIR_CLIENT,
415                        ROLE_FHIR_CLIENT,
416                        TakesArgumentEnum.YES,
417                        PermissionArgumentFormats.TYPE_IN_COMPARTMENT_WITH_OPTIONAL_FILTER_FORMAT),
418
419        /**
420         * User is allowed to read any resources of the given type
421         */
422        FHIR_READ_ALL_OF_TYPE(
423                        PermissionCategoryEnum.FHIR_CLIENT,
424                        ROLE_FHIR_CLIENT,
425                        TakesArgumentEnum.YES,
426                        PermissionArgumentFormats.RESOURCE_TYPE_OPTIONAL_FILTER_FORMAT),
427
428        /**
429         * User is allowed to write any resources of the given type
430         */
431        FHIR_WRITE_ALL_OF_TYPE(
432                        PermissionCategoryEnum.FHIR_CLIENT,
433                        ROLE_FHIR_CLIENT,
434                        TakesArgumentEnum.YES,
435                        PermissionArgumentFormats.RESOURCE_TYPE_OPTIONAL_FILTER_FORMAT),
436
437        /**
438         * User is allowed to read a specific resource instance by ID
439         */
440        FHIR_READ_INSTANCE(
441                        PermissionCategoryEnum.FHIR_CLIENT,
442                        ROLE_FHIR_CLIENT,
443                        TakesArgumentEnum.YES,
444                        PermissionArgumentFormats.INSTANCE_WITH_OPTIONAL_FILTER_FORMAT),
445
446        /**
447         * User is allowed to write a specific resource instance by ID
448         */
449        FHIR_WRITE_INSTANCE(
450                        PermissionCategoryEnum.FHIR_CLIENT,
451                        ROLE_FHIR_CLIENT,
452                        TakesArgumentEnum.YES,
453                        PermissionArgumentFormats.INSTANCE_WITH_OPTIONAL_FILTER_FORMAT),
454
455        /**
456         * User is allowed to access resources with a code
457         */
458        BLOCK_FHIR_READ_UNLESS_CODE_IN_VS(
459                        PermissionCategoryEnum.FHIR_CLIENT,
460                        TakesArgumentEnum.YES,
461                        true,
462                        PermissionArgumentFormats.CODE_IN_VALUE_SET_FILTER_FORMAT,
463                        new PermissionEnum[] {ROLE_FHIR_CLIENT}),
464
465        /**
466         * User is allowed to access resources with a code
467         */
468        BLOCK_FHIR_READ_UNLESS_CODE_NOT_IN_VS(
469                        PermissionCategoryEnum.FHIR_CLIENT,
470                        TakesArgumentEnum.YES,
471                        true,
472                        PermissionArgumentFormats.CODE_IN_VALUE_SET_FILTER_FORMAT,
473                        new PermissionEnum[] {ROLE_FHIR_CLIENT}),
474
475        /**
476         * User is permitted to invoke the $expunge operation with expungeDeletedResources=true
477         */
478        FHIR_EXPUNGE_DELETED(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
479
480        /**
481         * User is permitted to invoke the $expunge operation with expungePreviousVersions=true
482         */
483        FHIR_EXPUNGE_PREVIOUS_VERSIONS(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
484
485        /**
486         * User is permitted to invoke the $expunge operation with expungeEverything=true
487         */
488        FHIR_EXPUNGE_EVERYTHING(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
489
490        /**
491         * User is permitted to invoke the $delete-expunge operation
492         */
493        FHIR_DELETE_EXPUNGE(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
494
495        /**
496         * User is permitted to invoke the $livebundle-watchlist-add, $livebundle-watchlist-delete, $livebundle-watchlist, and $livebundle operations
497         */
498        FHIR_LIVEBUNDLE(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
499
500        /**
501         * User is permitted to invoke the operations
502         * $partition-management-create-partition,
503         * $partition-management-read-partition,
504         * $partition-management-update-partition,
505         * $partition-management-delete-partition,
506         * $partition-management-list-partitions,
507         */
508        FHIR_MANAGE_PARTITIONS(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
509
510        /**
511         * User is permitted to invoke the $meta, $meta-add, and $meta-delete operations on
512         * any resource.
513         */
514        FHIR_META_OPERATIONS_SUPERUSER(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
515
516        /**
517         * User may invoke any kind of operation
518         */
519        FHIR_EXTENDED_OPERATION_SUPERUSER(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
520
521        /**
522         * User may invoke operation with name specified by argument (e.g. $fooOperation)
523         */
524        FHIR_EXTENDED_OPERATION_ON_SERVER(
525                        PermissionCategoryEnum.FHIR_CLIENT,
526                        ROLE_FHIR_CLIENT,
527                        TakesArgumentEnum.YES,
528                        PermissionArgumentFormats.OPERATION_FORMAT),
529
530        /**
531         * User may invoke operation at the type level with type and name specified by argument (e.g. Patient/$fooOperation)
532         */
533        FHIR_EXTENDED_OPERATION_ON_TYPE(
534                        PermissionCategoryEnum.FHIR_CLIENT,
535                        ROLE_FHIR_CLIENT,
536                        TakesArgumentEnum.YES,
537                        PermissionArgumentFormats.OPERATION_ON_RESOURCE_TYPE_FORMAT),
538
539        /**
540         * User may invoke operation at the instance level for any type with name specified by argument (e.g. $fooOperation)
541         */
542        FHIR_EXTENDED_OPERATION_ON_ANY_INSTANCE(
543                        PermissionCategoryEnum.FHIR_CLIENT,
544                        ROLE_FHIR_CLIENT,
545                        TakesArgumentEnum.YES,
546                        PermissionArgumentFormats.OPERATION_FORMAT),
547
548        /**
549         * User may invoke operation at the instance level with type and name specified by argument (e.g. Patient/$fooOperation)
550         */
551        FHIR_EXTENDED_OPERATION_ON_ANY_INSTANCE_OF_TYPE(
552                        PermissionCategoryEnum.FHIR_CLIENT,
553                        ROLE_FHIR_CLIENT,
554                        TakesArgumentEnum.YES,
555                        PermissionArgumentFormats.OPERATION_ON_RESOURCE_TYPE_FORMAT),
556
557        /**
558         * User may invoke the MDM $match operation on a Patient
559         */
560        FHIR_OP_PATIENT_MATCH(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
561
562        /**
563         * User may invoke the $sdh.mdm-bundle-match operation on a Bundle
564         */
565        FHIR_OP_MDM_BUNDLE_MATCH(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
566
567        /**
568         * User may invoke the MDM $mdm-merge-golden-resources operation on Golden Resources
569         */
570        FHIR_OP_MDM_MERGE_GOLDEN_RESOURCES(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
571
572        /**
573         * User may invoke the MDM $mdm-update-link operation on a Golden Resource
574         */
575        FHIR_OP_MDM_UPDATE_LINK(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
576
577        /**
578         * User may invoke the MDM $mdm-create-link operation on a Golden Resource
579         */
580        FHIR_OP_MDM_CREATE_LINK(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
581
582        /**
583         * User may invoke the MDM $mdm-query-links operation
584         */
585        FHIR_OP_MDM_QUERY_LINKS(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
586
587        /**
588         * User may invoke the MDM $mdm-query-links operation
589         */
590        FHIR_OP_MDM_LINK_HISTORY(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
591
592        /**
593         * User may invoke the MDM $mdm-duplicate-golden-resources
594         */
595        FHIR_OP_MDM_DUPLICATE_GOLDEN_RESOURCES(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
596
597        /**
598         * User may invoke the MDM $mdm-not-duplicate
599         */
600        FHIR_OP_MDM_NOT_DUPLICATE(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
601
602        /**
603         * User may invoke the MDM $mdm-clear Operation
604         */
605        FHIR_OP_MDM_CLEAR(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
606
607        /**
608         * User may invoke the MDM $mdm-submit operation
609         */
610        FHIR_OP_MDM_SUBMIT(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
611
612        /**
613         * User may perform all MDM operations
614         */
615        FHIR_MDM_ADMIN(
616                        PermissionCategoryEnum.FHIR_CLIENT,
617                        FHIR_OP_MDM_SUBMIT,
618                        FHIR_OP_MDM_CLEAR,
619                        FHIR_OP_MDM_DUPLICATE_GOLDEN_RESOURCES,
620                        FHIR_OP_MDM_NOT_DUPLICATE,
621                        FHIR_OP_MDM_MERGE_GOLDEN_RESOURCES,
622                        FHIR_OP_MDM_QUERY_LINKS,
623                        FHIR_OP_MDM_LINK_HISTORY,
624                        FHIR_OP_MDM_UPDATE_LINK,
625                        FHIR_OP_MDM_CREATE_LINK),
626
627        /**
628         * Legacy permission for backward compatibility. Use corresponding MDM permission instead.
629         */
630        FHIR_OP_EMPI_MERGE_PERSONS(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
631
632        /**
633         * Legacy permission for backward compatibility. Use corresponding MDM permission instead.
634         */
635        FHIR_OP_EMPI_UPDATE_LINK(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
636
637        /**
638         * Legacy permission for backward compatibility. Use corresponding MDM permission instead.
639         */
640        FHIR_OP_EMPI_QUERY_LINKS(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
641
642        /**
643         * Legacy permission for backward compatibility. Use corresponding MDM permission instead.
644         */
645        FHIR_OP_EMPI_DUPLICATE_PERSONS(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
646
647        /**
648         * Legacy permission for backward compatibility. Use corresponding MDM permission instead.
649         */
650        FHIR_OP_EMPI_CLEAR(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
651
652        /**
653         * Legacy permission for backward compatibility. Use corresponding MDM permission instead.
654         */
655        FHIR_OP_EMPI_SUBMIT(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
656
657        /**
658         * Legacy permission for backward compatibility. Use corresponding MDM permission instead.
659         */
660        FHIR_EMPI_ADMIN(
661                        PermissionCategoryEnum.FHIR_CLIENT,
662                        FHIR_OP_EMPI_SUBMIT,
663                        FHIR_OP_EMPI_CLEAR,
664                        FHIR_OP_EMPI_DUPLICATE_PERSONS,
665                        FHIR_OP_EMPI_MERGE_PERSONS,
666                        FHIR_OP_EMPI_QUERY_LINKS,
667                        FHIR_OP_EMPI_UPDATE_LINK),
668
669        /**
670         * CQL Permission for evaluate-measure operation.
671         */
672        FHIR_OP_EVALUATE_MEASURE(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
673        /**
674         * Permission for submit-data operation.
675         */
676        FHIR_OP_SUBMIT_DATA(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
677        /**
678         * Permission for care-gaps operation.
679         */
680        FHIR_OP_CARE_GAPS(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
681        /**
682         * Permission for evaluate operation.
683         */
684        FHIR_OP_EVALUATE(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
685        /**
686         * Permission for $collect-data operation.
687         */
688        FHIR_OP_COLLECTDATA(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
689        /**
690         * Permission for $data-requirements operation.
691         */
692        FHIR_OP_DATAREQUIREMENTS(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
693        /**
694         * Permission for cql operation.
695         */
696        FHIR_OP_CQL(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
697        /**
698         * Permission for evaluate-measures operation.
699         */
700        FHIR_OP_EVALUATE_MEASURES(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
701        /**
702         * Permission for qpp-build operation.
703         */
704        DQM_QPP_BUILD(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
705        /**
706         * Permission for job-analytics operation
707         */
708        BATCH_JOB_ANALYTICS(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
709
710        /**
711         * User is permitted to call the $apply operation
712         */
713        FHIR_OP_APPLY(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
714
715        /**
716         * User is permitted to call the $prepopulate operation
717         */
718        FHIR_OP_PREPOPULATE(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
719
720        /**
721         * User is permitted to call the $populate operation
722         */
723        FHIR_OP_POPULATE(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
724
725        /**
726         * User is permitted to call the $extract operation
727         */
728        FHIR_OP_EXTRACT(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
729
730        /**
731         * User is permitted to call the $package operation
732         */
733        FHIR_OP_PACKAGE(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
734
735        /**
736         * User is permitted to call the $hapi.fhir.replace-references operation
737         */
738        FHIR_OP_REPLACE_REFERENCES(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
739
740        /**
741         * User is permitted to call the $merge operation
742         */
743        FHIR_OP_MERGE(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
744
745        /**
746         * User may perform all DTR operations
747         */
748        FHIR_DTR_USER(PermissionCategoryEnum.FHIR_CLIENT, FHIR_OP_PACKAGE, FHIR_OP_POPULATE),
749
750        /**
751         * User is allowed to perform any FHIR read/access-to-data operation, e.g. `read`, `search`, `history`, etc
752         */
753        FHIR_ALL_READ(
754                        PermissionCategoryEnum.FHIR_CLIENT,
755                        TakesArgumentEnum.NO,
756                        false,
757                        PermissionArgumentFormats.OPTIONAL_FILTER_FORMAT,
758                        new PermissionEnum[] {ROLE_FHIR_CLIENT, FHIR_READ_SEARCH_PARAMETERS}),
759
760        /**
761         * User is allowed to perform FHIR transactions
762         */
763        FHIR_TRANSACTION(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
764
765        /**
766         * User is allowed to perform FHIR GraphQL Operations
767         */
768        FHIR_GRAPHQL(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
769
770        /**
771         * User is allowed to perform FHIR transactions
772         */
773        FHIR_BATCH(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
774
775        /**
776         * User is allowed to perform FHIR PATCH operations
777         *
778         * @deprecated FHIR_PATCH will be removed:  Users should instead be granted more granular write permissions that cover PATCH operations.
779         */
780        @Deprecated
781        FHIR_PATCH(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
782
783        /**
784         * User is allowed to perform any FHIR write/modify operation, e.g. `create`, `update`, etc
785         */
786        FHIR_ALL_WRITE(
787                        PermissionCategoryEnum.FHIR_CLIENT,
788                        TakesArgumentEnum.NO,
789                        false,
790                        PermissionArgumentFormats.OPTIONAL_FILTER_FORMAT,
791                        new PermissionEnum[] {ROLE_FHIR_CLIENT, FHIR_MODIFY_SEARCH_PARAMETERS, FHIR_META_OPERATIONS_SUPERUSER}),
792
793        /**
794         * User is allowed to perform any FHIR delete operation
795         */
796        FHIR_ALL_DELETE(
797                        PermissionCategoryEnum.FHIR_CLIENT,
798                        TakesArgumentEnum.OPTIONAL,
799                        false,
800                        PermissionArgumentFormats.OPTIONAL_FILTER_FORMAT,
801                        new PermissionEnum[] {ROLE_FHIR_CLIENT}),
802
803        /**
804         * User is allowed to perform any FHIR delete operation on the given type
805         */
806        FHIR_DELETE_ALL_OF_TYPE(
807                        PermissionCategoryEnum.FHIR_CLIENT,
808                        ROLE_FHIR_CLIENT,
809                        TakesArgumentEnum.YES,
810                        PermissionArgumentFormats.RESOURCE_TYPE_OPTIONAL_FILTER_FORMAT),
811
812        /**
813         * User is allowed to perform any FHIR delete operation on a given compartment
814         */
815        FHIR_DELETE_ALL_IN_COMPARTMENT(
816                        PermissionCategoryEnum.FHIR_CLIENT,
817                        ROLE_FHIR_CLIENT,
818                        TakesArgumentEnum.YES,
819                        PermissionArgumentFormats.COMPARTMENT_WITH_OPTIONAL_FILTER_FORMAT),
820
821        /**
822         * User is allowed to perform any FHIR delete operation on a given compartment
823         */
824        FHIR_DELETE_TYPE_IN_COMPARTMENT(
825                        PermissionCategoryEnum.FHIR_CLIENT,
826                        ROLE_FHIR_CLIENT,
827                        TakesArgumentEnum.YES,
828                        PermissionArgumentFormats.TYPE_IN_COMPARTMENT_WITH_OPTIONAL_FILTER_FORMAT),
829
830        /**
831         * Any delete permissions granted to the user may be applied to cascaded deletes
832         * as well as normal deletes. Note that this permission allows cascaded deletes
833         * to occur, but does not actually grant any permission to delete resources in
834         * the first place. This permission must be combined with other permissions that
835         * grant the ability to cascade deletes.
836         */
837        FHIR_DELETE_CASCADE_ALLOWED(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
838
839        /**
840         * User is allowed to access the server capability statement
841         */
842        FHIR_CAPABILITIES(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
843
844        /**
845         * User is allowed to invoke the `$validate` operation to validate resources
846         */
847        FHIR_MANUAL_VALIDATION(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
848
849        /**
850         * User is allowed to invoke the `$process-message` operation to accept a message
851         */
852        FHIR_PROCESS_MESSAGE(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
853
854        /**
855         * User is permitted to upload external code systems
856         */
857        FHIR_UPLOAD_EXTERNAL_TERMINOLOGY(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
858
859        /**
860         * User is permitted to call the $get-resource-counts operation
861         */
862        FHIR_GET_RESOURCE_COUNTS(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
863
864        /**
865         * User is allowed to invoke the $trigger-subscription operation
866         */
867        FHIR_TRIGGER_SUBSCRIPTION(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
868
869        /**
870         * User is permitted to call read-only terminology methods, such as
871         * $lookup, $validate-code
872         */
873        ROLE_FHIR_TERMINOLOGY_READ_CLIENT(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
874
875        /**
876         * User is allowed to perform the patient $everything operation
877         */
878        FHIR_OP_PATIENT_EVERYTHING(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
879
880        /**
881         * User is allowed to perform the patient $everything operation with `Access All` permission
882         */
883        FHIR_OP_PATIENT_EVERYTHING_ACCESS_ALL(
884                        PermissionCategoryEnum.FHIR_CLIENT,
885                        ROLE_FHIR_CLIENT,
886                        TakesArgumentEnum.YES,
887                        PermissionArgumentFormats.INSTANCE_WITH_OPTIONAL_FILTER_FORMAT),
888
889        /**
890         * User is allowed to perform the patient $summary operation
891         */
892        FHIR_OP_PATIENT_SUMMARY(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
893
894        /**
895         * User is allowed to perform the encounter $everything operation
896         */
897        FHIR_OP_ENCOUNTER_EVERYTHING(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
898
899        /**
900         * User is allowed to perform the $snapshot operation
901         */
902        FHIR_OP_STRUCTUREDEFINITION_SNAPSHOT(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
903
904        /**
905         * User is allowed to perform the $member-match operation
906         */
907        FHIR_OP_MEMBER_MATCH(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
908
909        /**
910         * User is allowed to execute HFQL queries
911         */
912        HFQL_EXECUTE(),
913
914        /**
915         * Any read functions
916         */
917        ROLE_FHIR_CLIENT_SUPERUSER_RO(
918                        PermissionCategoryEnum.FHIR_CLIENT,
919                        FHIR_CAPABILITIES,
920                        FHIR_ALL_READ,
921                        FHIR_TRANSACTION,
922                        FHIR_GRAPHQL,
923                        FHIR_BATCH,
924                        FHIR_OP_ENCOUNTER_EVERYTHING,
925                        FHIR_OP_PATIENT_EVERYTHING,
926                        FHIR_OP_PATIENT_SUMMARY,
927                        FHIR_OP_BINARY_ACCESS_READ,
928                        FHIR_GET_RESOURCE_COUNTS,
929                        ROLE_FHIR_TERMINOLOGY_READ_CLIENT,
930                        FHIR_OP_INITIATE_BULK_DATA_EXPORT),
931
932        /**
933         * 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)
934         * Implied permissions are populated internally and not explicitly defined in the constructor.
935         */
936        ROLE_FHIR_CLIENT_SUPERUSER(PermissionCategoryEnum.FHIR_CLIENT),
937
938        /**
939         * User has all permissions to do anything
940         * Implied permissions are populated internally and not explicitly defined in the constructor.
941         */
942        ROLE_SUPERUSER(PermissionCategoryEnum.ADMIN),
943
944        /**
945         * User is not logged in or has not supplied credentials
946         */
947        ROLE_ANONYMOUS(),
948
949        /**
950         * User is allowed to initiate processing an ETL job
951         */
952        ETL_IMPORT_PROCESS_FILE(),
953
954        /**
955         * User is allowed to view CDA Document Templates
956         */
957        VIEW_CDA_TEMPLATE(PermissionCategoryEnum.CDA),
958
959        /**
960         * User is allowed to create new CDA Document Templates
961         */
962        CREATE_CDA_TEMPLATE(PermissionCategoryEnum.CDA, PermissionEnum.VIEW_CDA_TEMPLATE),
963
964        /**
965         * User is allowed to delete CDA Document Templates
966         */
967        DELETE_CDA_TEMPLATE(PermissionCategoryEnum.CDA, PermissionEnum.VIEW_CDA_TEMPLATE),
968
969        /**
970         * User is allowed to use CDA Document Templates,
971         * potentially persisting a Composition, Bundle, and returning sensitive information in the resultant XML
972         */
973        USE_CDA_TEMPLATE(PermissionCategoryEnum.CDA, PermissionEnum.VIEW_CDA_TEMPLATE),
974
975        /**
976         * User can set/update MDM match rules
977         */
978        MDM_UPDATE_MATCH_RULES(PermissionCategoryEnum.MDM),
979
980        /**
981         * User can see MDM match rules
982         */
983        MDM_VIEW_MATCH_RULES(PermissionCategoryEnum.MDM),
984
985        /**
986         * User can perform any MDM operations
987         */
988        MDM_ADMIN(PermissionCategoryEnum.MDM, PermissionEnum.MDM_VIEW_MATCH_RULES, PermissionEnum.MDM_UPDATE_MATCH_RULES),
989
990        /**
991         * User will have MDM expansion performed automatically on all queries
992         */
993        FHIR_AUTO_MDM(PermissionCategoryEnum.MDM),
994
995        /**
996         * Legacy permission for backward compatibility. Use corresponding MDM permission instead.
997         */
998        EMPI_UPDATE_MATCH_RULES(PermissionCategoryEnum.EMPI),
999
1000        /**
1001         * Legacy permission for backward compatibility. Use corresponding MDM permission instead.
1002         */
1003        EMPI_VIEW_MATCH_RULES(PermissionCategoryEnum.EMPI),
1004
1005        /**
1006         * Legacy permission for backward compatibility. Use corresponding MDM permission instead.
1007         */
1008        EMPI_ADMIN(
1009                        PermissionCategoryEnum.EMPI, PermissionEnum.EMPI_VIEW_MATCH_RULES, PermissionEnum.EMPI_UPDATE_MATCH_RULES),
1010
1011        /**
1012         * User can perform read operations from the package registry
1013         */
1014        PACKAGE_REGISTRY_READ(PermissionCategoryEnum.PACKAGE_REGISTRY),
1015
1016        /**
1017         * User can perform read operations from the package registry
1018         */
1019        PACKAGE_REGISTRY_WRITE(PermissionCategoryEnum.PACKAGE_REGISTRY),
1020
1021        /**
1022         * User can call CDS Hooks
1023         */
1024        INVOKE_CDS_HOOKS(PermissionCategoryEnum.CDS_HOOKS),
1025
1026        /**
1027         * User can perform read operations from the appSphere Admin Console
1028         */
1029        AG_ADMIN_CONSOLE_READ(PermissionCategoryEnum.AG_ADMIN_CONSOLE),
1030
1031        /**
1032         * User can perform write operations from the appSphere Admin Console
1033         */
1034        AG_ADMIN_CONSOLE_WRITE(PermissionCategoryEnum.AG_ADMIN_CONSOLE),
1035
1036        /**
1037         * User can perform read operations from the appSphere Developer Portal
1038         */
1039        AG_DEV_PORTAL_READ(PermissionCategoryEnum.AG_DEV_PORTAL),
1040
1041        /**
1042         * User can perform write operations from the appSphere Developer Portal
1043         */
1044        AG_DEV_PORTAL_WRITE(PermissionCategoryEnum.AG_DEV_PORTAL),
1045
1046        /**
1047         * User has permission to view batch jobs
1048         */
1049        VIEW_BATCH_JOBS(PermissionCategoryEnum.ADMIN),
1050
1051        /**
1052         * User has permission to manage (modify) batch jobs
1053         */
1054        MANAGE_BATCH_JOBS(PermissionCategoryEnum.ADMIN),
1055
1056        /**
1057         * User can perform a docref operation
1058         */
1059        DOCREF(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
1060
1061        /**
1062         * User can perform a CDA Import operation
1063         */
1064        CDA_IMPORT(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
1065
1066        /**
1067         * User can perform the $sdh.cda-to-fhir operation
1068         */
1069        SDH_CDA_TO_FHIR(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
1070
1071        /**
1072         * User can perform the $sdh.generate-cda operation
1073         */
1074        SMILE_GENERATE_CDA(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
1075
1076        /**
1077         * User can perform an update on the historical version of a resource
1078         */
1079        FHIR_UPDATE_REWRITE_HISTORY(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
1080
1081        SUBMIT_ATTACHMENT(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
1082
1083        /**
1084         * User can see (but not change) module configuration information (not including database passwords)
1085         * for a specific module id for a node id
1086         */
1087        VIEW_MODULE_CONFIG_FOR_MODULE(
1088                        PermissionCategoryEnum.ADMIN,
1089                        TakesArgumentEnum.YES,
1090                        false,
1091                        PermissionArgumentFormats.NODE_AND_MODULE_ID_PERMISSION_ARGUMENT_FORMAT,
1092                        new PermissionEnum[] {}),
1093        /**
1094         * User is allowed to modify a specific module id's configuration for a node id
1095         */
1096        UPDATE_MODULE_CONFIG_FOR_MODULE(
1097                        PermissionCategoryEnum.ADMIN,
1098                        TakesArgumentEnum.YES,
1099                        false,
1100                        PermissionArgumentFormats.NODE_AND_MODULE_ID_PERMISSION_ARGUMENT_FORMAT,
1101                        new PermissionEnum[] {VIEW_MODULE_CONFIG_FOR_MODULE}),
1102        /**
1103         * User is allowed to start/stop a specific module id for a node id
1104         */
1105        START_STOP_MODULE_FOR_MODULE(
1106                        PermissionCategoryEnum.ADMIN,
1107                        TakesArgumentEnum.YES,
1108                        false,
1109                        PermissionArgumentFormats.NODE_AND_MODULE_ID_PERMISSION_ARGUMENT_FORMAT,
1110                        new PermissionEnum[] {}),
1111        /**
1112         * User can start/stop/restart a specific module id for a node id
1113         */
1114        CONTROL_MODULE_FOR_MODULE(
1115                        PermissionCategoryEnum.ADMIN,
1116                        TakesArgumentEnum.YES,
1117                        false,
1118                        PermissionArgumentFormats.NODE_AND_MODULE_ID_PERMISSION_ARGUMENT_FORMAT,
1119                        new PermissionEnum[] {VIEW_MODULE_CONFIG_FOR_MODULE, START_STOP_MODULE_FOR_MODULE}),
1120
1121        /**
1122         * User is allowed to reconfigure and start/stop a specific module id for a node id
1123         */
1124        MODULE_ADMIN_FOR_MODULE(
1125                        PermissionCategoryEnum.ADMIN,
1126                        TakesArgumentEnum.YES,
1127                        false,
1128                        PermissionArgumentFormats.NODE_AND_MODULE_ID_PERMISSION_ARGUMENT_FORMAT,
1129                        new PermissionEnum[] {
1130                                UPDATE_MODULE_CONFIG_FOR_MODULE,
1131                                CONTROL_MODULE_FOR_MODULE,
1132                                START_STOP_MODULE_FOR_MODULE,
1133                                VIEW_MODULE_CONFIG_FOR_MODULE
1134                        }),
1135        ROLE_MDMUI_DATASTEWARD_FHIR(
1136                        PermissionCategoryEnum.FHIR_CLIENT,
1137                        FHIR_ALL_READ,
1138                        FHIR_BATCH,
1139                        FHIR_TRANSACTION,
1140                        FHIR_OP_MDM_DUPLICATE_GOLDEN_RESOURCES,
1141                        FHIR_OP_MDM_LINK_HISTORY,
1142                        FHIR_OP_MDM_MERGE_GOLDEN_RESOURCES,
1143                        FHIR_OP_MDM_NOT_DUPLICATE,
1144                        FHIR_OP_MDM_QUERY_LINKS,
1145                        FHIR_OP_MDM_UPDATE_LINK,
1146                        ROLE_FHIR_TERMINOLOGY_READ_CLIENT),
1147        ROLE_MDMUI_ADMIN_FHIR(
1148                        PermissionCategoryEnum.FHIR_CLIENT, ROLE_MDMUI_DATASTEWARD_FHIR, FHIR_OP_MDM_CLEAR, FHIR_OP_MDM_SUBMIT),
1149
1150        /** User will be assigned roles by giving permission APP_ROLE/MDM_UI_DATA_STEWARD */
1151        APP_ROLE(
1152                        PermissionCategoryEnum.ROLE,
1153                        TakesArgumentEnum.YES,
1154                        false,
1155                        PermissionArgumentFormats.ROLE_NAME_FORMAT,
1156                        new PermissionEnum[] {}),
1157
1158        CUSTOM_ROLE(
1159                        PermissionCategoryEnum.ROLE,
1160                        TakesArgumentEnum.YES,
1161                        false,
1162                        PermissionArgumentFormats.ROLE_NAME_FORMAT,
1163                        new PermissionEnum[] {}),
1164
1165        FHIR_OP_UPDATE_TOKENIZATION(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
1166        ;
1167
1168        private static final Set<PermissionEnum> ROLES = getRoles();
1169
1170        static {
1171                ROLE_SYSTEM.myImplies = getAllPermissions();
1172                ROLE_SUPERUSER.myImplies = getAllSuperuserPermissions();
1173                ROLE_FHIR_CLIENT_SUPERUSER.myImplies = getAllFhirSuperuserPermissions();
1174
1175                /*
1176                 * Creating EnumSet with enum elements that have not been initialized fails (not a bug).
1177                 * Use a static block to replace Set with EnumSet once everything is initialized.
1178                 * {@link https://bugs.openjdk.org/browse/JDK-8211749}.
1179                 */
1180                for (PermissionEnum next : values()) {
1181                        next.myImplies = unmodifiableEnumSet(next.myImplies.toArray(new PermissionEnum[0]));
1182                }
1183        }
1184
1185        private final TakesArgumentEnum myTakesArgument;
1186        private final boolean myNegativePermission;
1187        private Set<PermissionEnum> myImplies;
1188        private final PermissionCategoryEnum myCategory;
1189        /**
1190         * The format for the argument - defaults to no argument
1191         */
1192        private final PermissionArgumentFormat<?> myFormat;
1193
1194        /**
1195         * Constructor for permissions with just a name
1196         */
1197        PermissionEnum() {
1198                this(null);
1199        }
1200
1201        /**
1202         * Constructor for permissions with an assigned category
1203         */
1204        PermissionEnum(PermissionCategoryEnum theCategory) {
1205                this(theCategory, new PermissionEnum[] {});
1206        }
1207
1208        /**
1209         * Constructor for permissions that have implied (underlying) permissions
1210         */
1211        PermissionEnum(PermissionCategoryEnum theCategory, PermissionEnum... theImplies) {
1212                this(theCategory, TakesArgumentEnum.NO, false, PermissionArgumentFormats.NO_ARGUMENT_FORMAT, theImplies);
1213        }
1214
1215        /**
1216         * Constructor for permissions with arguments.
1217         */
1218        PermissionEnum(
1219                        PermissionCategoryEnum theCategory,
1220                        PermissionEnum theImplied,
1221                        TakesArgumentEnum theTakesArgument,
1222                        PermissionArgumentFormat<?> theFormat) {
1223                this(theCategory, theTakesArgument, false, theFormat, new PermissionEnum[] {theImplied});
1224        }
1225
1226        /**
1227         * Constructor for permissions with implied (underlying) permissions and/or with arguments.
1228         */
1229        PermissionEnum(
1230                        PermissionCategoryEnum theCategory,
1231                        TakesArgumentEnum theTakesArgument,
1232                        boolean theNegativePermission,
1233                        PermissionArgumentFormat<?> theFormat,
1234                        PermissionEnum[] theImplies) {
1235                assert theTakesArgument != null;
1236                assert !theNegativePermission || name().startsWith("BLOCK_");
1237                myImplies = Set.of(theImplies);
1238                myCategory = theCategory;
1239                myTakesArgument = theTakesArgument;
1240                myNegativePermission = theNegativePermission;
1241                myFormat = theFormat;
1242                validateInheritedPermissionsFormat(theImplies, theFormat);
1243        }
1244
1245        public static void validateInheritedPermissionsFormat(
1246                        PermissionEnum[] theImplies, PermissionArgumentFormat<?> theFormat) {
1247                if (Arrays.stream(theImplies).anyMatch(x -> x.isRequiresArgument() && (x.getFormat() != theFormat))) {
1248                        throw new IllegalArgumentException(
1249                                        "Implied Permissions with arguments must accept the same argument format as Parent permission. "
1250                                                        + theFormat);
1251                }
1252        }
1253
1254        @Deprecated(since = "7.2.0")
1255        public Set<PermissionCategoryEnum> getCategories() {
1256                return Set.of(myCategory);
1257        }
1258
1259        public PermissionCategoryEnum getCategory() {
1260                return myCategory;
1261        }
1262
1263        public Set<PermissionEnum> getImplies() {
1264                return myImplies;
1265        }
1266
1267        public boolean isSystemPermission() {
1268                return this == ROLE_SYSTEM_INITIALIZATION || this == ROLE_SYSTEM;
1269        }
1270
1271        public boolean isTakesArgument() {
1272                return myTakesArgument != TakesArgumentEnum.NO;
1273        }
1274
1275        public boolean isRequiresArgument() {
1276                return myTakesArgument == TakesArgumentEnum.YES;
1277        }
1278
1279        public boolean isArgumentOptional() {
1280                return myTakesArgument == TakesArgumentEnum.OPTIONAL;
1281        }
1282
1283        public boolean isNegative() {
1284                return myNegativePermission;
1285        }
1286
1287        /**
1288         * The format for the argument - defaults to NoArgument format
1289         */
1290        public PermissionArgumentFormat<?> getFormat() {
1291                return myFormat;
1292        }
1293
1294        private enum TakesArgumentEnum {
1295                YES,
1296                NO,
1297                OPTIONAL
1298        }
1299
1300        @Nonnull
1301        public static Optional<PermissionEnum> find(String thePermission) {
1302                try {
1303                        return Optional.of(PermissionEnum.valueOf(thePermission.toUpperCase(Locale.ROOT)));
1304                } catch (NullPointerException | IllegalArgumentException e) {
1305                        return Optional.empty();
1306                }
1307        }
1308
1309        @Nonnull
1310        public static List<PermissionEnum> findAll(List<String> thePermissions) {
1311                return Optional.ofNullable(thePermissions).stream()
1312                                .flatMap(Collection::stream)
1313                                .map(PermissionEnum::find)
1314                                .filter(Optional::isPresent)
1315                                .map(Optional::get)
1316                                .collect(Collectors.toList());
1317        }
1318
1319        private static <T extends Enum<T>> Set<T> unmodifiableEnumSet(T[] theValues) {
1320                if (theValues.length == 0) {
1321                        return Collections.emptySet();
1322                }
1323                Set<T> set = EnumSet.of(theValues[0], theValues);
1324                return Collections.unmodifiableSet(set);
1325        }
1326
1327        @Deprecated(since = "7.2.0")
1328        public static Set<PermissionEnum> roles() {
1329                return ROLES;
1330        }
1331
1332        public static String extractFirstSpaceSeparatedArgument(String theArgument) {
1333                if (isNotBlank(theArgument)) {
1334                        int spaceIdx = theArgument.indexOf(' ');
1335                        if (spaceIdx != -1) {
1336                                return trim(theArgument.substring(0, spaceIdx));
1337                        } else {
1338                                return theArgument;
1339                        }
1340                }
1341                return null;
1342        }
1343
1344        public static Collection<String> extractSpaceSeparatedResourceTypesFromArgument(String theArgument) {
1345                return extractSpaceSeparatedResourceTypesFromArgument(theArgument, 0);
1346        }
1347
1348        public static Collection<String> extractSpaceSeparatedResourceTypesFromArgument(
1349                        String theArgument, int theFromOffsetIndex) {
1350                if (isBlank(theArgument)) {
1351                        return null;
1352                }
1353                StringTokenizer tok = new StringTokenizer(theArgument, " ");
1354                List<String> retVal = new ArrayList<>();
1355                while (tok.hasNext()) {
1356                        String next = tok.next();
1357                        next = trim(next);
1358                        if (isNotBlank(next)) {
1359                                if (theFromOffsetIndex > 0) {
1360                                        theFromOffsetIndex--;
1361                                        continue;
1362                                }
1363                                retVal.add(next);
1364                        }
1365                }
1366                return retVal;
1367        }
1368
1369        private static Set<PermissionEnum> getAllPermissions() {
1370                return Arrays.stream(values())
1371                                .filter(p -> !p.isRole())
1372                                .filter(p -> !p.isRequiresArgument())
1373                                .collect(Collectors.toSet());
1374        }
1375
1376        private static Set<PermissionEnum> getAllSuperuserPermissions() {
1377                return Arrays.stream(values())
1378                                .filter(p -> !p.isRole())
1379                                .filter(p -> !p.isExpungePermission())
1380                                .filter(p -> !p.isRequiresArgument())
1381                                .collect(Collectors.toSet());
1382        }
1383
1384        private static Set<PermissionEnum> getAllFhirSuperuserPermissions() {
1385                Set<PermissionEnum> permissions = getAllSuperuserPermissions().stream()
1386                                .filter(PermissionEnum::isFhirPermission)
1387                                .collect(Collectors.toSet());
1388                permissions.add(ACCESS_FHIRWEB);
1389                return permissions;
1390        }
1391
1392        private static Set<PermissionEnum> getRoles() {
1393                Set<PermissionEnum> roles = Arrays.stream(values())
1394                                .filter(PermissionEnum::isRole)
1395                                .collect(Collectors.toCollection(() -> EnumSet.noneOf(PermissionEnum.class)));
1396                return Collections.unmodifiableSet(roles);
1397        }
1398
1399        public boolean isRole() {
1400                // unlike other roles, the terminology role is involved in the logic that checks the access
1401                return name().startsWith("ROLE_") && this != ROLE_FHIR_TERMINOLOGY_READ_CLIENT;
1402        }
1403
1404        public boolean isExpungePermission() {
1405                return name().toLowerCase().contains("expunge");
1406        }
1407
1408        /**
1409         * Determines if this is a FHIR delete permission.
1410         *
1411         * @return true if FHIR delete, false otherwise
1412         */
1413        public boolean isSuperuser() {
1414                return name().toLowerCase().contains("superuser");
1415        }
1416
1417        /**
1418         * Determines if this is a FHIR related permission.
1419         *
1420         * @return true if FHIR permission, false otherwise
1421         */
1422        public boolean isFhirPermission() {
1423                return PermissionCategoryEnum.FHIR_CLIENT.equals(myCategory);
1424        }
1425}