~wegtam/smederee

Showing details for patch 4a55f1bc67742c8a90a690541abba566018f473c.
2024-11-12 (Tue), 5:19 PM - Jens Grassel - 4a55f1bc67742c8a90a690541abba566018f473c

VCS: Improve handling of not found repositories or organisations.

- catch more occurences of possible errors due to not existing repos or owners
- improve error messages to the end user (custom view)
Summary of changes
1 files added
  • modules/hub/src/main/twirl/de/smederee/hub/views/errors/repositoryNotFound.scala.html
2 files modified with 179 lines added and 32 lines removed
  • modules/hub/src/main/resources/messages.properties with 2 added and 0 removed lines
  • modules/hub/src/main/scala/de/smederee/hub/VcsRepositoryRoutes.scala with 177 added and 32 removed lines
diff -rN -u old-smederee/modules/hub/src/main/resources/messages.properties new-smederee/modules/hub/src/main/resources/messages.properties
--- old-smederee/modules/hub/src/main/resources/messages.properties	2024-11-21 17:54:04.909315731 +0000
+++ new-smederee/modules/hub/src/main/resources/messages.properties	2024-11-21 17:54:04.913315736 +0000
@@ -16,6 +16,8 @@
 errors.forbidden.title=403 - Forbidden
 errors.internal-server-error.title=500 - Internal Server Error
 errors.internal-server-error.message=An error occured while processing the request.
+errors.repository.not-found.title=Not found
+errors.repository.not-found.message=No repository named "{0}" found for user or organisation "{1}"!
 errors.user-or-organisation.not-found.title=Not found
 errors.user-or-organisation.not-found.message=No user or organisation named "{0}" could be found!
 
diff -rN -u old-smederee/modules/hub/src/main/scala/de/smederee/hub/VcsRepositoryRoutes.scala new-smederee/modules/hub/src/main/scala/de/smederee/hub/VcsRepositoryRoutes.scala
--- old-smederee/modules/hub/src/main/scala/de/smederee/hub/VcsRepositoryRoutes.scala	2024-11-21 17:54:04.909315731 +0000
+++ new-smederee/modules/hub/src/main/scala/de/smederee/hub/VcsRepositoryRoutes.scala	2024-11-21 17:54:04.913315736 +0000
@@ -1092,9 +1092,19 @@
                     )
                 )
                 _ <- Sync[F].delay(log.info(s"Repository $repo ($requestedFilePath) is cloned."))
+                notFoundResponse = NotFound(
+                    views.html.errors.repositoryNotFound()(
+                        csrf = csrf,
+                        title = None,
+                        None
+                    )(
+                        repositoryOwnerName,
+                        repositoryName
+                    )
+                )
                 resp <- (repo, requestedFilePath) match {
-                    case (Some(_), Some(path)) => StaticFile.fromPath(path, req.some).getOrElseF(NotFound())
-                    case _                     => NotFound()
+                    case (Some(_), Some(path)) => StaticFile.fromPath(path, req.some).getOrElseF(notFoundResponse)
+                    case _                     => notFoundResponse
                 }
             } yield resp
     }
@@ -1594,7 +1604,17 @@
                     )
                 )
                 resp <- repo match {
-                    case None => NotFound()
+                    case None =>
+                        NotFound(
+                            views.html.errors.repositoryNotFound()(
+                                csrf = csrf,
+                                title = None,
+                                user.some
+                            )(
+                                repositoryOwnerName,
+                                repositoryName
+                            )
+                        )
                     case Some(repo) =>
                         Ok(
                             views.html.deleteRepository()(
@@ -1662,7 +1682,17 @@
                                 branches
                             )(formData.withDefaultValue(Chain.empty))
                         )
-                    case _ => NotFound()
+                    case _ =>
+                        NotFound(
+                            views.html.errors.repositoryNotFound()(
+                                csrf = csrf,
+                                title = None,
+                                user.some
+                            )(
+                                repositoryOwnerName,
+                                repositoryName
+                            )
+                        )
                 }
             } yield resp
     }
