app/controllers/RevokePermissions.scala (111 lines of code) (raw):

package controllers import aws.Federation import com.gu.googleauth.AuthAction import com.gu.janus.model.JanusData import conf.Config import logic.Revocation import logic.UserAccess._ import play.api.{Configuration, Logging, Mode} import play.api.mvc.{AbstractController, AnyContent, ControllerComponents} import software.amazon.awssdk.services.sts.StsClient import java.time.{Instant, ZoneOffset} class RevokePermissions( janusData: JanusData, controllerComponents: ControllerComponents, authAction: AuthAction[AnyContent], stsClient: StsClient, configuration: Configuration )(implicit mode: Mode, assetsFinder: AssetsFinder) extends AbstractController(controllerComponents) with Logging { def revoke = authAction { implicit request => val sortedAccounts = janusData.accounts.toList.sortBy(_.name.toLowerCase) Ok(views.html.revoke(sortedAccounts, request.user, janusData)) } def revokeRequest(accountId: String) = authAction { implicit request => (for { account <- janusData.accounts.find(accountId == _.authConfigKey) } yield { logger.info( s"REVOKE request in started for $accountId by ${username(request.user)}" ) Ok(views.html.revokeRequest(account, request.user, janusData)) .withHeaders(CACHE_CONTROL -> "no-cache") }) getOrElse { logger.warn( s"Account not found: REVOKE request for $accountId by ${username(request.user)}" ) NotFound( views.html.error("Account not found", Some(request.user), janusData) ) } } def revokeConfirmation(accountId: Option[String]) = authAction { implicit request => if (accountId.isEmpty) Ok(views.html.revokeConfirmation(None, request.user, janusData)) else { (for { account <- accountId .flatMap(aId => janusData.accounts.find(aId == _.authConfigKey)) } yield { Ok( views.html .revokeConfirmation(Some(account), request.user, janusData) ) }) getOrElse { logger.warn( s"Account not found: REVOKE confirmation screen for $accountId by ${username(request.user)}" ) NotFound( views.html.error("Account not found", Some(request.user), janusData) ) } } } def revokeAccount(accountId: String) = authAction { implicit request => val result = for { account <- janusData.accounts .find(accountId == _.authConfigKey) .toRight("Account not found") submission <- request.body.asFormUrlEncoded.toRight( "Could not parse submission" ) confirmationKey <- submission .get("confirm") .flatMap(_.headOption) .toRight("Missing account confirmation") targetRoleArn = Config.roleArn(account.authConfigKey, configuration) } yield { if (Revocation.checkConfirmation(confirmationKey, account)) { Federation.disableFederation( account, Instant.now(), targetRoleArn, stsClient ) logger.warn( s"Janus access revoked for $accountId by ${username(request.user)}" ) Redirect(routes.RevokePermissions.revokeConfirmation(Some(accountId))) } else { logger.warn( s"Confirmation key $confirmationKey did not match for $accountId by ${username(request.user)}" ) Redirect(routes.RevokePermissions.revokeRequest(accountId)) .flashing( "confirmation-error" -> "Confirmation did not match the account." ) } } result.fold( { errMsg => logger.warn( s"$errMsg: denied REVOKE confirmation screen for $accountId by ${username(request.user)}" ) BadRequest(views.html.error(errMsg, Some(request.user), janusData)) }, identity ) } }