001package ca.cdr.api.model.json;
002
003/*
004 * #%L
005 * Smile CDR - CDR
006 * %%
007 * Copyright (C) 2016 - 2026 Smile CDR, Inc.
008 * %%
009 * All rights reserved.
010 * #L%
011 */
012
013import ca.cdr.api.model.enm.PermissionEnum;
014import ca.cdr.api.model.enm.UserTwoFactorAuthEnum;
015import ca.uhn.fhir.context.ConfigurationException;
016import ca.uhn.fhir.model.api.IModelJson;
017import com.fasterxml.jackson.annotation.JsonProperty;
018import com.fasterxml.jackson.annotation.JsonPropertyOrder;
019import io.swagger.v3.oas.annotations.Operation;
020import io.swagger.v3.oas.annotations.Parameter;
021import io.swagger.v3.oas.annotations.media.Schema;
022import jakarta.annotation.Nonnull;
023import org.apache.commons.lang3.SerializationUtils;
024import org.apache.commons.lang3.Validate;
025import org.apache.commons.lang3.builder.ToStringBuilder;
026import org.apache.commons.lang3.builder.ToStringStyle;
027import org.hl7.fhir.dstu3.model.DateType;
028import org.springframework.security.core.userdetails.UserDetails;
029import tools.jackson.databind.annotation.JsonDeserialize;
030import tools.jackson.databind.annotation.JsonSerialize;
031
032import java.io.Serializable;
033import java.util.ArrayList;
034import java.util.Collection;
035import java.util.Date;
036import java.util.List;
037import java.util.Optional;
038import java.util.Set;
039import java.util.TreeSet;
040import java.util.stream.Collectors;
041
042import static org.apache.commons.lang3.StringUtils.defaultString;
043import static org.apache.commons.lang3.StringUtils.isNotBlank;
044
045/**
046 * Perhaps if anyone is wondering why we have such a vague fields such as associatedResources and/or defaultLaunchContexts, in our model in the first place.
047 * It's because the SMART spec has this concept of launch contexts, where the launch context is simply the patient/encounter/location that should
048 * be opened when the app starts.
049 * And there's nothing more implied there, just "this is what you should open", so the reason could be anything:
050 * - the user is that patient
051 * - the user has picked that patient from a list
052 * - the user is the parent of the patient
053 * - etc
054 */
055@Schema(name = "UserDetails", description = "A user definition")
056@JsonPropertyOrder({
057        "pid",
058        "nodeId",
059        "moduleId",
060        "username",
061        "familyName",
062        "givenName",
063        "notes",
064        "lastActive",
065        "lastConnected",
066        "credentialExpiry",
067        "accountLocked",
068        "systemUser",
069        "authorities",
070        "associatedResources",
071        "defaultLaunchContexts"
072})
073public class UserDetailsJson implements UserDetails, Cloneable, IHasAuthorities, ca.uhn.fhir.model.api.IModelJson {
074
075        private static final long serialVersionUID = 2L;
076
077        /*
078         * ******************************************************************
079         * Note: If you add properties, add them to the copy constructor too!
080         * ******************************************************************
081         */
082
083        @JsonProperty("accountDisabled")
084        @Parameter(description = "Is this account currently disabled?")
085        private Boolean myAccountDisabled;
086
087        @JsonProperty("notes")
088        @Parameter(description = "Any notes regarding this user")
089        private String myNotes;
090
091        @JsonProperty("email")
092        @Parameter(description = "The user email address")
093        private String myEmail;
094
095        @JsonProperty("accountExpiry")
096        @JsonSerialize(using = JsonDateSerializer.class)
097        @JsonDeserialize(using = JsonDateWithEmptyDeserializer.class)
098        @Parameter(description = "The expiry date for the user (if any) or null if the account should not expire")
099        private Date myAccountExpiry;
100
101        @JsonProperty("accountLocked")
102        @Parameter(description = "Is this account currently locked?")
103        private Boolean myAccountLocked;
104
105        @JsonProperty("failedLoginAttempts")
106        @Parameter(description = "Number of consecutive failed login attempts")
107        private int myFailedLoginAttempts;
108
109        @JsonProperty("authorities")
110        @Parameter(description = "Any authorities (permissions) granted to this user")
111        private List<GrantedAuthorityJson> myAuthorities;
112
113        @JsonProperty("associatedResources")
114        @Schema(
115                        description =
116                                        "A collection of \"associated resource\" IDs. Associated resources are FHIR resources with some connection to the given user, such as a Patient or Practitioner resource representing the actual user.",
117                        accessMode = Schema.AccessMode.READ_ONLY)
118        private List<AssociatedResourceJson> myAssociatedResources;
119
120        @JsonProperty("credentialExpiry")
121        @JsonSerialize(using = JsonDateSerializer.class)
122        @JsonDeserialize(using = JsonDateWithEmptyDeserializer.class)
123        @Parameter(description = "If set, provides the date that the user credentials will expire")
124        private Date myCredentialExpiry;
125
126        @JsonProperty("familyName")
127        @Parameter(description = "The user's family (last) name")
128        private String myFamilyName;
129
130        @JsonProperty("givenName")
131        @Parameter(description = "The user's given (first) name")
132        private String myGivenName;
133
134        @JsonProperty(value = "lastActive")
135        @JsonSerialize(using = JsonDateSerializer.class)
136        @JsonDeserialize(using = JsonDateDeserializer.class)
137        @Schema(
138                        accessMode = Schema.AccessMode.READ_ONLY,
139                        description =
140                                        "The date at which the user account was last used. Note that this property is read-only, and is only updated once per day, so it is accurate only to the date.")
141        private Date myLastActive;
142
143        @JsonProperty(value = "lastConnected")
144        @JsonSerialize(using = JsonDateSerializer.class)
145        @JsonDeserialize(using = JsonDateDeserializer.class)
146        @Schema(
147                        accessMode = Schema.AccessMode.READ_ONLY,
148                        description =
149                                        "The date at which the user last logged in. This property is read-only and is accurate to the minute.")
150        private Date myLastConnected;
151
152        @Schema(
153                        accessMode = Schema.AccessMode.READ_ONLY,
154                        description =
155                                        "The module ID associated with this user account. This is the module ID associated with the Inbound Security module that is responsible for authenticating this user.")
156        @JsonProperty("moduleId")
157        private String myModuleId;
158
159        @Schema(
160                        accessMode = Schema.AccessMode.READ_ONLY,
161                        description =
162                                        "The node ID associated with this user. This is the master node ID associated with the Inbound Security module that is responsible for authenticating this user.")
163        @JsonProperty("nodeId")
164        private String myNodeId;
165
166        @JsonProperty("password")
167        @Schema(
168                        description =
169                                        "The user password (note that this property will not be populated when sessions are made available to user code)",
170                        readOnly = true)
171        private String myPassword;
172
173        @JsonProperty("pid")
174        @Schema(accessMode = Schema.AccessMode.READ_ONLY, description = "The PID (internal ID) for this user")
175        private Long myPid;
176
177        @JsonProperty("username")
178        @Schema(accessMode = Schema.AccessMode.READ_ONLY, description = "The username for this user")
179        private String myUsername;
180
181        @JsonProperty("usernameNamespace")
182        @Schema(accessMode = Schema.AccessMode.READ_ONLY, description = "The username namespace associated with this user")
183        private String myUsernameNamespace;
184
185        @Schema(
186                        accessMode = Schema.AccessMode.READ_ONLY,
187                        description =
188                                        "If this is set, the user cannot be renamed or deleted (this property may only be set by the system)")
189        @JsonProperty("systemUser")
190        private boolean mySystemUser;
191
192        @Schema(
193                        accessMode = Schema.AccessMode.READ_ONLY,
194                        description =
195                                        "If this value is set, the user is backed by an external user directory (this property may only be set by the system)")
196        @JsonProperty("external")
197        private boolean myExternal;
198
199        @JsonProperty("defaultLaunchContexts")
200        @Schema(
201                        accessMode = Schema.AccessMode.READ_ONLY,
202                        description = "The SMART launch contexts associated with this account")
203        private List<LaunchContextJson> myDefaultLaunchContexts;
204
205        @JsonProperty("serviceAccount")
206        private Boolean myServiceAccount;
207
208        @JsonProperty("twoFactorAuthStatus")
209        private UserTwoFactorAuthEnum myTwoFactorAuthStatus;
210
211        /**
212         * Constructor
213         */
214        public UserDetailsJson() {
215                super();
216        }
217
218        /**
219         * Constructor
220         */
221        public UserDetailsJson(UserDetailsJson theCopyObject) {
222                this();
223
224                setPid(theCopyObject.getPid());
225
226                setUsername(theCopyObject.getUsername());
227                setUsernameNamespace(theCopyObject.getUsernameNamespace());
228                setPassword(theCopyObject.getPassword());
229
230                setNodeId(theCopyObject.getNodeId());
231                setModuleId(theCopyObject.getModuleId());
232
233                setFamilyName(theCopyObject.getFamilyName());
234                setGivenName(theCopyObject.getGivenName());
235                setEmail(theCopyObject.getEmail());
236
237                setNotes(theCopyObject.getNotes());
238                setFailedLoginAttempts(theCopyObject.getFailedLoginAttempts());
239                setAccountExpiry(theCopyObject.getAccountExpiry());
240                setAccountDisabled(theCopyObject.isAccountDisabled());
241                setAccountLocked(theCopyObject.isAccountLocked());
242                setServiceAccount(theCopyObject.isServiceAccount());
243                setSystemUser(theCopyObject.isSystemUser());
244                setCredentialExpiry(theCopyObject.getCredentialExpiry());
245                setLastActive(theCopyObject.getLastActive());
246                setLastConnected(theCopyObject.getLastConnected());
247
248                setAuthorities(theCopyObject.getAuthorities());
249                setExternal(theCopyObject.isExternal());
250
251                setTwoFactorAuthStatus(theCopyObject.getTwoFactorAuthStatus());
252
253                getDefaultLaunchContexts().addAll(theCopyObject.getDefaultLaunchContexts());
254                getAssociatedResources().addAll(theCopyObject.getAssociatedResources());
255        }
256
257        /*
258         * ******************************************************************
259         * Note: If you add properties, add them to the copy constructor too!
260         * ******************************************************************
261         */
262
263        public UserTwoFactorAuthEnum getTwoFactorAuthStatus() {
264                return myTwoFactorAuthStatus;
265        }
266
267        public UserDetailsJson setTwoFactorAuthStatus(UserTwoFactorAuthEnum theTwoFactorAuthStatus) {
268                myTwoFactorAuthStatus = theTwoFactorAuthStatus;
269                return this;
270        }
271
272        public void addAssociatedResource(String theType, String theResourceId) {
273                Validate.notBlank(theType, "The type must not be null");
274                AssociatedResourceTypeEnum type;
275                try {
276                        type = AssociatedResourceTypeEnum.valueOf(theType);
277                } catch (Exception e) {
278                        throw new ConfigurationException("Invalid type: " + theType);
279                }
280                addAssociatedResource(type, theResourceId);
281        }
282
283        public void addAssociatedResource(AssociatedResourceTypeEnum theType, String theResourceId) {
284                Validate.notNull(theType, "The type must not be null");
285                Validate.notBlank(theResourceId, "The resource ID must not be null");
286
287                getAssociatedResources()
288                                .add(new AssociatedResourceJson()
289                                                .setType(AssociatedResourceTypeEnum.SELF)
290                                                .setResourceId(theResourceId));
291        }
292
293        public void addAuthorities(GrantedAuthorityJson... theAuthority) {
294                for (GrantedAuthorityJson next : theAuthority) {
295                        addAuthority(next);
296                }
297        }
298
299        public UserDetailsJson addAuthority(PermissionEnum thePermission) {
300                getAuthorities().add(new GrantedAuthorityJson(thePermission));
301                return this;
302        }
303
304        public void addAuthority(GrantedAuthorityJson theAuthority) {
305                Validate.notNull(theAuthority, "theAuthority must not be null");
306                getAuthorities().add(theAuthority);
307        }
308
309        public LaunchContextJson addDefaultLaunchContext() {
310                LaunchContextJson ctx = new LaunchContextJson();
311                getDefaultLaunchContexts().add(ctx);
312                return ctx;
313        }
314
315        @SuppressWarnings("MethodDoesntCallSuperMethod")
316        @Override
317        public UserDetailsJson clone() {
318                return SerializationUtils.clone(this);
319        }
320
321        public Date getAccountExpiry() {
322                return myAccountExpiry;
323        }
324
325        public void setAccountExpiry(Date theAccountExpiry) {
326                myAccountExpiry = theAccountExpiry;
327        }
328
329        public boolean hasAccountExpiryDate() {
330                return myAccountExpiry != null;
331        }
332
333        public String getAccountExpiryDateAsIsoString() {
334                if (myAccountExpiry == null) {
335                        return "";
336                }
337                return new DateType(myAccountExpiry).getValueAsString();
338        }
339
340        public List<AssociatedResourceJson> getAssociatedResources() {
341                if (myAssociatedResources == null) {
342                        myAssociatedResources = new ArrayList<>();
343                }
344                return myAssociatedResources;
345        }
346
347        public boolean hasAuthorities() {
348                return myAuthorities != null;
349        }
350
351        @Override
352        @Nonnull
353        public List<GrantedAuthorityJson> getAuthorities() {
354                if (myAuthorities == null) {
355                        myAuthorities = new ArrayList<>();
356                }
357                return myAuthorities;
358        }
359
360        public UserDetailsJson setAuthorities(Collection<GrantedAuthorityJson> theAuthorities) {
361                myAuthorities = new ArrayList<>(theAuthorities);
362                return this;
363        }
364
365        public boolean hasCredentialExpiryDate() {
366                return myCredentialExpiry != null;
367        }
368
369        public Date getCredentialExpiry() {
370                return myCredentialExpiry;
371        }
372
373        public void setCredentialExpiry(Date theCredentialExpiry) {
374                myCredentialExpiry = theCredentialExpiry;
375        }
376
377        public String getCredentialExpiryDateAsIsoString() {
378                if (myCredentialExpiry == null) {
379                        return "";
380                }
381                return new DateType(myCredentialExpiry).getValueAsString();
382        }
383
384        public boolean hasDefaultLaunchContexts() {
385                return myDefaultLaunchContexts != null;
386        }
387
388        public List<LaunchContextJson> getDefaultLaunchContexts() {
389                if (myDefaultLaunchContexts == null) {
390                        myDefaultLaunchContexts = new ArrayList<>();
391                }
392                return myDefaultLaunchContexts;
393        }
394
395        public Optional<String> getDefaultLaunchContextResourceIdForContextType(@Nonnull String theContextType) {
396                for (LaunchContextJson contextParam : getDefaultLaunchContexts()) {
397                        if (theContextType.equalsIgnoreCase(contextParam.getContextType())) {
398                                return Optional.of(contextParam.getResourceId());
399                        }
400                }
401
402                return Optional.empty();
403        }
404
405        @SuppressWarnings("unused")
406        public String getDefaultLaunchContextsCommaSeparated(String theType) {
407                StringBuilder b = new StringBuilder();
408                getDefaultLaunchContexts().stream()
409                                .filter(t -> t.getContextType().equals(theType))
410                                .filter(t -> isNotBlank(t.getResourceId()))
411                                .forEach(t -> {
412                                        if (!b.isEmpty()) {
413                                                b.append(", ");
414                                        }
415                                        b.append(t.getResourceId());
416                                });
417                return b.toString();
418        }
419
420        public boolean hasEmail() {
421                return myEmail != null;
422        }
423
424        public String getEmail() {
425                return myEmail;
426        }
427
428        public UserDetailsJson setEmail(String theEmail) {
429                myEmail = theEmail;
430                return this;
431        }
432
433        public boolean hasFamilyName() {
434                return myFamilyName != null;
435        }
436
437        public String getFamilyName() {
438                return myFamilyName;
439        }
440
441        public UserDetailsJson setFamilyName(String theFamilyName) {
442                myFamilyName = theFamilyName;
443                return this;
444        }
445
446        public String getFullName() {
447                return (defaultString(myGivenName) + ' ' + defaultString(myFamilyName)).trim();
448        }
449
450        public boolean hasGivenName() {
451                return myGivenName != null;
452        }
453
454        public String getGivenName() {
455                return myGivenName;
456        }
457
458        public UserDetailsJson setGivenName(String theGivenName) {
459                myGivenName = theGivenName;
460                return this;
461        }
462
463        public Date getLastActive() {
464                return myLastActive;
465        }
466
467        public void setLastActive(Date theLastActive) {
468                myLastActive = theLastActive;
469        }
470
471        public Date getLastConnected() {
472                return myLastConnected;
473        }
474
475        public void setLastConnected(Date theLastConnected) {
476                myLastConnected = theLastConnected;
477        }
478
479        public String getModuleId() {
480                return myModuleId;
481        }
482
483        public UserDetailsJson setModuleId(String theModuleId) {
484                myModuleId = theModuleId;
485                return this;
486        }
487
488        public String getNodeId() {
489                return myNodeId;
490        }
491
492        public UserDetailsJson setNodeId(String theNodeId) {
493                myNodeId = theNodeId;
494                return this;
495        }
496
497        public boolean hasNotes() {
498                return myNotes != null;
499        }
500
501        public String getNotes() {
502                return myNotes;
503        }
504
505        public void setNotes(String theNotes) {
506                myNotes = theNotes;
507        }
508
509        @Override
510        public String getPassword() {
511                return myPassword;
512        }
513
514        public UserDetailsJson setPassword(String thePassword) {
515                myPassword = thePassword;
516                return this;
517        }
518
519        public boolean hasPassword() {
520                return myPassword != null;
521        }
522
523        public Long getPid() {
524                return myPid;
525        }
526
527        public UserDetailsJson setPid(Long thePid) {
528                myPid = thePid;
529                return this;
530        }
531
532        public Set<String> getAuthorityNames() {
533                return getAuthorities().stream()
534                                .map(t -> t.getPermission().name())
535                                .collect(Collectors.toCollection(TreeSet::new));
536        }
537
538        public Boolean getServiceUser() {
539                if (myServiceAccount == null) {
540                        return false;
541                }
542                return myServiceAccount;
543        }
544
545        public boolean hasUsername() {
546                return myUsername != null;
547        }
548
549        @Override
550        public String getUsername() {
551                return myUsername;
552        }
553
554        public UserDetailsJson setUsername(String theUsername) {
555                myUsername = theUsername;
556                return this;
557        }
558
559        @Override
560        public List<GrantedAuthorityJson> getPermissions() {
561                return getAuthorities();
562        }
563
564        @Operation(summary = "hasAuthority", description = "Does the user have the given permission?")
565        public boolean hasAuthority(
566                        @Parameter(name = "thePermission", description = "The name of the permission, e.g. 'ROLE_FHIR_CLIENT'")
567                                        String thePermission) {
568                for (GrantedAuthorityJson next : getAuthorities()) {
569                        if (next.getPermission().name().equals(thePermission)) {
570                                return true;
571                        }
572                }
573                return false;
574        }
575
576        public boolean hasAccountDisabled() {
577                return myAccountDisabled != null;
578        }
579
580        public boolean isAccountDisabled() {
581                if (myAccountDisabled == null) {
582                        return false;
583                }
584                return myAccountDisabled;
585        }
586
587        public void setAccountDisabled(boolean theAccountDisabled) {
588                myAccountDisabled = theAccountDisabled;
589        }
590
591        public boolean hasAccountLocked() {
592                return myAccountLocked != null;
593        }
594
595        public boolean isAccountLocked() {
596                if (myAccountLocked == null) {
597                        return false;
598                }
599                return myAccountLocked;
600        }
601
602        public void lockAccount() {
603                setAccountLocked(true);
604        }
605
606        public void setAccountLocked(boolean theAccountLocked) {
607                myAccountLocked = theAccountLocked;
608        }
609
610        public void setFailedLoginAttempts(int theFailedLoginAttempts) {
611                myFailedLoginAttempts = theFailedLoginAttempts;
612        }
613
614        public int getFailedLoginAttempts() {
615                return myFailedLoginAttempts;
616        }
617
618        public int incrementFailedLoginAttempts() {
619                setFailedLoginAttempts(getFailedLoginAttempts() + 1);
620                return getFailedLoginAttempts();
621        }
622
623        public void resetFailedLoginAttempts() {
624                setFailedLoginAttempts(0);
625        }
626
627        @Override
628        public boolean isAccountNonExpired() {
629                return myAccountExpiry == null || myAccountExpiry.getTime() > System.currentTimeMillis();
630        }
631
632        @Override
633        public boolean isAccountNonLocked() {
634                return !isAccountLocked();
635        }
636
637        @Override
638        public boolean isCredentialsNonExpired() {
639                return myCredentialExpiry == null || myCredentialExpiry.getTime() > System.currentTimeMillis();
640        }
641
642        @Override
643        public boolean isEnabled() {
644                return !isAccountDisabled();
645        }
646
647        public boolean isExternal() {
648                return myExternal;
649        }
650
651        public void setExternal(boolean theExternal) {
652                myExternal = theExternal;
653        }
654
655        public boolean hasServiceAccount() {
656                return myServiceAccount != null;
657        }
658
659        public boolean isServiceAccount() {
660                if (myServiceAccount == null) {
661                        return false;
662                }
663                return myServiceAccount;
664        }
665
666        public void setServiceAccount(boolean theServiceAccount) {
667                myServiceAccount = theServiceAccount;
668        }
669
670        public boolean isSystemUser() {
671                return mySystemUser;
672        }
673
674        public UserDetailsJson setSystemUser(boolean theSystemUser) {
675                mySystemUser = theSystemUser;
676                return this;
677        }
678
679        @Override
680        public String toString() {
681                ToStringBuilder b = new ToStringBuilder(this, ToStringStyle.NO_CLASS_NAME_STYLE);
682                b.append("pid", myPid);
683                b.append("username", myUsername);
684                b.append("familyName", myFamilyName);
685                b.append("givenName", myGivenName);
686                b.append("authorities", myAuthorities);
687                b.append("lastActive", myLastActive);
688                b.append("lastConnected", myLastConnected);
689                b.append("failedLoginAttempts", myFailedLoginAttempts);
690                if (myAccountDisabled != null && myAccountDisabled) {
691                        b.append("accountDisabled", myAccountDisabled);
692                }
693                if (myAccountExpiry != null) {
694                        b.append("accountExpiryDate", myAccountExpiry);
695                }
696                if (myAccountLocked != null && myAccountLocked) {
697                        b.append("accountLocked", myAccountLocked);
698                }
699                if (myCredentialExpiry != null) {
700                        b.append("credentialExpiryDate", myCredentialExpiry);
701                }
702                if (mySystemUser) {
703                        b.append("systemUser", mySystemUser);
704                }
705                if (myExternal) {
706                        b.append("external", myExternal);
707                }
708                b.append("nodeId", myNodeId);
709                b.append("moduleId", myModuleId);
710                return b.toString();
711        }
712
713        public String getUsernameNamespace() {
714                return myUsernameNamespace;
715        }
716
717        public void setUsernameNamespace(String theUsernameNamespace) {
718                myUsernameNamespace = theUsernameNamespace;
719        }
720
721        public boolean hasUsernameNamespace() {
722                return myUsernameNamespace != null;
723        }
724
725        @Operation(
726                        summary = "getOrCreateDefaultLaunchContext",
727                        description = "Returns the first default launch context for the given type, creating one if none exists")
728        public LaunchContextJson getOrCreateDefaultLaunchContext(
729                        @Parameter(name = "theContextType", description = "The context type, e.g. \"patient\" or \"practitioner\"")
730                                        String theContextType) {
731                for (LaunchContextJson next : getDefaultLaunchContexts()) {
732                        if (next.getContextType().equals(theContextType)) {
733                                return next;
734                        }
735                }
736
737                LaunchContextJson retVal = new LaunchContextJson().setContextType(theContextType);
738                getDefaultLaunchContexts().add(retVal);
739                return retVal;
740        }
741
742        @Operation(
743                        summary = "getOrCreateDefaultLaunchContext",
744                        description = "Returns the first default launch context for the given type, creating one if none exists")
745        public LaunchContextJson getOrCreateDefaultLaunchContext(
746                        @Parameter(name = "theContextType", description = "The context type, e.g. \"patient\" or \"practitioner\"")
747                                        String theContextType,
748                        @Parameter(name = "theIndex", description = "The index, starting at 0") int theIndex) {
749
750                int foundIndex = 0;
751                for (LaunchContextJson next : getDefaultLaunchContexts()) {
752                        if (next.getContextType().equals(theContextType)) {
753                                if (theIndex == foundIndex) {
754                                        return next;
755                                } else {
756                                        foundIndex++;
757                                }
758                        }
759                }
760
761                LaunchContextJson retVal = new LaunchContextJson().setContextType(theContextType);
762                getDefaultLaunchContexts().add(retVal);
763                return retVal;
764        }
765
766        /**
767         * What type of relationship does the user have to the
768         * given resource
769         */
770        public enum AssociatedResourceTypeEnum {
771
772                /**
773                 * This associated resource is the user themself
774                 */
775                SELF
776        }
777
778        /**
779         * This structure represents a link between a user in the auth database
780         * and a resource in the FHIR database. This can be used, for example,
781         * to specify that a particular user is a specific Patient in the
782         * CDR. That linkage can then be applied in order to make
783         * security/permission decisions.
784         */
785        @Schema(
786                        name = "AssociatedResource",
787                        description = "This structure represents a link between a user in the auth database "
788                                        + "and a resource in the FHIR database. This can be used, for example, "
789                                        + "to specify that a particular user is a specific Patient in the "
790                                        + "CDR. That linkage can then be applied in order to make "
791                                        + "security/permission decisions.")
792        public static class AssociatedResourceJson implements Serializable, IModelJson {
793
794                @JsonProperty("type")
795                @Schema(description = "The relationship between the user and the resource")
796                private AssociatedResourceTypeEnum myType;
797
798                @JsonProperty("resourceId")
799                @Schema(description = "The resource ID itself, e.g. 'Patient/123'", example = "Patient/123")
800                private String myResourceId;
801
802                public String getResourceId() {
803                        return myResourceId;
804                }
805
806                public AssociatedResourceJson setResourceId(String theResourceId) {
807                        myResourceId = theResourceId;
808                        return this;
809                }
810
811                public AssociatedResourceTypeEnum getType() {
812                        return myType;
813                }
814
815                public AssociatedResourceJson setType(String theType) {
816                        myType = AssociatedResourceTypeEnum.valueOf(theType);
817                        return this;
818                }
819
820                public AssociatedResourceJson setType(AssociatedResourceTypeEnum theType) {
821                        myType = theType;
822                        return this;
823                }
824        }
825
826        public static PermissionEnum toPermissionEnum(String thePermission) {
827                try {
828                        return PermissionEnum.valueOf(thePermission);
829                } catch (Exception e) {
830                        throw new ConfigurationException("Invalid permission name: " + thePermission);
831                }
832        }
833}