@@ -1708,8 +1738,21 @@
                 repositoryName
             ) as user =>
             for {
-                csrf <- Sync[F].delay(ar.req.getCsrfToken)
-                resp <- doShowRepositoryOverview(csrf)(user.some)(repositoryOwnerName, repositoryName)
+                csrf      <- Sync[F].delay(ar.req.getCsrfToken)
+                language  <- Sync[F].delay(user.language.getOrElse(LanguageCode("en")))
+                repoAndId <- loadRepo(user.some)(repositoryOwnerName, repositoryName)
+                resp <- repoAndId.fold(
+                    NotFound(
+                        views.html.errors.repositoryNotFound(lang = language)(
+                            csrf = csrf,
+                            title = None,
+                            user.some
+                        )(
+                            repositoryOwnerName,
+                            repositoryName
+                        )
+                    )
+                )(_ => doShowRepositoryOverview(csrf)(user.some)(repositoryOwnerName, repositoryName))
             } yield resp
     }
 
@@ -1718,8 +1761,20 @@
                 repositoryName
             ) =>
             for {
-                csrf <- Sync[F].delay(req.getCsrfToken)
-                resp <- doShowRepositoryOverview(csrf)(None)(repositoryOwnerName, repositoryName)
+                csrf      <- Sync[F].delay(req.getCsrfToken)
+                repoAndId <- loadRepo(None)(repositoryOwnerName, repositoryName)
+                resp <- repoAndId.fold(
+                    NotFound(
+                        views.html.errors.repositoryNotFound()(
+                            csrf = csrf,
+                            title = None,
+                            None
+                        )(
+                            repositoryOwnerName,
+                            repositoryName
+                        )
+                    )
+                )(_ => doShowRepositoryOverview(csrf)(None)(repositoryOwnerName, repositoryName))
             } yield resp
     }
 
@@ -1728,8 +1783,21 @@
                 repositoryName
             ) /: "files" /: filePath as user =>
             for {
-                csrf <- Sync[F].delay(ar.req.getCsrfToken)
-                resp <- doShowRepositoryFiles(csrf)(user.some)(repositoryOwnerName, repositoryName)(filePath)
+                csrf      <- Sync[F].delay(ar.req.getCsrfToken)
+                language  <- Sync[F].delay(user.language.getOrElse(LanguageCode("en")))
+                repoAndId <- loadRepo(user.some)(repositoryOwnerName, repositoryName)
+                resp <- repoAndId.fold(
+                    NotFound(
+                        views.html.errors.repositoryNotFound(lang = language)(
+                            csrf = csrf,
+                            title = None,
+                            user.some
+                        )(
+                            repositoryOwnerName,
+                            repositoryName
+                        )
+                    )
+                )(_ => doShowRepositoryFiles(csrf)(user.some)(repositoryOwnerName, repositoryName)(filePath))
             } yield resp
     }
 
@@ -1738,8 +1806,20 @@
                 repositoryName
             ) /: "files" /: filePath =>
             for {
-                csrf <- Sync[F].delay(req.getCsrfToken)
-                resp <- doShowRepositoryFiles(csrf)(None)(repositoryOwnerName, repositoryName)(filePath)
+                csrf      <- Sync[F].delay(req.getCsrfToken)
+                repoAndId <- loadRepo(None)(repositoryOwnerName, repositoryName)
+                resp <- repoAndId.fold(
+                    NotFound(
+                        views.html.errors.repositoryNotFound()(
+                            csrf = csrf,
+                            title = None,
+                            None
+                        )(
+                            repositoryOwnerName,
+                            repositoryName
+                        )
+                    )
+                )(_ => doShowRepositoryFiles(csrf)(None)(repositoryOwnerName, repositoryName)(filePath))
             } yield resp
     }
 
