Skip to content

Commit

Permalink
Use orga and project owner emails to notify (#7561)
Browse files Browse the repository at this point in the history
  • Loading branch information
frcroth committed Jan 22, 2024
1 parent 750a607 commit 9187eff
Show file tree
Hide file tree
Showing 5 changed files with 59 additions and 23 deletions.
3 changes: 2 additions & 1 deletion CHANGELOG.unreleased.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,9 @@ For upgrade instructions, please check the [migration guide](MIGRATIONS.released
- Updated antd UI library from version 4.24.8 to 4.24.15. [#7505](https://github.com/scalableminds/webknossos/pull/7505)
- Changed the default dataset search mode to also search in subfolders. [#7539](https://github.com/scalableminds/webknossos/pull/7539)
- When clicking a segment in the viewport, it is automatically focused in the segment list. A corresponding context menu entry was added as well. [#7512](https://github.com/scalableminds/webknossos/pull/7512)
- Updated the isValidName route in the API to return 200 for valid and invalid names. With this, the API version was bumped up to 6. [#7550](https://github.com/scalableminds/webknossos/pull/7550)
- Upgraded to Play 3. [#7562](https://github.com/scalableminds/webknossos/pull/7562)
- Updated the isValidName route in the API to return 200 for valid and invalid names. With this, the API version was bumped up to 6. [#7550](https://github.com/scalableminds/webknossos/pull/7550)
- When no Email Address for New-User Notifications is configured, the organization owner will be notified. For overtime notifications, the project owner and the organization owner will be notified. [#7561](https://github.com/scalableminds/webknossos/pull/7561)
- The metadata for ND datasets and their annotation has changed: upper bound of additionalAxes is now stored as an exclusive value, called "end" in the NML format. [#7547](https://github.com/scalableminds/webknossos/pull/7547)
- Added support for the *index_location* parameter in sharded Zarr 3 datasets. [#7553](https://github.com/scalableminds/webknossos/pull/7553)

Expand Down
17 changes: 14 additions & 3 deletions app/controllers/AuthenticationController.scala
Original file line number Diff line number Diff line change
Expand Up @@ -148,13 +148,19 @@ class AuthenticationController @Inject()(
_ <- Fox.runIf(inviteBox.isDefined)(Fox.runOptional(inviteBox.toOption)(i =>
inviteService.deactivateUsedInvite(i)(GlobalAccessContext)))
brainDBResult <- Fox.runIf(registerBrainDB)(brainTracing.registerIfNeeded(user, password.getOrElse("")))
newUserEmailRecipient <- organizationService.newUserMailRecipient(organization)(GlobalAccessContext)
_ = if (conf.Features.isWkorgInstance) {
mailchimpClient.registerUser(user, multiUser, tag = MailchimpTag.RegisteredAsUser)
} else {
Mailer ! Send(defaultMails.newUserMail(user.name, email, brainDBResult.flatten, autoActivate))
}
_ = Mailer ! Send(
defaultMails.registerAdminNotifyerMail(user.name, email, brainDBResult.flatten, organization, autoActivate))
defaultMails.registerAdminNotifierMail(user.name,
email,
brainDBResult.flatten,
organization,
autoActivate,
newUserEmailRecipient))
} yield {
user
}
Expand Down Expand Up @@ -356,9 +362,14 @@ class AuthenticationController @Inject()(
_ <- userService.joinOrganization(request.identity, organization._id, autoActivate = invite.autoActivate)
_ = analyticsService.track(JoinOrganizationEvent(request.identity, organization))
userEmail <- userService.emailFor(request.identity)
newUserEmailRecipient <- organizationService.newUserMailRecipient(organization)
_ = Mailer ! Send(
defaultMails
.registerAdminNotifyerMail(request.identity.name, userEmail, None, organization, invite.autoActivate))
defaultMails.registerAdminNotifierMail(request.identity.name,
userEmail,
None,
organization,
invite.autoActivate,
newUserEmailRecipient))
_ <- inviteService.deactivateUsedInvite(invite)(GlobalAccessContext)
} yield Ok
}
Expand Down
31 changes: 16 additions & 15 deletions app/mail/DefaultMails.scala
Original file line number Diff line number Diff line change
Expand Up @@ -16,58 +16,59 @@ class DefaultMails @Inject()(conf: WkConf) {
private val defaultSender = conf.Mail.defaultSender
private val newOrganizationMailingList = conf.WebKnossos.newOrganizationMailingList

def registerAdminNotifyerMail(name: String,
def registerAdminNotifierMail(name: String,
email: String,
brainDBResult: Option[String],
organization: Organization,
autoActivate: Boolean): Mail =
autoActivate: Boolean,
recipient: String): Mail =
Mail(
from = defaultSender,
subject =
s"WEBKNOSSOS | A new user ($name, $email) registered on $uri for ${organization.displayName} (${organization.name})",
bodyHtml = html.mail.notifyAdminNewUser(name, brainDBResult, uri, autoActivate).body,
recipients = List(organization.newUserMailingList)
recipients = List(recipient)
)

def overLimitMail(user: User,
projectName: String,
taskId: String,
annotationId: String,
organization: Organization): Mail =
recipients: List[String]): Mail =
Mail(
from = defaultSender,
subject = s"WEBKNOSSOS | Time limit reached. ${user.abbreviatedName} in $projectName",
bodyHtml = html.mail.notifyAdminTimeLimit(user.name, projectName, taskId, annotationId, uri).body,
recipients = List(organization.overTimeMailingList)
recipients = recipients
)

def newUserMail(name: String, receiver: String, brainDBresult: Option[String], enableAutoVerify: Boolean)(
def newUserMail(name: String, recipient: String, brainDBresult: Option[String], enableAutoVerify: Boolean)(
implicit mp: MessagesProvider): Mail =
Mail(
from = defaultSender,
subject = "Welcome to WEBKNOSSOS",
bodyHtml = html.mail.newUser(name, brainDBresult.map(Messages(_)), enableAutoVerify).body,
recipients = List(receiver)
recipients = List(recipient)
)

def activatedMail(name: String, receiver: String): Mail =
def activatedMail(name: String, recipient: String): Mail =
Mail(from = defaultSender,
subject = "WEBKNOSSOS | Account activated",
bodyHtml = html.mail.validateUser(name, uri).body,
recipients = List(receiver))
recipients = List(recipient))

def changePasswordMail(name: String, receiver: String): Mail =
def changePasswordMail(name: String, recipient: String): Mail =
Mail(from = defaultSender,
subject = "WEBKNOSSOS | Password changed",
bodyHtml = html.mail.passwordChanged(name, uri).body,
recipients = List(receiver))
recipients = List(recipient))

def resetPasswordMail(name: String, receiver: String, token: String): Mail =
def resetPasswordMail(name: String, recipient: String, token: String): Mail =
Mail(
from = defaultSender,
subject = "WEBKNOSSOS | Password Reset",
bodyHtml = html.mail.resetPassword(name, uri, token).body,
recipients = List(receiver)
recipients = List(recipient)
)

def newOrganizationMail(organizationDisplayName: String, creatorEmail: String, domain: String): Mail =
Expand All @@ -78,7 +79,7 @@ class DefaultMails @Inject()(conf: WkConf) {
recipients = List(newOrganizationMailingList)
)

def inviteMail(receiver: String,
def inviteMail(recipient: String,
inviteTokenValue: String,
autoVerify: Boolean,
organizationDisplayName: String,
Expand All @@ -88,7 +89,7 @@ class DefaultMails @Inject()(conf: WkConf) {
from = defaultSender,
subject = s"$senderName invited you to join their WEBKNOSSOS organization at $host",
bodyHtml = html.mail.invite(senderName, organizationDisplayName, inviteTokenValue, uri, autoVerify).body,
recipients = List(receiver)
recipients = List(recipient)
)
}

Expand Down
21 changes: 20 additions & 1 deletion app/models/organization/OrganizationService.scala
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import javax.inject.Inject
import models.dataset.{DataStore, DataStoreDAO}
import models.folder.{Folder, FolderDAO, FolderService}
import models.team.{PricingPlan, Team, TeamDAO}
import models.user.{Invite, MultiUserDAO, User, UserDAO}
import models.user.{Invite, MultiUserDAO, User, UserDAO, UserService}
import play.api.libs.json.{JsObject, Json}
import utils.{ObjectId, WkConf}

Expand All @@ -22,6 +22,7 @@ class OrganizationService @Inject()(organizationDAO: OrganizationDAO,
dataStoreDAO: DataStoreDAO,
folderDAO: FolderDAO,
folderService: FolderService,
userService: UserService,
rpc: RPC,
conf: WkConf,
)(implicit ec: ExecutionContext)
Expand Down Expand Up @@ -144,4 +145,22 @@ class OrganizationService @Inject()(organizationDAO: OrganizationDAO,
_ <- Fox.runOptional(organization.includedUsers)(includedUsers =>
bool2Fox(userCount + usersToAddCount <= includedUsers))
} yield ()

private def fallbackOnOwnerEmail(possiblyEmptyEmail: String, organization: Organization)(
implicit ctx: DBAccessContext): Fox[String] =
if (possiblyEmptyEmail.nonEmpty) {
Fox.successful(possiblyEmptyEmail)
} else {
for {
owner <- userDAO.findOwnerByOrg(organization._id)
ownerEmail <- userService.emailFor(owner)
} yield ownerEmail
}

def overTimeMailRecipient(organization: Organization)(implicit ctx: DBAccessContext): Fox[String] =
fallbackOnOwnerEmail(organization.overTimeMailingList, organization)

def newUserMailRecipient(organization: Organization)(implicit ctx: DBAccessContext): Fox[String] =
fallbackOnOwnerEmail(organization.newUserMailingList, organization)

}
10 changes: 7 additions & 3 deletions app/models/user/time/TimeSpanService.scala
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import mail.{DefaultMails, Send}

import javax.inject.Inject
import models.annotation._
import models.organization.OrganizationDAO
import models.organization.{OrganizationDAO, OrganizationService}
import models.project.ProjectDAO
import models.task.TaskDAO
import models.user.{User, UserService}
Expand All @@ -25,6 +25,7 @@ class TimeSpanService @Inject()(annotationDAO: AnnotationDAO,
taskDAO: TaskDAO,
brainTracing: BrainTracing,
annotationService: AnnotationService,
organizationService: OrganizationService,
projectDAO: ProjectDAO,
organizationDAO: OrganizationDAO,
timeSpanDAO: TimeSpanDAO,
Expand Down Expand Up @@ -174,10 +175,13 @@ class TimeSpanService @Inject()(annotationDAO: AnnotationDAO,
annotationTime <- annotation.tracingTime ?~> "no annotation.tracingTime"
timeLimit <- project.expectedTime ?~> "no project.expectedTime"
organization <- organizationDAO.findOne(user._organization)(GlobalAccessContext)
projectOwner <- userService.findOneCached(project._owner)(GlobalAccessContext)
projectOwnerEmail <- userService.emailFor(projectOwner)(GlobalAccessContext)
mailRecipient <- organizationService.overTimeMailRecipient(organization)(GlobalAccessContext)
} yield {
if (annotationTime >= timeLimit && annotationTime - time.toMillis < timeLimit) {
brainTracing.Mailer ! Send(
defaultMails.overLimitMail(user, project.name, task._id.toString, annotation.id, organization))
brainTracing.Mailer ! Send(defaultMails
.overLimitMail(user, project.name, task._id.toString, annotation.id, List(mailRecipient, projectOwnerEmail)))
}
}

Expand Down

0 comments on commit 9187eff

Please sign in to comment.