diff --git a/app/org/maproulette/framework/repository/UserRepository.scala b/app/org/maproulette/framework/repository/UserRepository.scala index 58f0379f..e6364f74 100644 --- a/app/org/maproulette/framework/repository/UserRepository.scala +++ b/app/org/maproulette/framework/repository/UserRepository.scala @@ -237,6 +237,16 @@ class UserRepository @Inject() ( } } + def getSuperUserIdsFromDatabase(): List[Long] = { + db.withConnection { implicit c => + // Search the grants table for grantee_id (eg the user's maproulette id) where the role is -1 (superuser) + // and the grantee_type is 5 (user). + anorm + .SQL("SELECT grantee_id AS id FROM grants WHERE role = -1 AND grantee_type = 5") + .as(SqlParser.scalar[Long].*) + } + } + def getUserTaskCounts(userId: Long, dateFilter: DateParameter)( implicit c: Option[Connection] = None ): Map[String, Int] = { diff --git a/app/org/maproulette/framework/service/UserService.scala b/app/org/maproulette/framework/service/UserService.scala index 581c646d..86f4a305 100644 --- a/app/org/maproulette/framework/service/UserService.scala +++ b/app/org/maproulette/framework/service/UserService.scala @@ -5,8 +5,6 @@ package org.maproulette.framework.service -import anorm.SqlParser - import java.util.UUID import javax.inject.{Inject, Singleton} import org.apache.commons.lang3.StringUtils @@ -26,7 +24,6 @@ import org.maproulette.permissions.Permission import org.maproulette.session.SearchParameters import org.maproulette.utils.{Crypto, Utils, Writers} import org.slf4j.LoggerFactory -import play.api.db.Database import play.api.libs.json.{JsString, JsValue, Json} /** @@ -34,7 +31,6 @@ import play.api.libs.json.{JsString, JsValue, Json} */ @Singleton class UserService @Inject() ( - db: Database, repository: UserRepository, savedObjectsRepository: UserSavedObjectsRepository, serviceManager: ServiceManager, @@ -54,7 +50,7 @@ class UserService @Inject() ( // On startup, seed the super user ids that exist in the database seedSuperUserIds() - promoteSuperUsersInConfig() + //promoteSuperUsersInConfig() /** * Check if a given maproulette user id is a superuser @@ -68,21 +64,31 @@ class UserService @Inject() ( def promoteUserToSuperUser(user: User, grantor: User): Boolean = { if (isSuperUser(user.id)) { logger.info( - s"Skipping superuser promotion, MapRoulette user id=${user.id} (osm_id=${user.osmProfile.id}) is already a superuser" + s"MapRoulette uid=${user.id} (osm_id=${user.osmProfile.id}) is already a superuser, skipping role promotion" ) return true } - logger.warn(s"Adding superuser role to user id=${user.id} (osm_id=${user.osmProfile.id})") - val grantName = s"User ${user.id} has Superuser" + logger.warn(s"Adding superuser role to uid=${user.id} (osm_id=${user.osmProfile.id})") + val grantName = + s"Grant superuser role on uid=${user.id} (osm_id=${user.osmProfile.id}), requested by uid=${grantor.id}" val superUserGrant = new Grant(-1, grantName, Grantee.user(user.id), Grant.ROLE_SUPER_USER, GrantTarget.project(0)) - serviceManager.grant.createGrant(superUserGrant, grantor) - superUsers += user.id - true + + serviceManager.grant.createGrant(superUserGrant, grantor) match { + case Some(grantedUser) => + superUsers += grantedUser.id + true + case _ => + // The grant.createGrant function will throw an exception if it fails, so we should never get here. But just in case... + logger.warn( + s"Failed to add superuser role to uid=${user.id} requested by uid=${grantor.id}" + ) + false + } } - private def promoteSuperUsersInConfig(): Unit = { + def promoteSuperUsersInConfig(): Unit = { val usersToPromote: List[User] = config.superAccounts .flatMap { osmId => retrieveByOSMId(osmId.toLong) match { @@ -97,7 +103,7 @@ class UserService @Inject() ( .flatMap { user => if (isSuperUser(user.id)) { logger.info( - s"Skipping superuser promotion, MapRoulette user id=${user.id} is already a superuser" + s"MapRoulette uid=${user.id} (osm_id=${user.osmProfile.id}) is already a superuser, skipping role promotion" ) None } else { @@ -111,14 +117,7 @@ class UserService @Inject() ( } private def seedSuperUserIds(): Unit = { - db.withConnection { implicit c => - // Search the grants table for grantee_id (eg the user's maproulette id) where the role is -1 (superuser) - // and the grantee_type is 5 (user). - val superIds = anorm - .SQL("SELECT grantee_id AS id FROM grants WHERE role = -1 AND grantee_type = 5") - .as(SqlParser.scalar[Long].*) - superUsers ++= superIds - } + superUsers ++= repository.getSuperUserIdsFromDatabase() } /** diff --git a/app/org/maproulette/jobs/Bootstrap.scala b/app/org/maproulette/jobs/Bootstrap.scala index dc188f44..827a0d9e 100644 --- a/app/org/maproulette/jobs/Bootstrap.scala +++ b/app/org/maproulette/jobs/Bootstrap.scala @@ -4,8 +4,9 @@ */ package org.maproulette.jobs -import javax.inject.{Inject, Singleton} +import javax.inject.{Inject, Provider, Singleton} import org.maproulette.Config +import org.maproulette.framework.service.UserService import org.slf4j.LoggerFactory import play.api.db.Database import play.api.inject.ApplicationLifecycle @@ -16,7 +17,12 @@ import scala.concurrent.Future * @author mcuthbert */ @Singleton -class Bootstrap @Inject() (appLifeCycle: ApplicationLifecycle, db: Database, config: Config) { +class Bootstrap @Inject() ( + appLifeCycle: ApplicationLifecycle, + db: Database, + config: Config, + userService: Provider[UserService] +) { private val logger = LoggerFactory.getLogger(this.getClass) @@ -35,6 +41,8 @@ class Bootstrap @Inject() (appLifeCycle: ApplicationLifecycle, db: Database, con case _ => // do nothing } } + + userService.get().promoteSuperUsersInConfig() } appLifeCycle.addStopHook { () =>