Skip to content

Commit

Permalink
add v3 export endpoint; fix ExecuteGroup right creation
Browse files Browse the repository at this point in the history
  • Loading branch information
IngoRoessner committed Nov 19, 2024
1 parent c954512 commit b9bac59
Show file tree
Hide file tree
Showing 8 changed files with 122 additions and 13 deletions.
4 changes: 3 additions & 1 deletion lib/api/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ type Query interface {

//migration
Import(imports map[string][]model.ResourceRights) (err error)
Export() (exports map[string][]model.ResourceRights, err error)
Export(token string) (exports map[string][]model.ResourceRights, err error)
}

type V3 interface {
Expand All @@ -63,4 +63,6 @@ type V3 interface {
GetRights(token string, kind string, resource string) (result model.ResourceRights, err error)

GetTermAggregation(token string, kind string, rights string, field string, limit int) (result []model.TermAggregationResultElement, err error)

ExportKind(token string, kind string, limit int, offset int) (result []model.ResourceRights, err error)
}
2 changes: 1 addition & 1 deletion lib/api/v1endpoints.go
Original file line number Diff line number Diff line change
Expand Up @@ -569,7 +569,7 @@ func V1Endpoints(router *httprouter.Router, config configuration.Config, q Query

router.GET("/export", func(res http.ResponseWriter, r *http.Request, ps httprouter.Params) {
res.Header().Set("Deprecation", "true")
exports, err := q.Export()
exports, err := q.Export(auth.GetAuthToken(r))
if err != nil {
http.Error(res, err.Error(), http.StatusInternalServerError)
return
Expand Down
33 changes: 33 additions & 0 deletions lib/api/v3endpoints.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package api

import (
"encoding/json"
"fmt"
"github.com/SENERGY-Platform/permission-search/lib/auth"
"github.com/SENERGY-Platform/permission-search/lib/configuration"
"github.com/SENERGY-Platform/permission-search/lib/model"
Expand Down Expand Up @@ -263,5 +264,37 @@ func V3Endpoints(router *httprouter.Router, config configuration.Config, q Query
writer.Header().Set("Content-Type", "application/json; charset=utf-8")
json.NewEncoder(writer).Encode(result)
})

router.GET("/v3/export/:resource", func(res http.ResponseWriter, r *http.Request, ps httprouter.Params) {
var err error
token := auth.GetAuthToken(r)
resource := ps.ByName("resource")
limit := 100
limitStr := r.URL.Query().Get("limit")
if limitStr != "" {
limit, err = strconv.Atoi(limitStr)
if err != nil {
http.Error(res, fmt.Sprintf("invalit limit: %v", err.Error()), http.StatusBadRequest)
return
}
}
offset := 0
offsetStr := r.URL.Query().Get("offset")
if offsetStr != "" {
offset, err = strconv.Atoi(offsetStr)
if err != nil {
http.Error(res, fmt.Sprintf("invalit offset: %v", err.Error()), http.StatusBadRequest)
return
}
}
exports, err := q.ExportKind(token, resource, limit, offset)
if err != nil {
http.Error(res, err.Error(), http.StatusInternalServerError)
return
}
res.Header().Set("Content-Type", "application/json; charset=utf-8")
json.NewEncoder(res).Encode(exports)
})

return true
}
54 changes: 54 additions & 0 deletions lib/apiv3_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,60 @@ func TestApiV3(t *testing.T) {

time.Sleep(10 * time.Second) //kafka latency

t.Run("export", func(t *testing.T) {
list, err := c.ExportKind(admintoken, "aspects", 3, 1)
if err != nil {
t.Error(err)
return
}
if len(list) != 3 {
t.Error(len(list))
return
}
expected := []model.ResourceRights{
{
ResourceRightsBase: model.ResourceRightsBase{
UserRights: map[string]model.Right{"testOwner": {Read: true, Write: true, Execute: true, Administrate: true}},
GroupRights: map[string]model.Right{
"admin": {Read: true, Write: true, Execute: true, Administrate: true},
"user": {Read: true, Write: false, Execute: true, Administrate: false},
},
},
ResourceId: "aspect1",
Features: map[string]interface{}{"name": "aspect1_name", "raw": map[string]interface{}{"name": "aspect1_name", "rdf_type": "aspect_type"}},
Creator: "testOwner",
},
{
ResourceRightsBase: model.ResourceRightsBase{
UserRights: map[string]model.Right{"testOwner": {Read: true, Write: true, Execute: true, Administrate: true}},
GroupRights: map[string]model.Right{
"admin": {Read: true, Write: true, Execute: true, Administrate: true},
"user": {Read: true, Write: false, Execute: true, Administrate: false},
},
},
ResourceId: "aspect2",
Features: map[string]interface{}{"name": "aspect2_name", "raw": map[string]interface{}{"name": "aspect2_name", "rdf_type": "aspect_type"}},
Creator: "testOwner",
},
{
ResourceRightsBase: model.ResourceRightsBase{
UserRights: map[string]model.Right{"testOwner": {Read: true, Write: true, Execute: true, Administrate: true}},
GroupRights: map[string]model.Right{
"admin": {Read: true, Write: true, Execute: true, Administrate: true},
"user": {Read: true, Write: false, Execute: true, Administrate: false},
},
},
ResourceId: "aspect3",
Features: map[string]interface{}{"name": "aspect3_name", "raw": map[string]interface{}{"name": "aspect3_name", "rdf_type": "aspect_type"}},
Creator: "testOwner",
},
}
if !reflect.DeepEqual(expected, list) {
t.Errorf("\ne:%#v\na:%#v\n", expected, list)
return
}
})

t.Run("client list", func(t *testing.T) {
actual, err := c.List(ctoken, "aspects", client.ListOptions{})
if err != nil {
Expand Down
2 changes: 2 additions & 0 deletions lib/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ type Client interface {
GetRights(token string, kind string, resource string) (result model.ResourceRights, err error)

GetTermAggregation(token string, kind string, rights string, field string, limit int) (result []model.TermAggregationResultElement, err error)

ExportKind(token string, kind string, limit int, offset int) (result []model.ResourceRights, err error)
}

type impl struct {
Expand Down
18 changes: 14 additions & 4 deletions lib/client/v3.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,40 +52,50 @@ func (this *impl) Query(token string, query model.QueryMessage) (result interfac

func (this *impl) List(token string, kind string, options model.ListOptions) (result []map[string]interface{}, err error) {
req, err := http.NewRequest(http.MethodGet, this.baseUrl+"/v3/resources/"+url.PathEscape(kind)+"?"+options.QueryValues().Encode(), nil)
req.Header.Set("Authorization", token)
if err != nil {
return result, err
}
req.Header.Set("Authorization", token)
result, _, err = do[[]map[string]interface{}](req)
return
}

func (this *impl) Total(token string, kind string, options model.ListOptions) (result int64, err error) {
req, err := http.NewRequest(http.MethodGet, this.baseUrl+"/v3/total/"+url.PathEscape(kind)+"?"+options.QueryValues().Encode(), nil)
req.Header.Set("Authorization", token)
if err != nil {
return result, err
}
req.Header.Set("Authorization", token)
result, _, err = do[int64](req)
return
}

func (this *impl) CheckUserOrGroup(token string, kind string, resource string, rights string) (err error) {
req, err := http.NewRequest(http.MethodHead, this.baseUrl+"/v3/resources/"+url.PathEscape(kind)+"/"+url.PathEscape(resource)+"?rights="+rights, nil)
req.Header.Set("Authorization", token)
if err != nil {
return err
}
req.Header.Set("Authorization", token)
_, err = head(req)
return
}

func (this *impl) GetTermAggregation(token string, kind string, rights string, term string, limit int) (result []model.TermAggregationResultElement, err error) {
req, err := http.NewRequest(http.MethodHead, this.baseUrl+"/v3/aggregates/term/"+url.PathEscape(kind)+"/"+url.PathEscape(term)+"?limit="+strconv.Itoa(limit)+"&rights="+rights, nil)
req.Header.Set("Authorization", token)
if err != nil {
return result, err
}
req.Header.Set("Authorization", token)
result, _, err = do[[]model.TermAggregationResultElement](req)
return
}

func (this *impl) ExportKind(token string, kind string, limit int, offset int) (result []model.ResourceRights, err error) {
req, err := http.NewRequest(http.MethodGet, this.baseUrl+"/v3/export/"+url.PathEscape(kind)+"?limit="+strconv.Itoa(limit)+"&offset="+strconv.Itoa(offset), nil)
if err != nil {
return result, err
}
req.Header.Set("Authorization", token)
result, _, err = do[[]model.ResourceRights](req)
return
}
2 changes: 1 addition & 1 deletion lib/model/model.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ func (entry *Entry) AddGroupRights(group string, rights string) {
case 'w':
entry.WriteGroups = append(entry.WriteGroups, group)
case 'x':
entry.ExecuteGroups = append(entry.AdminGroups, group)
entry.ExecuteGroups = append(entry.ExecuteGroups, group)
}
}
}
Expand Down
20 changes: 14 additions & 6 deletions lib/query/migration.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"context"
"encoding/json"
"errors"
"github.com/SENERGY-Platform/permission-search/lib/auth"
"github.com/SENERGY-Platform/permission-search/lib/model"
"github.com/opensearch-project/opensearch-go/opensearchutil"
)
Expand Down Expand Up @@ -55,23 +56,23 @@ func (this *Query) ImportResource(kind string, resource model.ResourceRights) (e
return nil
}

func (this *Query) Export() (exports map[string][]model.ResourceRights, err error) {
func (this *Query) Export(token string) (exports map[string][]model.ResourceRights, err error) {
exports = map[string][]model.ResourceRights{}
for kind := range this.config.Resources {
exports[kind], err = this.ExportKindAll(kind)
exports[kind], err = this.ExportKindAll(token, kind)
if err != nil {
return
}
}
return
}

func (this *Query) ExportKindAll(kind string) (result []model.ResourceRights, err error) {
func (this *Query) ExportKindAll(token string, kind string) (result []model.ResourceRights, err error) {
result = []model.ResourceRights{}
limit := 100
offset := 0
for {
temp, err := this.ExportKind(kind, limit, offset)
temp, err := this.ExportKind(token, kind, limit, offset)
if err != nil {
return result, err
}
Expand All @@ -81,10 +82,16 @@ func (this *Query) ExportKindAll(kind string) (result []model.ResourceRights, er
}
offset = offset + limit
}
return
}

func (this *Query) ExportKind(kind string, limit int, offset int) (result []model.ResourceRights, err error) {
func (this *Query) ExportKind(tokenStr string, kind string, limit int, offset int) (result []model.ResourceRights, err error) {
token, err := auth.Parse(tokenStr)
if err != nil {
return nil, err
}
if !token.IsAdmin() {
return nil, errors.New("only admins may export")
}
ctx := context.Background()
query := map[string]interface{}{
"query": map[string]interface{}{
Expand All @@ -96,6 +103,7 @@ func (this *Query) ExportKind(kind string, limit int, offset int) (result []mode
this.opensearchClient.Search.WithContext(ctx),
this.opensearchClient.Search.WithSize(limit),
this.opensearchClient.Search.WithFrom(offset),
this.opensearchClient.Search.WithSort("resource:asc"),
this.opensearchClient.Search.WithBody(opensearchutil.NewJSONReader(query)),
)
if err != nil {
Expand Down

0 comments on commit b9bac59

Please sign in to comment.