@@ -1749,10 +1829,20 @@
             ) / "history" :? HistoryFromQueryParameter(fromCount) as user =>
             for {
                 csrf      <- Sync[F].delay(ar.req.getCsrfToken)
+                language  <- Sync[F].delay(user.language.getOrElse(LanguageCode("en")))
                 repoAndId <- loadRepo(user.some)(repositoryOwnerName, repositoryName)
-                resp <- repoAndId.fold(NotFound())(_ =>
-                    doShowRepositoryHistory(csrf)(user.some)(repositoryOwnerName, repositoryName)(fromCount)
-                )
+                resp <- repoAndId.fold(
+                    NotFound(
+                        views.html.errors.repositoryNotFound(lang = language)(
+                            csrf = csrf,
+                            title = None,
+                            user.some
+                        )(
+                            repositoryOwnerName,
+                            repositoryName
+                        )
+                    )
+                )(_ => doShowRepositoryHistory(csrf)(user.some)(repositoryOwnerName, repositoryName)(fromCount))
             } yield resp
     }
 
@@ -1763,9 +1853,18 @@
             for {
                 csrf      <- Sync[F].delay(req.getCsrfToken)
                 repoAndId <- loadRepo(None)(repositoryOwnerName, repositoryName)
-                resp <- repoAndId.fold(NotFound())(_ =>
-                    doShowRepositoryHistory(csrf)(None)(repositoryOwnerName, repositoryName)(fromCount)
-                )
+                resp <- repoAndId.fold(
+                    NotFound(
+                        views.html.errors.repositoryNotFound()(
+                            csrf = csrf,
+                            title = None,
+                            None
+                        )(
+                            repositoryOwnerName,
+                            repositoryName
+                        )
+                    )
+                )(_ => doShowRepositoryHistory(csrf)(None)(repositoryOwnerName, repositoryName)(fromCount))
             } yield resp
     }
 
@@ -1785,10 +1884,20 @@
             ) / "patch" / DarcsHashPathParameter(hash) as user =>
             for {
                 csrf      <- Sync[F].delay(ar.req.getCsrfToken)
+                language  <- Sync[F].delay(user.language.getOrElse(LanguageCode("en")))
                 repoAndId <- loadRepo(user.some)(repositoryOwnerName, repositoryName)
-                resp <- repoAndId.fold(NotFound())(_ =>
-                    doShowRepositoryPatchDetails(csrf)(user.some)(repositoryOwnerName, repositoryName)(hash)
-                )
+                resp <- repoAndId.fold(
+                    NotFound(
+                        views.html.errors.repositoryNotFound(lang = language)(
+                            csrf = csrf,
+                            title = None,
+                            user.some
+                        )(
+                            repositoryOwnerName,
+                            repositoryName
+                        )
+                    )
+                )(_ => doShowRepositoryPatchDetails(csrf)(user.some)(repositoryOwnerName, repositoryName)(hash))
             } yield resp
     }
 
@@ -1797,11 +1906,23 @@
                 repositoryName
             ) / "patch" / DarcsHashPathParameter(hash) =>
             for {
-                csrf      <- Sync[F].delay(req.getCsrfToken)
-                repoAndId <- loadRepo(None)(repositoryOwnerName, repositoryName)
-                resp <- repoAndId.fold(NotFound())(_ =>
-                    doShowRepositoryPatchDetails(csrf)(None)(repositoryOwnerName, repositoryName)(hash)
-                )
+                csrf <- Sync[F].delay(req.getCsrfToken)
+                repoAndId <- loadRepo(None)(
+                    repositoryOwnerName,
+                    repositoryName
+                )
+                resp <- repoAndId.fold(
+                    NotFound(
+                        views.html.errors.repositoryNotFound()(
+                            csrf = csrf,
+                            title = None,
+                            None
+                        )(
+                            repositoryOwnerName,
+                            repositoryName
+                        )
+                    )
+                )(_ => doShowRepositoryPatchDetails(csrf)(None)(repositoryOwnerName, repositoryName)(hash))
             } yield resp
     }
 
