Skip to content

Commit

Permalink
Merge pull request #4108 from nationalarchives/TDRD-type-and-user-con…
Browse files Browse the repository at this point in the history
…trol

Add user as well as consignment type check to all transferring body pages
  • Loading branch information
annielh authored Sep 5, 2024
2 parents 911c32f + d9ffce6 commit 8d630df
Show file tree
Hide file tree
Showing 46 changed files with 416 additions and 92 deletions.
39 changes: 21 additions & 18 deletions app/auth/TokenSecurity.scala
Original file line number Diff line number Diff line change
Expand Up @@ -40,20 +40,20 @@ trait TokenSecurity extends OidcSecurity with I18nSupport {
RequestWithToken(request, accessToken)
}

def judgmentTypeAction(consignmentId: UUID)(action: Request[AnyContent] => Future[Result]): Action[AnyContent] = {
consignmentTypeAction(consignmentId, "judgment")(action)
}

def judgmentUserAction(action: Request[AnyContent] => Future[Result]): Action[AnyContent] = secureAction.async { request =>
createResult(action, request, request.token.isJudgmentUser)
}

def judgmentUserAndTypeAction(consignmentId: UUID)(action: Request[AnyContent] => Future[Result]): Action[AnyContent] = {
validatedAction(consignmentId, "judgment", _.isJudgmentUser)(action)
}

def standardUserAction(action: Request[AnyContent] => Future[Result]): Action[AnyContent] = secureAction.async { request =>
createResult(action, request, request.token.isStandardUser)
}

