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