Skip to content

Commit

Permalink
Merge pull request #45 from imulab/features/all_resource
Browse files Browse the repository at this point in the history
Features/all resource
  • Loading branch information
imulab authored Feb 1, 2020
2 parents c85ee93 + 962b42d commit b5e5451
Show file tree
Hide file tree
Showing 21 changed files with 1,893 additions and 35 deletions.
6 changes: 6 additions & 0 deletions cmd/api/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,15 @@ func Command() *cli.Command {
app := args.Initialize()
defer app.Close()

app.ensureSchemaRegistered()

var router = httprouter.New()
{
router.GET("/ServiceProviderConfig", ServiceProviderConfigHandler(app.ServiceProviderConfig()))
router.GET("/Schemas", SchemasHandler())
router.GET("/Schemas/:id", SchemaByIdHandler())
router.GET("/ResourceTypes", ResourceTypesHandler(app.UserResourceType(), app.GroupResourceType()))
router.GET("/ResourceTypes/:id", ResourceTypeByIdHandler(app.userResourceType, app.GroupResourceType()))

router.GET("/Users/:id", GetHandler(app.UserGetService(), app.Logger()))
router.GET("/Users", SearchHandler(app.UserQueryService(), app.Logger()))
Expand Down
107 changes: 106 additions & 1 deletion cmd/api/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/readpref"
"net/http"
"net/http/httptest"
)

// CreateHandler returns a route handler function for creating SCIM resources.
Expand Down Expand Up @@ -241,7 +242,111 @@ func ServiceProviderConfigHandler(config *spec.ServiceProviderConfig) func(rw ht
}

return func(rw http.ResponseWriter, r *http.Request, params httprouter.Params) {
rw.WriteHeader(200)
rw.Header().Set("Content-Type", "application/json+scim")
_, _ = rw.Write(raw)
}
}

// ResourceTypesHandler returns a route handler function for getting all defined ResourceType.
func ResourceTypesHandler(resourceTypes ...*spec.ResourceType) func(rw http.ResponseWriter, r *http.Request, params httprouter.Params) {
result := &service.QueryResponse{
TotalResults: len(resourceTypes),
StartIndex: 1,
ItemsPerPage: len(resourceTypes),
Resources: []json.Serializable{},
}
for _, resourceType := range resourceTypes {
result.Resources = append(result.Resources, json.ResourceTypeToSerializable(resourceType))
}

// use recorder to cache render result
recorder := httptest.NewRecorder()
if err := handlerutil.WriteSearchResultToResponse(recorder, result); err != nil {
panic(err)
}

return func(rw http.ResponseWriter, r *http.Request, params httprouter.Params) {
rw.Header().Set("Content-Type", recorder.Header().Get("Content-Type"))
_, _ = rw.Write(recorder.Body.Bytes())
}
}

// ResourceTypeByIdHandler returns a route handler function get ResourceType by its id.
func ResourceTypeByIdHandler(resourceTypes ...*spec.ResourceType) func(rw http.ResponseWriter, r *http.Request, params httprouter.Params) {
cache := map[string]gojson.RawMessage{}
for _, resourceType := range resourceTypes {
raw, err := json.Serialize(json.ResourceTypeToSerializable(resourceType))
if err != nil {
panic(err)
}
cache[resourceType.ID()] = raw
}

return func(rw http.ResponseWriter, r *http.Request, params httprouter.Params) {
raw, ok := cache[params.ByName("id")]
if !ok {
_ = handlerutil.WriteError(rw, fmt.Errorf("%w: resource type is not found", spec.ErrNotFound))
return
}

rw.Header().Set("Content-Type", "application/json+scim")
_, _ = rw.Write(raw)
}
}

// SchemasHandler returns a route handler function for getting all defined Schema.
func SchemasHandler() func(rw http.ResponseWriter, r *http.Request, params httprouter.Params) {
result := &service.QueryResponse{StartIndex: 1, Resources: []json.Serializable{}}
if err := spec.Schemas().ForEachSchema(func(schema *spec.Schema) error {
if schema.ID() == spec.CoreSchemaId {
return nil
}
result.Resources = append(result.Resources, json.SchemaToSerializable(schema))
return nil
}); err != nil {
panic(err)
}
result.TotalResults = len(result.Resources)
result.ItemsPerPage = len(result.Resources)

// use recorder to cache render result
recorder := httptest.NewRecorder()
if err := handlerutil.WriteSearchResultToResponse(recorder, result); err != nil {
panic(err)
}

return func(rw http.ResponseWriter, r *http.Request, params httprouter.Params) {
rw.Header().Set("Content-Type", recorder.Header().Get("Content-Type"))
_, _ = rw.Write(recorder.Body.Bytes())
}
}

