Skip to content

Commit a8611b5

Browse files
committed
#1872 Added quota for user creation
1 parent 618fb08 commit a8611b5

File tree

2 files changed

+35
-18
lines changed

2 files changed

+35
-18
lines changed

migration/src/main/scala/org/thp/thehive/migration/th4/Output.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -326,7 +326,7 @@ class Output @Inject() (
326326
override def createUser(inputUser: InputUser): Try[IdMapping] =
327327
authTransaction(inputUser.metaData.createdBy) { implicit graph => implicit authContext =>
328328
logger.debug(s"Create user ${inputUser.user.login}")
329-
userSrv.checkUser(inputUser.user).flatMap(userSrv.createEntity).map { createdUser =>
329+
userSrv.checkUserLogin(inputUser.user).flatMap(userSrv.createEntity).map { createdUser =>
330330
updateMetaData(createdUser, inputUser.metaData)
331331
inputUser
332332
.avatar

thehive/app/org/thp/thehive/services/UserSrv.scala

Lines changed: 34 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ import play.api.libs.json.{JsObject, Json}
2323

2424
import java.util.regex.Pattern
2525
import java.util.{List => JList, Map => JMap}
26-
import javax.inject.{Inject, Named, Singleton}
26+
import javax.inject.{Inject, Named, Provider, Singleton}
2727
import scala.util.{Failure, Success, Try}
2828

2929
@Singleton
@@ -32,14 +32,33 @@ class UserSrv @Inject() (
3232
roleSrv: RoleSrv,
3333
auditSrv: AuditSrv,
3434
attachmentSrv: AttachmentSrv,
35+
organisationSrvProvider: Provider[OrganisationSrv],
3536
@Named("integrity-check-actor") integrityCheckActor: ActorRef
3637
) extends VertexSrv[User] {
38+
lazy val organisationSrv: OrganisationSrv = organisationSrvProvider.get
39+
3740
val defaultUserDomain: Option[String] = configuration.getOptional[String]("auth.defaultUserDomain")
3841
val fullUserNameRegex: Pattern = "[\\p{Graph}&&[^@.]](?:[\\p{Graph}&&[^@]]*)*@\\p{Alnum}+(?:[\\p{Alnum}-.])*".r.pattern
3942

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

42-
def checkUser(user: User): Try[User] = {
45+
def addOrCreateUser(user: User, avatar: Option[FFile], organisation: Organisation with Entity, profile: Profile with Entity)(implicit
46+
graph: Graph,
47+
authContext: AuthContext
48+
): Try[RichUser] =
49+
getByName(user.login)
50+
.getOrFail("User")
51+
.orElse {
52+
for {
53+
validUser <- checkUserLogin(user)
54+
_ <- checkUserQuota(organisation)
55+
createdUser <- createEntity(validUser)
56+
_ <- avatar.map(setAvatar(createdUser, _)).flip
57+
} yield createdUser
58+
}
59+
.flatMap(addUserToOrganisation(_, organisation, profile))
60+
61+
def checkUserLogin(user: User): Try[User] = {
4362
val login =
4463
if (!user.login.contains('@') && defaultUserDomain.isDefined) s"${user.login}@${defaultUserDomain.get}".toLowerCase
4564
else user.login.toLowerCase
@@ -48,6 +67,19 @@ class UserSrv @Inject() (
4867
else Failure(BadRequestError(s"User login is invalid, it must be an email address (found: ${user.login})"))
4968
}
5069

70+
def checkUserQuota(organisation: Organisation with Entity)(implicit
71+
graph: Graph,
72+
authContext: AuthContext
73+
): Try[Unit] = {
74+
val userQuota = configuration.getOptional[Long]("quota.organisation.user.count")
75+
val userCount = organisationSrv.get(organisation).users.getCount
76+
77+
userQuota.fold[Try[Unit]](Success(()))(quota =>
78+
if (userCount < quota) Success(())
79+
else Failure(BadRequestError(s"User quota is reached, this organisation cannot have more users"))
80+
)
81+
}
82+
5183
// TODO return Try[Unit]
5284
def addUserToOrganisation(user: User with Entity, organisation: Organisation with Entity, profile: Profile with Entity)(implicit
5385
graph: Graph,
@@ -64,21 +96,6 @@ class UserSrv @Inject() (
6496
} yield richUser
6597
}
6698

67-
def addOrCreateUser(user: User, avatar: Option[FFile], organisation: Organisation with Entity, profile: Profile with Entity)(implicit
68-
graph: Graph,
69-
authContext: AuthContext
70-
): Try[RichUser] =
71-
getByName(user.login)
72-
.getOrFail("User")
73-
.orElse {
74-
for {
75-
validUser <- checkUser(user)
76-
createdUser <- createEntity(validUser)
77-
_ <- avatar.map(setAvatar(createdUser, _)).flip
78-
} yield createdUser
79-
}
80-
.flatMap(addUserToOrganisation(_, organisation, profile))
81-
8299
def canSetPassword(user: User with Entity)(implicit graph: Graph, authContext: AuthContext): Boolean = {
83100
val userOrganisations = get(user).organisations.value(_.name).toSet
84101
val operatorOrganisations = current.organisations(Permissions.manageUser).value(_.name).toSeq

0 commit comments

Comments
 (0)