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