// Perms is a middleware function that attempts to cache the // user's remote repository permissions (ie in GitHub) to minimize // remote calls that might be expensive, slow or rate-limited. func Perms(c *gin.Context) { var ( owner = c.Param("owner") name = c.Param("name") user, _ = c.Get("user") ) if user == nil { c.Next() return } // if the item already exists in the cache // we can continue the middleware chain and // exit afterwards. v := cache.GetPerms(c, user.(*model.User), owner, name, ) if v != nil { c.Set("perm", v) c.Next() return } // otherwise, if the item isn't cached we execute // the middleware chain and then cache the permissions // after the request is processed. c.Next() perm, ok := c.Get("perm") if ok { cache.SetPerms(c, user.(*model.User), perm.(*model.Perm), owner, name, ) } }
func PostRepo(c *gin.Context) { remote := remote.FromContext(c) user := session.User(c) owner := c.Param("owner") name := c.Param("name") if user == nil { c.AbortWithStatus(403) return } r, err := remote.Repo(user, owner, name) if err != nil { c.String(404, err.Error()) return } m, err := cache.GetPerms(c, user, owner, name) if err != nil { c.String(404, err.Error()) return } if !m.Admin { c.String(403, "Administrative access is required.") return } // error if the repository already exists _, err = store.GetRepoOwnerName(c, owner, name) if err == nil { c.String(409, "Repository already exists.") return } // set the repository owner to the // currently authenticated user. r.UserID = user.ID r.AllowPush = true r.AllowPull = true r.Timeout = 60 // 1 hour default build time r.Hash = base32.StdEncoding.EncodeToString( securecookie.GenerateRandomKey(32), ) // crates the jwt token used to verify the repository t := token.New(token.HookToken, r.FullName) sig, err := t.Sign(r.Hash) if err != nil { c.String(500, err.Error()) return } link := fmt.Sprintf( "%s/hook?access_token=%s", httputil.GetURL(c.Request), sig, ) // activate the repository before we make any // local changes to the database. err = remote.Activate(user, r, link) if err != nil { c.String(500, err.Error()) return } // persist the repository err = store.CreateRepo(c, r) if err != nil { c.String(500, err.Error()) return } c.JSON(200, r) }
func SetPerm() gin.HandlerFunc { PUBLIC_MODE := os.Getenv("PUBLIC_MODE") return func(c *gin.Context) { user := User(c) repo := Repo(c) perm := &model.Perm{} switch { // if the user is not authenticated, and the // repository is private, the user has NO permission // to view the repository. case user == nil && repo.IsPrivate == true: perm.Pull = false perm.Push = false perm.Admin = false // if the user is not authenticated, but the repository // is public, the user has pull-rights only. case user == nil && repo.IsPrivate == false: perm.Pull = true perm.Push = false perm.Admin = false case user.Admin: perm.Pull = true perm.Push = true perm.Admin = true // otherwise if the user is authenticated we should // check the remote system to get the users permissiosn. default: var err error perm, err = cache.GetPerms(c, user, repo.Owner, repo.Name) if err != nil { perm.Pull = false perm.Push = false perm.Admin = false // debug log.Errorf("Error fetching permission for %s %s", user.Login, repo.FullName) } // if we couldn't fetch permissions, but the repository // is public, we should grant the user pull access. if err != nil && repo.IsPrivate == false { perm.Pull = true } } // all build logs are visible in public mode if PUBLIC_MODE != "" { perm.Pull = true } if user != nil { log.Debugf("%s granted %+v permission to %s", user.Login, perm, repo.FullName) } else { log.Debugf("Guest granted %+v to %s", perm, repo.FullName) } c.Set("perm", perm) c.Next() } }