Merge pull request #299 from tulliobotti64/16277-filter_user_by_organization
gateway: add api to get authenticated user organizations
This commit is contained in:
commit
a1997490e7
|
@ -57,6 +57,18 @@ func (h *ActionHandler) GetUser(ctx context.Context, userRef string) (*cstypes.U
|
||||||
return user, nil
|
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 {
|
type GetUsersRequest struct {
|
||||||
Start string
|
Start string
|
||||||
Limit int
|
Limit int
|
||||||
|
|
|
@ -23,6 +23,7 @@ import (
|
||||||
|
|
||||||
"agola.io/agola/internal/services/gateway/action"
|
"agola.io/agola/internal/services/gateway/action"
|
||||||
"agola.io/agola/internal/util"
|
"agola.io/agola/internal/util"
|
||||||
|
csapitypes "agola.io/agola/services/configstore/api/types"
|
||||||
cstypes "agola.io/agola/services/configstore/types"
|
cstypes "agola.io/agola/services/configstore/types"
|
||||||
gwapitypes "agola.io/agola/services/gateway/api/types"
|
gwapitypes "agola.io/agola/services/gateway/api/types"
|
||||||
|
|
||||||
|
@ -590,3 +591,47 @@ func (h *UserCreateRunHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)
|
||||||
h.log.Errorf("err: %+v", err)
|
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
|
||||||
|
}
|
||||||
|
|
|
@ -187,6 +187,7 @@ func (g *Gateway) Run(ctx context.Context) error {
|
||||||
createUserHandler := api.NewCreateUserHandler(logger, g.ah)
|
createUserHandler := api.NewCreateUserHandler(logger, g.ah)
|
||||||
deleteUserHandler := api.NewDeleteUserHandler(logger, g.ah)
|
deleteUserHandler := api.NewDeleteUserHandler(logger, g.ah)
|
||||||
userCreateRunHandler := api.NewUserCreateRunHandler(logger, g.ah)
|
userCreateRunHandler := api.NewUserCreateRunHandler(logger, g.ah)
|
||||||
|
userOrgsHandler := api.NewUserOrgsHandler(logger, g.ah)
|
||||||
|
|
||||||
createUserLAHandler := api.NewCreateUserLAHandler(logger, g.ah)
|
createUserLAHandler := api.NewCreateUserLAHandler(logger, g.ah)
|
||||||
deleteUserLAHandler := api.NewDeleteUserLAHandler(logger, g.ah)
|
deleteUserLAHandler := api.NewDeleteUserLAHandler(logger, g.ah)
|
||||||
|
@ -283,6 +284,7 @@ func (g *Gateway) Run(ctx context.Context) error {
|
||||||
apirouter.Handle("/users", authForcedHandler(createUserHandler)).Methods("POST")
|
apirouter.Handle("/users", authForcedHandler(createUserHandler)).Methods("POST")
|
||||||
apirouter.Handle("/users/{userref}", authForcedHandler(deleteUserHandler)).Methods("DELETE")
|
apirouter.Handle("/users/{userref}", authForcedHandler(deleteUserHandler)).Methods("DELETE")
|
||||||
apirouter.Handle("/user/createrun", authForcedHandler(userCreateRunHandler)).Methods("POST")
|
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", authForcedHandler(createUserLAHandler)).Methods("POST")
|
||||||
apirouter.Handle("/users/{userref}/linkedaccounts/{laid}", authForcedHandler(deleteUserLAHandler)).Methods("DELETE")
|
apirouter.Handle("/users/{userref}/linkedaccounts/{laid}", authForcedHandler(deleteUserLAHandler)).Methods("DELETE")
|
||||||
|
|
|
@ -106,3 +106,8 @@ type UserCreateRunRequest struct {
|
||||||
PullRequestRefRegexes []string `json:"pull_request_ref_regexes,omitempty"`
|
PullRequestRefRegexes []string `json:"pull_request_ref_regexes,omitempty"`
|
||||||
Variables map[string]string `json:"variables,omitempty"`
|
Variables map[string]string `json:"variables,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type UserOrgsResponse struct {
|
||||||
|
Organization *OrgResponse
|
||||||
|
Role MemberRole
|
||||||
|
}
|
||||||
|
|
|
@ -60,7 +60,6 @@ func (c *Client) doRequest(ctx context.Context, method, path string, query url.V
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
u.RawQuery = query.Encode()
|
u.RawQuery = query.Encode()
|
||||||
|
|
||||||
req, err := http.NewRequest(method, u.String(), ibody)
|
req, err := http.NewRequest(method, u.String(), ibody)
|
||||||
req = req.WithContext(ctx)
|
req = req.WithContext(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -611,3 +610,9 @@ func (c *Client) GetVersion(ctx context.Context) (*gwapitypes.VersionResponse, *
|
||||||
resp, err := c.getParsedResponse(ctx, "GET", "/version", nil, jsonContent, nil, &res)
|
resp, err := c.getParsedResponse(ctx, "GET", "/version", nil, jsonContent, nil, &res)
|
||||||
return res, resp, err
|
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
|
||||||
|
}
|
||||||
|
|
|
@ -42,6 +42,7 @@ import (
|
||||||
rstypes "agola.io/agola/services/runservice/types"
|
rstypes "agola.io/agola/services/runservice/types"
|
||||||
|
|
||||||
"code.gitea.io/sdk/gitea"
|
"code.gitea.io/sdk/gitea"
|
||||||
|
"github.com/google/go-cmp/cmp"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
"go.uber.org/zap/zaptest"
|
"go.uber.org/zap/zaptest"
|
||||||
errors "golang.org/x/xerrors"
|
errors "golang.org/x/xerrors"
|
||||||
|
@ -1935,3 +1936,67 @@ 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)
|
||||||
|
}
|
||||||
|
|
||||||
|
expectedOrgs := []*gwapitypes.UserOrgsResponse{
|
||||||
|
{
|
||||||
|
Organization: &gwapitypes.OrgResponse{ID: org01.ID, Name: "org01", Visibility: gwapitypes.VisibilityPublic},
|
||||||
|
Role: gwapitypes.MemberRoleMember,
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
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 (-want +got):\n%s", diff)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue