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