Skip to content
This repository has been archived by the owner on Feb 17, 2020. It is now read-only.

Commit

Permalink
Introducing locked flag for users and checking if unset before every …
Browse files Browse the repository at this point in the history
…login. Closes #32
  • Loading branch information
peterbanda committed Oct 1, 2019
1 parent ed96abf commit b02d07e
Show file tree
Hide file tree
Showing 6 changed files with 27 additions and 27 deletions.
31 changes: 14 additions & 17 deletions app/org/ada/web/controllers/AuthController.scala
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ class AuthController @Inject() (
/**
* Login form definition.
*/
val loginForm = Form {
private val loginForm = Form {
tuple(
"id" -> nonEmptyText,
"password" -> nonEmptyText
Expand All @@ -39,6 +39,12 @@ class AuthController @Inject() (
// )
}

private val unauthorizedMessage = "It appears that you don't have sufficient rights for access. Please login to proceed."
private val unauthorizedRedirect = loginRedirect(unauthorizedMessage)

private def loginRedirect(errorMessage: String) =
Redirect(routes.AuthController.login).flashing("errors" -> errorMessage)

/**
* Redirect to login page.
*/
Expand Down Expand Up @@ -84,15 +90,15 @@ class AuthController @Inject() (
authenticateAux(
(formWithErrors: Form[(String, String)]) => BadRequest(views.html.auth.login(formWithErrors)),
BadRequest(views.html.auth.login(loginForm.withGlobalError("Invalid user id or password"))),
Redirect(routes.AuthController.unauthorized()),
loginRedirect("User not found or locked."),
(userId: String) => gotoLoginSucceeded(userId)
)

case Accepts.Json() =>
authenticateAux(
(formWithErrors: Form[(String, String)]) => BadRequest(formWithErrors.errorsAsJson),
Unauthorized("Invalid user id or password\n"),
Unauthorized("User not found.\n"),
Unauthorized("User not found or locked.\n"),
(userId: String) => gotoLoginSucceeded(userId, Future(Ok(s"User '${userId}' successfully logged in. Check the header for a 'PLAY_SESSION' cookie.\n")))
)
}
Expand All @@ -101,7 +107,7 @@ class AuthController @Inject() (
private def authenticateAux(
badFormResult: Form[(String, String)] => Result,
authenticationUnsuccessfulResult: Result,
userNotFoundResult: Result,
userNotFoundOrLockedResult: Result,
loginSuccessfulResult: String => Future[Result])(
implicit request: Request[_]
): Future[Result] = {
Expand All @@ -119,36 +125,27 @@ class AuthController @Inject() (
Future(authenticationUnsuccessfulResult)
} else
userOption match {
case Some(user) => loginSuccessfulResult(user.ldapDn)
case None => Future(userNotFoundResult)
case Some(user) => if (user.locked) Future(userNotFoundOrLockedResult) else loginSuccessfulResult(user.ldapDn)
case None => Future(userNotFoundOrLockedResult)
}
} yield
response
)
}

/**
* TODO: Give more specific error message (e.g. you are supposed to be admin)
* Redirect user on authorization failure.
*/
def unauthorized = AuthAction { implicit request =>
val message = "It appears that you don't have sufficient rights for access. Please login to proceed."
Future(Ok(views.html.auth.login(loginForm)).flashing("errors" -> message))
}

// immediately login as basic user
def loginBasic = Action.async { implicit request =>
if(userManager.debugUsers.nonEmpty)
gotoLoginSucceeded(userManager.basicUser.ldapDn)
else
Future(Redirect(routes.AuthController.unauthorized()))
Future(unauthorizedRedirect)
}

// immediately login as admin user
def loginAdmin = Action.async { implicit request =>
if (userManager.debugUsers.nonEmpty)
gotoLoginSucceeded(userManager.adminUser.ldapDn)
else
Future(Redirect(routes.AuthController.unauthorized()))
Future(unauthorizedRedirect)
}
}
5 changes: 3 additions & 2 deletions app/org/ada/web/controllers/UserController.scala
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import org.ada.web.controllers.core.AdaCrudControllerImpl
import org.ada.web.controllers.dataset._
import org.ada.server.dataaccess.RepoTypes.{DataSpaceMetaInfoRepo, UserRepo}
import play.api.data.Form
import play.api.data.Forms.{email, ignored, mapping, nonEmptyText, seq, text}
import play.api.data.Forms.{email, ignored, mapping, boolean, nonEmptyText, seq, text}
import org.ada.server.models.{DataSpaceMetaInfo, User}
import org.incal.core.dataaccess.AscSort
import reactivemongo.bson.BSONObjectID
Expand Down Expand Up @@ -37,7 +37,8 @@ class UserController @Inject() (
"name" -> nonEmptyText,
"email" -> email,
"roles" -> seq(text),
"permissions" -> seq(text)
"permissions" -> seq(text),
"locked" -> boolean
)(User.apply)(User.unapply))

override protected val entityNameKey = "user"
Expand Down
13 changes: 7 additions & 6 deletions app/org/ada/web/controllers/UserProfileController.scala
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,10 @@ class UserProfileController @Inject() (userRepo: UserRepo) extends AdaBaseContro
mapping(
"id" -> ignored(Option.empty[BSONObjectID]),
"name" -> text,
"email" -> ignored("placeholder"),
//"LDAP DN" -> ignored("placeholder"),
//"affiliation" -> text,
"email" -> email,
"roles" -> ignored(Seq[String]()),
"permissions" -> ignored(Seq[String]())
"permissions" -> ignored(Seq[String]()),
"locked" -> ignored(false)
)(User.apply)(User.unapply))

