Skip to content

Commit

Permalink
gateway: add api to get authenticated user organizations
Browse files Browse the repository at this point in the history
  • Loading branch information
tulliosorintdev committed Feb 18, 2022
1 parent d0d219c commit 7dfc12c
Show file tree
Hide file tree
Showing 6 changed files with 138 additions and 1 deletion.
12 changes: 12 additions & 0 deletions internal/services/gateway/action/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,18 @@ func (h *ActionHandler) GetUser(ctx context.Context, userRef string) (*cstypes.U
return user, nil
}

func (h *ActionHandler) GetUserOrgs(ctx context.Context, userRef string) ([]*csapitypes.UserOrgsResponse, error) {
if !h.IsUserLogged(ctx) {
return nil, errors.Errorf("user not logged in")
}

orgs, resp, err := h.configstoreClient.GetUserOrgs(ctx, userRef)
if err != nil {
return nil, ErrFromRemote(resp, err)
}
return orgs, nil
}

type GetUsersRequest struct {
Start string
Limit int
Expand Down
45 changes: 45 additions & 0 deletions internal/services/gateway/api/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (

"agola.io/agola/internal/services/gateway/action"
"agola.io/agola/internal/util"
csapitypes "agola.io/agola/services/configstore/api/types"
cstypes "agola.io/agola/services/configstore/types"
gwapitypes "agola.io/agola/services/gateway/api/types"

Expand Down Expand Up @@ -590,3 +591,47 @@ func (h *UserCreateRunHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)
h.log.Errorf("err: %+v", err)
}
}

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

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

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

userIDVal := ctx.Value("userid")
if userIDVal == nil {
httpError(w, util.NewErrBadRequest(errors.Errorf("user not authenticated")))
return
}
userRef := userIDVal.(string)

userOrgs, err := h.ah.GetUserOrgs(ctx, userRef)
if httpError(w, err) {
h.log.Errorf("err: %+v", err)
return
}

res := make([]*gwapitypes.UserOrgsResponse, len(userOrgs))
for i, userOrg := range userOrgs {
res[i] = createUserOrgsResponse(userOrg)
}

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

