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(
771                        PermissionCategoryEnum.FHIR_CLIENT,
772                        new PermissionEnum[] {ROLE_FHIR_CLIENT},
773                        TakesArgumentEnum.OPTIONAL,
774                        false,
775                        PermissionArgumentFormats.OPTIONAL_FILTER_FORMAT),
776
777        /**
778         * User is allowed to perform any FHIR delete operation on the given type
779         */
780        FHIR_DELETE_ALL_OF_TYPE(
781                        PermissionCategoryEnum.FHIR_CLIENT,
782                        ROLE_FHIR_CLIENT,
783                        TakesArgumentEnum.YES,
784                        PermissionArgumentFormats.RESOURCE_TYPE_OPTIONAL_FILTER_FORMAT),
785
786        /**
787         * User is allowed to perform any FHIR delete operation on a given compartment
788         */
789        FHIR_DELETE_ALL_IN_COMPARTMENT(
790                        PermissionCategoryEnum.FHIR_CLIENT,
791                        ROLE_FHIR_CLIENT,
792                        TakesArgumentEnum.YES,
793                        PermissionArgumentFormats.COMPARTMENT_WITH_OPTIONAL_FILTER_FORMAT),
794
795        /**
796         * User is allowed to perform any FHIR delete operation on a given compartment
797         */
798        FHIR_DELETE_TYPE_IN_COMPARTMENT(
799                        PermissionCategoryEnum.FHIR_CLIENT,
800                        ROLE_FHIR_CLIENT,
801                        TakesArgumentEnum.YES,
802                        PermissionArgumentFormats.TYPE_IN_COMPARTMENT_WITH_OPTIONAL_FILTER_FORMAT),
803
804        /**
805         * Any delete permissions granted to the user may be applied to cascaded deletes
806         * as well as normal deletes. Note that this permission allows cascaded deletes
807         * to occur, but does not actually grant any permission to delete resources in
808         * the first place. This permission must be combined with other permissions that
809         * grant the ability to cascade deletes.
810         */
811        FHIR_DELETE_CASCADE_ALLOWED(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
812
813        /**
814         * User is allowed to access the server capability statement
815         */
816        FHIR_CAPABILITIES(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
817
818        /**
819         * User is allowed to invoke the `$validate` operation to validate resources
820         */
821        FHIR_MANUAL_VALIDATION(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
822
823        /**
824         * User is allowed to invoke the `$process-message` operation to accept a message
825         */
826        FHIR_PROCESS_MESSAGE(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
827
828        /**
829         * User is permitted to upload external code systems
830         */
831        FHIR_UPLOAD_EXTERNAL_TERMINOLOGY(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
832
833        /**
834         * User is permitted to call the $get-resource-counts operation
835         */
836        FHIR_GET_RESOURCE_COUNTS(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
837
838        /**
839         * User is allowed to invoke the $trigger-subscription operation
840         */
841        FHIR_TRIGGER_SUBSCRIPTION(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
842
843        /**
844         * User is permitted to call read-only terminology methods, such as
845         * $lookup, $validate-code
846         */
847        ROLE_FHIR_TERMINOLOGY_READ_CLIENT(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
848
849        /**
850         * User is allowed to perform the patient $everything operation
851         */
852        FHIR_OP_PATIENT_EVERYTHING(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
853
854        /**
855         * User is allowed to perform the patient $everything operation with `Access All` permission
856         */
857        FHIR_OP_PATIENT_EVERYTHING_ACCESS_ALL(
858                        PermissionCategoryEnum.FHIR_CLIENT,
859                        ROLE_FHIR_CLIENT,
860                        TakesArgumentEnum.YES,
861                        PermissionArgumentFormats.INSTANCE_WITH_OPTIONAL_FILTER_FORMAT),
862
863        /**
864         * User is allowed to perform the patient $summary operation
865         */
866        FHIR_OP_PATIENT_SUMMARY(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
867
868        /**
869         * User is allowed to perform the encounter $everything operation
870         */
871        FHIR_OP_ENCOUNTER_EVERYTHING(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
872
873        /**
874         * User is allowed to perform the $snapshot operation
875         */
876        FHIR_OP_STRUCTUREDEFINITION_SNAPSHOT(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
877
878        /**
879         * User is allowed to perform the $member-match operation
880         */
881        FHIR_OP_MEMBER_MATCH(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
882
883        /**
884         * User is allowed to execute HFQL queries
885         */
886        HFQL_EXECUTE(),
887
888        /**
889         * Any read functions
890         */
891        ROLE_FHIR_CLIENT_SUPERUSER_RO(PermissionCategoryEnum.FHIR_CLIENT, new PermissionEnum[] {
892                FHIR_CAPABILITIES,
893                FHIR_ALL_READ,
894                FHIR_TRANSACTION,
895                FHIR_GRAPHQL,
896                FHIR_BATCH,
897                FHIR_OP_ENCOUNTER_EVERYTHING,
898                FHIR_OP_PATIENT_EVERYTHING,
899                FHIR_OP_PATIENT_SUMMARY,
900                FHIR_OP_BINARY_ACCESS_READ,
901                FHIR_GET_RESOURCE_COUNTS,
902                ROLE_FHIR_TERMINOLOGY_READ_CLIENT,
903                FHIR_OP_INITIATE_BULK_DATA_EXPORT
904        }),
905
906        /**
907         * 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)
908         * Implied permissions are populated internally and not explicitly defined in the constructor.
909         */
910        ROLE_FHIR_CLIENT_SUPERUSER(PermissionCategoryEnum.FHIR_CLIENT),
911
912        /**
913         * User has all permissions to do anything
914         * Implied permissions are populated internally and not explicitly defined in the constructor.
915         */
916        ROLE_SUPERUSER(PermissionCategoryEnum.ADMIN),
917
918        /**
919         * User is not logged in or has not supplied credentials
920         */
921        ROLE_ANONYMOUS(),
922
923        /**
924         * User is allowed to initiate processing an ETL job
925         */
926        ETL_IMPORT_PROCESS_FILE(),
927
928        /**
929         * User is allowed to view CDA Document Templates
930         */
931        VIEW_CDA_TEMPLATE(PermissionCategoryEnum.CDA),
932
933        /**
934         * User is allowed to create new CDA Document Templates
935         */
936        CREATE_CDA_TEMPLATE(PermissionCategoryEnum.CDA, PermissionEnum.VIEW_CDA_TEMPLATE),
937
938        /**
939         * User is allowed to delete CDA Document Templates
940         */
941        DELETE_CDA_TEMPLATE(PermissionCategoryEnum.CDA, PermissionEnum.VIEW_CDA_TEMPLATE),
942
943        /**
944         * User is allowed to use CDA Document Templates,
945         * potentially persisting a Composition, Bundle, and returning sensitive information in the resultant XML
946         */
947        USE_CDA_TEMPLATE(PermissionCategoryEnum.CDA, PermissionEnum.VIEW_CDA_TEMPLATE),
948
949        /**
950         * User can set/update MDM match rules
951         */
952        MDM_UPDATE_MATCH_RULES(PermissionCategoryEnum.MDM),
953
954        /**
955         * User can see MDM match rules
956         */
957        MDM_VIEW_MATCH_RULES(PermissionCategoryEnum.MDM),
958
959        /**
960         * User can perform any MDM operations
961         */
962        MDM_ADMIN(
963                        PermissionCategoryEnum.MDM,
964                        new PermissionEnum[] {PermissionEnum.MDM_VIEW_MATCH_RULES, PermissionEnum.MDM_UPDATE_MATCH_RULES}),
965
966        /**
967         * User will have MDM expansion performed automatically on all queries
968         */
969        FHIR_AUTO_MDM(PermissionCategoryEnum.MDM),
970
971        /**
972         * Legacy permission for backward compatibility. Use corresponding MDM permission instead.
973         */
974        EMPI_UPDATE_MATCH_RULES(PermissionCategoryEnum.EMPI),
975
976        /**
977         * Legacy permission for backward compatibility. Use corresponding MDM permission instead.
978         */
979        EMPI_VIEW_MATCH_RULES(PermissionCategoryEnum.EMPI),
980
981        /**
982         * Legacy permission for backward compatibility. Use corresponding MDM permission instead.
983         */
984        EMPI_ADMIN(
985                        PermissionCategoryEnum.EMPI,
986                        new PermissionEnum[] {PermissionEnum.EMPI_VIEW_MATCH_RULES, PermissionEnum.EMPI_UPDATE_MATCH_RULES}),
987
988        /**
989         * User can perform read operations from the package registry
990         */
991        PACKAGE_REGISTRY_READ(PermissionCategoryEnum.PACKAGE_REGISTRY),
992
993        /**
994         * User can perform read operations from the package registry
995         */
996        PACKAGE_REGISTRY_WRITE(PermissionCategoryEnum.PACKAGE_REGISTRY),
997
998        /**
999         * User can call CDS Hooks
1000         */
1001        INVOKE_CDS_HOOKS(PermissionCategoryEnum.CDS_HOOKS),
1002
1003        /**
1004         * User can perform read operations from the appSphere Admin Console
1005         */
1006        AG_ADMIN_CONSOLE_READ(PermissionCategoryEnum.AG_ADMIN_CONSOLE),
1007
1008        /**
1009         * User can perform write operations from the appSphere Admin Console
1010         */
1011        AG_ADMIN_CONSOLE_WRITE(PermissionCategoryEnum.AG_ADMIN_CONSOLE),
1012
1013        /**
1014         * User can perform read operations from the appSphere Developer Portal
1015         */
1016        AG_DEV_PORTAL_READ(PermissionCategoryEnum.AG_DEV_PORTAL),
1017
1018        /**
1019         * User can perform write operations from the appSphere Developer Portal
1020         */
1021        AG_DEV_PORTAL_WRITE(PermissionCategoryEnum.AG_DEV_PORTAL),
1022
1023        /**
1024         * User has permission to view batch jobs
1025         */
1026        VIEW_BATCH_JOBS(PermissionCategoryEnum.ADMIN),
1027
1028        /**
1029         * User has permission to manage (modify) batch jobs
1030         */
1031        MANAGE_BATCH_JOBS(PermissionCategoryEnum.ADMIN),
1032
1033        /**
1034         * User can perform a docref operation
1035         */
1036        DOCREF(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
1037
1038        /**
1039         * User can perform a CDA Import operation
1040         */
1041        CDA_IMPORT(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
1042
1043        /**
1044         * User can perform an update on the historical version of a resource
1045         */
1046        FHIR_UPDATE_REWRITE_HISTORY(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
1047
1048        SUBMIT_ATTACHMENT(PermissionCategoryEnum.FHIR_CLIENT, ROLE_FHIR_CLIENT),
1049
1050        /**
1051         * User can see (but not change) module configuration information (not including database passwords)
1052         * for a specific module id for a node id
1053         */
1054        VIEW_MODULE_CONFIG_FOR_MODULE(
1055                        PermissionCategoryEnum.ADMIN,
1056                        new PermissionEnum[] {},
1057                        TakesArgumentEnum.YES,
1058                        false,
1059                        PermissionArgumentFormats.NODE_AND_MODULE_ID_PERMISSION_ARGUMENT_FORMAT),
1060        /**
1061         * User is allowed to modify a specific module id's configuration for a node id
1062         */
1063        UPDATE_MODULE_CONFIG_FOR_MODULE(
1064                        PermissionCategoryEnum.ADMIN,
1065                        new PermissionEnum[] {VIEW_MODULE_CONFIG_FOR_MODULE},
1066                        TakesArgumentEnum.YES,
1067                        false,
1068                        PermissionArgumentFormats.NODE_AND_MODULE_ID_PERMISSION_ARGUMENT_FORMAT),
1069        /**
1070         * User is allowed to start/stop a specific module id for a node id
1071         */
1072        START_STOP_MODULE_FOR_MODULE(
1073                        PermissionCategoryEnum.ADMIN,
1074                        new PermissionEnum[] {},
1075                        TakesArgumentEnum.YES,
1076                        false,
1077                        PermissionArgumentFormats.NODE_AND_MODULE_ID_PERMISSION_ARGUMENT_FORMAT),
1078        /**
1079         * User can start/stop/restart a specific module id for a node id
1080         */
1081        CONTROL_MODULE_FOR_MODULE(
1082                        PermissionCategoryEnum.ADMIN,
1083                        new PermissionEnum[] {VIEW_MODULE_CONFIG_FOR_MODULE, START_STOP_MODULE_FOR_MODULE},
1084                        TakesArgumentEnum.YES,
1085                        false,
1086                        PermissionArgumentFormats.NODE_AND_MODULE_ID_PERMISSION_ARGUMENT_FORMAT),
1087
1088        /**
1089         * User is allowed to reconfigure and start/stop a specific module id for a node id
1090         */
1091        MODULE_ADMIN_FOR_MODULE(
1092                        PermissionCategoryEnum.ADMIN,
1093                        new PermissionEnum[] {
1094                                UPDATE_MODULE_CONFIG_FOR_MODULE,
1095                                CONTROL_MODULE_FOR_MODULE,
1096                                START_STOP_MODULE_FOR_MODULE,
1097                                VIEW_MODULE_CONFIG_FOR_MODULE
1098                        },
1099                        TakesArgumentEnum.YES,
1100                        false,
1101                        PermissionArgumentFormats.NODE_AND_MODULE_ID_PERMISSION_ARGUMENT_FORMAT),
1102        ROLE_MDMUI_DATASTEWARD_FHIR(PermissionCategoryEnum.FHIR_CLIENT, new PermissionEnum[] {
1103                FHIR_ALL_READ,
1104                FHIR_BATCH,
1105                FHIR_TRANSACTION,
1106                FHIR_OP_MDM_DUPLICATE_GOLDEN_RESOURCES,
1107                FHIR_OP_MDM_LINK_HISTORY,
1108                FHIR_OP_MDM_MERGE_GOLDEN_RESOURCES,
1109                FHIR_OP_MDM_NOT_DUPLICATE,
1110                FHIR_OP_MDM_QUERY_LINKS,
1111                FHIR_OP_MDM_UPDATE_LINK,
1112                ROLE_FHIR_TERMINOLOGY_READ_CLIENT
1113        }),
1114        ROLE_MDMUI_ADMIN_FHIR(
1115                        PermissionCategoryEnum.FHIR_CLIENT,
1116                        new PermissionEnum[] {ROLE_MDMUI_DATASTEWARD_FHIR, FHIR_OP_MDM_CLEAR, FHIR_OP_MDM_SUBMIT});
1117
1118        private static final Set<PermissionEnum> ROLES = getRoles();
1119
1120        static {
1121                ROLE_SYSTEM.myImplies = getAllPermissions();
1122                ROLE_SUPERUSER.myImplies = getAllSuperuserPermissions();
1123                ROLE_FHIR_CLIENT_SUPERUSER.myImplies = getAllFhirSuperuserPermissions();
1124
1125                /*
1126                 * Creating EnumSet with enum elements that have not been initialized fails (not a bug).
1127                 * Use a static block to replace Set with EnumSet once everything is initialized.
1128                 * {@link https://bugs.openjdk.org/browse/JDK-8211749}.
1129                 */
1130                for (PermissionEnum next : values()) {
1131                        next.myImplies = unmodifiableEnumSet(next.myImplies.toArray(new PermissionEnum[0]));
1132                }
1133        }
1134
1135        private final TakesArgumentEnum myTakesArgument;
1136        private final boolean myNegativePermission;
1137        private Set<PermissionEnum> myImplies;
1138        private final PermissionCategoryEnum myCategory;
1139        /**
1140         * The format for the argument - defaults to no argument
1141         */
1142        private final PermissionArgumentFormat<?> myFormat;
1143
1144        /**
1145         * Constructor for permissions with just a name
1146         */
1147        PermissionEnum() {
1148                this(null);
1149        }
1150
1151        /**
1152         * Constructor for permissions with an assigned category
1153         */
1154        PermissionEnum(PermissionCategoryEnum theCategory) {
1155                this(theCategory, new PermissionEnum[] {});
1156        }
1157
1158        /**
1159         * Constructor for permissions that have implied (underlying) permissions
1160         */
1161        PermissionEnum(PermissionCategoryEnum theCategory, PermissionEnum... theImplies) {
1162                this(theCategory, theImplies, TakesArgumentEnum.NO, false, PermissionArgumentFormats.NO_ARGUMENT_FORMAT);
1163        }
1164
1165        /**
1166         * Constructor for permissions with arguments.
1167         */
1168        PermissionEnum(
1169                        PermissionCategoryEnum theCategory,
1170                        PermissionEnum theImplied,
1171                        TakesArgumentEnum theTakesArgument,
1172                        PermissionArgumentFormat<?> theFormat) {
1173                this(theCategory, new PermissionEnum[] {theImplied}, theTakesArgument, false, theFormat);
1174        }
1175
1176        /**
1177         * Constructor for permissions with implied (underlying) permissions and/or with arguments.
1178         */
1179        PermissionEnum(
1180                        PermissionCategoryEnum theCategory,
1181                        PermissionEnum[] theImplies,
1182                        TakesArgumentEnum theTakesArgument,
1183                        boolean theNegativePermission,
1184                        PermissionArgumentFormat<?> theFormat) {
1185                assert theTakesArgument != null;
1186                assert !theNegativePermission || name().startsWith("BLOCK_");
1187                myImplies = Set.of(theImplies);
1188                myCategory = theCategory;
1189                myTakesArgument = theTakesArgument;
1190                myNegativePermission = theNegativePermission;
1191                myFormat = theFormat;
1192                validateInheritedPermissionsFormat(theImplies, theFormat);
1193        }
1194
1195        public static void validateInheritedPermissionsFormat(
1196                        PermissionEnum[] theImplies, PermissionArgumentFormat<?> theFormat) {
1197                if (Arrays.stream(theImplies).anyMatch(x -> x.isRequiresArgument() && (x.getFormat() != theFormat))) {
1198                        throw new IllegalArgumentException(
1199                                        "Implied Permissions with arguments must accept the same argument format as Parent permission. "
1200                                                        + theFormat);
1201                }
1202        }
1203
1204        @Deprecated(since = "7.2.0")
1205        public Set<PermissionCategoryEnum> getCategories() {
1206                return Set.of(myCategory);
1207        }
1208
1209        public PermissionCategoryEnum getCategory() {
1210                return myCategory;
1211        }
1212
1213        public Set<PermissionEnum> getImplies() {
1214                return myImplies;
1215        }
1216
1217        public boolean isSystemPermission() {
1218                return this == ROLE_SYSTEM_INITIALIZATION || this == ROLE_SYSTEM;
1219        }
1220
1221        public boolean isTakesArgument() {
1222                return myTakesArgument != TakesArgumentEnum.NO;
1223        }
1224
1225        public boolean isRequiresArgument() {
1226                return myTakesArgument == TakesArgumentEnum.YES;
1227        }
1228
1229        public boolean isArgumentOptional() {
1230                return myTakesArgument == TakesArgumentEnum.OPTIONAL;
1231        }
1232
1233        public boolean isNegative() {
1234                return myNegativePermission;
1235        }
1236
1237        /**
1238         * The format for the argument - defaults to NoArgument format
1239         */
1240        public PermissionArgumentFormat getFormat() {
1241                return myFormat;
1242        }
1243
1244        private enum TakesArgumentEnum {
1245                YES,
1246                NO,
1247                OPTIONAL
1248        }
1249
1250        @Nonnull
1251        public static Optional<PermissionEnum> find(String thePermission) {
1252                try {
1253                        return Optional.of(PermissionEnum.valueOf(thePermission.toUpperCase(Locale.ROOT)));
1254                } catch (NullPointerException | IllegalArgumentException e) {
1255                        return Optional.empty();
1256                }
1257        }
1258
1259        @Nonnull
1260        public static List<PermissionEnum> findAll(List<String> thePermissions) {
1261                return Optional.ofNullable(thePermissions).stream()
1262                                .flatMap(Collection::stream)
1263                                .map(PermissionEnum::find)
1264                                .filter(Optional::isPresent)
1265                                .map(Optional::get)
1266                                .collect(Collectors.toList());
1267        }
1268
1269        private static <T extends Enum<T>> Set<T> unmodifiableEnumSet(T[] theValues) {
1270                if (theValues.length == 0) {
1271                        return Collections.emptySet();
1272                }
1273                Set<T> set = EnumSet.of(theValues[0], theValues);
1274                return Collections.unmodifiableSet(set);
1275        }
1276
1277        @Deprecated(since = "7.2.0")
1278        public static Set<PermissionEnum> roles() {
1279                return ROLES;
1280        }
1281
1282        public static String extractFirstSpaceSeparatedArgument(String theArgument) {
1283                if (isNotBlank(theArgument)) {
1284                        int spaceIdx = theArgument.indexOf(' ');
1285                        if (spaceIdx != -1) {
1286                                return trim(theArgument.substring(0, spaceIdx));
1287                        } else {
1288                                return theArgument;
1289                        }
1290                }
1291                return null;
1292        }
1293
1294        public static Collection<String> extractSpaceSeparatedResourceTypesFromArgument(String theArgument) {
1295                return extractSpaceSeparatedResourceTypesFromArgument(theArgument, 0);
1296        }
1297
1298        public static Collection<String> extractSpaceSeparatedResourceTypesFromArgument(
1299                        String theArgument, int theFromOffsetIndex) {
1300                if (isBlank(theArgument)) {
1301                        return null;
1302                }
1303                StringTokenizer tok = new StringTokenizer(theArgument, " ");
1304                List<String> retVal = new ArrayList<>();
1305                while (tok.hasNext()) {
1306                        String next = tok.next();
1307                        next = trim(next);
1308                        if (isNotBlank(next)) {
1309                                if (theFromOffsetIndex > 0) {
1310                                        theFromOffsetIndex--;
1311                                        continue;
1312                                }
1313                                retVal.add(next);
1314                        }
1315                }
1316                return retVal;
1317        }
1318
1319        private static Set<PermissionEnum> getAllPermissions() {
1320                return Arrays.stream(values())
1321                                .filter(p -> !p.isRole())
1322                                .filter(p -> !p.isRequiresArgument())
1323                                .collect(Collectors.toSet());
1324        }
1325
1326        private static Set<PermissionEnum> getAllSuperuserPermissions() {
1327                return Arrays.stream(values())
1328                                .filter(p -> !p.isRole())
1329                                .filter(p -> !p.isExpungePermission())
1330                                .filter(p -> !p.isRequiresArgument())
1331                                .collect(Collectors.toSet());
1332        }
1333
1334        private static Set<PermissionEnum> getAllFhirSuperuserPermissions() {
1335                Set<PermissionEnum> permissions = getAllSuperuserPermissions().stream()
1336                                .filter(PermissionEnum::isFhirPermission)
1337                                .collect(Collectors.toSet());
1338                permissions.add(ACCESS_FHIRWEB);
1339                return permissions;
1340        }
1341
1342        private static Set<PermissionEnum> getRoles() {
1343                Set<PermissionEnum> roles = Arrays.stream(values())
1344                                .filter(PermissionEnum::isRole)
1345                                .collect(Collectors.toCollection(() -> EnumSet.noneOf(PermissionEnum.class)));
1346                return Collections.unmodifiableSet(roles);
1347        }
1348
1349        boolean isRole() {
1350                // unlike other roles, the terminology role is involved in the logic that checks the access
1351                return name().startsWith("ROLE_") && this != ROLE_FHIR_TERMINOLOGY_READ_CLIENT;
1352        }
1353
1354        public boolean isExpungePermission() {
1355                return name().toLowerCase().contains("expunge");
1356        }
1357
1358        /**
1359         * Determines if this is a FHIR delete permission.
1360         *
1361         * @return true if FHIR delete, false otherwise
1362         */
1363        public boolean isSuperuser() {
1364                return name().toLowerCase().contains("superuser");
1365        }
1366
1367        /**
1368         * Determines if this is a FHIR related permission.
1369         *
1370         * @return true if FHIR permission, false otherwise
1371         */
1372        public boolean isFhirPermission() {
1373                return PermissionCategoryEnum.FHIR_CLIENT.equals(myCategory);
1374        }
1375}