Skip to content

Commit

Permalink
Custom support users
Browse files Browse the repository at this point in the history
  • Loading branch information
mechkg committed Feb 3, 2017
1 parent 780b707 commit c95f5c5
Show file tree
Hide file tree
Showing 9 changed files with 91 additions and 46 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ trait FoodDatabaseErrorHandler extends Results {
}

def translateDatabaseResult[T](result: Either[AnyError, T])(implicit writer: Writer[T]) = result match {
case Right(()) => Ok
case Right(result) => Ok(write(result)).as(ContentTypes.JSON)
case Left(error) => translateDatabaseError(error)
}
Expand Down
47 changes: 47 additions & 0 deletions ApiPlayServer/app/controllers/system/SurveyAdminController.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*
This file is part of Intake24.
Copyright 2015, 2016 Newcastle University.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package controllers.system

import javax.inject.Inject

import com.mohiva.play.silhouette.api.util.PasswordHasherRegistry
import parsers.UpickleUtil
import play.api.libs.concurrent.Execution.Implicits.defaultContext
import play.api.mvc.Controller
import security.{DeadboltActionsAdapter, Roles}
import uk.ac.ncl.openlab.intake24.services.systemdb.admin.{SecureUserRecord, UserAdminService}
import upickle.default._

import scala.concurrent.Future

case class UserRef(surveyId: String, id: String)

case class SupportUsersUpdateRequest(users: Seq[UserRef])

