// Login authenticates the session and returns the // remote user details. func (g *Github) Login(res http.ResponseWriter, req *http.Request) (*model.User, bool, error) { var config = &oauth2.Config{ ClientId: g.Client, ClientSecret: g.Secret, Scope: DefaultScope, AuthURL: fmt.Sprintf("%s/login/oauth/authorize", g.URL), TokenURL: fmt.Sprintf("%s/login/oauth/access_token", g.URL), RedirectURL: fmt.Sprintf("%s/authorize", httputil.GetURL(req)), } // get the OAuth code var code = req.FormValue("code") if len(code) == 0 { var random = GetRandom() http.Redirect(res, req, config.AuthCodeURL(random), http.StatusSeeOther) return nil, false, nil } var trans = &oauth2.Transport{ Config: config, } if g.SkipVerify { trans.Transport = &http.Transport{ Proxy: http.ProxyFromEnvironment, TLSClientConfig: &tls.Config{ InsecureSkipVerify: true, }, } } var token, err = trans.Exchange(code) if err != nil { return nil, false, fmt.Errorf("Error exchanging token. %s", err) } var client = NewClient(g.API, token.AccessToken, g.SkipVerify) var useremail, errr = GetUserEmail(client) if errr != nil { return nil, false, fmt.Errorf("Error retrieving user or verified email. %s", errr) } if len(g.Orgs) > 0 { allowedOrg, err := UserBelongsToOrg(client, g.Orgs) if err != nil { return nil, false, fmt.Errorf("Could not check org membership. %s", err) } if !allowedOrg { return nil, false, fmt.Errorf("User does not belong to correct org. Must belong to %v", g.Orgs) } } user := model.User{} user.Login = *useremail.Login user.Email = *useremail.Email user.Token = token.AccessToken user.Avatar = *useremail.AvatarURL return &user, g.Open, nil }
func ShowRepoBadges(c *gin.Context) { user := session.User(c) repo := session.Repo(c) c.HTML(200, "repo_badge.html", gin.H{ "User": user, "Repo": repo, "Link": httputil.GetURL(c.Request), }) }
func DeleteRepo(c *gin.Context) { remote := remote.FromContext(c) repo := session.Repo(c) user := session.User(c) err := store.DeleteRepo(c, repo) if err != nil { c.AbortWithError(http.StatusInternalServerError, err) return } remote.Deactivate(user, repo, httputil.GetURL(c.Request)) c.Writer.WriteHeader(http.StatusOK) }
// Login authenticates the session and returns the // remote user details. func (g *Gitlab) Login(res http.ResponseWriter, req *http.Request) (*model.User, bool, error) { var config = &oauth2.Config{ ClientId: g.Client, ClientSecret: g.Secret, Scope: DefaultScope, AuthURL: fmt.Sprintf("%s/oauth/authorize", g.URL), TokenURL: fmt.Sprintf("%s/oauth/token", g.URL), RedirectURL: fmt.Sprintf("%s/authorize", httputil.GetURL(req)), } trans_ := &http.Transport{ Proxy: http.ProxyFromEnvironment, TLSClientConfig: &tls.Config{InsecureSkipVerify: g.SkipVerify}, } // get the OAuth code var code = req.FormValue("code") if len(code) == 0 { http.Redirect(res, req, config.AuthCodeURL("drone"), http.StatusSeeOther) return nil, false, nil } var trans = &oauth2.Transport{Config: config, Transport: trans_} var token_, err = trans.Exchange(code) if err != nil { return nil, false, fmt.Errorf("Error exchanging token. %s", err) } client := NewClient(g.URL, token_.AccessToken, g.SkipVerify) login, err := client.CurrentUser() if err != nil { return nil, false, err } user := &model.User{} user.Login = login.Username user.Email = login.Email user.Token = token_.AccessToken user.Secret = token_.RefreshToken if strings.HasPrefix(login.AvatarUrl, "http") { user.Avatar = login.AvatarUrl } else { user.Avatar = g.URL + "/" + login.AvatarUrl } return user, true, nil }
// ¯\_(ツ)_/¯ func (g *Gitlab) Oauth2Transport(r *http.Request) *oauth2.Transport { return &oauth2.Transport{ Config: &oauth2.Config{ ClientId: g.Client, ClientSecret: g.Secret, Scope: DefaultScope, AuthURL: fmt.Sprintf("%s/oauth/authorize", g.URL), TokenURL: fmt.Sprintf("%s/oauth/token", g.URL), RedirectURL: fmt.Sprintf("%s/authorize", httputil.GetURL(r)), //settings.Server.Scheme, settings.Server.Hostname), }, Transport: &http.Transport{ Proxy: http.ProxyFromEnvironment, TLSClientConfig: &tls.Config{InsecureSkipVerify: g.SkipVerify}, }, } }
func ShowRepoConf(c *gin.Context) { user := session.User(c) repo := session.Repo(c) key, _ := store.GetKey(c, repo) token, _ := token.New( token.CsrfToken, user.Login, ).Sign(user.Hash) c.HTML(200, "repo_config.html", gin.H{ "User": user, "Repo": repo, "Key": key, "Csrf": token, "Link": httputil.GetURL(c.Request), }) }
func PostRepo(c *gin.Context) { remote := remote.FromContext(c) user := session.User(c) owner := c.Param("owner") name := c.Param("name") paramActivate := c.Request.FormValue("activate") 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 := remote.Perm(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 = crypto.Rand() // 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 } // generate an RSA key and add to the repo key, err := crypto.GeneratePrivateKey() if err != nil { c.String(500, err.Error()) return } keys := new(model.Key) keys.Public = string(crypto.MarshalPublicKey(&key.PublicKey)) keys.Private = string(crypto.MarshalPrivateKey(key)) var activate bool activate, err = strconv.ParseBool(paramActivate) if err != nil { activate = true } if activate { 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, keys, 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 } keys.RepoID = r.ID err = store.CreateKey(c, keys) if err != nil { c.String(500, err.Error()) return } c.JSON(200, r) }
func PostBuild(c *gin.Context) { remote_ := remote.FromContext(c) repo := session.Repo(c) fork := c.DefaultQuery("fork", "false") num, err := strconv.Atoi(c.Param("number")) if err != nil { c.AbortWithError(http.StatusBadRequest, err) return } user, err := store.GetUser(c, repo.UserID) if err != nil { log.Errorf("failure to find repo owner %s. %s", repo.FullName, err) c.AbortWithError(500, err) return } build, err := store.GetBuildNumber(c, repo, num) if err != nil { log.Errorf("failure to get build %d. %s", num, err) c.AbortWithError(404, err) return } // if the remote has a refresh token, the current access token // may be stale. Therefore, we should refresh prior to dispatching // the job. if refresher, ok := remote_.(remote.Refresher); ok { ok, _ := refresher.Refresh(user) if ok { store.UpdateUser(c, user) } } // fetch the .drone.yml file from the database raw, sec, err := remote_.Script(user, repo, build) if err != nil { log.Errorf("failure to get .drone.yml for %s. %s", repo.FullName, err) c.AbortWithError(404, err) return } key, _ := store.GetKey(c, repo) netrc, err := remote_.Netrc(user, repo) if err != nil { log.Errorf("failure to generate netrc for %s. %s", repo.FullName, err) c.AbortWithError(500, err) return } jobs, err := store.GetJobList(c, build) if err != nil { log.Errorf("failure to get build %d jobs. %s", build.Number, err) c.AbortWithError(404, err) return } // must not restart a running build if build.Status == model.StatusPending || build.Status == model.StatusRunning { c.String(409, "Cannot re-start a started build") return } // forking the build creates a duplicate of the build // and then executes. This retains prior build history. if forkit, _ := strconv.ParseBool(fork); forkit { build.ID = 0 build.Number = 0 for _, job := range jobs { job.ID = 0 job.NodeID = 0 } err := store.CreateBuild(c, build, jobs...) if err != nil { c.String(500, err.Error()) return } } // todo move this to database tier // and wrap inside a transaction build.Status = model.StatusPending build.Started = 0 build.Finished = 0 build.Enqueued = time.Now().UTC().Unix() for _, job := range jobs { job.Status = model.StatusPending job.Started = 0 job.Finished = 0 job.ExitCode = 0 job.NodeID = 0 job.Enqueued = build.Enqueued store.UpdateJob(c, job) } err = store.UpdateBuild(c, build) if err != nil { c.AbortWithStatus(500) return } c.JSON(202, build) // get the previous build so taht we can send // on status change notifications last, _ := store.GetBuildLastBefore(c, repo, build.Branch, build.ID) engine_ := context.Engine(c) go engine_.Schedule(c.Copy(), &engine.Task{ User: user, Repo: repo, Build: build, BuildPrev: last, Jobs: jobs, Keys: key, Netrc: netrc, Config: string(raw), Secret: string(sec), System: &model.System{ Link: httputil.GetURL(c.Request), Plugins: strings.Split(os.Getenv("PLUGIN_FILTER"), " "), Globals: strings.Split(os.Getenv("PLUGIN_PARAMS"), " "), }, }) }
// Login authenticates the session and returns the // remote user details. func (bb *Bitbucket) Login(res http.ResponseWriter, req *http.Request) (*model.User, bool, error) { config := &oauth2.Config{ ClientID: bb.Client, ClientSecret: bb.Secret, Endpoint: bitbucket.Endpoint, RedirectURL: fmt.Sprintf("%s/authorize", httputil.GetURL(req)), } // get the OAuth code var code = req.FormValue("code") if len(code) == 0 { http.Redirect(res, req, config.AuthCodeURL("drone"), http.StatusSeeOther) return nil, false, nil } var token, err = config.Exchange(oauth2.NoContext, code) if err != nil { return nil, false, fmt.Errorf("Error exchanging token. %s", err) } client := NewClient(config.Client(oauth2.NoContext, token)) curr, err := client.FindCurrent() if err != nil { return nil, false, err } // convers the current bitbucket user to the // common drone user structure. user := model.User{} user.Login = curr.Login user.Token = token.AccessToken user.Secret = token.RefreshToken user.Expiry = token.Expiry.UTC().Unix() user.Avatar = curr.Links.Avatar.Href // gets the primary, confirmed email from bitbucket emails, err := client.ListEmail() if err != nil { return nil, false, err } for _, email := range emails.Values { if email.IsPrimary && email.IsConfirmed { user.Email = email.Email break } } // if the installation is restricted to a subset // of organizations, get the orgs and verify the // user is a member. if len(bb.Orgs) != 0 { resp, err := client.ListTeams(&ListTeamOpts{Page: 1, PageLen: 100, Role: "member"}) if err != nil { return nil, false, err } var member bool for _, team := range resp.Values { for _, team_ := range bb.Orgs { if team.Login == team_ { member = true break } } } if !member { return nil, false, fmt.Errorf("User does not belong to correct org. Must belong to %v", bb.Orgs) } } return &user, bb.Open, nil }