Skip to content

Commit

Permalink
#1872 Added quota for user creation
Browse files Browse the repository at this point in the history
  • Loading branch information
rriclet committed Mar 23, 2021
1 parent 618fb08 commit a8611b5
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -326,7 +326,7 @@ class Output @Inject() (
override def createUser(inputUser: InputUser): Try[IdMapping] =
authTransaction(inputUser.metaData.createdBy) { implicit graph => implicit authContext =>
logger.debug(s"Create user ${inputUser.user.login}")
userSrv.checkUser(inputUser.user).flatMap(userSrv.createEntity).map { createdUser =>
userSrv.checkUserLogin(inputUser.user).flatMap(userSrv.createEntity).map { createdUser =>
updateMetaData(createdUser, inputUser.metaData)
inputUser
.avatar
Expand Down
51 changes: 34 additions & 17 deletions thehive/app/org/thp/thehive/services/UserSrv.scala
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import play.api.libs.json.{JsObject, Json}

import java.util.regex.Pattern
import java.util.{List => JList, Map => JMap}
import javax.inject.{Inject, Named, Singleton}
import javax.inject.{Inject, Named, Provider, Singleton}
import scala.util.{Failure, Success, Try}

@Singleton
Expand All @@ -32,14 +32,33 @@ class UserSrv @Inject() (
roleSrv: RoleSrv,
auditSrv: AuditSrv,
attachmentSrv: AttachmentSrv,
organisationSrvProvider: Provider[OrganisationSrv],
@Named("integrity-check-actor") integrityCheckActor: ActorRef
) extends VertexSrv[User] {
lazy val organisationSrv: OrganisationSrv = organisationSrvProvider.get

val defaultUserDomain: Option[String] = configuration.getOptional[String]("auth.defaultUserDomain")
val fullUserNameRegex: Pattern = "[\\p{Graph}&&[^@.]](?:[\\p{Graph}&&[^@]]*)*@\\p{Alnum}+(?:[\\p{Alnum}-.])*".r.pattern

val userAttachmentSrv = new EdgeSrv[UserAttachment, User, Attachment]

def checkUser(user: User): Try[User] = {
def addOrCreateUser(user: User, avatar: Option[FFile], organisation: Organisation with Entity, profile: Profile with Entity)(implicit
graph: Graph,
authContext: AuthContext
): Try[RichUser] =
getByName(user.login)
.getOrFail("User")
.orElse {
for {
validUser <- checkUserLogin(user)
_ <- checkUserQuota(organisation)
createdUser <- createEntity(validUser)
_ <- avatar.map(setAvatar(createdUser, _)).flip
} yield createdUser
}
.flatMap(addUserToOrganisation(_, organisation, profile))

def checkUserLogin(user: User): Try[User] = {
val login =
if (!user.login.contains('@') && defaultUserDomain.isDefined) s"${user.login}@${defaultUserDomain.get}".toLowerCase
else user.login.toLowerCase
Expand All @@ -48,6 +67,19 @@ class UserSrv @Inject() (
else Failure(BadRequestError(s"User login is invalid, it must be an email address (found: ${user.login})"))
}

def checkUserQuota(organisation: Organisation with Entity)(implicit
graph: Graph,
authContext: AuthContext
): Try[Unit] = {
val userQuota = configuration.getOptional[Long]("quota.organisation.user.count")
val userCount = organisationSrv.get(organisation).users.getCount

userQuota.fold[Try[Unit]](Success(()))(quota =>
if (userCount < quota) Success(())
else Failure(BadRequestError(s"User quota is reached, this organisation cannot have more users"))
)
}

// TODO return Try[Unit]
def addUserToOrganisation(user: User with Entity, organisation: Organisation with Entity, profile: Profile with Entity)(implicit
graph: Graph,
Expand All @@ -64,21 +96,6 @@ class UserSrv @Inject() (
} yield richUser
}

def addOrCreateUser(user: User, avatar: Option[FFile], organisation: Organisation with Entity, profile: Profile with Entity)(implicit
graph: Graph,
authContext: AuthContext
): Try[RichUser] =
getByName(user.login)
.getOrFail("User")
.orElse {
for {
validUser <- checkUser(user)
createdUser <- createEntity(validUser)
_ <- avatar.map(setAvatar(createdUser, _)).flip
} yield createdUser
}
.flatMap(addUserToOrganisation(_, organisation, profile))

def canSetPassword(user: User with Entity)(implicit graph: Graph, authContext: AuthContext): Boolean = {
val userOrganisations = get(user).organisations.value(_.name).toSet
val operatorOrganisations = current.organisations(Permissions.manageUser).value(_.name).toSeq
Expand Down

0 comments on commit a8611b5

Please sign in to comment.