-
Notifications
You must be signed in to change notification settings - Fork 187
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
graph: add appRoleAssignments and minimal application resource #5318
Changes from all commits
05165ca
9be87a6
26958ad
6b223fb
122b430
71459bc
203a9cc
005e4a1
5e141cd
70e6a38
f7ce8aa
91e9c24
5b92aef
42f05fa
bcca738
72bffa2
9cf3ef4
3b81f43
41c3199
887ad05
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
package config | ||
|
||
// Application defines the available graph application configuration. | ||
type Application struct { | ||
ID string `yaml:"id" env:"GRAPH_APPLICATION_ID" desc:"The ocis application id shown in the graph. All app roles are tied to this."` | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @butonic could you add a changelog item here? Just pulled the latest oCIS docker image and had it fail with an error until I added the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. AKA "I went to the changelog first, didn't find anything obvious and ended up here in your PR" There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. sorry, yes ... I hope you got at least a meaningful error message? Unfortunately, rolling a random application id also is also suboptimal because we would have to write it to the yaml config, which might be readonly ... I'm thinking about a solution for that. maybe store it in the metadata instead of the yaml file ... |
||
DisplayName string `yaml:"displayname" env:"GRAPH_APPLICATION_DISPLAYNAME" desc:"The oCIS application name"` | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
package svc | ||
|
||
import ( | ||
"fmt" | ||
"net/http" | ||
|
||
"github.com/go-chi/chi/v5" | ||
"github.com/go-chi/render" | ||
libregraph "github.com/owncloud/libre-graph-api-go" | ||
settingssvc "github.com/owncloud/ocis/v2/protogen/gen/ocis/services/settings/v0" | ||
"github.com/owncloud/ocis/v2/services/graph/pkg/service/v0/errorcode" | ||
) | ||
|
||
// ListApplications implements the Service interface. | ||
func (g Graph) ListApplications(w http.ResponseWriter, r *http.Request) { | ||
logger := g.logger.SubloggerWithRequestID(r.Context()) | ||
logger.Info().Interface("query", r.URL.Query()).Msg("calling list applications") | ||
|
||
lbr, err := g.roleService.ListRoles(r.Context(), &settingssvc.ListBundlesRequest{}) | ||
if err != nil { | ||
logger.Error().Err(err).Msg("could not list roles: transport error") | ||
errorcode.GeneralException.Render(w, r, http.StatusInternalServerError, err.Error()) | ||
return | ||
} | ||
|
||
roles := make([]libregraph.AppRole, 0, len(lbr.Bundles)) | ||
for _, bundle := range lbr.GetBundles() { | ||
role := libregraph.NewAppRole(bundle.GetId()) | ||
role.SetDisplayName(bundle.GetDisplayName()) | ||
roles = append(roles, *role) | ||
} | ||
|
||
application := libregraph.NewApplication(g.config.Application.ID) | ||
application.SetDisplayName(g.config.Application.DisplayName) | ||
application.SetAppRoles(roles) | ||
|
||
applications := []*libregraph.Application{ | ||
application, | ||
} | ||
|
||
render.Status(r, http.StatusOK) | ||
render.JSON(w, r, &ListResponse{Value: applications}) | ||
} | ||
|
||
// GetApplication implements the Service interface. | ||
func (g Graph) GetApplication(w http.ResponseWriter, r *http.Request) { | ||
logger := g.logger.SubloggerWithRequestID(r.Context()) | ||
logger.Info().Interface("query", r.URL.Query()).Msg("calling get application") | ||
|
||
applicationID := chi.URLParam(r, "applicationID") | ||
|
||
if applicationID != g.config.Application.ID { | ||
errorcode.ItemNotFound.Render(w, r, http.StatusNotFound, fmt.Sprintf("requested id %s does not match expected application id %v", applicationID, g.config.Application.ID)) | ||
return | ||
} | ||
|
||
lbr, err := g.roleService.ListRoles(r.Context(), &settingssvc.ListBundlesRequest{}) | ||
if err != nil { | ||
logger.Error().Err(err).Msg("could not list roles: transport error") | ||
errorcode.GeneralException.Render(w, r, http.StatusInternalServerError, err.Error()) | ||
return | ||
} | ||
|
||
roles := make([]libregraph.AppRole, 0, len(lbr.Bundles)) | ||
for _, bundle := range lbr.GetBundles() { | ||
role := libregraph.NewAppRole(bundle.GetId()) | ||
role.SetDisplayName(bundle.GetDisplayName()) | ||
roles = append(roles, *role) | ||
} | ||
|
||
application := libregraph.NewApplication(applicationID) | ||
application.SetDisplayName(g.config.Application.DisplayName) | ||
application.SetAppRoles(roles) | ||
|
||
render.Status(r, http.StatusOK) | ||
render.JSON(w, r, application) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,135 @@ | ||
package svc_test | ||
|
||
import ( | ||
"context" | ||
"encoding/json" | ||
"io" | ||
"net/http" | ||
"net/http/httptest" | ||
|
||
"github.com/go-chi/chi/v5" | ||
. "github.com/onsi/ginkgo/v2" | ||
. "github.com/onsi/gomega" | ||
libregraph "github.com/owncloud/libre-graph-api-go" | ||
"github.com/stretchr/testify/mock" | ||
|
||
ogrpc "github.com/owncloud/ocis/v2/ocis-pkg/service/grpc" | ||
"github.com/owncloud/ocis/v2/ocis-pkg/shared" | ||
settingsmsg "github.com/owncloud/ocis/v2/protogen/gen/ocis/messages/settings/v0" | ||
settings "github.com/owncloud/ocis/v2/protogen/gen/ocis/services/settings/v0" | ||
"github.com/owncloud/ocis/v2/services/graph/mocks" | ||
"github.com/owncloud/ocis/v2/services/graph/pkg/config" | ||
"github.com/owncloud/ocis/v2/services/graph/pkg/config/defaults" | ||
identitymocks "github.com/owncloud/ocis/v2/services/graph/pkg/identity/mocks" | ||
service "github.com/owncloud/ocis/v2/services/graph/pkg/service/v0" | ||
) | ||
|
||
type applicationList struct { | ||
Value []*libregraph.Application | ||
} | ||
|
||
var _ = Describe("Applications", func() { | ||
var ( | ||
svc service.Service | ||
ctx context.Context | ||
cfg *config.Config | ||
gatewayClient *mocks.GatewayClient | ||
eventsPublisher mocks.Publisher | ||
roleService *mocks.RoleService | ||
identityBackend *identitymocks.Backend | ||
|
||
rr *httptest.ResponseRecorder | ||
) | ||
|
||
BeforeEach(func() { | ||
eventsPublisher.On("Publish", mock.Anything, mock.Anything, mock.Anything).Return(nil) | ||
|
||
identityBackend = &identitymocks.Backend{} | ||
roleService = &mocks.RoleService{} | ||
gatewayClient = &mocks.GatewayClient{} | ||
|
||
rr = httptest.NewRecorder() | ||
ctx = context.Background() | ||
|
||
cfg = defaults.FullDefaultConfig() | ||
cfg.Identity.LDAP.CACert = "" // skip the startup checks, we don't use LDAP at all in this tests | ||
cfg.TokenManager.JWTSecret = "loremipsum" | ||
cfg.Commons = &shared.Commons{} | ||
cfg.GRPCClientTLS = &shared.GRPCClientTLS{} | ||
cfg.Application.ID = "some-application-ID" | ||
|
||
_ = ogrpc.Configure(ogrpc.GetClientOptions(cfg.GRPCClientTLS)...) | ||
svc, _ = service.NewService( | ||
service.Config(cfg), | ||
service.WithGatewayClient(gatewayClient), | ||
service.EventsPublisher(&eventsPublisher), | ||
service.WithIdentityBackend(identityBackend), | ||
service.WithRoleService(roleService), | ||
) | ||
}) | ||
|
||
Describe("ListApplications", func() { | ||
It("lists the configured application with appRoles", func() { | ||
roleService.On("ListRoles", mock.Anything, mock.Anything, mock.Anything).Return(&settings.ListBundlesResponse{ | ||
Bundles: []*settingsmsg.Bundle{ | ||
{ | ||
Id: "some-appRole-ID", | ||
Type: settingsmsg.Bundle_TYPE_ROLE, | ||
DisplayName: "A human readable name for a role", | ||
}, | ||
}, | ||
}, nil) | ||
|
||
r := httptest.NewRequest(http.MethodGet, "/graph/v1.0/applications", nil) | ||
svc.ListApplications(rr, r) | ||
|
||
Expect(rr.Code).To(Equal(http.StatusOK)) | ||
|
||
data, err := io.ReadAll(rr.Body) | ||
Expect(err).ToNot(HaveOccurred()) | ||
|
||
responseList := applicationList{} | ||
err = json.Unmarshal(data, &responseList) | ||
Expect(err).ToNot(HaveOccurred()) | ||
Expect(len(responseList.Value)).To(Equal(1)) | ||
Expect(responseList.Value[0].Id).To(Equal(cfg.Application.ID)) | ||
Expect(len(responseList.Value[0].GetAppRoles())).To(Equal(1)) | ||
Expect(responseList.Value[0].GetAppRoles()[0].GetId()).To(Equal("some-appRole-ID")) | ||
Expect(responseList.Value[0].GetAppRoles()[0].GetDisplayName()).To(Equal("A human readable name for a role")) | ||
}) | ||
}) | ||
|
||
Describe("GetApplication", func() { | ||
It("gets the application with appRoles", func() { | ||
roleService.On("ListRoles", mock.Anything, mock.Anything, mock.Anything).Return(&settings.ListBundlesResponse{ | ||
Bundles: []*settingsmsg.Bundle{ | ||
{ | ||
Id: "some-appRole-ID", | ||
Type: settingsmsg.Bundle_TYPE_ROLE, | ||
DisplayName: "A human readable name for a role", | ||
}, | ||
}, | ||
}, nil) | ||
|
||
r := httptest.NewRequest(http.MethodGet, "/graph/v1.0/applications/some-application-ID", nil) | ||
rctx := chi.NewRouteContext() | ||
rctx.URLParams.Add("applicationID", cfg.Application.ID) | ||
r = r.WithContext(context.WithValue(ctx, chi.RouteCtxKey, rctx)) | ||
svc.GetApplication(rr, r) | ||
|
||
Expect(rr.Code).To(Equal(http.StatusOK)) | ||
|
||
data, err := io.ReadAll(rr.Body) | ||
Expect(err).ToNot(HaveOccurred()) | ||
|
||
application := libregraph.Application{} | ||
err = json.Unmarshal(data, &application) | ||
Expect(err).ToNot(HaveOccurred()) | ||
Expect(application.Id).To(Equal(cfg.Application.ID)) | ||
Expect(len(application.GetAppRoles())).To(Equal(1)) | ||
Expect(application.GetAppRoles()[0].GetId()).To(Equal("some-appRole-ID")) | ||
Expect(application.GetAppRoles()[0].GetDisplayName()).To(Equal("A human readable name for a role")) | ||
}) | ||
}) | ||
|
||
}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.