diff --git a/model/repo.go b/model/repo.go index 09496962..4b22cf53 100644 --- a/model/repo.go +++ b/model/repo.go @@ -1,5 +1,10 @@ package model +import ( + "strings" + "fmt" +) + type RepoLite struct { Owner string `json:"owner"` Name string `json:"name"` @@ -38,6 +43,25 @@ type Repo struct { Perm *Perm `json:"-" meddler:"-"` } +func (r *Repo) ResetVisibility() { + r.Visibility = VisibilityPublic + if r.IsPrivate { + r.Visibility = VisibilityPrivate + } +} + +// ParseRepo parses the repository owner and name from a string. +func ParseRepo(str string) (user, repo string, err error) { + var parts = strings.Split(str, "/") + if len(parts) != 2 { + err = fmt.Errorf("Error: Invalid or missing repository. eg octocat/hello-world.") + return + } + user = parts[0] + repo = parts[1] + return +} + // Update updates the repository with values from the given Repo. func (r *Repo) Update(from *Repo) { r.Avatar = from.Avatar diff --git a/router/router.go b/router/router.go index fb5bd1c1..c9a8b5fc 100644 --- a/router/router.go +++ b/router/router.go @@ -105,6 +105,7 @@ func Load(mux *httptreemux.ContextMux, middleware ...gin.HandlerFunc) http.Handl repo.DELETE("", session.MustRepoAdmin(), server.DeleteRepo) repo.POST("/chown", session.MustRepoAdmin(), server.ChownRepo) repo.POST("/repair", session.MustRepoAdmin(), server.RepairRepo) + repo.POST("/move", session.MustRepoAdmin(), server.MoveRepo) repo.POST("/builds/:number", session.MustPush, server.PostBuild) repo.DELETE("/builds/:number", session.MustAdmin(), server.ZombieKill) diff --git a/server/repo.go b/server/repo.go index 78d4c845..1edcc30c 100644 --- a/server/repo.go +++ b/server/repo.go @@ -195,7 +195,7 @@ func RepairRepo(c *gin.Context) { repo := session.Repo(c) user := session.User(c) - // crates the jwt token used to verify the repository + // creates the jwt token used to verify the repository t := token.New(token.HookToken, repo.FullName) sig, err := t.Sign(repo.Hash) if err != nil { @@ -219,3 +219,52 @@ func RepairRepo(c *gin.Context) { } c.Writer.WriteHeader(http.StatusOK) } + +func MoveRepo(c *gin.Context) { + remote := remote.FromContext(c) + repo := session.Repo(c) + user := session.User(c) + + to, exists := c.GetQuery("to") + if !exists { + err := fmt.Errorf("Missing required to query value") + c.AbortWithError(http.StatusInternalServerError, err) + return + } + + owner, name, errParse := model.ParseRepo(to) + if errParse != nil { + c.AbortWithError(http.StatusInternalServerError, errParse) + return + } + + from, err := remote.Repo(user, owner, name) + if err != nil { + c.AbortWithError(http.StatusInternalServerError, err) + return + } + if !from.Perm.Admin { + c.AbortWithStatus(http.StatusUnauthorized) + return + } + + repo.Name = from.Name + repo.Owner = from.Owner + repo.FullName = from.FullName + repo.Avatar = from.Avatar + repo.Link = from.Link + repo.Clone = from.Clone + repo.IsPrivate = from.IsPrivate + if repo.IsPrivate != from.IsPrivate { + repo.ResetVisibility() + } + + errStore := store.UpdateRepo(c, repo) + if errStore != nil { + c.AbortWithError(http.StatusInternalServerError, errStore) + return + } + + RepairRepo(c) +} +