Skip to content

Commit

Permalink
Gateway: add api user/runs and user/projectgroups
Browse files Browse the repository at this point in the history
  • Loading branch information
alessandro-sorint committed Feb 24, 2022
1 parent a199749 commit 2b7f321
Show file tree
Hide file tree
Showing 5 changed files with 500 additions and 0 deletions.
163 changes: 163 additions & 0 deletions internal/services/gateway/action/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import (
"agola.io/agola/internal/util"
csapitypes "agola.io/agola/services/configstore/api/types"
cstypes "agola.io/agola/services/configstore/types"
rsapitypes "agola.io/agola/services/runservice/api/types"

"github.com/golang-jwt/jwt/v4"
errors "golang.org/x/xerrors"
Expand Down Expand Up @@ -959,3 +960,165 @@ func (h *ActionHandler) UserCreateRun(ctx context.Context, req *UserCreateRunReq

return h.CreateRuns(ctx, creq)
}

type GetUserRunsRequest struct {
PhaseFilter []string
ResultFilter []string
LastRun bool
ChangeGroups []string
StartRunID string
Limit int
Asc bool
}

func (h *ActionHandler) GetUserRuns(ctx context.Context, req *GetUserRunsRequest) (*rsapitypes.GetRunsResponse, error) {
projectgroups, err := h.GetUserProjectgroups(ctx, &GetUserProjectgroups{
UserType: true,
OrgType: true,
OnlyOwner: false,
})
if err != nil {
return nil, errors.Errorf("failed to get projectgroups: %v", err)
}

groups := make([]string, 0)
for _, pg := range projectgroups {
if pg.Parent.Type == cstypes.ConfigTypeUser {
groups = append(groups, "/user/"+pg.Parent.ID)
}

projects, err := h.GetProjectGroupProjects(ctx, pg.Path)
if err != nil {
return nil, errors.Errorf("failed to get projectgroupprojects %s: %v", pg.Path, err)
}

for _, p := range projects {
groups = append(groups, "/project/"+p.ID)
}

}

runsResp, resp, err := h.runserviceClient.GetRuns(ctx, req.PhaseFilter, req.ResultFilter, groups, req.LastRun, req.ChangeGroups, req.StartRunID, req.Limit, req.Asc)
if err != nil {
return nil, ErrFromRemote(resp, err)
}

return runsResp, nil
}

type GetUserProjectgroups struct {
UserType bool
OrgType bool
OnlyOwner bool
}

func (h *ActionHandler) GetUserProjectgroups(ctx context.Context, req *GetUserProjectgroups) ([]*csapitypes.ProjectGroup, error) {
userID := ""
usernames := make([]string, 0)

if h.IsUserAdmin(ctx) {
if req.UserType {
users, err := h.GetUsers(ctx, &GetUsersRequest{})
if err != nil {
return nil, err
}

for _, user := range users {
usernames = append(usernames, user.Name)
}
}
} else {
userIDVal := ctx.Value("userid")
userID = userIDVal.(string)

user, err := h.GetUser(ctx, userID)
if err != nil {
return nil, err
}

usernames = append(usernames, user.Name)
}

projectgroups := make([]*csapitypes.ProjectGroup, 0)

if req.UserType {
for _, u := range usernames {
projectgroup, err := h.GetProjectGroup(ctx, "user/"+u)
if err != nil {
return nil, err
}
projectgroups = append(projectgroups, projectgroup)

userProjectgroups, err := h.getUserProjectgroupsSubgroups(ctx, projectgroup.Path)
if err != nil {
return nil, err
}

projectgroups = append(projectgroups, userProjectgroups...)
}
}

if req.OrgType {
var userOrgs []*csapitypes.UserOrgsResponse
var err error
if h.IsUserAdmin(ctx) {
orgsResponse, err := h.GetOrgs(ctx, &GetOrgsRequest{})
if err != nil {
return nil, err
}

userOrgs = make([]*csapitypes.UserOrgsResponse, len(orgsResponse))
for _, o := range orgsResponse {
userOrgs = append(userOrgs, &csapitypes.UserOrgsResponse{Organization: o, Role: cstypes.MemberRoleOwner})
}
} else {
userOrgs, err = h.GetUserOrgs(ctx, userID)
if err != nil {
return nil, err
}
}

for _, uo := range userOrgs {
if req.OnlyOwner && uo.Role != cstypes.MemberRoleOwner {
continue
}

projectgroup, err := h.GetProjectGroup(ctx, "org/"+uo.Organization.Name)
if err != nil {
return nil, err
}
projectgroups = append(projectgroups, projectgroup)

orgProjectgroups, err := h.getUserProjectgroupsSubgroups(ctx, projectgroup.Path)
if err != nil {
return nil, err
}

projectgroups = append(projectgroups, orgProjectgroups...)
}
}

return projectgroups, nil
}

func (h *ActionHandler) getUserProjectgroupsSubgroups(ctx context.Context, projectgroupRef string) ([]*csapitypes.ProjectGroup, error) {
projectgroups := make([]*csapitypes.ProjectGroup, 0)

subgroups, err := h.GetProjectGroupSubgroups(ctx, projectgroupRef)
if err != nil {
return nil, err
}

for _, subgroup := range subgroups {
projectgroups = append(projectgroups, subgroup)

p, err := h.getUserProjectgroupsSubgroups(ctx, subgroup.Path)
if err != nil {
return nil, err
}

projectgroups = append(projectgroups, p...)
}

return projectgroups, nil
}
107 changes: 107 additions & 0 deletions internal/services/gateway/api/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -635,3 +635,110 @@ func createUserOrgsResponse(o *csapitypes.UserOrgsResponse) *gwapitypes.UserOrgs

return userOrgs
}