/**
Expand Down Expand Up @@ -62,14 +61,16 @@ class UserProfileController @Inject() (userRepo: UserRepo) extends AdaBaseContro
* Save changes made in user settings page to database.
* Extracts current user from token for information match.
*/
@Deprecated // TODO: unused?
def updateSettings = restrictSubjectPresentAny(noCaching = true) { implicit request =>
currentUserFromRequest.map { case DeadboltUser(user) =>
userUpdateForm.bindFromRequest.fold(
{ formWithErrors =>
Future(BadRequest(formWithErrors.errors.toString).flashing("failure" -> "An unexpected error occured"))
Future(BadRequest(formWithErrors.errors.toString).flashing("failure" -> "An unexpected error occurred"))
},
(newUserData: User) =>
userRepo.update(newUserData).map { _ =>
// we allow only email to be updated
userRepo.update(user.copy(email = newUserData.email)).map { _ =>
render {
case Accepts.Html() => Redirect(routes.UserProfileController.profile()).flashing("success" -> "Profile has been updated")
case Accepts.Json() => Ok(Json.obj("message" -> "Profile successfully updated"))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,6 @@ import org.incal.spark_ml.models.VectorScalerType
import org.ada.server.services.importers.TranSMARTService
import org.ada.web.services.{DataSpaceService, WidgetGenerationService}
import org.ada.web.services.widgetgen.DistributionWidgetGeneratorHelper
import play.api.i18n.Messages

import scala.math.Ordering.Implicits._
import scala.concurrent.{Future, TimeoutException}
Expand Down
2 changes: 2 additions & 0 deletions app/views/user/elements.scala.html
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,8 @@

@inputText("user", "name", form)
@inputText("user", "email", form)
@checkbox("user", "locked", form)

@labelValue("user", "Roles"){
@dynamicStringTable("role", form.value.map(_.roles).getOrElse(Nil))
}
Expand Down
2 changes: 1 addition & 1 deletion build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ PlayKeys.devSettings := Seq(
)

libraryDependencies ++= Seq(
"org.adada" %% "ada-server" % "0.8.1.RC.8.RC.4",
"org.adada" %% "ada-server" % "0.8.1.RC.8",
"org.in-cal" %% "incal-play" % "0.2.2",
"com.typesafe.play" %% "play-mailer" % "6.0.1", // to send emails
"com.typesafe.play" %% "play-mailer-guice" % "6.0.1", // to send emails (Guice)
Expand Down

0 comments on commit b02d07e

Please sign in to comment.