// SchemaByIdHandler returns a route handler function get Schema by its id.
func SchemaByIdHandler() func(rw http.ResponseWriter, r *http.Request, params httprouter.Params) {
cache := map[string]gojson.RawMessage{}
if err := spec.Schemas().ForEachSchema(func(schema *spec.Schema) error {
if schema.ID() == spec.CoreSchemaId {
return nil
}

raw, err := json.Serialize(json.SchemaToSerializable(schema))
if err != nil {
return err
}
cache[schema.ID()] = raw

return nil
}); err != nil {
panic(err)
}

return func(rw http.ResponseWriter, r *http.Request, params httprouter.Params) {
raw, ok := cache[params.ByName("id")]
if !ok {
_ = handlerutil.WriteError(rw, fmt.Errorf("%w: schema is not found", spec.ErrNotFound))
return
}

rw.Header().Set("Content-Type", "application/json+scim")
_, _ = rw.Write(raw)
}
Expand Down
4 changes: 4 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,18 @@ require (
github.com/imulab/go-scim/mongo/v2 v2.0.0
github.com/imulab/go-scim/pkg/v2 v2.0.0
github.com/julienschmidt/httprouter v1.3.0
github.com/opencontainers/runc v1.0.0-rc9 // indirect
github.com/ory/dockertest v3.3.5+incompatible
github.com/rs/zerolog v1.17.2
github.com/satori/go.uuid v1.2.0
github.com/streadway/amqp v0.0.0-20200108173154-1c71cc93ed71
github.com/stretchr/objx v0.2.0 // indirect
github.com/stretchr/testify v1.4.0
github.com/urfave/cli/v2 v2.1.1
go.mongodb.org/mongo-driver v1.2.1
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e
golang.org/x/sys v0.0.0-20200121082415-34d275377bf9 // indirect
gopkg.in/yaml.v2 v2.2.7 // indirect
)

replace github.com/imulab/go-scim/mongo/v2 => ./mongo/v2
Expand Down
9 changes: 9 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ github.com/opencontainers/image-spec v1.0.1 h1:JMemWkRwHx4Zj+fVxWoMCFm/8sYGGrUVo
github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
github.com/opencontainers/runc v1.0.0-rc5 h1:rYjdzMDXVly2Av0RLs3nf/iVkaWh2UrDhuTdTT2KggQ=
github.com/opencontainers/runc v1.0.0-rc5/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
github.com/opencontainers/runc v1.0.0-rc9 h1:/k06BMULKF5hidyoZymkoDCzdJzltZpz/UU4LguQVtc=
github.com/opencontainers/runc v1.0.0-rc9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
github.com/ory/dockertest v3.3.5+incompatible h1:iLLK6SQwIhcbrG783Dghaaa3WPzGc+4Emza6EbVUUGA=
github.com/ory/dockertest v3.3.5+incompatible/go.mod h1:1vX4m9wsvi00u5bseYwXaSnhNrne+V0E6LAcBILJdPs=
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
Expand All @@ -69,7 +71,10 @@ github.com/streadway/amqp v0.0.0-20200108173154-1c71cc93ed71/go.mod h1:AZpEONHx3
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48=
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4=
Expand Down Expand Up @@ -103,6 +108,8 @@ golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9 h1:L2auWcuQIvxz9xSEqzESnV/QN/gNRXNApHi3fYwl2w0=
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200121082415-34d275377bf9 h1:N19i1HjUnR7TF7rMt8O4p3dLvqvmYyzB6ifMFmrbY50=
golang.org/x/sys v0.0.0-20200121082415-34d275377bf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
Expand All @@ -116,3 +123,5 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.7 h1:VUgggvou5XRW9mHwD/yXxIYSMtY0zoKQf/v226p2nyo=
gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
3 changes: 2 additions & 1 deletion pkg/v2/crud/register.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ import (
// Register calls expr.RegisterURN for the main schema ids and all schema extension ids in the resource type.
func Register(resourceType *spec.ResourceType) {
expr.RegisterURN(resourceType.Schema().ID())
resourceType.ForEachExtension(func(extension *spec.Schema, required bool) {
_ = resourceType.ForEachExtension(func(extension *spec.Schema, required bool) error {
expr.RegisterURN(extension.ID())
return nil
})
}
2 changes: 1 addition & 1 deletion pkg/v2/handlerutil/response.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,8 @@ func WriteError(rw http.ResponseWriter, err error) error {
errMsg.ScimType = spec.ErrInternal.Type
}

rw.WriteHeader(errMsg.Status)
rw.Header().Set("Content-Type", "application/json+scim")
rw.WriteHeader(errMsg.Status)

raw, jsonErr := json.Marshal(errMsg)
if jsonErr != nil {
Expand Down
16 changes: 16 additions & 0 deletions pkg/v2/json/adapt.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package json

import (
"github.com/imulab/go-scim/pkg/v2/json/internal"
"github.com/imulab/go-scim/pkg/v2/spec"
)

// SchemaToSerializable returns a Serializable wrapper for a schema so it can be used to call json.Serialize
func SchemaToSerializable(sch *spec.Schema) Serializable {
return &internal.SerializableSchema{Sch: sch}
}

// ResourceTypeToSerializable returns a Serializable wrapper for a resource type so it can be used to call json.Serialize
func ResourceTypeToSerializable(resourceType *spec.ResourceType) Serializable {
return &internal.SerializableResourceType{ResourceType: resourceType}
}
Loading

0 comments on commit b5e5451

Please sign in to comment.