From 2a95c93f0dbecd7be2f8684cd9e2f01c113c260e Mon Sep 17 00:00:00 2001 From: Simone Gotti Date: Tue, 11 Jun 2019 15:09:41 +0200 Subject: [PATCH] gateway: add UserCreateRun api and related action add an api to execute a user direct run. This method will replace the current custom webhook way to create a direct run. --- internal/gitsources/agolagit/agolagit.go | 11 ++++-- internal/services/gateway/action/user.go | 49 ++++++++++++++++++++++++ internal/services/gateway/api/client.go | 9 +++++ internal/services/gateway/api/user.go | 37 ++++++++++++++++++ internal/services/gateway/gateway.go | 2 + 5 files changed, 104 insertions(+), 4 deletions(-) diff --git a/internal/gitsources/agolagit/agolagit.go b/internal/gitsources/agolagit/agolagit.go index bc01e52..130cb2f 100644 --- a/internal/gitsources/agolagit/agolagit.go +++ b/internal/gitsources/agolagit/agolagit.go @@ -30,7 +30,10 @@ import ( errors "golang.org/x/xerrors" ) -var jsonContent = http.Header{"content-type": []string{"application/json"}} +var ( + branchRefPrefix = "refs/heads/" + tagRefPrefix = "refs/tags/" +) // Client represents a Gogs API client. type Client struct { @@ -131,7 +134,7 @@ func (c *Client) GetRepoInfo(repopath string) (*gitsource.RepoInfo, error) { } func (c *Client) GetFile(repopath, commit, file string) ([]byte, error) { - resp, err := c.getResponse("GET", fmt.Sprintf("%s/raw/%s/%s", repopath, commit, file), nil, nil, nil) + resp, err := c.getResponse("GET", fmt.Sprintf("%s.git/raw/%s/%s", repopath, commit, file), nil, nil, nil) if err != nil { return nil, err } @@ -182,11 +185,11 @@ func (c *Client) GetCommit(repopath, commitSHA string) (*gitsource.Commit, error } func (c *Client) BranchRef(branch string) string { - return "" + return branchRefPrefix + branch } func (c *Client) TagRef(tag string) string { - return "" + return tagRefPrefix + tag } func (c *Client) PullRequestRef(prID string) string { diff --git a/internal/services/gateway/action/user.go b/internal/services/gateway/action/user.go index 95fedcf..29d2293 100644 --- a/internal/services/gateway/action/user.go +++ b/internal/services/gateway/action/user.go @@ -17,9 +17,12 @@ package action import ( "context" "encoding/json" + "fmt" + "strings" "time" gitsource "github.com/sorintlab/agola/internal/gitsources" + "github.com/sorintlab/agola/internal/gitsources/agolagit" "github.com/sorintlab/agola/internal/services/common" csapi "github.com/sorintlab/agola/internal/services/configstore/api" "github.com/sorintlab/agola/internal/services/types" @@ -814,3 +817,49 @@ func (h *ActionHandler) DeleteUserToken(ctx context.Context, userRef, tokenName } return nil } + +func (h *ActionHandler) UserCreateRun(ctx context.Context, repoPath, branch, commitSHA, message string) error { + curUserID := h.CurrentUserID(ctx) + + user, resp, err := h.configstoreClient.GetUser(ctx, curUserID) + if err != nil { + return errors.Errorf("failed to get user %q: %w", curUserID, ErrFromRemote(resp, err)) + } + + // Verify that the repo is owned by the user + repoParts := strings.Split(repoPath, "/") + if len(repoParts) != 2 { + return util.NewErrBadRequest(errors.Errorf("wrong repo path: %q", repoPath)) + } + if repoParts[0] != user.ID { + return util.NewErrUnauthorized(errors.Errorf("repo %q not owned", repoPath)) + } + + gitSource := agolagit.New(h.apiExposedURL + "/repos") + cloneURL := fmt.Sprintf("%s/%s.git", h.apiExposedURL+"/repos", repoPath) + + req := &CreateRunRequest{ + RunType: types.RunTypeUser, + RefType: types.RunRefTypeBranch, + RunCreationTrigger: types.RunCreationTriggerTypeManual, + + Project: nil, + User: user, + RepoPath: repoPath, + GitSource: gitSource, + CommitSHA: commitSHA, + Message: message, + Branch: branch, + Tag: "", + PullRequestID: "", + Ref: gitSource.BranchRef(branch), + CloneURL: cloneURL, + + CommitLink: "", + BranchLink: "", + TagLink: "", + PullRequestLink: "", + } + + return h.CreateRuns(ctx, req) +} diff --git a/internal/services/gateway/api/client.go b/internal/services/gateway/api/client.go index 7a7a0a4..9098b98 100644 --- a/internal/services/gateway/api/client.go +++ b/internal/services/gateway/api/client.go @@ -282,6 +282,15 @@ func (c *Client) DeleteUser(ctx context.Context, userRef string) (*http.Response return c.getResponse(ctx, "DELETE", fmt.Sprintf("/users/%s", userRef), nil, jsonContent, nil) } +func (c *Client) UserCreateRun(ctx context.Context, req *UserCreateRunRequest) (*http.Response, error) { + reqj, err := json.Marshal(req) + if err != nil { + return nil, err + } + + return c.getResponse(ctx, "POST", "/user/createrun", nil, jsonContent, bytes.NewReader(reqj)) +} + func (c *Client) CreateUserLA(ctx context.Context, userRef string, req *CreateUserLARequest) (*CreateUserLAResponse, *http.Response, error) { reqj, err := json.Marshal(req) if err != nil { diff --git a/internal/services/gateway/api/user.go b/internal/services/gateway/api/user.go index 090c8fa..70db531 100644 --- a/internal/services/gateway/api/user.go +++ b/internal/services/gateway/api/user.go @@ -603,3 +603,40 @@ func (h *LoginUserHandler) loginUser(ctx context.Context, req *LoginUserRequest) } return resp, nil } + +type UserCreateRunRequest struct { + RepoPath string `json:"repo_path,omitempty"` + Branch string `json:"branch,omitempty"` + CommitSHA string `json:"commit_sha,omitempty"` + Message string `json:"message,omitempty"` +} + +type UserCreateRunHandler struct { + log *zap.SugaredLogger + ah *action.ActionHandler +} + +func NewUserCreateRunHandler(logger *zap.Logger, ah *action.ActionHandler) *UserCreateRunHandler { + return &UserCreateRunHandler{log: logger.Sugar(), ah: ah} +} + +func (h *UserCreateRunHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { + ctx := r.Context() + + var req UserCreateRunRequest + d := json.NewDecoder(r.Body) + if err := d.Decode(&req); err != nil { + httpError(w, util.NewErrBadRequest(err)) + return + } + + err := h.ah.UserCreateRun(ctx, req.RepoPath, req.Branch, req.CommitSHA, req.Message) + if httpError(w, err) { + h.log.Errorf("err: %+v", err) + return + } + + if err := httpResponse(w, http.StatusCreated, nil); err != nil { + h.log.Errorf("err: %+v", err) + } +} diff --git a/internal/services/gateway/gateway.go b/internal/services/gateway/gateway.go index f559cc9..c6d81d1 100644 --- a/internal/services/gateway/gateway.go +++ b/internal/services/gateway/gateway.go @@ -177,6 +177,7 @@ func (g *Gateway) Run(ctx context.Context) error { usersHandler := api.NewUsersHandler(logger, g.ah) createUserHandler := api.NewCreateUserHandler(logger, g.ah) deleteUserHandler := api.NewDeleteUserHandler(logger, g.ah) + userCreateRunHandler := api.NewUserCreateRunHandler(logger, g.ah) createUserLAHandler := api.NewCreateUserLAHandler(logger, g.ah) deleteUserLAHandler := api.NewDeleteUserLAHandler(logger, g.ah) @@ -264,6 +265,7 @@ func (g *Gateway) Run(ctx context.Context) error { apirouter.Handle("/users", authForcedHandler(usersHandler)).Methods("GET") apirouter.Handle("/users", authForcedHandler(createUserHandler)).Methods("POST") apirouter.Handle("/users/{userref}", authForcedHandler(deleteUserHandler)).Methods("DELETE") + apirouter.Handle("/user/createrun", authForcedHandler(userCreateRunHandler)).Methods("POST") apirouter.Handle("/users/{userref}/linkedaccounts", authForcedHandler(createUserLAHandler)).Methods("POST") apirouter.Handle("/users/{userref}/linkedaccounts/{laid}", authForcedHandler(deleteUserLAHandler)).Methods("DELETE")