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