func createUserOrgsResponse(o *csapitypes.UserOrgsResponse) *gwapitypes.UserOrgsResponse {
userOrgs := &gwapitypes.UserOrgsResponse{
Organization: createOrgResponse(o.Organization),
Role: gwapitypes.MemberRole(o.Role),
}

return userOrgs
}
2 changes: 2 additions & 0 deletions internal/services/gateway/gateway.go
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,7 @@ func (g *Gateway) Run(ctx context.Context) error {
createUserHandler := api.NewCreateUserHandler(logger, g.ah)
deleteUserHandler := api.NewDeleteUserHandler(logger, g.ah)
userCreateRunHandler := api.NewUserCreateRunHandler(logger, g.ah)
userOrgsHandler := api.NewUserOrgsHandler(logger, g.ah)

createUserLAHandler := api.NewCreateUserLAHandler(logger, g.ah)
deleteUserLAHandler := api.NewDeleteUserLAHandler(logger, g.ah)
Expand Down Expand Up @@ -283,6 +284,7 @@ func (g *Gateway) Run(ctx context.Context) error {
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("/user/orgs", authForcedHandler(userOrgsHandler)).Methods("GET")

apirouter.Handle("/users/{userref}/linkedaccounts", authForcedHandler(createUserLAHandler)).Methods("POST")
apirouter.Handle("/users/{userref}/linkedaccounts/{laid}", authForcedHandler(deleteUserLAHandler)).Methods("DELETE")
Expand Down
5 changes: 5 additions & 0 deletions services/gateway/api/types/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,3 +106,8 @@ type UserCreateRunRequest struct {
PullRequestRefRegexes []string `json:"pull_request_ref_regexes,omitempty"`
Variables map[string]string `json:"variables,omitempty"`
}

type UserOrgsResponse struct {
Organization *OrgResponse
Role MemberRole
}
7 changes: 6 additions & 1 deletion services/gateway/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,6 @@ func (c *Client) doRequest(ctx context.Context, method, path string, query url.V
return nil, err
}
u.RawQuery = query.Encode()

req, err := http.NewRequest(method, u.String(), ibody)
req = req.WithContext(ctx)
if err != nil {
Expand Down Expand Up @@ -611,3 +610,9 @@ func (c *Client) GetVersion(ctx context.Context) (*gwapitypes.VersionResponse, *
resp, err := c.getParsedResponse(ctx, "GET", "/version", nil, jsonContent, nil, &res)
return res, resp, err
}

func (c *Client) GetUserOrgs(ctx context.Context) ([]*gwapitypes.UserOrgsResponse, *http.Response, error) {
userOrgs := []*gwapitypes.UserOrgsResponse{}
resp, err := c.getParsedResponse(ctx, "GET", "/user/orgs", nil, jsonContent, nil, &userOrgs)
return userOrgs, resp, err
}
68 changes: 68 additions & 0 deletions tests/setup_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ import (
gwapitypes "agola.io/agola/services/gateway/api/types"
gwclient "agola.io/agola/services/gateway/client"
rstypes "agola.io/agola/services/runservice/types"
"github.com/google/go-cmp/cmp"

"code.gitea.io/sdk/gitea"
"go.uber.org/zap"
Expand Down Expand Up @@ -1935,3 +1936,70 @@ def main(ctx):
}
}
}

func TestUserOrgs(t *testing.T) {
dir, err := ioutil.TempDir("", "agola")
if err != nil {
t.Fatalf("unexpected err: %v", err)
}
defer os.RemoveAll(dir)

ctx, cancel := context.WithCancel(context.Background())
defer cancel()

tetcd, tgitea, c := setup(ctx, t, dir)
defer shutdownGitea(tgitea)
defer shutdownEtcd(tetcd)

gwClient := gwclient.NewClient(c.Gateway.APIExposedURL, "admintoken")

org01, _, err := gwClient.CreateOrg(ctx, &gwapitypes.CreateOrgRequest{Name: "org01", Visibility: gwapitypes.VisibilityPublic})
if err != nil {
t.Fatalf("unexpected err: %v", err)
}
org02, _, err := gwClient.CreateOrg(ctx, &gwapitypes.CreateOrgRequest{Name: "org02", Visibility: gwapitypes.VisibilityPrivate})
if err != nil {
t.Fatalf("unexpected err: %v", err)
}
_, _, err = gwClient.CreateOrg(ctx, &gwapitypes.CreateOrgRequest{Name: "org03", Visibility: gwapitypes.VisibilityPublic})
if err != nil {
t.Fatalf("unexpected err: %v", err)
}

_, token := createLinkedAccount(ctx, t, tgitea, c)

_, _, err = gwClient.AddOrgMember(ctx, "org01", giteaUser01, gwapitypes.MemberRoleMember)
if err != nil {
t.Fatalf("unexpected err: %v", err)
}
_, _, err = gwClient.AddOrgMember(ctx, "org02", giteaUser01, gwapitypes.MemberRoleOwner)
if err != nil {
t.Fatalf("unexpected err: %v", err)
}

gwClientNew := gwclient.NewClient(c.Gateway.APIExposedURL, token)

orgs, _, err := gwClientNew.GetUserOrgs(ctx)
if err != nil {
t.Fatalf("unexpected err: %v", err)
}
if len(orgs) != 2 {
t.Fatalf("expected len 2 got: %d", len(orgs))
}

expectedOrgs := make([]*gwapitypes.UserOrgsResponse, 2)

expectedOrgs[0] = &gwapitypes.UserOrgsResponse{
Organization: &gwapitypes.OrgResponse{
ID: org01.ID, Name: "org01", Visibility: gwapitypes.VisibilityPublic},
Role: gwapitypes.MemberRoleMember}

expectedOrgs[1] = &gwapitypes.UserOrgsResponse{
Organization: &gwapitypes.OrgResponse{
ID: org02.ID, Name: "org02", Visibility: gwapitypes.VisibilityPrivate},
Role: gwapitypes.MemberRoleOwner}

if diff := cmp.Diff(expectedOrgs, orgs); diff != "" {
t.Fatalf("user orgs mismatch (-expected +got):\n%s", diff)
}
}

0 comments on commit 7dfc12c

Please sign in to comment.