Exemple #1
0
// 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,
		)
	}
}
Exemple #2
0
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)
}
Exemple #3
0
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()
	}
}