type UserRunsHandler struct {
log *zap.SugaredLogger
ah *action.ActionHandler
}

func NewUserRunsHandler(logger *zap.Logger, ah *action.ActionHandler) *UserRunsHandler {
return &UserRunsHandler{log: logger.Sugar(), ah: ah}
}

func (h *UserRunsHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()

q := r.URL.Query()

phaseFilter := q["phase"]
resultFilter := q["result"]
changeGroups := q["changegroup"]
_, lastRun := q["lastrun"]

limitS := q.Get("limit")
limit := DefaultRunsLimit
if limitS != "" {
var err error
limit, err = strconv.Atoi(limitS)
if err != nil {
httpError(w, util.NewErrBadRequest(errors.Errorf("cannot parse limit: %w", err)))
return
}
}
if limit < 0 {
httpError(w, util.NewErrBadRequest(errors.Errorf("limit must be greater or equal than 0")))
return
}
if limit > MaxRunsLimit {
limit = MaxRunsLimit
}
asc := false
if _, ok := q["asc"]; ok {
asc = true
}

start := q.Get("start")

runs := make([]*gwapitypes.RunsResponse, 0)
areq := &action.GetUserRunsRequest{
PhaseFilter: phaseFilter,
ResultFilter: resultFilter,
LastRun: lastRun,
ChangeGroups: changeGroups,
StartRunID: start,
Limit: limit,
Asc: asc,
}
runsResp, err := h.ah.GetUserRuns(ctx, areq)
if httpError(w, err) {
h.log.Errorf("err: %+v", err)
return
}

for _, r := range runsResp.Runs {
runs = append(runs, createRunsResponse(r))
}

if err := httpResponse(w, http.StatusOK, runs); err != nil {
h.log.Errorf("err: %+v", err)
}
}

type UserProjectGroupsHandler struct {
log *zap.SugaredLogger
ah *action.ActionHandler
}

func NewUserProjectGroupsHandler(logger *zap.Logger, ah *action.ActionHandler) *UserProjectGroupsHandler {
return &UserProjectGroupsHandler{log: logger.Sugar(), ah: ah}
}

