Skip to content

Commit

Permalink
Ajoute le role de responsable de territoire par organisme
Browse files Browse the repository at this point in the history
  • Loading branch information
niladic committed Feb 6, 2024
1 parent 046c4a6 commit 88a49a2
Show file tree
Hide file tree
Showing 16 changed files with 209 additions and 30 deletions.
2 changes: 2 additions & 0 deletions app/controllers/CSVImportController.scala
Original file line number Diff line number Diff line change
Expand Up @@ -341,6 +341,8 @@ case class CSVImportController @Inject() (
firstLoginDate = none,
phoneNumber = userData.user.phoneNumber,
observableOrganisationIds = Nil,
managingOrganisationIds = Nil,
managingAreaIds = Nil,
sharedAccount = userData.user.name.nonEmpty,
internalSupportComment = None,
)
Expand Down
2 changes: 2 additions & 0 deletions app/controllers/SignupController.scala
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,8 @@ case class SignupController @Inject() (
firstLoginDate = Instant.now().some,
phoneNumber = form.phoneNumber,
observableOrganisationIds = Nil,
managingOrganisationIds = Nil,
managingAreaIds = Nil,
sharedAccount = form.sharedAccount,
internalSupportComment = None
)
Expand Down
4 changes: 4 additions & 0 deletions app/controllers/UserController.scala
Original file line number Diff line number Diff line change
Expand Up @@ -484,6 +484,8 @@ case class UserController @Inject() (
cguAcceptationDate = cguDate,
phoneNumber = updatedUserData.phoneNumber,
observableOrganisationIds = updatedUserData.observableOrganisationIds.distinct,
managingOrganisationIds = updatedUserData.managingOrganisationIds.distinct,
managingAreaIds = updatedUserData.managingAreaIds.distinct,
sharedAccount = updatedUserData.sharedAccount,
internalSupportComment = updatedUserData.internalSupportComment
)
Expand Down Expand Up @@ -606,6 +608,8 @@ case class UserController @Inject() (
firstLoginDate = none,
phoneNumber = userToAdd.phoneNumber,
observableOrganisationIds = Nil,
managingOrganisationIds = Nil,
managingAreaIds = Nil,
sharedAccount = userToAdd.sharedAccount,
internalSupportComment = None
)
Expand Down
18 changes: 18 additions & 0 deletions app/models/Authorization.scala
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,13 @@ object Authorization {
if (user.groupAdmin && not(user.disabled))
Some(ManagerOfGroups(user.groupIds.toSet))
else None,
if (
(user.managingAreaIds.nonEmpty || user.managingOrganisationIds.nonEmpty) && not(
user.disabled
)
)
Some(ManagerOfAreas(user.managingAreaIds.toSet, user.managingOrganisationIds.toSet))
else None,
if (user.observableOrganisationIds.nonEmpty && not(user.disabled))
Some(ObserverOfOrganisations(user.observableOrganisationIds.toSet))
else None
Expand All @@ -45,6 +52,10 @@ object Authorization {
case class InstructorOfGroups(groupsManaged: Set[UUID]) extends UserRight
case class AdminOfAreas(administeredAreas: Set[UUID]) extends UserRight
case class ManagerOfGroups(groupsManaged: Set[UUID]) extends UserRight

case class ManagerOfAreas(areas: Set[UUID], organisations: Set[Organisation.Id])
extends UserRight

case class ObserverOfOrganisations(organisations: Set[Organisation.Id]) extends UserRight
}

Expand Down Expand Up @@ -132,6 +143,13 @@ object Authorization {
case _ => false
}

def isAreaManager(areaIds: Set[UUID], organisationIds: Set[Organisation.Id]): Check =
_.rights.exists {
case UserRight.ManagerOfAreas(managingAreaIds, managingOrganisationIds) =>
areaIds.subsetOf(managingAreaIds) && organisationIds.subsetOf(managingOrganisationIds)
case _ => false
}

def isObserver: Check =
_.rights.exists {
case UserRight.ObserverOfOrganisations(organisations) => organisations.nonEmpty
Expand Down
25 changes: 24 additions & 1 deletion app/models/User.scala
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,9 @@ case class User(
// * can see stats+deployment of all areas,
// * can see all users,
// * can see one user but not edit it
observableOrganisationIds: List[Organisation.Id] = Nil,
observableOrganisationIds: List[Organisation.Id],
managingOrganisationIds: List[Organisation.Id],
managingAreaIds: List[UUID],
sharedAccount: Boolean = false,
// This is a comment only visible by the admins
internalSupportComment: Option[String],
Expand Down Expand Up @@ -111,6 +113,8 @@ case class User(

lazy val phoneNumberLog: String = phoneNumber.map(withQuotes).getOrElse("<vide>")
lazy val observableOrganisationIdsLog: String = observableOrganisationIds.map(_.id).mkString(", ")
lazy val managingOrganisationIdsLog: String = managingOrganisationIds.map(_.id).mkString(", ")
lazy val managingAreaIdsLog: String = managingAreaIds.mkString(", ")
lazy val sharedAccountLog: String = sharedAccount.toString

lazy val internalSupportCommentLog: String =
Expand Down Expand Up @@ -138,6 +142,8 @@ case class User(
("Newsletter", newsletterAcceptationDateLog),
("Première connexion", firstLoginDateLog),
("Observation des organismes", observableOrganisationIdsLog),
("Responsable des organismes", managingOrganisationIdsLog),
("Responsable des territoires", managingAreaIdsLog),
("Information Support", internalSupportCommentLog),
).map { case (fieldName, value) => s"$fieldName : $value" }.mkString(" | ") + "]"

Expand Down Expand Up @@ -188,6 +194,18 @@ case class User(
observableOrganisationIdsLog,
other.observableOrganisationIdsLog
),
(
"Responsable des organismes",
managingOrganisationIds =!= other.managingOrganisationIds,
managingOrganisationIdsLog,
other.managingOrganisationIdsLog
),
(
"Responsable des territoires",
managingAreaIds =!= other.managingAreaIds,
managingAreaIdsLog,
other.managingAreaIdsLog
),
(
"Information Support",
internalSupportCommentLog =!= other.internalSupportCommentLog,
Expand Down Expand Up @@ -225,6 +243,8 @@ case class User(
firstLoginDate = firstLoginDate,
phoneNumber = pseudoPhone,
observableOrganisationIds = observableOrganisationIds,
managingOrganisationIds = managingOrganisationIds,
managingAreaIds = managingAreaIds,
sharedAccount = sharedAccount,
internalSupportComment = none,
)
Expand All @@ -251,6 +271,9 @@ object User {
groupAdmin = false,
disabled = true,
firstLoginDate = none,
observableOrganisationIds = Nil,
managingOrganisationIds = Nil,
managingAreaIds = Nil,
internalSupportComment = None
)

Expand Down
6 changes: 6 additions & 0 deletions app/models/dataModels.scala
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,8 @@ object dataModels {
firstLoginDate = user.firstLoginDate,
phoneNumber = user.phoneNumber,
observableOrganisationIds = user.observableOrganisationIds.distinct.map(_.id),
managingOrganisationIds = user.managingOrganisationIds.distinct.map(_.id),
managingAreaIds = user.managingAreaIds.distinct,
sharedAccount = user.sharedAccount,
internalSupportComment = user.internalSupportComment,
)
Expand Down Expand Up @@ -323,6 +325,8 @@ object dataModels {
firstLoginDate: Option[Instant],
phoneNumber: Option[String],
observableOrganisationIds: List[String],
managingOrganisationIds: List[String],
managingAreaIds: List[UUID],
sharedAccount: Boolean,
internalSupportComment: Option[String]
) {
Expand Down Expand Up @@ -350,6 +354,8 @@ object dataModels {
firstLoginDate = firstLoginDate,
phoneNumber = phoneNumber,
observableOrganisationIds = observableOrganisationIds.map(Organisation.Id.apply),
managingOrganisationIds = managingOrganisationIds.map(Organisation.Id.apply),
managingAreaIds = managingAreaIds,
sharedAccount = sharedAccount,
internalSupportComment = internalSupportComment
)
Expand Down
6 changes: 6 additions & 0 deletions app/models/formModels.scala
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,8 @@ object formModels {
groupIds = user.groupIds,
phoneNumber = user.phoneNumber,
observableOrganisationIds = user.observableOrganisationIds,
managingOrganisationIds = user.managingOrganisationIds,
managingAreaIds = user.managingAreaIds,
sharedAccount = user.sharedAccount,
internalSupportComment = user.internalSupportComment
)
Expand Down Expand Up @@ -341,6 +343,8 @@ object formModels {
"groupIds" -> default(list(uuid), Nil),
"phoneNumber" -> normalizedOptionalText,
"observableOrganisationIds" -> list(of[Organisation.Id]),
"managingOrganisationIds" -> list(of[Organisation.Id]),
"managingAreaIds" -> list(uuid),
Keys.User.sharedAccount -> boolean,
"internalSupportComment" -> normalizedOptionalText
)(EditUserFormData.apply)(EditUserFormData.unapply)
Expand All @@ -363,6 +367,8 @@ object formModels {
groupIds: List[UUID],
phoneNumber: Option[String],
observableOrganisationIds: List[Organisation.Id],
managingOrganisationIds: List[Organisation.Id],
managingAreaIds: List[UUID],
sharedAccount: Boolean,
internalSupportComment: Option[String]
)
Expand Down
39 changes: 28 additions & 11 deletions app/serializers/ApiModel.scala
Original file line number Diff line number Diff line change
Expand Up @@ -150,9 +150,24 @@ object ApiModel {
}

object UserInfos {

case class Group(id: UUID, name: String, currentUserCanEditGroup: Boolean)

case class Permissions(
helper: Boolean,
instructor: Boolean,
groupAdmin: Boolean,
admin: Boolean,
expert: Boolean,
managingOrganisations: List[String],
managingAreas: List[String],
)

implicit val userInfosGroupFormat: Format[UserInfos.Group] = Json.format[UserInfos.Group]

implicit val userInfosPermissionsFormat: Format[UserInfos.Permissions] =
Json.format[UserInfos.Permissions]

implicit val userInfosFormat: Format[UserInfos] = Json.format[UserInfos]

def fromUser(
Expand Down Expand Up @@ -181,8 +196,6 @@ object ApiModel {
qualite = user.qualite,
email = user.email,
phoneNumber = user.phoneNumber,
helper = user.helperRoleName.nonEmpty,
instructor = user.instructorRoleName.nonEmpty,
areas = user.areas.flatMap(Area.fromId).map(_.toString).sorted,
groupNames = groups.map(_.name),
groups = groups
Expand All @@ -191,12 +204,19 @@ object ApiModel {
),
groupEmails = groups.flatMap(_.email),
organisations = organisations,
groupAdmin = user.groupAdminRoleName.nonEmpty,
admin = user.adminRoleName.nonEmpty,
expert = user.expert,
disabled = user.disabledRoleName.nonEmpty,
sharedAccount = user.sharedAccount,
cgu = user.cguAcceptationDate.nonEmpty,
permissions = Permissions(
helper = user.helperRoleName.nonEmpty,
instructor = user.instructorRoleName.nonEmpty,
groupAdmin = user.groupAdminRoleName.nonEmpty,
admin = user.adminRoleName.nonEmpty,
expert = user.expert,
managingOrganisations =
user.managingOrganisationIds.flatMap(Organisation.byId).map(_.shortName).sorted,
managingAreas = user.managingAreaIds.flatMap(Area.fromId).map(_.toString).sorted,
)
)
}

Expand All @@ -211,19 +231,16 @@ object ApiModel {
qualite: String,
email: String,
phoneNumber: Option[String],
helper: Boolean,
instructor: Boolean,
areas: List[String],
groupNames: List[String],
groups: List[UserInfos.Group],
groupEmails: List[String],
organisations: List[String],
groupAdmin: Boolean,
admin: Boolean,
expert: Boolean,
disabled: Boolean,
sharedAccount: Boolean,
cgu: Boolean
cgu: Boolean,
// This case class is a workaround for the 22 fields tuple limit in play-json
permissions: UserInfos.Permissions,
)

object UserGroupInfos {
Expand Down
4 changes: 4 additions & 0 deletions app/services/UserService.scala
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ class UserService @Inject() (
"first_login_date",
"phone_number",
"observable_organisation_ids",
"managing_organisation_ids",
"managing_area_ids",
"shared_account",
"internal_support_comment"
)
Expand Down Expand Up @@ -353,6 +355,8 @@ class UserService @Inject() (
phone_number = ${row.phoneNumber},
disabled = ${row.disabled},
observable_organisation_ids = array[${row.observableOrganisationIds}]::varchar[],
managing_organisation_ids = array[${row.managingOrganisationIds}]::varchar[],
managing_area_ids = array[${row.managingAreaIds}]::uuid[],
shared_account = ${row.sharedAccount},
internal_support_comment = ${row.internalSupportComment}
WHERE id = ${row.id}::uuid
Expand Down
25 changes: 25 additions & 0 deletions app/views/editUser.scala.html
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,31 @@
>@{organisation.shortName} - @{organisation.name}</option>
}
</select>

<b class="mdl-cell mdl-cell--12-col">Responsable d’organismes</b>
<select name="managingOrganisationIds[]"
class="use-slimselect"
@if(!currentUser.admin) { disabled }
multiple>
@for(organisation <- Organisation.all) {
<option value="@{organisation.id.id}"
@if(form.value.exists(_.managingOrganisationIds.contains[Organisation.Id](organisation.id))){ selected }
>@{organisation.shortName} - @{organisation.name}</option>
}
</select>
<b class="mdl-cell mdl-cell--12-col">Responsable de territoires</b>
<select id="user-managing-area-ids"
name="managingAreaIds[]"
class="use-slimselect"
@if(!currentUser.admin) { disabled }
multiple>
@for(area <- Area.all) {
<option value="@area.id"
@if(form.value.exists(_.managingAreaIds.contains[UUID](area.id))){ selected }
>@area.name</option>
}
</select>

@if(form("areas").hasErrors) {
<p style="color: red; font-weight: bold;">@form("areas").errors.map(_.format).mkString(", ")</p>
}
Expand Down
10 changes: 10 additions & 0 deletions conf/evolutions/default/70.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
--- !Ups

ALTER TABLE "user" ADD COLUMN managing_organisation_ids varchar[] DEFAULT ARRAY[]::varchar[] NOT NULL;
ALTER TABLE "user" ADD COLUMN managing_area_ids varchar[] DEFAULT ARRAY[]::varchar[] NOT NULL;


--- !Downs

ALTER TABLE "user" DROP COLUMN managing_area_ids;
ALTER TABLE "user" DROP COLUMN managing_organisation_ids;
3 changes: 3 additions & 0 deletions test/browser/AnswerSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,9 @@ class AnswerSpec extends Specification with Tables with BaseSpec {
cguAcceptationDate = Some(Time.nowParis()),
firstLoginDate = None,
groupIds = groups.map(_.id),
observableOrganisationIds = Nil,
managingOrganisationIds = Nil,
managingAreaIds = Nil,
internalSupportComment = None
)
val result = userService.add(List(user))
Expand Down
Loading

0 comments on commit 88a49a2

Please sign in to comment.