Skip to content

Commit

Permalink
Ajoute la vue "mes groupes" à la page groupe (#1080)
Browse files Browse the repository at this point in the history
  • Loading branch information
niladic committed Jul 1, 2021
1 parent 46e4a7e commit d7a8f20
Show file tree
Hide file tree
Showing 12 changed files with 618 additions and 493 deletions.
255 changes: 239 additions & 16 deletions app/controllers/GroupController.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,18 @@ import java.util.UUID

import actions.{LoginAction, RequestWithUserData}
import cats.syntax.all._
import constants.Constants
import Operators._
import javax.inject.{Inject, Singleton}
import models.{Area, Authorization, Organisation, UserGroup}
import models.formModels.{normalizedOptionalText, normalizedText}
import models.{Area, Authorization, Error, EventType, Organisation, User, UserGroup}
import models.formModels.{normalizedOptionalText, normalizedText, AddUserToGroupFormData}
import org.webjars.play.WebJarsUtil
import play.api.Configuration
import play.api.data.Form
import play.api.data.Forms.{email, ignored, list, mapping, of, optional, text, uuid}
import play.api.data.validation.Constraints.maxLength
import play.api.mvc.{Action, AnyContent, InjectedController}
import play.api.i18n.I18nSupport
import play.api.mvc.{Action, AnyContent, Call, InjectedController, RequestHeader, Result}
import play.libs.ws.WSClient
import services._
import helper.BooleanHelper.not
Expand All @@ -34,9 +36,11 @@ import models.EventType.{
UserGroupEdited
}
import scala.concurrent.{ExecutionContext, Future}
import serializers.Keys

@Singleton
case class GroupController @Inject() (
applicationService: ApplicationService,
loginAction: LoginAction,
groupService: UserGroupService,
notificationService: NotificationService,
Expand All @@ -46,10 +50,176 @@ case class GroupController @Inject() (
userService: UserService
)(implicit ec: ExecutionContext, webJarsUtil: WebJarsUtil)
extends InjectedController
with I18nSupport
with Operators.Common
with GroupOperators
with UserOperators {

private val groupPageRedirectValue: String = "groupPage"

private def groupModificationOriginPage(implicit request: RequestHeader): (Boolean, Call) =
(
request.getQueryString(Keys.QueryParam.redirect),
request.getQueryString(Keys.QueryParam.groupId)
) match {
case (Some(`groupPageRedirectValue`), Some(groupId)) =>
(true, routes.GroupController.editGroup(UUID.fromString(groupId)))
case _ =>
(false, routes.GroupController.showEditMyGroups)
}

def addToGroup(groupId: UUID) =
addOrRemoveUserAction(groupId) { implicit request =>
val (originIsGroupPage, redirectPage) = groupModificationOriginPage
AddUserToGroupFormData.form
.bindFromRequest()
.fold(
err => {
val message = "L’adresse email n'est pas correcte"
eventService.log(EventType.AddUserToGroupBadUserInput, message)
if (originIsGroupPage) withGroup(groupId)(group => editGroupPage(group, err))
else editMyGroupsPage(err)
},
data =>
userService
.byEmailFuture(data.email)
.zip(userService.byGroupIdsFuture(List(groupId), includeDisabled = true))
.flatMap {
case (None, _) =>
eventService.log(
EventType.AddUserToGroupBadUserInput,
s"Tentative d'ajout de l'utilisateur inexistant ${data.email} au groupe $groupId"
)
Future.successful(
Redirect(redirectPage)
.flashing("error" -> "L’utilisateur n’existe pas dans Administration+")
)
case (Some(userToAdd), usersInGroup)
if usersInGroup.map(_.id).contains[UUID](userToAdd.id) =>
eventService.log(
EventType.AddUserToGroupBadUserInput,
s"Tentative d'ajout de l'utilisateur ${userToAdd.id} déjà présent au groupe $groupId",
involvesUser = userToAdd.id.some
)
Future.successful(
Redirect(redirectPage)
.flashing("error" -> "L’utilisateur est déjà présent dans le groupe")
)
case (Some(userToAdd), _) =>
userService
.addToGroup(userToAdd.id, groupId)
.map { _ =>
eventService.log(
EventType.UserGroupEdited,
s"Utilisateur ${userToAdd.id} ajouté au groupe $groupId",
involvesUser = userToAdd.id.some
)
Redirect(redirectPage)
.flashing("success" -> "L’utilisateur a été ajouté au groupe")
}
}
)
}

def enableUser(userId: UUID) =
loginAction.async { implicit request =>
val (_, redirectPage) = groupModificationOriginPage
withUser(
userId,
includeDisabled = true,
errorMessage = s"L'utilisateur $userId n'existe pas et ne peut pas être réactivé",
errorResult = Redirect(redirectPage)
.flashing(
"error" -> ("L’utilisateur n’existe pas dans Administration+. " +
"S’il s’agit d’une erreur, vous pouvez contacter le support.")
)
.some
) { otherUser =>
asUserWithAuthorization(Authorization.canEnableOtherUser(otherUser))(() =>
(
EventType.EditUserUnauthorized,
s"L'utilisateur n'est pas autorisé à réactiver l'utilisateur $userId"
)
) { () =>
userService
.enable(userId)
.map(
_.fold(
error => {
eventService.logError(error)
Redirect(redirectPage).flashing("error" -> Constants.error500FlashMessage)
},
_ => {
eventService.log(
EventType.UserEdited,
s"Utilisateur $userId réactivé",
involvesUser = userId.some
)
Redirect(redirectPage)
.flashing("success" -> "L’utilisateur a bien été réactivé.")
}
)
)
}
}
}

def removeFromGroup(userId: UUID, groupId: UUID) =
addOrRemoveUserAction(groupId) { implicit request =>
val (_, redirectPage) = groupModificationOriginPage
withUser(
userId,
includeDisabled = true,
errorMessage = s"L'utilisateur $userId n'existe pas et ne peut pas être désactivé",
errorResult = Redirect(redirectPage)
.flashing(
"error" -> ("L’utilisateur n’existe pas dans Administration+. " +
"S’il s’agit d’une erreur, vous pouvez contacter le support.")
)
.some
) { otherUser =>
val result: Future[Either[Error, Result]] =
if (otherUser.groupIds.toSet.size <= 1) {
userService
.disable(userId)
.map(_.map { _ =>
eventService.log(
EventType.UserEdited,
s"Utilisateur $userId désactivé",
involvesUser = userId.some
)
Redirect(redirectPage).flashing("success" -> "L’utilisateur a bien été désactivé.")
})
} else {
userService
.removeFromGroup(userId, groupId)
.map(_.map { _ =>
eventService.log(
EventType.UserGroupEdited,
s"Utilisateur $userId retiré du groupe $groupId",
involvesUser = userId.some
)
Redirect(redirectPage)
.flashing("success" -> "L’utilisateur a bien été retiré du groupe.")
})
}
result.map(
_.fold(
error => {
eventService.logError(error)
Redirect(redirectPage).flashing("error" -> Constants.error500FlashMessage)
},
identity
)
)
}
}

def showEditMyGroups =
loginAction.async { implicit request =>
editMyGroupsPage(AddUserToGroupFormData.form)
}

def deleteUnusedGroupById(groupId: UUID): Action[AnyContent] =
loginAction.async { implicit request =>
withGroup(groupId) { group: UserGroup =>
Expand Down Expand Up @@ -88,18 +258,7 @@ case class GroupController @Inject() (
),
Unauthorized("Vous ne pouvez pas éditer ce groupe : êtes-vous dans la bonne zone ?").some
) { () =>
val groupUsers = userService.byGroupIds(List(id), includeDisabled = true)
eventService.log(EditGroupShowed, s"Visualise la vue de modification du groupe")
val isEmpty = groupService.isGroupEmpty(group.id)
Future(
Ok(
views.html.editGroup(request.currentUser, request.rights)(
group,
groupUsers,
isEmpty
)
)
)
editGroupPage(group, AddUserToGroupFormData.form)
}
}
}
Expand Down Expand Up @@ -208,7 +367,71 @@ case class GroupController @Inject() (
}
}

def addGroupForm[A](timeZone: ZoneId)(implicit request: RequestWithUserData[A]) =
private def addOrRemoveUserAction(
groupId: UUID
)(inner: RequestWithUserData[_] => Future[Result]): Action[AnyContent] =
loginAction.async { implicit request =>
asUserWithAuthorization(Authorization.canAddOrRemoveOtherUser(groupId))(
() =>
(
EventType.EditGroupUnauthorized,
s"L'utilisateur n'est pas autorisé à éditer le groupe $groupId"
), {
val message = "Vous n’avez pas le droit de modifier ce groupe"
Redirect(routes.GroupController.showEditMyGroups).flashing("error" -> message).some
}
)(() => inner(request))
}

private def editMyGroupsPage(
addUserForm: Form[AddUserToGroupFormData]
)(implicit request: RequestWithUserData[_]): Future[Result] =
for {
groups <- groupService.byIdsFuture(request.currentUser.groupIds)
users <- userService.byGroupIdsFuture(groups.map(_.id), includeDisabled = true)
applications <- applicationService.allForUserIds(users.map(_.id))
} yield {
eventService.log(EventType.EditMyGroupShowed, "Visualise la modification de ses groupes")
Ok(
views.editMyGroups
.page(
request.currentUser,
request.rights,
addUserForm,
groups,
users,
applications,
identity
)
)
}

private def editGroupPage(group: UserGroup, addUserForm: Form[AddUserToGroupFormData])(implicit
request: RequestWithUserData[_]
): Future[Result] = {
val groupUsers = userService.byGroupIds(List(group.id), includeDisabled = true)
eventService.log(EditGroupShowed, s"Visualise la vue de modification du groupe")
val isEmpty = groupService.isGroupEmpty(group.id)
applicationService
.allForUserIds(groupUsers.map(_.id))
.map(applications =>
Ok(
views.html.editGroup(request.currentUser, request.rights)(
group,
groupUsers,
isEmpty,
applications,
addUserForm,
url =>
(url + "?" +
Keys.QueryParam.redirect + "=" + groupPageRedirectValue + "&" +
Keys.QueryParam.groupId + "=" + group.id.toString)
)
)
)
}

private def addGroupForm[A](timeZone: ZoneId)(implicit request: RequestWithUserData[A]) =
Form(
mapping(
"id" -> ignored(UUID.randomUUID()),
Expand Down
8 changes: 4 additions & 4 deletions app/controllers/Operators.scala
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ object Operators {
groupId: UUID
)(
payload: UserGroup => Future[Result]
)(implicit request: RequestWithUserData[AnyContent], ec: ExecutionContext): Future[Result] =
)(implicit request: RequestWithUserData[_], ec: ExecutionContext): Future[Result] =
groupService
.groupById(groupId)
.fold({
Expand All @@ -52,7 +52,7 @@ object Operators {

def asAdminOfGroupZone(group: UserGroup)(event: () => (EventType, String))(
payload: () => Future[Result]
)(implicit request: RequestWithUserData[AnyContent], ec: ExecutionContext): Future[Result] =
)(implicit request: RequestWithUserData[_], ec: ExecutionContext): Future[Result] =
if (not(request.currentUser.admin)) {
val (eventType, description) = event()
eventService.log(eventType, description = description)
Expand Down Expand Up @@ -174,8 +174,8 @@ object Operators {
def applicationService: ApplicationService
def eventService: EventService

private def manageApplicationError[A](applicationId: UUID, error: Error)(implicit
request: RequestWithUserData[A],
private def manageApplicationError(applicationId: UUID, error: Error)(implicit
request: RequestWithUserData[_],
ec: ExecutionContext
): Future[Result] = {
val result =
Expand Down
Loading

0 comments on commit d7a8f20

Please sign in to comment.