class SurveyAdminController @Inject()(service: UserAdminService, passwordHasherRegistry: PasswordHasherRegistry, deadbolt: DeadboltActionsAdapter) extends Controller
with SystemDatabaseErrorHandler with UpickleUtil {

def updateGlobalSupportUsers() = deadbolt.restrict(Roles.superuser)(upickleBodyParser[SupportUsersUpdateRequest]) {
request =>
Future {
???
// translateDatabaseResult(service.createOrUpdateUsers(request.body.surveyId, secureUserRecords))
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ trait SystemDatabaseErrorHandler extends Results {
}

def translateDatabaseResult[T](result: Either[AnyError, T])(implicit writer: Writer[T]) = result match {
case Right(()) => Ok
case Right(result) => Ok(write(result)).as(ContentTypes.JSON)
case Left(error) => translateDatabaseError(error)
}
Expand Down
7 changes: 6 additions & 1 deletion ApiPlayServer/app/modules/Intake24ServicesModule.scala
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,9 @@ import uk.ac.ncl.openlab.intake24.services.fooddb.admin._
import uk.ac.ncl.openlab.intake24.services.fooddb.images._
import uk.ac.ncl.openlab.intake24.services.fooddb.user.{FoodDataService, FoodDatabaseService}
import uk.ac.ncl.openlab.intake24.services.foodindex.{FoodIndex, FoodIndexDataService}
import uk.ac.ncl.openlab.intake24.services.foodindex.english.{EnglishWordOpsPlingImpl, EnglishWordOps, FoodIndexImpl_en_GB}
import uk.ac.ncl.openlab.intake24.services.foodindex.english.{EnglishWordOps, EnglishWordOpsPlingImpl, FoodIndexImpl_en_GB}
import uk.ac.ncl.openlab.intake24.services.systemdb.admin.UserAdminService
import uk.ac.ncl.openlab.intake24.systemsql.admin.UserAdminImpl

class Intake24ServicesModule(env: Environment, config: Configuration) extends AbstractModule {
@Provides
Expand Down Expand Up @@ -96,6 +98,8 @@ class Intake24ServicesModule(env: Environment, config: Configuration) extends Ab
bind(classOf[FoodsAdminService]).to(classOf[ObservableFoodsAdminServiceImpl])
bind(classOf[LocalesAdminService]).to(classOf[ObservableLocalesAdminServiceImpl])

bind(classOf[UserAdminService]).to(classOf[UserAdminImpl])

// User facing services

bind(classOf[AsServedSetsAdminService]).to(classOf[AsServedSetsAdminStandaloneImpl])
Expand Down Expand Up @@ -132,5 +136,6 @@ class Intake24ServicesModule(env: Environment, config: Configuration) extends Ab
bind(classOf[FoodDatabaseService]).to(classOf[FoodDatabaseUserImpl])
bind(classOf[FoodDataService]).to(classOf[FoodDataUserStandaloneImpl])


}
}
53 changes: 15 additions & 38 deletions ApiPlayServer/app/modules/SilhouetteModule.scala
Original file line number Diff line number Diff line change
Expand Up @@ -18,36 +18,21 @@ limitations under the License.

package modules

import com.google.inject.AbstractModule
import com.google.inject.Provides
import com.mohiva.play.silhouette.api.services.AuthenticatorService
import com.mohiva.play.silhouette.impl.authenticators.JWTAuthenticator
import com.mohiva.play.silhouette.api.EventBus
import com.mohiva.play.silhouette.api.Environment
import com.google.inject.{AbstractModule, Provides, Singleton}
import com.mohiva.play.silhouette.api.{Environment, EventBus}
import com.mohiva.play.silhouette.api.crypto.Base64AuthenticatorEncoder
import com.mohiva.play.silhouette.api.repositories.AuthInfoRepository
import com.mohiva.play.silhouette.api.services.{AuthenticatorService, IdentityService}
import com.mohiva.play.silhouette.api.util._
import com.mohiva.play.silhouette.impl.authenticators.{JWTAuthenticator, JWTAuthenticatorService, JWTAuthenticatorSettings}
import com.mohiva.play.silhouette.impl.util.{DefaultFingerprintGenerator, SecureRandomIDGenerator}
import models.User
import play.api.libs.concurrent.Execution.Implicits.defaultContext
import com.mohiva.play.silhouette.api.services.IdentityService
import security.IdentityServiceImpl
import net.codingwell.scalaguice.ScalaModule
import com.mohiva.play.silhouette.api.util.IDGenerator
import com.mohiva.play.silhouette.impl.util.SecureRandomIDGenerator
import com.mohiva.play.silhouette.api.util.PasswordHasher

import com.mohiva.play.silhouette.api.util.FingerprintGenerator
import com.mohiva.play.silhouette.impl.util.DefaultFingerprintGenerator
import play.api.Configuration
import com.mohiva.play.silhouette.api.util.Clock
import com.mohiva.play.silhouette.impl.authenticators.JWTAuthenticatorSettings
import com.mohiva.play.silhouette.impl.authenticators.JWTAuthenticatorService
import play.api.libs.concurrent.Execution.Implicits.defaultContext
import security.{AuthInfoServiceImpl, IdentityServiceImpl, Intake24ApiEnv, ShiroPasswordHasher}

import scala.concurrent.duration._
import com.mohiva.play.silhouette.api.repositories.AuthInfoRepository
import security.AuthInfoServiceImpl
import com.mohiva.play.silhouette.impl.providers.CredentialsProvider
import security.ShiroPasswordHasher
import security.Intake24ApiEnv
import com.mohiva.play.silhouette.api.util.RequestPart
import com.mohiva.play.silhouette.api.crypto.Base64AuthenticatorEncoder
import com.mohiva.play.silhouette.api.util.PasswordHasherRegistry


class SilhouetteModule extends AbstractModule with ScalaModule {
Expand Down Expand Up @@ -96,19 +81,11 @@ class SilhouetteModule extends AbstractModule with ScalaModule {
new JWTAuthenticatorService(settings, None, new Base64AuthenticatorEncoder(), idGenerator, clock)
}

/**
* Provides the credentials provider.
*
* @param authInfoRepository The auth info repository implementation.
* @param passwordHasher The default password hasher implementation.
* @return The credentials provider.
*/
@Provides
def provideCredentialsProvider(
authInfoRepository: AuthInfoRepository): CredentialsProvider = {
@Singleton
def providePasswordHasherRegistry() = {
val shiroHasher = new ShiroPasswordHasher()

val shiroHasher = new ShiroPasswordHasher

new CredentialsProvider(authInfoRepository, PasswordHasherRegistry(shiroHasher, Seq()))
PasswordHasherRegistry(shiroHasher, Seq())
}
}
9 changes: 4 additions & 5 deletions ApiPlayServer/app/parsers/UpickleUtil.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package parsers

import play.api.mvc.{BodyParser, BodyParsers, Result, Results}
import play.api.http.ContentTypes
import uk.ac.ncl.openlab.intake24.api.shared.ErrorDescription

import scala.concurrent.Future
import upickle.default._
Expand All @@ -13,15 +14,13 @@ trait UpickleUtil {

import BodyParsers.parse._

private case class ErrorBody(error: String, message: String)

def parseJson[T](json: String)(implicit reader: Reader[T]): Either[Result, T] = {
try {
Right(read[T](json))
} catch {
case Invalid.Data(_, msg) => Left(Results.BadRequest(write(ErrorBody("json_exception", msg))))
case Invalid.Json(msg, _) => Left(Results.BadRequest(write(ErrorBody("json_exception", msg))))
case e: Throwable => Left(Results.BadRequest(write(ErrorBody("json_exception", s"${e.getClass.getName}: ${e.getMessage}"))))
case Invalid.Data(_, msg) => Left(Results.BadRequest(write(ErrorDescription("InvalidJson", msg))))
case Invalid.Json(msg, _) => Left(Results.BadRequest(write(ErrorDescription("InvalidJson", msg))))
case e: Throwable => Left(Results.BadRequest(write(ErrorDescription("InvalidJson", s"${e.getClass.getName}: ${e.getMessage}"))))
}
}

Expand Down
11 changes: 10 additions & 1 deletion ApiPlayServer/conf/routes
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

# SHARED CONTROLLERS #

POST /signin controllers.Auth.signin
POST /signin controllers.system.SigninController.signin

GET /index/lookup/:locale/:term controllers.FoodIndexController.lookup(locale, term)

Expand Down Expand Up @@ -129,3 +129,12 @@ POST /admin/images/process-for-selection-screen con

# GET /index/synsets/:locale controllers.FoodIndexController.synsets(locale: String)
# GET /index/split-list/:locale controllers.FoodIndexController.splitList(locale: String)



# User management

POST /admin/users/create-or-update controllers.system.UserAdminController.createOrUpdateUsers()

POST /admin/update-global-support-users controllers.system.SurveyAdminController.updateGlobalSupportUsers()
# POST /admin/surveys/:surveyId/support-users/update controllers.system.SurveyAdminController.updateSurveySupportUsers(surveyId: String)
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import uk.ac.ncl.openlab.intake24.sql.SqlResourceLoader
import uk.ac.ncl.openlab.intake24.systemsql.SystemSqlService
import uk.ac.ncl.openlab.intake24.services.systemdb.errors.UpdateError

class UserAdminImpl @Inject()(@Named("intake24_foods") val dataSource: DataSource) extends UserAdminService with SystemSqlService with SqlResourceLoader {
class UserAdminImpl @Inject()(@Named("intake24_system") val dataSource: DataSource) extends UserAdminService with SystemSqlService with SqlResourceLoader {

private def updateUserRolesQuery(surveyId: String, roles: Map[String, Set[String]])(implicit connection: Connection): Either[ParentError, Unit] = {
SQL("DELETE FROM user_roles WHERE survey_id={survey_id} AND user_id IN ({user_ids})")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ case class SecureUserRecord(username: String, passwordHashBase64: String, passwo
name: Option[String], email: Option[String], phone: Option[String],
roles: Set[String], permissions: Set[String], customFields: Map[String, String])

case class UserRef(surveyId: String, userId: String)

trait UserAdminService {

def getCustomUserData(surveyId: String, userId: String): Either[LookupError, Map[String, String]]
Expand All @@ -21,4 +23,8 @@ trait UserAdminService {
def getUserById(surveyId: String, name: String): Either[LookupError, SecureUserRecord]

def getUsersByRole(surveyId: String, role: String): Either[LookupError, Seq[SecureUserRecord]]

/* def updateGlobalSupportUsers(supportUsers: Seq[UserRef]): Either[ParentError, Unit]
def updateSupportUsersForSurvey(surveyId: String, supportUsers: Seq[UserRef]): Either[ParentError, Unit] */
}

0 comments on commit c95f5c5

Please sign in to comment.