PageRenderTime 26ms CodeModel.GetById 32ms RepoModel.GetById 1ms app.codeStats 0ms

/app/controllers/organization/Groups.scala

https://github.com/delving/culture-hub
Scala | 260 lines | 226 code | 29 blank | 5 comment | 28 complexity | 1d8e8e81f3c8655292de09b8864cd5de MD5 | raw file
  1. package controllers.organization
  2. import extensions.JJson
  3. import com.mongodb.casbah.Imports._
  4. import models._
  5. import models.HubMongoContext._
  6. import play.api.i18n.Messages
  7. import controllers.{ OrganizationController, Token }
  8. import play.api.mvc.{ Results, AnyContent, RequestHeader, Action }
  9. import play.api.data.Forms._
  10. import extensions.Formatters._
  11. import play.api.data.Form
  12. import core.CultureHubPlugin
  13. import core.access.{ ResourceType, Resource }
  14. import collection.JavaConverters._
  15. import play.api.Logger
  16. import scala.Some
  17. import com.escalatesoft.subcut.inject.BindingModule
  18. /**
  19. *
  20. * @author Gerald de Jong <gerald@delving.eu>
  21. */
  22. class Groups(implicit val bindingModule: BindingModule) extends OrganizationController {
  23. def list = OrganizationMember {
  24. MultitenantAction {
  25. implicit request =>
  26. val groups = Group.dao.list(userName, configuration.orgId).filterNot(_.isSystemGroup).map { group =>
  27. GroupListModel(
  28. id = group._id.toString,
  29. name = group.name,
  30. description = Role.get(group.roleKey).getDescription(getLang),
  31. size = group.users.size
  32. )
  33. }.toSeq
  34. val groupsData = Map("groups" -> groups)
  35. Ok(Template('groups -> JJson.generate(groupsData)))
  36. }
  37. }
  38. def groups(groupId: Option[ObjectId]) = OrganizationMember {
  39. MultitenantAction {
  40. implicit request =>
  41. if (groupId != None && !canUpdateGroup(configuration.orgId, groupId.get) || groupId == None && !canCreateGroup(configuration.orgId)) {
  42. Forbidden(Messages("hub.YouDoNotHaveAccess"))
  43. } else {
  44. val group: Option[Group] = groupId.flatMap(Group.dao.findOneById(_))
  45. val usersAsTokens = group match {
  46. case None => JJson.generate(List())
  47. case Some(g) =>
  48. val userTokens = g.users.map(m => Token(m, m))
  49. JJson.generate(userTokens)
  50. }
  51. Ok(Template(
  52. 'id -> groupId,
  53. 'data -> load(configuration.orgId, groupId),
  54. 'groupForm -> GroupViewModel.groupForm,
  55. 'users -> usersAsTokens,
  56. 'roles -> Role.allPrimaryRoles(configuration).
  57. filterNot(_ == Role.OWN).
  58. map(role => role.key -> role.getDescription(getLang)).
  59. toMap.asJava
  60. ))
  61. }
  62. }
  63. }
  64. def remove(groupId: Option[ObjectId]) = OrganizationAdmin {
  65. implicit request =>
  66. if (!groupId.isDefined) {
  67. Results.BadRequest
  68. } else {
  69. Group.dao.remove(MongoDBObject("_id" -> groupId, "orgId" -> configuration.orgId))
  70. Ok
  71. }
  72. }
  73. def submit: Action[AnyContent] = OrganizationMember {
  74. MultitenantAction {
  75. implicit request =>
  76. GroupViewModel.groupForm.bindFromRequest.fold(
  77. formWithErrors => handleValidationError(formWithErrors),
  78. groupForm => {
  79. Logger("CultureHub").debug("Received group submission: " + groupForm)
  80. val groupId = groupForm.id
  81. if (groupForm.id != None && !canUpdateGroup(configuration.orgId, groupId.get) || groupId == None && !canCreateGroup(configuration.orgId)) {
  82. Forbidden(Messages("hub.YouDoNotHaveAccess"))
  83. } else {
  84. val role = try {
  85. Role.get(groupForm.roleKey)
  86. } catch {
  87. case t: Throwable =>
  88. reportSecurity("Attempting to save Group with role " + groupForm.roleKey)
  89. return MultitenantAction {
  90. BadRequest("Invalid Role " + groupForm.roleKey)
  91. }
  92. }
  93. if (role == Role.OWN && (groupForm.id == None || groupForm.id != None && Group.dao.findOneById(groupForm.id.get) == None)) {
  94. reportSecurity("User %s tried to create an owners team!".format(connectedUser))
  95. return MultitenantAction {
  96. Forbidden("Your IP has been logged and reported to the police.")
  97. }
  98. }
  99. val persisted = groupForm.id match {
  100. case None =>
  101. Group.dao.insert(
  102. Group(
  103. name = groupForm.name,
  104. orgId = configuration.orgId,
  105. roleKey = role.key
  106. )
  107. ) match {
  108. case None => None
  109. case Some(id) =>
  110. groupForm.users.foreach(u => Group.dao.addUser(configuration.orgId, u.id, id))
  111. groupForm.resources.foreach(r => Group.dao.addResource(configuration.orgId, r.id, role.resourceType.get, id))
  112. Some(groupForm.copy(id = Some(id)))
  113. }
  114. case Some(id) =>
  115. Group.dao.findOneById(groupForm.id.get) match {
  116. case None => return MultitenantAction {
  117. NotFound("Group with ID %s was not found".format(id))
  118. }
  119. case Some(g) =>
  120. g.roleKey match {
  121. case Role.OWN.key => // do nothing
  122. case _ =>
  123. val resources: Seq[Resource] = role.resourceType.map { resourceType =>
  124. val lookup = CultureHubPlugin.getResourceLookup(role.resourceType.get).get
  125. groupForm.resources.flatMap { resourceToken =>
  126. lookup.findResourceByKey(configuration.orgId, resourceToken.id)
  127. }
  128. }.getOrElse {
  129. Seq.empty
  130. }
  131. Group.dao.updateGroupInfo(id, groupForm.name, role, groupForm.users.map(_.id), resources.map(r => PersistedResource(r)))
  132. groupForm.users.foreach(u => Group.dao.addUser(configuration.orgId, u.id, id))
  133. }
  134. Some(groupForm)
  135. }
  136. }
  137. persisted match {
  138. case Some(group) => Json(group)
  139. case None => Error(Messages("hub.CouldNotSaveGroup"))
  140. }
  141. }
  142. })
  143. }
  144. }
  145. def searchResourceTokens(resourceType: String, q: String) = OrganizationMember {
  146. MultitenantAction {
  147. implicit request =>
  148. val maybeLookup = CultureHubPlugin.getResourceLookup(ResourceType(resourceType))
  149. maybeLookup.map { lookup =>
  150. val tokens = lookup.findResources(configuration.orgId, q).map { resource =>
  151. Token(resource.getResourceKey, resource.getResourceKey, Some(resource.getResourceType.resourceType))
  152. }
  153. Json(tokens)
  154. }.getOrElse(
  155. Json(Seq.empty)
  156. )
  157. }
  158. }
  159. private def load(orgId: String, groupId: Option[ObjectId])(implicit configuration: OrganizationConfiguration): String = {
  160. val resourceRoles = Role.allPrimaryRoles(configuration).filterNot(_.resourceType.isEmpty)
  161. val defaultGroupViewModel = GroupViewModel(
  162. roleKey = Role.allPrimaryRoles(configuration).head.key,
  163. rolesWithResources = resourceRoles.map(_.key),
  164. rolesWithResourceAdmin = Role.allPrimaryRoles(configuration).filter(_.isResourceAdmin).map(_.key),
  165. rolesResourceType = resourceRoles.map(r => RoleResourceType(r.key, r.resourceType.get.resourceType, Messages("accessControl.resourceType." + r.resourceType.get.resourceType)))
  166. )
  167. groupId.flatMap(Group.dao.findOneById(_)) match {
  168. case None => JJson.generate(defaultGroupViewModel)
  169. case Some(group) => JJson.generate(
  170. GroupViewModel(
  171. id = Some(group._id),
  172. name = group.name,
  173. roleKey = group.roleKey,
  174. canChangeGrantType = group.roleKey != Role.OWN.key,
  175. users = group.users.map(u => Token(u, u)),
  176. resources = group.resources.map(r => Token(r.getResourceKey, r.getResourceKey, Some(r.getResourceType.resourceType))),
  177. rolesWithResources = defaultGroupViewModel.rolesWithResources,
  178. rolesWithResourceAdmin = defaultGroupViewModel.rolesWithResourceAdmin,
  179. rolesResourceType = defaultGroupViewModel.rolesResourceType
  180. )
  181. )
  182. }
  183. }
  184. private def canUpdateGroup[A](orgId: String, groupId: ObjectId)(implicit request: MultitenantRequest[A]): Boolean = {
  185. groupId != null && organizationServiceLocator.byDomain.isAdmin(orgId, userName)
  186. }
  187. private def canCreateGroup[A](orgId: String)(implicit request: MultitenantRequest[A]): Boolean =
  188. organizationServiceLocator.byDomain.isAdmin(orgId, userName)
  189. }
  190. case class GroupViewModel(id: Option[ObjectId] = None,
  191. name: String = "",
  192. roleKey: String,
  193. canChangeGrantType: Boolean = true,
  194. users: Seq[Token] = Seq.empty[Token],
  195. resources: Seq[Token] = Seq.empty[Token],
  196. rolesWithResources: Seq[String] = Seq.empty,
  197. rolesWithResourceAdmin: Seq[String] = Seq.empty,
  198. rolesResourceType: Seq[RoleResourceType] = Seq.empty)
  199. case class RoleResourceType(roleKey: String, resourceType: String, resourceTypeName: String)
  200. object GroupViewModel {
  201. // ~~~ Form utilities
  202. import extensions.Formatters._
  203. val tokenListMapping = seq(
  204. play.api.data.Forms.mapping(
  205. "id" -> text,
  206. "name" -> text,
  207. "tokenType" -> optional(text),
  208. "data" -> optional(of[Map[String, String]])
  209. )(Token.apply)(Token.unapply)
  210. )
  211. val groupForm: Form[GroupViewModel] = Form(
  212. mapping(
  213. "id" -> optional(of[ObjectId]),
  214. "name" -> nonEmptyText,
  215. "roleKey" -> nonEmptyText,
  216. "canChangeGrantType" -> boolean,
  217. "users" -> tokenListMapping,
  218. "resources" -> tokenListMapping,
  219. "rolesWithResources" -> seq(nonEmptyText),
  220. "rolesWithResourceAdmin" -> seq(nonEmptyText),
  221. "rolesResourceType" -> seq(
  222. mapping(
  223. "roleKey" -> nonEmptyText,
  224. "resourceType" -> nonEmptyText,
  225. "resourceTypeName" -> nonEmptyText
  226. )(RoleResourceType.apply)(RoleResourceType.unapply)
  227. )
  228. )(GroupViewModel.apply)(GroupViewModel.unapply)
  229. )
  230. }
  231. case class GroupListModel(id: String, name: String, size: Int, description: String)