-
Notifications
You must be signed in to change notification settings - Fork 196
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
graph: add appRoleAssignments and minimal application resource (#5318)
* bump libregraph-go lib Signed-off-by: Jörn Friedrich Dreyer <[email protected]> * add appRoleAssignment stubs Signed-off-by: Jörn Friedrich Dreyer <[email protected]> * add get application stub Signed-off-by: Jörn Friedrich Dreyer <[email protected]> * fetch appRoles for application from settings service Signed-off-by: Jörn Friedrich Dreyer <[email protected]> * initial list appRoleAssignments implementation Signed-off-by: Jörn Friedrich Dreyer <[email protected]> * initial create appRoleAssignment implementation, extract assignmentToAppRoleAssignment, configurable app id and displayname Signed-off-by: Jörn Friedrich Dreyer <[email protected]> * initial delete appRoleAssignment implementation, changed error handling and logging Signed-off-by: Jörn Friedrich Dreyer <[email protected]> * initial expand appRoleAssignment on users Signed-off-by: Jörn Friedrich Dreyer <[email protected]> * test user expand appRoleAssignment Signed-off-by: Jörn Friedrich Dreyer <[email protected]> * test appRoleAssignment Signed-off-by: Jörn Friedrich Dreyer <[email protected]> * fix education test by actually using the mocked roleManager Signed-off-by: Jörn Friedrich Dreyer <[email protected]> * test getapplication Signed-off-by: Jörn Friedrich Dreyer <[email protected]> * list assignments Signed-off-by: Jörn Friedrich Dreyer <[email protected]> * use common not exists error handling Signed-off-by: Jörn Friedrich Dreyer <[email protected]> * default to just 'ownCloud Infinite Scale' as application name Signed-off-by: Jörn Friedrich Dreyer <[email protected]> * fix store_test Signed-off-by: Jörn Friedrich Dreyer <[email protected]> * roll application uuid on init Signed-off-by: Jörn Friedrich Dreyer <[email protected]> * fix tests Signed-off-by: Jörn Friedrich Dreyer <[email protected]> * extract method Signed-off-by: Jörn Friedrich Dreyer <[email protected]> * Apply suggestions from code review Co-authored-by: Michael Barz <[email protected]> Signed-off-by: Jörn Friedrich Dreyer <[email protected]> Co-authored-by: Michael Barz <[email protected]>
- Loading branch information
Showing
29 changed files
with
1,085 additions
and
115 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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."` | ||
DisplayName string `yaml:"displayname" env:"GRAPH_APPLICATION_DISPLAYNAME" desc:"The oCIS application name"` | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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")) | ||
}) | ||
}) | ||
|
||
}) |
Oops, something went wrong.