@@ -1811,10 +1932,20 @@
             ) / "stats" as user =>
             for {
                 csrf      <- Sync[F].delay(ar.req.getCsrfToken)
+                language  <- Sync[F].delay(user.language.getOrElse(LanguageCode("en")))
                 repoAndId <- loadRepo(user.some)(repositoryOwnerName, repositoryName)
-                resp <- repoAndId.fold(NotFound())(_ =>
-                    doShowRepositoryStatistics(csrf)(user.some)(repositoryOwnerName, repositoryName)
-                )
+                resp <- repoAndId.fold(
+                    NotFound(
+                        views.html.errors.repositoryNotFound(lang = language)(
+                            csrf = csrf,
+                            title = None,
+                            user.some
+                        )(
+                            repositoryOwnerName,
+                            repositoryName
+                        )
+                    )
+                )(_ => doShowRepositoryStatistics(csrf)(user.some)(repositoryOwnerName, repositoryName))
             } yield resp
     }
 
@@ -1823,11 +1954,25 @@
                 repositoryName
             ) / "stats" =>
             for {
-                csrf      <- Sync[F].delay(req.getCsrfToken)
-                repoAndId <- loadRepo(None)(repositoryOwnerName, repositoryName)
-                resp <- repoAndId.fold(NotFound())(_ =>
+                csrf <- Sync[F].delay(req.getCsrfToken)
+                repoAndId <- loadRepo(None)(
+                    repositoryOwnerName,
+                    repositoryName
+                )
+                resp <- repoAndId.fold(
+                    NotFound(
+                        views.html.errors.repositoryNotFound()(
+                            csrf = csrf,
+                            title = None,
+                            None
+                        )(
+                            repositoryOwnerName,
+                            repositoryName
+                        )
+                    )
+                )(_ =>
                     doShowRepositoryStatistics(csrf)(None)(repositoryOwnerName, repositoryName)
-                )
+                ) // TODO: Move repo check -> NotFound to middleware!
             } yield resp
     }
 
diff -rN -u old-smederee/modules/hub/src/main/twirl/de/smederee/hub/views/errors/repositoryNotFound.scala.html new-smederee/modules/hub/src/main/twirl/de/smederee/hub/views/errors/repositoryNotFound.scala.html
--- old-smederee/modules/hub/src/main/twirl/de/smederee/hub/views/errors/repositoryNotFound.scala.html	1970-01-01 00:00:00.000000000 +0000
+++ new-smederee/modules/hub/src/main/twirl/de/smederee/hub/views/errors/repositoryNotFound.scala.html	2024-11-21 17:54:04.913315736 +0000
@@ -0,0 +1,31 @@
+@import de.smederee.hub.*
+@import de.smederee.hub.views.html.*
+
+@(
+  baseUri: Uri = Uri(path = Uri.Path.Root),
+  lang: LanguageCode = LanguageCode("en")
+)(
+  csrf: Option[CsrfToken] = None,
+  title: Option[String] = None,
+  user: Option[Account]
+)(
+  repositoryOwner: Username,
+  repositoryName: VcsRepositoryName,
+)
+@main(baseUri, lang)()(csrf, title = Option(Messages("errors.repository.not-found.title")(using lang.toLocale)), user) {
+@defining(lang.toLocale) { implicit locale =>
+  <div class="content">
+    <div class="pure-g">
+      <div class="pure-u-1-1 pure-u-md-1-1">
+        <div class="l-box">
+          <p class="alert alert-error">
+            <span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true"></span>
+            <span class="sr-only">@Messages("errors.repository.not-found.title"):</span>
+            @Messages("errors.repository.not-found.message", repositoryName.toString, repositoryOwner.toString)
+          </p>
+        </div>
+      </div>
+    </div>
+  </div>
+}
+}