11import { MageEventId } from '../entities/events/entities.events'
22import { Team , TeamId } from '../entities/teams/entities.teams'
3- import { User , UserId , UserRepository , UserRepositoryError } from '../entities/users/entities.users'
4- import { createEnrollmentCandidateUser , IdentityProvider , IdentityProviderUser , UserIngressBindingsRepository , UserIngressBindings } from './ingress.entities'
5- import { EnrollNewUser } from './ingress.services.api'
3+ import { UserExpanded , UserId , UserRepository , UserRepositoryError } from '../entities/users/entities.users'
4+ import { createEnrollmentCandidateUser , IdentityProvider , IdentityProviderUser , UserIngressBindingsRepository , UserIngressBindings , determinUserIngressBindingAdmission } from './ingress.entities'
5+ import { AdmissionDeniedReason , AdmissionResult , AdmitUserFromIdentityProviderAccount , EnrollNewUser } from './ingress.services.api'
66
77export interface AssignTeamMember {
88 ( member : UserId , team : TeamId ) : Promise < boolean >
@@ -12,20 +12,74 @@ export interface FindEventTeam {
1212 ( mageEventId : MageEventId ) : Promise < Team | null >
1313}
1414
15- export function CreateProcessNewUserEnrollmentService ( userRepo : UserRepository , ingressBindingRepo : UserIngressBindingsRepository , findEventTeam : FindEventTeam , assignTeamMember : AssignTeamMember ) : EnrollNewUser {
16- return async function processNewUserEnrollment ( idpAccount : IdentityProviderUser , idp : IdentityProvider ) : Promise < { mageAccount : User , ingressBindings : UserIngressBindings } > {
15+ export function CreateUserAdmissionService ( userRepo : UserRepository , ingressBindingRepo : UserIngressBindingsRepository , enrollNewUser : EnrollNewUser ) : AdmitUserFromIdentityProviderAccount {
16+ return async function ( idpAccount : IdentityProviderUser , idp : IdentityProvider ) : Promise < AdmissionResult > {
17+ return userRepo . findByUsername ( idpAccount . username )
18+ . then ( existingAccount => {
19+ if ( existingAccount ) {
20+ return ingressBindingRepo . readBindingsForUser ( existingAccount . id ) . then ( ingressBindings => {
21+ return { enrolled : false , mageAccount : existingAccount , ingressBindings }
22+ } )
23+ }
24+ console . info ( `enrolling new user account ${ idpAccount . username } from identity provider ${ idp . name } ` )
25+ return enrollNewUser ( idpAccount , idp ) . then ( enrollment => ( { enrolled : true , ...enrollment } ) )
26+ } )
27+ . then < AdmissionResult > ( userIngress => {
28+ const { enrolled, mageAccount, ingressBindings } = userIngress
29+ const idpAdmission = determinUserIngressBindingAdmission ( idpAccount , idp , ingressBindings )
30+ if ( idpAdmission . deny ) {
31+ console . error ( `user ${ mageAccount . username } has no ingress binding to identity provider ${ idp . name } ` )
32+ return { action : 'denied' , reason : AdmissionDeniedReason . NameConflict , enrolled, mageAccount }
33+ }
34+ if ( idpAdmission . admitNew ) {
35+ return ingressBindingRepo . saveUserIngressBinding ( mageAccount . id , idpAdmission . admitNew )
36+ . then < AdmissionResult > ( ( ) => ( { action : 'admitted' , mageAccount, enrolled } ) )
37+ . catch ( err => {
38+ console . error ( `error saving ingress binding for user ${ mageAccount . username } to idp ${ idp . name } ` , err )
39+ return { action : 'denied' , reason : AdmissionDeniedReason . InternalError , mageAccount, enrolled }
40+ } )
41+ }
42+ return { action : 'admitted' , mageAccount, enrolled }
43+ } )
44+ . then < AdmissionResult > ( userIngress => {
45+ const { action, mageAccount, enrolled } = userIngress
46+ if ( ! mageAccount ) {
47+ return { action : 'denied' , reason : AdmissionDeniedReason . InternalError , mageAccount, enrolled }
48+ }
49+ if ( action === 'denied' ) {
50+ return userIngress
51+ }
52+ if ( ! mageAccount . active ) {
53+ return { action : 'denied' , reason : AdmissionDeniedReason . PendingApproval , mageAccount, enrolled }
54+ }
55+ if ( ! mageAccount . enabled ) {
56+ return { action : 'denied' , reason : AdmissionDeniedReason . Disabled , mageAccount, enrolled }
57+ }
58+ return userIngress
59+ } )
60+ . catch < AdmissionResult > ( err => {
61+ console . error ( `error admitting user account ${ idpAccount . username } from identity provider ${ idp . name } ` , err )
62+ return { action : 'denied' , reason : AdmissionDeniedReason . InternalError , enrolled : false , mageAccount : null }
63+ } )
64+ }
65+ }
66+
67+ export function CreateNewUserEnrollmentService ( userRepo : UserRepository , ingressBindingRepo : UserIngressBindingsRepository , findEventTeam : FindEventTeam , assignTeamMember : AssignTeamMember ) : EnrollNewUser {
68+ return async function processNewUserEnrollment ( idpAccount : IdentityProviderUser , idp : IdentityProvider ) : Promise < { mageAccount : UserExpanded , ingressBindings : UserIngressBindings } > {
1769 console . info ( `enrolling new user account ${ idpAccount . username } from identity provider ${ idp . name } ` )
1870 const candidate = createEnrollmentCandidateUser ( idpAccount , idp )
1971 const mageAccount = await userRepo . create ( candidate )
2072 if ( mageAccount instanceof UserRepositoryError ) {
2173 throw mageAccount
2274 }
75+ const now = new Date ( )
2376 const ingressBindings = await ingressBindingRepo . saveUserIngressBinding (
2477 mageAccount . id ,
2578 {
2679 idpId : idp . id ,
2780 idpAccountId : idpAccount . username ,
28- idpAccountAttrs : { } ,
81+ created : now ,
82+ updated : now ,
2983 }
3084 )
3185 if ( ingressBindings instanceof Error ) {
0 commit comments