func (h *UserProjectGroupsHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()

q := r.URL.Query()

_, usertype := q["usertype"]
_, orgtype := q["orgtype"]
_, onlyowner := q["onlyowner"]

req := &action.GetUserProjectgroups{
UserType: usertype,
OrgType: orgtype,
OnlyOwner: onlyowner,
}
csprojectgroups, err := h.ah.GetUserProjectgroups(ctx, req)
if httpError(w, err) {
h.log.Errorf("err: %+v", err)
return
}

subgroups := make([]*gwapitypes.ProjectGroupResponse, len(csprojectgroups))
for i, g := range csprojectgroups {
subgroups[i] = createProjectGroupResponse(g)
}

if err := httpResponse(w, http.StatusOK, subgroups); err != nil {
h.log.Errorf("err: %+v", err)
}
}
4 changes: 4 additions & 0 deletions internal/services/gateway/gateway.go
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,8 @@ func (g *Gateway) Run(ctx context.Context) error {
deleteUserHandler := api.NewDeleteUserHandler(logger, g.ah)
userCreateRunHandler := api.NewUserCreateRunHandler(logger, g.ah)
userOrgsHandler := api.NewUserOrgsHandler(logger, g.ah)
userRunsHandler := api.NewUserRunsHandler(logger, g.ah)
userProjectGroupsHandler := api.NewUserProjectGroupsHandler(logger, g.ah)

createUserLAHandler := api.NewCreateUserLAHandler(logger, g.ah)
deleteUserLAHandler := api.NewDeleteUserLAHandler(logger, g.ah)
Expand Down Expand Up @@ -285,6 +287,8 @@ func (g *Gateway) Run(ctx context.Context) error {
apirouter.Handle("/users/{userref}", authForcedHandler(deleteUserHandler)).Methods("DELETE")
apirouter.Handle("/user/createrun", authForcedHandler(userCreateRunHandler)).Methods("POST")
apirouter.Handle("/user/orgs", authForcedHandler(userOrgsHandler)).Methods("GET")
apirouter.Handle("/user/runs", authForcedHandler(userRunsHandler)).Methods("GET")
apirouter.Handle("/user/projectgroups", authForcedHandler(userProjectGroupsHandler)).Methods("GET")

apirouter.Handle("/users/{userref}/linkedaccounts", authForcedHandler(createUserLAHandler)).Methods("POST")
apirouter.Handle("/users/{userref}/linkedaccounts/{laid}", authForcedHandler(deleteUserLAHandler)).Methods("DELETE")
Expand Down
44 changes: 44 additions & 0 deletions services/gateway/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -616,3 +616,47 @@ func (c *Client) GetUserOrgs(ctx context.Context) ([]*gwapitypes.UserOrgsRespons
resp, err := c.getParsedResponse(ctx, "GET", "/user/orgs", nil, jsonContent, nil, &userOrgs)
return userOrgs, resp, err
}

func (c *Client) GetUserProjectGroups(ctx context.Context, userType, orgType, onlyOwner bool) ([]*gwapitypes.ProjectGroupResponse, *http.Response, error) {
q := url.Values{}

if userType {
q.Add("usertype", "")
}
if orgType {
q.Add("orgtype", "")
}
if onlyOwner {
q.Add("onlyowner", "")
}

projectsGroup := []*gwapitypes.ProjectGroupResponse{}
resp, err := c.getParsedResponse(ctx, "GET", "/user/projectgroups", q, jsonContent, nil, &projectsGroup)
return projectsGroup, resp, err
}

func (c *Client) GetUserRuns(ctx context.Context, phaseFilter, resultFilter, runGroups []string, start string, limit int, asc bool) ([]*gwapitypes.RunsResponse, *http.Response, error) {
q := url.Values{}
for _, phase := range phaseFilter {
q.Add("phase", phase)
}
for _, result := range resultFilter {
q.Add("result", result)
}
for _, runGroup := range runGroups {
q.Add("rungroup", runGroup)
}
if start != "" {
q.Add("start", start)
}
if limit > 0 {
q.Add("limit", strconv.Itoa(limit))
}
if asc {
q.Add("asc", "")
}

getRunsResponse := []*gwapitypes.RunsResponse{}
resp, err := c.getParsedResponse(ctx, "GET", "/user/runs", q, jsonContent, nil, &getRunsResponse)
return getRunsResponse, resp, err
}

0 comments on commit 2b7f321

Please sign in to comment.