Skip to content
This repository has been archived by the owner on Mar 11, 2021. It is now read-only.

[WIP] permissions API #2246

Open
wants to merge 81 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 51 commits
Commits
Show all changes
81 commits
Select commit Hold shift + click to select a range
b6fcaba
Eliminate some more duplicate names for deployments API refactoring
stooke Jan 26, 2018
36e590a
Merge remote-tracking branch 'upstream/master'
stooke Jan 26, 2018
58342c7
Merge remote-tracking branch 'upstream/master'
stooke Jan 29, 2018
a45161a
Merge remote-tracking branch 'upstream/master'
stooke Feb 6, 2018
dbcf947
Merge remote-tracking branch 'upstream/master'
stooke Feb 7, 2018
99d3f01
remove unused /apps API
stooke Feb 8, 2018
e45ac78
Merge remote-tracking branch 'upstream/master'
stooke Feb 8, 2018
2b06816
Merge remote-tracking branch 'upstream/master'
stooke Feb 9, 2018
94159dc
Merge remote-tracking branch 'upstream/master'
stooke Feb 22, 2018
9bb38c8
Merge remote-tracking branch 'upstream/master'
stooke Feb 23, 2018
ad3b87f
Merge remote-tracking branch 'upstream/master'
stooke Feb 27, 2018
e32a323
Merge remote-tracking branch 'upstream/master'
stooke Feb 28, 2018
1a9481d
Merge remote-tracking branch 'upstream/master'
stooke Mar 2, 2018
ff47976
Merge remote-tracking branch 'upstream/master'
stooke Mar 19, 2018
29461ed
Merge remote-tracking branch 'upstream/master'
stooke Mar 26, 2018
15ee913
Merge remote-tracking branch 'upstream/master'
stooke Apr 5, 2018
7df6871
Merge remote-tracking branch 'upstream/master'
stooke Apr 6, 2018
f9a252e
Merge remote-tracking branch 'upstream/master'
stooke Apr 9, 2018
99f3d57
Merge remote-tracking branch 'upstream/master'
stooke Apr 10, 2018
8193a2f
Merge remote-tracking branch 'upstream/master'
stooke Apr 13, 2018
7ebe5eb
Merge remote-tracking branch 'upstream/master'
stooke Apr 18, 2018
d1514f0
Merge remote-tracking branch 'upstream/master'
stooke Apr 19, 2018
d2eb5e3
Merge remote-tracking branch 'upstream/master'
stooke Apr 24, 2018
63c3ec9
Merge remote-tracking branch 'upstream/master'
stooke Apr 25, 2018
fa0d3bd
Merge remote-tracking branch 'upstream/master'
stooke Apr 27, 2018
2418c94
Merge remote-tracking branch 'upstream/master'
stooke Apr 30, 2018
7a7c9e8
Merge remote-tracking branch 'upstream/master'
stooke May 9, 2018
e4c3a6c
Merge remote-tracking branch 'upstream/master'
stooke May 28, 2018
e2b0461
Merge remote-tracking branch 'upstream/master'
stooke Jun 28, 2018
38e5982
Merge remote-tracking branch 'upstream/master'
stooke Jul 18, 2018
270268d
Merge remote-tracking branch 'upstream/master'
stooke Aug 2, 2018
58929c0
Merge remote-tracking branch 'upstream/master' into jst-perms2
stooke Aug 3, 2018
8d58119
new auth JSON API code prototype
stooke Aug 3, 2018
3d9ebdb
Merge remote-tracking branch 'upstream/master' into jst-perms2
stooke Aug 14, 2018
57dd758
Merge remote-tracking branch 'upstream/master' into jst-perms2
stooke Aug 16, 2018
d8c553e
Initial implementation of OpenShift authz checking
ebaron Jul 24, 2018
bd04f78
Remove unused interactions in delete cassettes
ebaron Jul 26, 2018
a768678
Add CanDeploy to filter deployable environments, maintain full list i…
ebaron Jul 27, 2018
5136927
Implement authz check for DeleteDeployment
ebaron Jul 27, 2018
9fd101e
Implement remaining methods, add tests for access control failure on …
ebaron Jul 31, 2018
2c42ebc
Fix URLProvider changes, add tests for CanDeploy
ebaron Aug 1, 2018
e571140
Better test error conditions
ebaron Aug 1, 2018
efe93cd
Clean up code
ebaron Aug 2, 2018
0d756c5
Add more internal environments to kubeclient tests
ebaron Aug 2, 2018
d3325c0
Improve documentation, avoid boolean parameter for getting namespace
ebaron Aug 16, 2018
2ae089a
Also check for wildcard rules
ebaron Aug 20, 2018
271c627
added ebaron deployments-check-k8s-auth branch
stooke Aug 22, 2018
34c95bb
move perms to /api/spaces
stooke Aug 29, 2018
39776d0
Merge branch 'master' into deployments-check-k8s-auth
ebaron Sep 4, 2018
23c654e
merge with upstream and ebaron
stooke Sep 4, 2018
4bfae3b
updated from ebaron
stooke Sep 4, 2018
e5dd365
Merge remote-tracking branch 'upstream/master' into jst-perms2
stooke Sep 5, 2018
afae2f4
Initial implementation of OpenShift authz checking
ebaron Jul 24, 2018
989e036
Remove unused interactions in delete cassettes
ebaron Jul 26, 2018
92d1a87
Add CanDeploy to filter deployable environments, maintain full list i…
ebaron Jul 27, 2018
9e62c5c
Implement authz check for DeleteDeployment
ebaron Jul 27, 2018
ec4bad9
Implement remaining methods, add tests for access control failure on …
ebaron Jul 31, 2018
f28fce8
Fix URLProvider changes, add tests for CanDeploy
ebaron Aug 1, 2018
b814a8a
Better test error conditions
ebaron Aug 1, 2018
adbb22c
Clean up code
ebaron Aug 2, 2018
8ea65cb
Add more internal environments to kubeclient tests
ebaron Aug 2, 2018
9d34f9f
Improve documentation, avoid boolean parameter for getting namespace
ebaron Aug 16, 2018
9b5b770
Also check for wildcard rules
ebaron Aug 20, 2018
ad29c04
Reduce size of go-vcr cassettes
ebaron Sep 7, 2018
86eaae2
working paerms - no tests
stooke Sep 10, 2018
8375f46
Merge remote-tracking branch 'ebaron/deployments-check-k8s-auth' into…
stooke Sep 10, 2018
8231adf
fixed unit tests
stooke Sep 10, 2018
d3fe4c4
Merge remote-tracking branch 'upstream/master' into jst-perms2
stooke Sep 10, 2018
c904053
get rid of some test files
stooke Sep 11, 2018
03e3aa0
Merge remote-tracking branch 'upstream/master' into jst-perms2
stooke Sep 11, 2018
ed803fa
get rid of some test files
stooke Sep 11, 2018
5f64cc5
get rid of debug code
stooke Sep 12, 2018
85236ea
small comment cleanup
stooke Sep 12, 2018
421c6bd
Merge remote-tracking branch 'upstream/master' into jst-perms2
stooke Sep 17, 2018
6e601e8
Merge remote-tracking branch 'upstream/master' into jst-perms2
stooke Sep 27, 2018
bfae026
added more deployment stats permission code
stooke Sep 28, 2018
1f459ca
Merge remote-tracking branch 'upstream/master' into jst-perms2
stooke Sep 28, 2018
cb9fdb5
Merge remote-tracking branch 'upstream/master' into jst-perms2
stooke Oct 1, 2018
3fe9177
get rid of tostring(), add (broken) test for qp=true
stooke Oct 4, 2018
a6aeb73
Merge remote-tracking branch 'upstream/master' into jst-perms2
stooke Oct 4, 2018
aa8b1b6
Merge remote-tracking branch 'upstream/master' into jst-perms2
stooke Nov 2, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions 17c1e9de-a89a-494b-91c4-819a013cb3b9
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"data":{"attributes":{"created-at":"2018-07-02T04:00:57.297291Z","description":"","name":"rgarg-osiotest1-AGILE-space-2018-07-02T05-00-57","updated-at":"2018-07-02T04:00:57.297291Z","version":0},"id":"17c1e9de-a89a-494b-91c4-819a013cb3b9","links":{"backlog":{"meta":{"totalCount":46},"self":"https://api.openshift.io/api/spaces/17c1e9de-a89a-494b-91c4-819a013cb3b9/backlog"},"filters":"https://api.openshift.io/api/filters","related":"https://api.openshift.io/api/spaces/17c1e9de-a89a-494b-91c4-819a013cb3b9","self":"https://api.openshift.io/api/spaces/17c1e9de-a89a-494b-91c4-819a013cb3b9","workitemlinktypes":"https://api.openshift.io/api/spacetemplates/f405fa41-a8bb-46db-8800-2dbe13da1418/workitemlinktypes","workitemtypes":"https://api.openshift.io/api/spacetemplates/f405fa41-a8bb-46db-8800-2dbe13da1418/workitemtypes"},"relationships":{"areas":{"links":{"related":"https://api.openshift.io/api/spaces/17c1e9de-a89a-494b-91c4-819a013cb3b9/areas"}},"backlog":{"links":{"related":"https://api.openshift.io/api/spaces/17c1e9de-a89a-494b-91c4-819a013cb3b9/backlog"},"meta":{"totalCount":46}},"codebases":{"links":{"related":"https://api.openshift.io/api/spaces/17c1e9de-a89a-494b-91c4-819a013cb3b9/codebases"}},"collaborators":{"links":{"related":"https://api.openshift.io/api/spaces/17c1e9de-a89a-494b-91c4-819a013cb3b9/collaborators"}},"filters":{"links":{"related":"https://api.openshift.io/api/filters"}},"iterations":{"links":{"related":"https://api.openshift.io/api/spaces/17c1e9de-a89a-494b-91c4-819a013cb3b9/iterations"}},"labels":{"links":{"related":"https://api.openshift.io/api/spaces/17c1e9de-a89a-494b-91c4-819a013cb3b9/labels"}},"owned-by":{"data":{"id":"02227dc6-f4fe-451b-9549-4c5b7becc5e7","type":"identities"},"links":{"related":"https://api.openshift.io/api/users/02227dc6-f4fe-451b-9549-4c5b7becc5e7"}},"space-template":{"data":{"id":"f405fa41-a8bb-46db-8800-2dbe13da1418","type":"spacetemplates"},"links":{"related":"https://api.openshift.io/api/spacetemplates/f405fa41-a8bb-46db-8800-2dbe13da1418","self":"https://api.openshift.io/api/spacetemplates/f405fa41-a8bb-46db-8800-2dbe13da1418"}},"workitemlinktypes":{"links":{"related":"https://api.openshift.io/api/spacetemplates/f405fa41-a8bb-46db-8800-2dbe13da1418/workitemlinktypes"}},"workitems":{"links":{"related":"https://api.openshift.io/api/spaces/17c1e9de-a89a-494b-91c4-819a013cb3b9/workitems"}},"workitemtypegroups":{"links":{"related":"https://api.openshift.io/api/spacetemplates/f405fa41-a8bb-46db-8800-2dbe13da1418/workitemtypegroups"}},"workitemtypes":{"links":{"related":"https://api.openshift.io/api/spacetemplates/f405fa41-a8bb-46db-8800-2dbe13da1418/workitemtypes"}}},"type":"spaces"}}
10 changes: 10 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,16 @@ regenerate: clean-generated generate
dev: prebuild-check deps generate $(FRESH_BIN) docker-compose-up
F8_DEVELOPER_MODE_ENABLED=true $(FRESH_BIN)


