~jan0sch/smederee
Showing details for patch b580cc42faa2d739e1aecf525c6af72b26e78a2b.
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 2025-01-31 22:36:58.684300233 +0000 +++ new-smederee/modules/hub/src/main/scala/de/smederee/hub/VcsRepositoryRoutes.scala 2025-01-31 22:36:58.684300233 +0000 @@ -71,6 +71,43 @@ // The base URI for our site which that be passed into some templates which create links themselfes. private val baseUri = linkConfig.createFullUri(Uri()) + /** Load the repository metadata with the given owner and name from the database and return it and its primary key id + * if the repository exists and is readable by the given user account. + * + * @param currentUser + * The user account that is requesting access to the repository or None for a guest user. + * @param repositoryOwnerName + * The name of the account that owns the repository. + * @param repositoryName + * The name of the repository. A repository name must start with a letter or number and must contain only + * alphanumeric ASCII characters as well as minus or underscore signs. It must be between 2 and 64 characters long. + * @return + * An option to a tuple holding the [[VcsRepository]] and its primary key id. + */ + private def loadRepo( + currentUser: Option[Account] + )(repositoryOwnerName: Username, repositoryName: VcsRepositoryName): F[Option[(VcsRepository, Long)]] = + for { + owner <- vcsMetadataRepo.findVcsRepositoryOwner(repositoryOwnerName) + loadedRepo <- owner match { + case None => Sync[F].pure(None) + case Some(owner) => + ( + vcsMetadataRepo.findVcsRepository(owner, repositoryName), + vcsMetadataRepo.findVcsRepositoryId(owner, repositoryName) + ).mapN { + case (Some(repo), Some(repoId)) => (repo, repoId).some + case _ => None + } + } + // TODO Replace with whatever we implement as proper permission model. ;-) + repoAndId = currentUser match { + case None => loadedRepo.filter(tuple => tuple._1.isPrivate === false) + case Some(user) => + loadedRepo.filter(tuple => tuple._1.isPrivate === false || tuple._1.owner === user.toVcsRepositoryOwner) + } + } yield repoAndId + /** Delete the given directory recursively. It is checked if the given directory is a direct sub directory of the * owner's directory under `repositoriesDirectory` and only if this is the case is the directory removed. * @@ -150,17 +187,8 @@ user: Option[Account] )(repositoryOwnerName: Username, repositoryName: VcsRepositoryName): F[Option[fs2.io.file.Path]] = for { - owner <- vcsMetadataRepo.findVcsRepositoryOwner(repositoryOwnerName) - loadedRepo <- owner match { - case None => Sync[F].pure(None) - case Some(owner) => vcsMetadataRepo.findVcsRepository(owner, repositoryName) - } - // TODO Replace with whatever we implement as proper permission model. ;-) - repo = user match { - case None => loadedRepo.filter(r => r.isPrivate === false) - case Some(user) => - loadedRepo.filter(r => r.isPrivate === false || r.owner === user.toVcsRepositoryOwner) - } + repoAndId <- loadRepo(user)(repositoryOwnerName, repositoryName) + repo = repoAndId.map(_._1) repositoryOwnerDirectory <- Sync[F].delay( os.Path( Paths.get( @@ -276,17 +304,8 @@ csrf: Option[CsrfToken] )(user: Option[Account])(repositoryOwnerName: Username, repositoryName: VcsRepositoryName): F[Response[F]] = for { - owner <- vcsMetadataRepo.findVcsRepositoryOwner(repositoryOwnerName) - loadedRepo <- owner match { - case None => Sync[F].pure(None) - case Some(owner) => vcsMetadataRepo.findVcsRepository(owner, repositoryName) - } - // TODO Replace with whatever we implement as proper permission model. ;-) - repo = user match { - case None => loadedRepo.filter(r => r.isPrivate === false) - case Some(user) => - loadedRepo.filter(r => r.isPrivate === false || r.owner === user.toVcsRepositoryOwner) - } + repoAndId <- loadRepo(user)(repositoryOwnerName, repositoryName) + repo = repoAndId.map(_._1) actionBaseUri <- Sync[F].delay( linkConfig.createFullUri( Uri(path = @@ -372,17 +391,8 @@ user: Option[Account] )(repositoryOwnerName: Username, repositoryName: VcsRepositoryName)(filePath: Uri.Path): F[Response[F]] = for { - owner <- vcsMetadataRepo.findVcsRepositoryOwner(repositoryOwnerName) - loadedRepo <- owner match { - case None => Sync[F].pure(None) - case Some(owner) => vcsMetadataRepo.findVcsRepository(owner, repositoryName) - } - // TODO Replace with whatever we implement as proper permission model. ;-) - repo = user match { - case None => loadedRepo.filter(r => r.isPrivate === false) - case Some(user) => - loadedRepo.filter(r => r.isPrivate === false || r.owner === user.toVcsRepositoryOwner) - } + repoAndId <- loadRepo(user)(repositoryOwnerName, repositoryName) + repo = repoAndId.map(_._1) requestedFilePath <- repo .traverse(_ => Sync[F].delay( @@ -491,17 +501,8 @@ fromEntry: Option[Int] ): F[Response[F]] = for { - owner <- vcsMetadataRepo.findVcsRepositoryOwner(repositoryOwnerName) - loadedRepo <- owner match { - case None => Sync[F].pure(None) - case Some(owner) => vcsMetadataRepo.findVcsRepository(owner, repositoryName) - } - // TODO Replace with whatever we implement as proper permission model. ;-) - repo = user match { - case None => loadedRepo.filter(r => r.isPrivate === false) - case Some(user) => - loadedRepo.filter(r => r.isPrivate === false || r.owner === user.toVcsRepositoryOwner) - } + repoAndId <- loadRepo(user)(repositoryOwnerName, repositoryName) + repo = repoAndId.map(_._1) directory <- Sync[F].delay( os.Path( Paths.get( @@ -589,17 +590,8 @@ user: Option[Account] )(repositoryOwnerName: Username, repositoryName: VcsRepositoryName)(hash: DarcsHash): F[Response[F]] = for { - owner <- vcsMetadataRepo.findVcsRepositoryOwner(repositoryOwnerName) - loadedRepo <- owner match { - case None => Sync[F].pure(None) - case Some(owner) => vcsMetadataRepo.findVcsRepository(owner, repositoryName) - } - // TODO Replace with whatever we implement as proper permission model. ;-) - repo = user match { - case None => loadedRepo.filter(r => r.isPrivate === false) - case Some(user) => - loadedRepo.filter(r => r.isPrivate === false || r.owner === user.toVcsRepositoryOwner) - } + repoAndId <- loadRepo(user)(repositoryOwnerName, repositoryName) + repo = repoAndId.map(_._1) directory <- Sync[F].delay( os.Path( Paths.get( @@ -771,14 +763,9 @@ ) / "fork" as user => ar.req.decodeStrict[F, UrlForm] { urlForm => for { - csrf <- Sync[F].delay(ar.req.getCsrfToken) - owner <- vcsMetadataRepo.findVcsRepositoryOwner(repositoryOwnerName) - loadedSourceRepo <- owner match { - case None => Sync[F].pure(None) - case Some(owner) => vcsMetadataRepo.findVcsRepository(owner, repositoryName) - } - // TODO Replace with whatever we implement as proper permission model. ;-) - sourceRepository = loadedSourceRepo.filter(r => r.isPrivate === false) + csrf <- Sync[F].delay(ar.req.getCsrfToken) + repoAndId <- loadRepo(user.some)(repositoryOwnerName, repositoryName) + sourceRepository = repoAndId.map(_._1) // Check if a repository with that name already exists for the user. loadedTargetRepo <- vcsMetadataRepo.findVcsRepository(user.toVcsRepositoryOwner, repositoryName) // If no repo exists we copy and adjust the source one, otherwise we return `None`. @@ -983,13 +970,8 @@ "An unvalidated account is not allowed to edit a repository!" ) // FIXME Proper error handling! ) - owner <- vcsMetadataRepo.findVcsRepositoryOwner(repositoryOwnerName) - loadedRepo <- owner match { - case None => Sync[F].pure(None) - case Some(owner) => vcsMetadataRepo.findVcsRepository(owner, repositoryName) - } - // TODO Replace with whatever we implement as proper permission model. ;-) - repo = loadedRepo.filter(r => r.isPrivate === false || r.owner === user.toVcsRepositoryOwner) + repoAndId <- loadRepo(user.some)(repositoryOwnerName, repositoryName) + repo = repoAndId.map(_._1) resp <- repo match { case None => NotFound() case Some(repo) => @@ -1096,14 +1078,9 @@ repositoryName ) / "delete" as user => for { - csrf <- Sync[F].delay(ar.req.getCsrfToken) - owner <- vcsMetadataRepo.findVcsRepositoryOwner(repositoryOwnerName) - loadedRepo <- owner match { - case None => Sync[F].pure(None) - case Some(owner) => vcsMetadataRepo.findVcsRepository(owner, repositoryName) - } - // TODO Replace with whatever we implement as proper permission model. ;-) - repo = loadedRepo.filter(r => r.isPrivate === false || r.owner === user.toVcsRepositoryOwner) + csrf <- Sync[F].delay(ar.req.getCsrfToken) + repoAndId <- loadRepo(user.some)(repositoryOwnerName, repositoryName) + repo = repoAndId.map(_._1) deleteAction <- Sync[F].delay( linkConfig.createFullUri( Uri(path = @@ -1151,14 +1128,9 @@ repositoryName ) / "edit" as user => for { - csrf <- Sync[F].delay(ar.req.getCsrfToken) - owner <- vcsMetadataRepo.findVcsRepositoryOwner(repositoryOwnerName) - loadedRepo <- owner match { - case None => Sync[F].pure(None) - case Some(owner) => vcsMetadataRepo.findVcsRepository(owner, repositoryName) - } - // TODO Replace with whatever we implement as proper permission model. ;-) - repo = loadedRepo.filter(r => r.isPrivate === false || r.owner === user.toVcsRepositoryOwner) + csrf <- Sync[F].delay(ar.req.getCsrfToken) + repoAndId <- loadRepo(user.some)(repositoryOwnerName, repositoryName) + repo = repoAndId.map(_._1) editAction <- Sync[F].delay( linkConfig.createFullUri( Uri(path =