def standardTypeAction(consignmentId: UUID)(action: Request[AnyContent] => Future[Result]): Action[AnyContent] = {
consignmentTypeAction(consignmentId, "standard")(action)
def standardUserAndTypeAction(consignmentId: UUID)(action: Request[AnyContent] => Future[Result]): Action[AnyContent] = {
validatedAction(consignmentId, "standard", _.isStandardUser)(action)
}

def tnaUserAction(action: Request[AnyContent] => Future[Result]): Action[AnyContent] = secureAction.async { request =>
Expand All @@ -76,17 +76,20 @@ trait TokenSecurity extends OidcSecurity with I18nSupport {
}
}

private def consignmentTypeAction(consignmentId: UUID, expectedConsignmentType: String)(action: Request[AnyContent] => Future[Result]): Action[AnyContent] = secureAction.async {
request =>
val token = request.token
consignmentService
.getConsignmentType(consignmentId, token.bearerAccessToken)
.flatMap(consignmentType => {
// These are custom user annotation traces used in Xray
val current = Span.current()
current.setAttribute(consignmentIdKey, consignmentId.toString)
current.setAttribute(userIdKey, token.userId.toString)
createResult(action, request, consignmentType == expectedConsignmentType)
})
private def validatedAction(
consignmentId: UUID,
expectedConsignmentType: String,
isPermitted: Token => Boolean = _ => true
)(action: Request[AnyContent] => Future[Result]): Action[AnyContent] = secureAction.async { request =>
val token = request.token
consignmentService
.getConsignmentType(consignmentId, token.bearerAccessToken)
.flatMap(consignmentType => {
// These are custom user annotation traces used in Xray
val current = Span.current()
current.setAttribute(consignmentIdKey, consignmentId.toString)
current.setAttribute(userIdKey, token.userId.toString)
createResult(action, request, consignmentType == expectedConsignmentType && isPermitted(token))
})
}
}
4 changes: 2 additions & 2 deletions app/controllers/AddAdditionalMetadataController.scala
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ class AddAdditionalMetadataController @Inject() (
extends TokenSecurity
with I18nSupport {

def addAdditionalMetadata(consignmentId: UUID, metadataType: String, fileIds: List[UUID]): Action[AnyContent] = standardTypeAction(consignmentId) {
def addAdditionalMetadata(consignmentId: UUID, metadataType: String, fileIds: List[UUID]): Action[AnyContent] = standardUserAndTypeAction(consignmentId) {
implicit request: Request[AnyContent] =>
for {
consignment <- getConsignmentFileMetadata(consignmentId, metadataType, fileIds)
Expand All @@ -52,7 +52,7 @@ class AddAdditionalMetadataController @Inject() (
} yield result
}

def addAdditionalMetadataSubmit(consignmentId: UUID, metadataType: String, fileIds: List[UUID]): Action[AnyContent] = standardTypeAction(consignmentId) {
def addAdditionalMetadataSubmit(consignmentId: UUID, metadataType: String, fileIds: List[UUID]): Action[AnyContent] = standardUserAndTypeAction(consignmentId) {
implicit request: Request[AnyContent] =>
for {
formFields <- cache.getOrElseUpdate[List[FormField]]("formFields") {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ class AdditionalMetadataClosureStatusController @Inject() (

private val additionalProperties: List[String] = List(clientSideOriginalFilepath, fileType)

def getClosureStatusPage(consignmentId: UUID, metadataType: String, fileIds: List[UUID]): Action[AnyContent] = standardTypeAction(consignmentId) {
def getClosureStatusPage(consignmentId: UUID, metadataType: String, fileIds: List[UUID]): Action[AnyContent] = standardUserAndTypeAction(consignmentId) {
implicit request: Request[AnyContent] =>
for {
closureProperties <- displayPropertiesService.getDisplayProperties(consignmentId, request.token.bearerAccessToken, Some(metadataType)).map(_.map(_.summary))
Expand Down Expand Up @@ -75,7 +75,7 @@ class AdditionalMetadataClosureStatusController @Inject() (
} yield response
}

def submitClosureStatus(consignmentId: UUID, metadataType: String, fileIds: List[UUID]): Action[AnyContent] = standardTypeAction(consignmentId) {
def submitClosureStatus(consignmentId: UUID, metadataType: String, fileIds: List[UUID]): Action[AnyContent] = standardUserAndTypeAction(consignmentId) {
implicit request: Request[AnyContent] =>
val errorFunction: Form[ClosureStatusFormData] => Future[Result] = { formWithErrors: Form[ClosureStatusFormData] =>
for {
Expand Down
4 changes: 2 additions & 2 deletions app/controllers/AdditionalMetadataController.scala
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ class AdditionalMetadataController @Inject() (

val byClosureType: DisplayProperty => Boolean = (dp: DisplayProperty) => dp.propertyType == "Closure"

def start(consignmentId: UUID): Action[AnyContent] = standardTypeAction(consignmentId) { implicit request: Request[AnyContent] =>
def start(consignmentId: UUID): Action[AnyContent] = standardUserAndTypeAction(consignmentId) { implicit request: Request[AnyContent] =>
(for {
consignmentStatuses <- consignmentStatusService.getConsignmentStatuses(consignmentId, request.token.bearerAccessToken)
pageArgs <- getStartPageDetails(consignmentId, request.token)
Expand Down Expand Up @@ -65,7 +65,7 @@ class AdditionalMetadataController @Inject() (
}
}

def validate(consignmentId: UUID): Action[AnyContent] = standardTypeAction(consignmentId) { implicit request: Request[AnyContent] =>
def validate(consignmentId: UUID): Action[AnyContent] = standardUserAndTypeAction(consignmentId) { implicit request: Request[AnyContent] =>
(for {
pageArgs <- getStartPageDetails(consignmentId, request.token)
statuses <- consignmentService.getConsignmentFilesData(consignmentId, request.token.bearerAccessToken)
Expand Down
4 changes: 2 additions & 2 deletions app/controllers/AdditionalMetadataEntryMethodController.scala
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ class AdditionalMetadataEntryMethodController @Inject() (
)(AdditionalMetadataEntryData.apply)(AdditionalMetadataEntryData.unapply)
)

def additionalMetadataEntryMethodPage(consignmentId: UUID): Action[AnyContent] = standardTypeAction(consignmentId) { implicit request: Request[AnyContent] =>
def additionalMetadataEntryMethodPage(consignmentId: UUID): Action[AnyContent] = standardUserAndTypeAction(consignmentId) { implicit request: Request[AnyContent] =>
if (applicationConfig.blockDraftMetadataUpload) {
Future(Ok(views.html.notFoundError(name = request.token.name, isLoggedIn = true, isJudgmentUser = false)))
} else {
Expand All @@ -46,7 +46,7 @@ class AdditionalMetadataEntryMethodController @Inject() (
}
}

def submitAdditionalMetadataEntryMethod(consignmentId: UUID): Action[AnyContent] = standardTypeAction(consignmentId) { implicit request: Request[AnyContent] =>
def submitAdditionalMetadataEntryMethod(consignmentId: UUID): Action[AnyContent] = standardUserAndTypeAction(consignmentId) { implicit request: Request[AnyContent] =>
val token = request.token.bearerAccessToken
if (applicationConfig.blockDraftMetadataUpload) {
Future(Ok(views.html.notFoundError(name = request.token.name, isLoggedIn = true, isJudgmentUser = false)))
Expand Down
4 changes: 2 additions & 2 deletions app/controllers/AdditionalMetadataNavigationController.scala
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ class AdditionalMetadataNavigationController @Inject() (
val controllerComponents: SecurityComponents
) extends TokenSecurity {

def getAllFiles(consignmentId: UUID, metadataType: String, expanded: Option[String] = Some("false")): Action[AnyContent] = standardTypeAction(consignmentId) {
def getAllFiles(consignmentId: UUID, metadataType: String, expanded: Option[String] = Some("false")): Action[AnyContent] = standardUserAndTypeAction(consignmentId) {
implicit request: Request[AnyContent] =>
for {
allFiles <- consignmentService.getAllConsignmentFiles(consignmentId, request.token.bearerAccessToken, metadataType)
Expand All @@ -27,7 +27,7 @@ class AdditionalMetadataNavigationController @Inject() (
}
}

def submitFiles(consignmentId: UUID, metadataType: String): Action[AnyContent] = standardTypeAction(consignmentId) { implicit request: Request[AnyContent] =>
def submitFiles(consignmentId: UUID, metadataType: String): Action[AnyContent] = standardUserAndTypeAction(consignmentId) { implicit request: Request[AnyContent] =>
val formData = request.body.asFormUrlEncoded
val action = formData.flatMap(_.get("action")).map(_.head)
val fileIds = formData
Expand Down
2 changes: 1 addition & 1 deletion app/controllers/AdditionalMetadataSummaryController.scala
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ class AdditionalMetadataSummaryController @Inject() (
) extends TokenSecurity {

def getSelectedSummaryPage(consignmentId: UUID, metadataType: String, fileIds: List[UUID], page: Option[String] = None): Action[AnyContent] =
standardTypeAction(consignmentId) { implicit request: Request[AnyContent] =>
standardUserAndTypeAction(consignmentId) { implicit request: Request[AnyContent] =>
for {
consignment <- consignmentService.getConsignmentFileMetadata(consignmentId, request.token.bearerAccessToken, Some(metadataType), Some(fileIds))
displayProperties <- displayPropertiesService.getDisplayProperties(consignmentId, request.token.bearerAccessToken, Some(metadataType))
Expand Down
2 changes: 1 addition & 1 deletion app/controllers/BeforeUploadingController.scala
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ class BeforeUploadingController @Inject() (
extends TokenSecurity
with I18nSupport {

def beforeUploading(consignmentId: UUID): Action[AnyContent] = judgmentTypeAction(consignmentId) { implicit request: Request[AnyContent] =>
def beforeUploading(consignmentId: UUID): Action[AnyContent] = judgmentUserAndTypeAction(consignmentId) { implicit request: Request[AnyContent] =>
consignmentService
.getConsignmentRef(consignmentId, request.token.bearerAccessToken)
.map(reference => Ok(views.html.judgment.judgmentBeforeUploading(consignmentId, reference, request.token.name)))
Expand Down
4 changes: 2 additions & 2 deletions app/controllers/ConfirmTransferController.scala
Original file line number Diff line number Diff line change
Expand Up @@ -80,12 +80,12 @@ class ConfirmTransferController @Inject() (
}
}

def confirmTransfer(consignmentId: UUID): Action[AnyContent] = standardTypeAction(consignmentId) { implicit request: Request[AnyContent] =>
def confirmTransfer(consignmentId: UUID): Action[AnyContent] = standardUserAndTypeAction(consignmentId) { implicit request: Request[AnyContent] =>
loadStandardPageBasedOnCtStatus(consignmentId, Ok)
}

def finalTransferConfirmationSubmit(consignmentId: UUID): Action[AnyContent] =
standardTypeAction(consignmentId) { implicit request: Request[AnyContent] =>
standardUserAndTypeAction(consignmentId) { implicit request: Request[AnyContent] =>
val errorFunction: Form[FinalTransferConfirmationData] => Future[Result] = { formWithErrors: Form[FinalTransferConfirmationData] =>
loadStandardPageBasedOnCtStatus(consignmentId, BadRequest, formWithErrors)
}
Expand Down
4 changes: 2 additions & 2 deletions app/controllers/DeleteAdditionalMetadataController.scala
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ class DeleteAdditionalMetadataController @Inject() (
with I18nSupport {

def confirmDeleteAdditionalMetadata(consignmentId: UUID, metadataType: String, fileIds: List[UUID]): Action[AnyContent] =
standardTypeAction(consignmentId) { implicit request: Request[AnyContent] =>
standardUserAndTypeAction(consignmentId) { implicit request: Request[AnyContent] =>
if (fileIds.isEmpty) {
Future.failed(new IllegalArgumentException("fileIds are empty"))
} else {
Expand Down Expand Up @@ -55,7 +55,7 @@ class DeleteAdditionalMetadataController @Inject() (
}

def deleteAdditionalMetadata(consignmentId: UUID, metadataType: String, fileIds: List[UUID]): Action[AnyContent] =
standardTypeAction(consignmentId) { implicit request: Request[AnyContent] =>
standardUserAndTypeAction(consignmentId) { implicit request: Request[AnyContent] =>
if (fileIds.isEmpty) {
Future.failed(new IllegalArgumentException("fileIds are empty"))
} else {
Expand Down
4 changes: 2 additions & 2 deletions app/controllers/DownloadMetadataController.scala
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ class DownloadMetadataController @Inject() (
) extends TokenSecurity
with Logging {

def downloadMetadataPage(consignmentId: UUID): Action[AnyContent] = standardTypeAction(consignmentId) { implicit request: Request[AnyContent] =>
def downloadMetadataPage(consignmentId: UUID): Action[AnyContent] = standardUserAndTypeAction(consignmentId) { implicit request: Request[AnyContent] =>
consignmentService
.getConsignmentRef(consignmentId, request.token.bearerAccessToken)
.map { ref =>
Expand All @@ -41,7 +41,7 @@ class DownloadMetadataController @Inject() (
}
}

def downloadMetadataFile(consignmentId: UUID): Action[AnyContent] = standardTypeAction(consignmentId) { implicit request: Request[AnyContent] =>
def downloadMetadataFile(consignmentId: UUID): Action[AnyContent] = standardUserAndTypeAction(consignmentId) { implicit request: Request[AnyContent] =>
if (request.token.isTNAUser) logger.info(s"TNA User: ${request.token.userId} downloaded metadata for consignmentId: $consignmentId")
for {
metadata <- consignmentService.getConsignmentFileMetadata(consignmentId, request.token.bearerAccessToken, None, None)
Expand Down
4 changes: 2 additions & 2 deletions app/controllers/DraftMetadataChecksController.scala
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ class DraftMetadataChecksController @Inject() (
extends TokenSecurity
with I18nSupport {

def draftMetadataChecksPage(consignmentId: UUID): Action[AnyContent] = standardTypeAction(consignmentId) { implicit request: Request[AnyContent] =>
def draftMetadataChecksPage(consignmentId: UUID): Action[AnyContent] = standardUserAndTypeAction(consignmentId) { implicit request: Request[AnyContent] =>
if (applicationConfig.blockDraftMetadataUpload) {
Future(Ok(views.html.notFoundError(name = request.token.name, isLoggedIn = true, isJudgmentUser = false)))
} else {
Expand All @@ -38,7 +38,7 @@ class DraftMetadataChecksController @Inject() (
}
}

def draftMetadataValidationProgress(consignmentId: UUID): Action[AnyContent] = standardTypeAction(consignmentId) { implicit request =>
def draftMetadataValidationProgress(consignmentId: UUID): Action[AnyContent] = standardUserAndTypeAction(consignmentId) { implicit request =>
consignmentStatusService
.getConsignmentStatuses(consignmentId, request.token.bearerAccessToken)
.map(_.asJson.noSpaces)
Expand Down
2 changes: 1 addition & 1 deletion app/controllers/DraftMetadataChecksResultsController.scala
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ class DraftMetadataChecksResultsController @Inject() (
extends TokenSecurity
with I18nSupport {

def draftMetadataChecksResultsPage(consignmentId: UUID): Action[AnyContent] = standardTypeAction(consignmentId) { implicit request: Request[AnyContent] =>
def draftMetadataChecksResultsPage(consignmentId: UUID): Action[AnyContent] = standardUserAndTypeAction(consignmentId) { implicit request: Request[AnyContent] =>
if (applicationConfig.blockDraftMetadataUpload) {
Future(Ok(views.html.notFoundError(name = request.token.name, isLoggedIn = true, isJudgmentUser = false)))
} else {
Expand Down
2 changes: 1 addition & 1 deletion app/controllers/DraftMetadataUploadController.scala
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ class DraftMetadataUploadController @Inject() (
extends TokenSecurity
with I18nSupport {

def draftMetadataUploadPage(consignmentId: UUID): Action[AnyContent] = standardTypeAction(consignmentId) { implicit request: Request[AnyContent] =>
def draftMetadataUploadPage(consignmentId: UUID): Action[AnyContent] = standardUserAndTypeAction(consignmentId) { implicit request: Request[AnyContent] =>
if (applicationConfig.blockDraftMetadataUpload) {
Future(Ok(views.html.notFoundError(name = request.token.name, isLoggedIn = true, isJudgmentUser = false)))
} else {
Expand Down
23 changes: 12 additions & 11 deletions app/controllers/FileChecksController.scala
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ class FileChecksController @Inject() (
} yield Ok(result.asJson.noSpaces)
}

def fileChecksPage(consignmentId: UUID, uploadFailed: Option[String]): Action[AnyContent] = standardTypeAction(consignmentId) { implicit request: Request[AnyContent] =>
def fileChecksPage(consignmentId: UUID, uploadFailed: Option[String]): Action[AnyContent] = standardUserAndTypeAction(consignmentId) { implicit request: Request[AnyContent] =>
val token = request.token.bearerAccessToken
for {
reference <- consignmentService.getConsignmentRef(consignmentId, token)
Expand All @@ -109,18 +109,19 @@ class FileChecksController @Inject() (
} yield result
}

def judgmentFileChecksPage(consignmentId: UUID, uploadFailed: Option[String]): Action[AnyContent] = judgmentTypeAction(consignmentId) { implicit request: Request[AnyContent] =>
val token = request.token.bearerAccessToken
for {
reference <- consignmentService.getConsignmentRef(consignmentId, token)
result <- uploadFailed match {
case Some("true") => handleFailedUpload(consignmentId, reference, isJudgmentUser = true, token)
case _ => handleSuccessfulUpload(consignmentId, reference, isJudgmentUser = true)
}
} yield result
def judgmentFileChecksPage(consignmentId: UUID, uploadFailed: Option[String]): Action[AnyContent] = judgmentUserAndTypeAction(consignmentId) {
implicit request: Request[AnyContent] =>
val token = request.token.bearerAccessToken
for {
reference <- consignmentService.getConsignmentRef(consignmentId, token)
result <- uploadFailed match {
case Some("true") => handleFailedUpload(consignmentId, reference, isJudgmentUser = true, token)
case _ => handleSuccessfulUpload(consignmentId, reference, isJudgmentUser = true)
}
} yield result
}

def judgmentCompleteTransfer(consignmentId: UUID): Action[AnyContent] = judgmentTypeAction(consignmentId) { implicit request: Request[AnyContent] =>
def judgmentCompleteTransfer(consignmentId: UUID): Action[AnyContent] = judgmentUserAndTypeAction(consignmentId) { implicit request: Request[AnyContent] =>
for {
_ <- waitForFileChecksToBeCompleted(consignmentId)
result <- JudgmentCompleteTransfer(consignmentId)
Expand Down
4 changes: 2 additions & 2 deletions app/controllers/FileChecksResultsController.scala
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ class FileChecksResultsController @Inject() (
extends TokenSecurity
with I18nSupport {

def fileCheckResultsPage(consignmentId: UUID): Action[AnyContent] = standardTypeAction(consignmentId) { implicit request: Request[AnyContent] =>
def fileCheckResultsPage(consignmentId: UUID): Action[AnyContent] = standardUserAndTypeAction(consignmentId) { implicit request: Request[AnyContent] =>
val pageTitle = "Results of your checks"

for {
Expand Down Expand Up @@ -57,7 +57,7 @@ class FileChecksResultsController @Inject() (
}
}

def judgmentFileCheckResultsPage(consignmentId: UUID, transferProgress: Option[String]): Action[AnyContent] = judgmentTypeAction(consignmentId) {
def judgmentFileCheckResultsPage(consignmentId: UUID, transferProgress: Option[String]): Action[AnyContent] = judgmentUserAndTypeAction(consignmentId) {
implicit request: Request[AnyContent] =>
val pageTitle = "Results of checks"
for {
Expand Down
2 changes: 1 addition & 1 deletion app/controllers/MetadataReviewStatusController.scala
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ class MetadataReviewStatusController @Inject() (
val applicationConfig: ApplicationConfig
) extends TokenSecurity {

def metadataReviewStatusPage(consignmentId: UUID): Action[AnyContent] = standardTypeAction(consignmentId) { implicit request: Request[AnyContent] =>
def metadataReviewStatusPage(consignmentId: UUID): Action[AnyContent] = standardUserAndTypeAction(consignmentId) { implicit request: Request[AnyContent] =>
if (applicationConfig.blockMetadataReview) {
Future(Ok(views.html.notFoundError(name = request.token.name, isLoggedIn = true, isJudgmentUser = false)))
} else {
Expand Down
Loading

0 comments on commit 8d630df

Please sign in to comment.