.PHONY: dev-pp
dev-pp: prebuild-check deps generate $(FRESH_BIN) docker-compose-up
FABRIC8_WIT_API_URL=https://api.prod-preview.openshift.io F8_CONFIG_FILE_PATH=jstconfig-pp.yaml F8_DEVELOPER_MODE_ENABLED=true $(FRESH_BIN)

.PHONY: dev-prod
dev-prod: prebuild-check deps generate $(FRESH_BIN) docker-compose-up
FABRIC8_WIT_API_URL=https://api.openshift.io F8_CONFIG_FILE_PATH=jstconfig-prod.yaml F8_DEVELOPER_MODE_ENABLED=true $(FRESH_BIN)


.PHONY: docker-compose-up
docker-compose-up:
ifeq ($(UNAME_S),Darwin)
Expand Down
8 changes: 8 additions & 0 deletions Makefile.mine
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@

.PHONY: dev-pp
dev-pp: prebuild-check deps generate $(FRESH_BIN) docker-compose-up
FABRIC8_WIT_API_URL=https://api.prod-preview.openshift.io F8_CONFIG_FILE_PATH=jstconfig-pp.yaml F8_DEVELOPER_MODE_ENABLED=true $(FRESH_BIN)

.PHONY: dev-prod
dev-prod: prebuild-check deps generate $(FRESH_BIN) docker-compose-up
FABRIC8_WIT_API_URL=https://api.openshift.io F8_CONFIG_FILE_PATH=jstconfig-prod.yaml F8_DEVELOPER_MODE_ENABLED=true $(FRESH_BIN)
4 changes: 4 additions & 0 deletions actions/rules/action_field_set.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,11 @@ func (act ActionFieldSet) storeWorkItem(wi *workitem.WorkItem) (*workitem.WorkIt
var storeResultWorkItem *workitem.WorkItem
err := application.Transactional(act.Db, func(appl application.Application) error {
var err error
<<<<<<< HEAD
storeResultWorkItem, err = appl.WorkItems().Save(act.Ctx, wi.SpaceID, *wi, *act.UserID)
=======
storeResultWorkItem, _, err = appl.WorkItems().Save(act.Ctx, wi.SpaceID, *wi, *act.UserID)
>>>>>>> upstream/master
if err != nil {
return errs.Wrap(err, "error updating work item")
}
Expand Down
49 changes: 49 additions & 0 deletions controller/deployments.go
Original file line number Diff line number Diff line change
Expand Up @@ -332,12 +332,46 @@ func (c *DeploymentsController) ShowDeploymentStats(ctx *app.ShowDeploymentStats
// ShowSpace runs the showSpace action.
func (c *DeploymentsController) ShowSpace(ctx *app.ShowSpaceDeploymentsContext) error {

// TODO - get from ctx
//checkPerms := true

kc, err := c.GetKubeClient(ctx)
defer cleanup(kc)
if err != nil {
return jsonapi.JSONErrorResponse(ctx, err)
}

/****
guid := goauuid.UUID(ctx.SpaceID)
spaceURLStr := rest.AbsoluteURL(ctx.Request, fmt.Sprintf(witclient.ShowSpacePath(guid)))

if checkPerms {
canRead, err := kc.CanGetSpace()
if err != nil {
return jsonapi.JSONErrorResponse(ctx, err)
}
if !canRead {
// return a non-space with empty permissions
emptySpace := &app.SimpleSpace{
ID: ctx.SpaceID,
Type: "space",
Links: &app.SimpleSpaceLinks{
Space: &app.LinkWithAccess{
Href: &spaceURLStr,
Meta: &app.EndpointAccess{
Methods: []string{},
},
},
},
}
res := &app.SimpleSpaceSingle{
Data: emptySpace,
}

return ctx.OK(res)
}
}
**/
kubeSpaceName, err := c.getSpaceNameFromSpaceID(ctx, ctx.SpaceID)
if err != nil || kubeSpaceName == nil {
return jsonapi.JSONErrorResponse(ctx, errors.NewNotFoundError("osio space", ctx.SpaceID.String()))
Expand All @@ -354,7 +388,22 @@ func (c *DeploymentsController) ShowSpace(ctx *app.ShowSpaceDeploymentsContext)

// Kubernetes doesn't know about space ID, so add it here
space.ID = ctx.SpaceID
/**
// next, try to get permissions
allowedMethods := []string{"GET"}

if err != nil {
return jsonapi.JSONErrorResponse(ctx, errs.Wrapf(err, "could not retrieve space %s", *kubeSpaceName))
}
space.Links = &app.SimpleSpaceLinks{
Space: &app.LinkWithAccess{
Href: &spaceURLStr,
Meta: &app.EndpointAccess{
Methods: []string{"GET", "POST", "DELETE", "PATCH"},
},
},
}
***/
res := &app.SimpleSpaceSingle{
Data: space,
}
Expand Down
4 changes: 2 additions & 2 deletions controller/deployments_osioclient.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ var _ ResponseReader = (*IOResponseReader)(nil)

// WitClient is an interface for mocking the witclient.Client
type WitClient interface {
ShowSpace(ctx context.Context, path string, ifModifiedSince *string, ifNoneMatch *string) (*http.Response, error)
ShowSpace(ctx context.Context, path string, qp *bool, ifModifiedSince *string, ifNoneMatch *string) (*http.Response, error)
ShowUserService(ctx context.Context, path string) (*http.Response, error)
}

Expand Down Expand Up @@ -141,7 +141,7 @@ func (osioclient *OSIOClient) GetUserServices(ctx context.Context) (*app.UserSer
func (osioclient *OSIOClient) GetSpaceByID(ctx context.Context, spaceID uuid.UUID) (*app.Space, error) {
guid := goauuid.UUID(spaceID)
urlpath := witclient.ShowSpacePath(guid)
resp, err := osioclient.wc.ShowSpace(goasupport.ForwardContextRequestID(ctx), urlpath, nil, nil)
resp, err := osioclient.wc.ShowSpace(goasupport.ForwardContextRequestID(ctx), urlpath, nil, nil, nil)
if err != nil {
return nil, errs.Wrapf(err, "could not connect to %s", urlpath)
}
Expand Down
2 changes: 1 addition & 1 deletion controller/deployments_osioclient_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ type MockWitClient struct {
UserServiceHttpResponseError error
}

func (m *MockWitClient) ShowSpace(ctx context.Context, path string, ifModifiedSince *string, ifNoneMatch *string) (*http.Response, error) {
func (m *MockWitClient) ShowSpace(ctx context.Context, path string, qp *bool, ifModifiedSince *string, ifNoneMatch *string) (*http.Response, error) {
return m.SpaceHttpResponse, m.SpaceHttpResponseError
}

Expand Down
15 changes: 6 additions & 9 deletions controller/deployments_urlprovider.go
Original file line number Diff line number Diff line change
Expand Up @@ -199,23 +199,20 @@ func (up *tenantURLProvider) GetEnvironmentMapping() map[string]string {
log.Error(nil, map[string]interface{}{
"namespace": envNS,
}, "namespace has no type")
} else if !isInternalNamespace(*envName) {
} else {
result[*envName] = envNS
}
}
return result
}

// Types of namespaces where the user does not deploy applications
var internalNamespaceTypes = []string{"user", "che", "jenkins"}
var internalNamespaceTypes = map[string]struct{}{"user": {}, "che": {}, "jenkins": {}}

func isInternalNamespace(envType string) bool {
for _, internalType := range internalNamespaceTypes {
if envType == internalType {
return true
}
}
return false
// CanDeploy returns true if the environment type provided can be deployed to as part of a pipeline
func (up *tenantURLProvider) CanDeploy(envType string) bool {
_, pres := internalNamespaceTypes[envType]
return !pres
}

func (up *tenantURLProvider) GetAPIToken() (*string, error) {
Expand Down
40 changes: 36 additions & 4 deletions controller/deployments_urlprovider_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -225,22 +225,31 @@ func TestTenantGetEnvironmentMapping(t *testing.T) {
testName: "Basic",
inputFile: "user-services.json",
expectedMap: map[string]string{
"run": "theuser-run",
"stage": "theuser-stage",
"user": "theuser",
"run": "theuser-run",
"stage": "theuser-stage",
"che": "theuser-che",
"jenkins": "theuser-jenkins",
},
},
{
testName: "No Type",
inputFile: "user-services-no-type.json",
expectedMap: map[string]string{
"run": "theuser-run",
"user": "theuser",
"run": "theuser-run",
"che": "theuser-che",
"jenkins": "theuser-jenkins",
},
},
{
testName: "Empty Type",
inputFile: "user-services-empty-type.json",
expectedMap: map[string]string{
"run": "theuser-run",
"user": "theuser",
"run": "theuser-run",
"che": "theuser-che",
"jenkins": "theuser-jenkins",
},
},
}
Expand All @@ -259,6 +268,29 @@ func TestTenantGetEnvironmentMapping(t *testing.T) {
}
}

func TestTenantCanDeploy(t *testing.T) {
testCases := []struct {
envType string
expected bool
}{
{"user", false},
{"test", true},
{"stage", true},
{"run", true},
{"che", false},
{"jenkins", false},
}

for _, testCase := range testCases {
t.Run(testCase.envType, func(t *testing.T) {
provider, err := getDefaultTenantProvider()
require.NoError(t, err)
result := provider.CanDeploy(testCase.envType)
require.Equal(t, testCase.expected, result, "Incorrect result from CanDeploy")
})
}
}

//////////////////////////////////////////////////////////////////////////////////////////////////

func tostring(item interface{}) string {
Expand Down
75 changes: 72 additions & 3 deletions controller/space.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,13 +48,14 @@ type SpaceController struct {
resourceManager auth.ResourceManager
DeploymentsClient *http.Client
CodebaseClient *http.Client
ClientGetter
}

// NewSpaceController creates a space controller.
func NewSpaceController(
service *goa.Service,
db application.DB,
config SpaceConfiguration,
config *configuration.Registry,
resourceManager auth.ResourceManager) *SpaceController {

return &SpaceController{
Expand All @@ -64,6 +65,9 @@ func NewSpaceController(
resourceManager: resourceManager,
DeploymentsClient: http.DefaultClient,
CodebaseClient: http.DefaultClient,
ClientGetter: &defaultClientGetter{
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The DeleteSpace method uses the above DeploymentsClient to call the deployments API via the Goa-generated client. Should we do the same here instead of using the ClientGetter?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did it this way because the new CanGet*() API's are internal, and it seemed more efficient to call directly. However, it's messy in several ways: I had to pass in config.Registry instead of SpaceConfiguration, and it uses the internal CanGetSpace() call, which is ... internal. So I felt slightly dirty coding it.

If I understand it, your proposal is to call //deployments/Space/{spaceID}?qp=true under the hood and use the output of that?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh right, I forgot that in order to get the permissions data we have to get all the space data as well. I don't think this would be a good idea, because of the substantial overhead for data we won't use. Perhaps we should stick with your current approach.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could add a parameter to only get the root space object, but maybe I should just leave that in a comment?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or even just skip getting any actual data for the space and only return the permissions. This may be over-complicating one API endpoint though. I'm fine with leaving as a comment for now. I imagine this would need to be addressed when moving deployments out of WIT though.

config: config,
},
}
}

Expand Down Expand Up @@ -470,6 +474,11 @@ func (c *SpaceController) List(ctx *app.ListSpaceContext) error {
// Show runs the show action.
func (c *SpaceController) Show(ctx *app.ShowSpaceContext) error {
var s *space.Space
s = &space.Space{
Name: "fakespacename",
}

/**
err := application.Transactional(c.db, func(appl application.Application) error {
var err error
s, err = appl.Spaces().Load(ctx.Context, ctx.SpaceID)
Expand All @@ -484,8 +493,46 @@ func (c *SpaceController) Show(ctx *app.ShowSpaceContext) error {
if err != nil {
return jsonapi.JSONErrorResponse(ctx, err)
}
***/
var methods []string
if ctx.Qp != nil && *ctx.Qp {
// 'qp' (QueryPerms query parameter) is true:
// ask Kubernetes if this user can access this space
// (this is different from the WIT Space database access)
kc, err := c.GetKubeClient(ctx)
defer cleanup(kc)
if err != nil {
log.Error(ctx, map[string]interface{}{
"err": err,
"space_id": ctx.SpaceID,
}, "unable create a KubeClient")
return jsonapi.JSONErrorResponse(ctx, err)
}
canRead, err := kc.CanGetSpace()
if err != nil {
log.Error(ctx, map[string]interface{}{
"err": err,
"space_id": ctx.SpaceID,
}, "unable retrieve permissions from CanGetSpace()")
return jsonapi.JSONErrorResponse(ctx, err)
}
if canRead {
methods = []string{"GET"}
} else {
methods = []string{}
}
} else {
methods = []string{}
}

return ctx.ConditionalRequest(*s, c.config.GetCacheControlSpace, func() error {
spaceData, err := ConvertSpaceFromModel(ctx.Request, *s, IncludeBacklogTotalCount(ctx.Context, c.db))
var spaceData *app.Space
var err error
if ctx.Qp != nil && *ctx.Qp {
spaceData, err = ConvertSpaceFromModel(ctx.Request, *s /*IncludeBacklogTotalCount(ctx.Context, c.db),*/, IncludeMethodAccess(ctx.Context, ctx.Request, methods))
} else {
spaceData, err = ConvertSpaceFromModel(ctx.Request, *s, IncludeBacklogTotalCount(ctx.Context, c.db))
}
if err != nil {
log.Error(ctx, map[string]interface{}{
"err": err,
Expand Down Expand Up @@ -626,7 +673,7 @@ func ConvertSpaceToModel(appSpace app.Space) space.Space {
// conversion from internal to API
type SpaceConvertFunc func(*http.Request, *space.Space, *app.Space) error

// IncludeBacklog returns a SpaceConvertFunc that includes the a link to the backlog
// IncludeBacklogTotalCount returns a SpaceConvertFunc that includes the a link to the backlog
// along with the total count of items in the backlog of the current space
func IncludeBacklogTotalCount(ctx context.Context, db application.DB) SpaceConvertFunc {
return func(req *http.Request, modelSpace *space.Space, appSpace *app.Space) error {
Expand All @@ -640,6 +687,22 @@ func IncludeBacklogTotalCount(ctx context.Context, db application.DB) SpaceConve
}
}

// IncludeMethodAccess returns a SpaceConvertFunc that includes method access metadata
// along with the total count of items in the backlog of the current space
func IncludeMethodAccess(ctx context.Context, req *http.Request, perms []string) SpaceConvertFunc {
return func(req *http.Request, modelSpace *space.Space, appSpace *app.Space) error {
spaceIDStr := modelSpace.ID.String()
relatedDeployments := rest.AbsoluteURL(req, fmt.Sprintf("/api/deployments/spaces/%s", spaceIDStr))
appSpace.Links.Deployments = &app.LinkWithAccess{
Href: &relatedDeployments,
Meta: &app.EndpointAccess{
Methods: perms,
},
}
return nil
}
}

// ConvertSpacesFromModel converts between internal and external REST representation
func ConvertSpacesFromModel(request *http.Request, spaces []space.Space, additional ...SpaceConvertFunc) ([]*app.Space, error) {
var result = make([]*app.Space, len(spaces))
Expand All @@ -656,6 +719,12 @@ func ConvertSpacesFromModel(request *http.Request, spaces []space.Space, additio
// ConvertSpaceFromModel converts between internal and external REST representation
func ConvertSpaceFromModel(request *http.Request, sp space.Space, options ...SpaceConvertFunc) (*app.Space, error) {
selfURL := rest.AbsoluteURL(request, app.SpaceHref(sp.ID))
/** selfWithPerms := &app.LinkWithAccess{
Href: &selfURL,
Meta: &app.EndpointAccess{
Methods: []string{"GET", "POST", "DELETE", "PATCH"},
},
}**/
spaceIDStr := sp.ID.String()
relatedIterations := rest.AbsoluteURL(request, fmt.Sprintf("/api/spaces/%s/iterations", spaceIDStr))
relatedAreas := rest.AbsoluteURL(request, fmt.Sprintf("/api/spaces/%s/areas", spaceIDStr))
Expand Down
Loading