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