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