Skip to content

Commit

Permalink
Update non-patient enrollment logic (#168)
Browse files Browse the repository at this point in the history
# Update non-patient enrollment logic

## ♻️ Current situation & Problem
Currently, all users receive a welcome message when enrolling. In the
future, only patients should receive that message.


## ⚙️ Release Notes 
*Add a bullet point list summary of the feature and possible migration
guides if this is a breaking change so this section can be added to the
release notes.*
*Include code snippets that provide examples of the feature implemented
or links to the documentation if it appends or changes the public
interface.*


## 📚 Documentation
*Please ensure that you properly document any additions in conformance
to [Spezi Documentation
Guide](https://github.com/StanfordSpezi/.github/blob/main/DOCUMENTATIONGUIDE.md).*
*You can use this section to describe your solution, but we encourage
contributors to document your reasoning and changes using in-line
documentation.*


## ✅ Testing
*Please ensure that the PR meets the testing requirements set by CodeCov
and that new functionality is appropriately tested.*
*This section describes important information about the tests and why
some elements might not be testable.*


### Code of Conduct & Contributing Guidelines 

By submitting creating this pull request, you agree to follow our [Code
of
Conduct](https://github.com/StanfordBDHG/.github/blob/main/CODE_OF_CONDUCT.md)
and [Contributing
Guidelines](https://github.com/StanfordBDHG/.github/blob/main/CONTRIBUTING.md):
- [x] I agree to follow the [Code of
Conduct](https://github.com/StanfordBDHG/.github/blob/main/CODE_OF_CONDUCT.md)
and [Contributing
Guidelines](https://github.com/StanfordBDHG/.github/blob/main/CONTRIBUTING.md).
  • Loading branch information
pauljohanneskraft authored Oct 29, 2024
1 parent 28f4c54 commit e64ba6c
Show file tree
Hide file tree
Showing 6 changed files with 44 additions and 26 deletions.
6 changes: 4 additions & 2 deletions functions/src/functions/blocking.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,10 @@ export const beforeUserCreatedFunction = beforeUserCreated(
'Organization does not match invitation code.',
)

await userService.enrollUser(invitation, userId, { isSingleSignOn: true })
await factory.trigger().userEnrolled(userId)
const userDoc = await userService.enrollUser(invitation, userId, {
isSingleSignOn: true,
})
await factory.trigger().userEnrolled(userDoc)
},
)

Expand Down
6 changes: 4 additions & 2 deletions functions/src/functions/enrollUser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,15 @@ export const enrollUser = validatedOnCall(
if (invitation === undefined)
throw new https.HttpsError('not-found', 'Invitation not found')

await userService.enrollUser(invitation, userId, { isSingleSignOn: false })
const userDoc = await userService.enrollUser(invitation, userId, {
isSingleSignOn: false,
})

logger.debug(
`setupUser: User '${userId}' successfully enrolled in the study with invitation code: ${invitationCode}`,
)

await triggerService.userEnrolled(userId)
await triggerService.userEnrolled(userDoc)

logger.debug(`setupUser: User '${userId}' enrollment triggers finished`)
},
Expand Down
16 changes: 11 additions & 5 deletions functions/src/services/trigger/triggerService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -284,26 +284,32 @@ export class TriggerService {
})
}

async userEnrolled(userId: string) {
async userEnrolled(user: Document<User>) {
if (user.content.type !== UserType.patient) {
logger.error(
`TriggerService.userEnrolled(${user.id}): Skipping user of type ${user.content.type}.`,
)
return
}
try {
await this.updateRecommendationsForUser(userId)
await this.updateRecommendationsForUser(user.id)
} catch (error) {
logger.error(
`TriggerService.userEnrolled(${userId}): Updating recommendations failed due to ${String(error)}`,
`TriggerService.userEnrolled(${user.id}): Updating recommendations failed due to ${String(error)}`,
)
}

try {
await this.factory.message().addMessage(
userId,
user.id,
UserMessage.createWelcome({
videoReference: VideoReference.welcome,
}),
{ notify: true },
)
} catch (error) {
logger.error(
`TriggerService.userEnrolled(${userId}): Adding welcome message failed due to ${String(error)}`,
`TriggerService.userEnrolled(${user.id}): Adding welcome message failed due to ${String(error)}`,
)
}
}
Expand Down
36 changes: 22 additions & 14 deletions functions/src/services/user/databaseUserService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ export class DatabaseUserService implements UserService {
invitation: Document<Invitation>,
userId: string,
options: { isSingleSignOn: boolean },
): Promise<void> {
): Promise<Document<User>> {
logger.info(
`About to enroll user ${userId} using invitation at '${invitation.id}' with code '${invitation.content.code}'.`,
)
Expand Down Expand Up @@ -164,24 +164,30 @@ export class DatabaseUserService implements UserService {
`Updated auth information for user with id '${userId}' using invitation auth content.`,
)

const invitationCollections = await this.databaseService.runTransaction(
async (collections, transaction) => {
const invitationRef = collections.invitations.doc(invitation.id)
const invitationCollections = await invitationRef.listCollections()
const { invitationCollections, userDoc } =
await this.databaseService.runTransaction(
async (collections, transaction) => {
const invitationRef = collections.invitations.doc(invitation.id)
const invitationCollections = await invitationRef.listCollections()

transaction.set(
collections.users.doc(userId),
new User({
const userRef = collections.users.doc(userId)
const userData = new User({
...invitation.content.user,
lastActiveDate: new Date(),
invitationCode: invitation.content.code,
dateOfEnrollment: new Date(),
}),
)

return invitationCollections
},
)
})
const userDoc: Document<User> = {
id: userId,
path: userRef.path,
lastUpdate: new Date(),
content: userData,
}
transaction.set(userRef, userData)

return { invitationCollections, userDoc }
},
)

logger.info(
`Created user with id '${userId}' using invitation content. Will now copy invitation collections: [${invitationCollections.map((collection) => `'${collection.id}'`).join(', ')}].`,
Expand Down Expand Up @@ -220,6 +226,8 @@ export class DatabaseUserService implements UserService {
if (!options.isSingleSignOn) {
await this.updateClaims(userId)
}

return userDoc
}

async deleteInvitation(invitation: Document<Invitation>): Promise<void> {
Expand Down
4 changes: 2 additions & 2 deletions functions/src/services/user/userService.mock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,8 @@ export class MockUserService implements UserService {
async enrollUser(
invitation: Document<Invitation>,
userId: string,
): Promise<void> {
return
): Promise<Document<User>> {
return this.getUser(userId)
}

// Methods - Organizations
Expand Down
2 changes: 1 addition & 1 deletion functions/src/services/user/userService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ export interface UserService {
invitation: Document<Invitation>,
userId: string,
options: { isSingleSignOn: boolean },
): Promise<void>
): Promise<Document<User>>
deleteInvitation(invitation: Document<Invitation>): Promise<void>

// Organizations
Expand Down

0 comments on commit e64ba6c

Please sign in to comment.