Skip to content

Commit

Permalink
more config updates, use new tokenauth.Claims.CanAccess function [#346]
Browse files Browse the repository at this point in the history
  • Loading branch information
roberlander2 committed Feb 14, 2023
1 parent 544982c commit 24fa2df
Show file tree
Hide file tree
Showing 5 changed files with 221 additions and 126 deletions.
156 changes: 51 additions & 105 deletions core/administration.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,9 @@ import (

"github.com/google/uuid"
"github.com/rokwire/core-auth-library-go/v2/authutils"
"github.com/rokwire/logging-library-go/errors"
"github.com/rokwire/logging-library-go/logutils"
"github.com/rokwire/core-auth-library-go/v2/tokenauth"
"github.com/rokwire/logging-library-go/v2/errors"
"github.com/rokwire/logging-library-go/v2/logutils"
)

func (app *Application) getTODO() error {
Expand All @@ -37,69 +38,65 @@ func (app *Application) getGroupsUnprotected(clientID string, filter model.Group
return groups, nil
}

func (app *Application) getManagedGroupConfigs(clientID string) ([]model.ManagedGroupConfigData, error) {
return app.storage.FindManagedGroupConfigs(clientID)
}
// func (app *Application) getManagedGroupConfigs(clientID string) ([]model.ManagedGroupConfigData, error) {
// return app.storage.FindManagedGroupConfigs(clientID)
// }

func (app *Application) createManagedGroupConfig(config model.ManagedGroupConfig) (*model.ManagedGroupConfig, error) {
config.ID = uuid.NewString()
config.DateCreated = time.Now()
config.DateUpdated = nil
err := app.storage.InsertManagedGroupConfig(config)
return &config, err
}

func (app *Application) updateManagedGroupConfig(config model.ManagedGroupConfig) error {
return app.storage.UpdateManagedGroupConfig(config)
}
// func (app *Application) createManagedGroupConfig(config model.ManagedGroupConfig) (*model.ManagedGroupConfig, error) {
// config.ID = uuid.NewString()
// config.DateCreated = time.Now()
// config.DateUpdated = nil
// err := app.storage.InsertManagedGroupConfig(config)
// return &config, err
// }

func (app *Application) deleteManagedGroupConfig(id string, clientID string) error {
return app.storage.DeleteManagedGroupConfig(id, clientID)
}
// func (app *Application) updateManagedGroupConfig(config model.ManagedGroupConfig) error {
// return app.storage.UpdateManagedGroupConfig(config)
// }

func (app *Application) getConfig(configType string, appID string, orgID string) (*model.Config, error) {
return app.storage.FindConfig(configType, appID, orgID)
}
// func (app *Application) deleteManagedGroupConfig(id string, clientID string) error {
// return app.storage.DeleteManagedGroupConfig(id, clientID)
// }

func (app *Application) admGetConfig(id string, appID string, orgID string, system bool) (*model.Config, error) {
func (app *Application) getConfig(id string, claims *tokenauth.Claims) (*model.Config, error) {
config, err := app.storage.FindConfigByID(id)
if err != nil {
return nil, errors.WrapErrorAction(logutils.ActionFind, model.TypeConfig, nil, err)
}
if config == nil {
return nil, errors.ErrorData(logutils.StatusMissing, model.TypeConfig, &logutils.FieldArgs{"id": id})
}

ok, err := app.checkConfigAccess(config, appID, orgID, system)
err = claims.CanAccess(config.AppID, config.OrgID, config.System)
if err != nil {
return nil, errors.WrapErrorAction(logutils.ActionValidate, "config access", nil, err)
}
if !ok {
return nil, errors.ErrorAction(logutils.ActionGet, model.TypeConfig, logutils.StringArgs("invalid claims"))
}

return config, nil
}

func (app *Application) admGetConfigs(configType *string, appID string, orgID string, system bool) ([]model.Config, error) {
func (app *Application) getConfigs(configType *string, claims *tokenauth.Claims) ([]model.Config, error) {
configs, err := app.storage.FindConfigs(configType)
if err != nil {
return nil, errors.WrapErrorAction(logutils.ActionFind, model.TypeConfig, nil, err)
}

if !system {
allowedConfigs := make([]model.Config, 0)
for _, config := range configs {
ok, _ := app.checkConfigAccess(&config, appID, orgID, system)
if ok {
allowedConfigs = append(allowedConfigs, config)
}
allowedConfigs := make([]model.Config, 0)
for _, config := range configs {
if err := claims.CanAccess(config.AppID, config.OrgID, config.System); err == nil {
allowedConfigs = append(allowedConfigs, config)
}
return allowedConfigs, nil
}

return configs, nil
return allowedConfigs, nil
}

func (app *Application) admCreateConfig(config model.Config, appID string, orgID string, system bool) (*model.Config, error) {
_, err := app.checkConfigAccess(&config, appID, orgID, system)
func (app *Application) createConfig(config model.Config, claims *tokenauth.Claims) (*model.Config, error) {
// must be a system config if applying to all orgs
if config.OrgID == authutils.AllOrgs && !config.System {
return nil, errors.ErrorData(logutils.StatusInvalid, "config system status", &logutils.FieldArgs{"config.org_id": authutils.AllOrgs})
}

err := claims.CanAccess(config.AppID, config.OrgID, config.System)
if err != nil {
return nil, errors.WrapErrorAction(logutils.ActionValidate, "config access", nil, err)
}
Expand All @@ -113,7 +110,12 @@ func (app *Application) admCreateConfig(config model.Config, appID string, orgID
return &config, nil
}

func (app *Application) admUpdateConfig(config model.Config, appID string, orgID string, system bool) error {
func (app *Application) updateConfig(config model.Config, claims *tokenauth.Claims) error {
// must be a system config if applying to all orgs
if config.OrgID == authutils.AllOrgs && !config.System {
return errors.ErrorData(logutils.StatusInvalid, "config system status", &logutils.FieldArgs{"config.org_id": authutils.AllOrgs})
}

oldConfig, err := app.storage.FindConfig(config.Type, config.AppID, config.OrgID)
if err != nil {
return errors.WrapErrorAction(logutils.ActionFind, model.TypeConfig, nil, err)
Expand All @@ -122,10 +124,11 @@ func (app *Application) admUpdateConfig(config model.Config, appID string, orgID
return errors.ErrorData(logutils.StatusMissing, model.TypeConfig, &logutils.FieldArgs{"type": config.Type, "app_id": config.AppID, "org_id": config.OrgID})
}

if !system && oldConfig.System {
// cannot update a system config if not a system admin
if !claims.System && oldConfig.System {
return errors.ErrorData(logutils.StatusInvalid, "system claim", nil)
}
_, err = app.checkConfigAccess(&config, appID, orgID, system)
err = claims.CanAccess(config.AppID, config.OrgID, config.System)
if err != nil {
return errors.WrapErrorAction(logutils.ActionValidate, "config access", nil, err)
}
Expand All @@ -140,80 +143,23 @@ func (app *Application) admUpdateConfig(config model.Config, appID string, orgID
return nil
}

func (app *Application) admDeleteConfig(id string, appID string, orgID string, system bool) error {
func (app *Application) deleteConfig(id string, claims *tokenauth.Claims) error {
config, err := app.storage.FindConfigByID(id)
if err != nil {
return errors.WrapErrorAction(logutils.ActionFind, model.TypeConfig, nil, err)
}
if config == nil {
return errors.ErrorData(logutils.StatusMissing, model.TypeConfig, &logutils.FieldArgs{"id": id})
}

ok, err := app.checkConfigAccess(config, appID, orgID, system)
err = claims.CanAccess(config.AppID, config.OrgID, config.System)
if err != nil {
return errors.WrapErrorAction(logutils.ActionValidate, "config access", nil, err)
}
if !ok {
return errors.ErrorAction(logutils.ActionDelete, model.TypeConfig, logutils.StringArgs("invalid claims"))
}

err = app.storage.DeleteConfig(id)
if err != nil {
return errors.WrapErrorAction(logutils.ActionDelete, model.TypeConfig, nil, err)
}
return nil
}

// TODO: how to determine config access without application, organization data?
func (app *Application) checkConfigAccess(config *model.Config, appIDClaim string, orgIDClaim string, systemClaim bool) (bool, error) {
if config == nil {
return false, errors.ErrorData(logutils.StatusMissing, model.TypeConfig, nil)
}

claimsMatch := true
sysOrgIDClaim := systemClaim
if !systemClaim {
// org admins: cannot manage system configs, can only manage configs for their orgID
if config.System {
return false, errors.ErrorData(logutils.StatusInvalid, "system claim", nil)
}
if config.OrgID != orgIDClaim {
return false, errors.ErrorData(logutils.StatusInvalid, model.TypeConfig, &logutils.FieldArgs{"org_id": config.OrgID})
}
sysOrgIDClaim = false
} else {
// system admins: configs access allowed for any orgID (can use "all" when using the system organization)
organization, err := app.storage.FindOrganization(orgIDClaim)
if err != nil {
return false, errors.WrapErrorAction(logutils.ActionFind, model.TypeOrganization, &logutils.FieldArgs{"id": orgIDClaim}, err)
}
if organization == nil {
return false, errors.ErrorData(logutils.StatusMissing, model.TypeOrganization, &logutils.FieldArgs{"id": orgIDClaim})
}

sysOrgIDClaim = organization.System
if config.OrgID != authutils.AllOrgs {
if config.OrgID != orgIDClaim {
claimsMatch = false
}
} else if !organization.System {
return false, errors.ErrorData(logutils.StatusInvalid, model.TypeConfig, &logutils.FieldArgs{"org_id": authutils.AllOrgs, "org.system": false})
}
}

// all admins (including system admins): configs access allowed for any appID (can use "all" when using an admin application)
application, err := app.storage.FindApplication(nil, appIDClaim)
if err != nil {
return false, errors.WrapErrorAction(logutils.ActionFind, model.TypeApplication, &logutils.FieldArgs{"id": appIDClaim}, err)
}
if application == nil {
return false, errors.ErrorData(logutils.StatusMissing, model.TypeApplication, &logutils.FieldArgs{"id": appIDClaim})
}
if config.AppID != authutils.AllApps {
// give access to any appID to system admins using the system organization and an admin application
if (!application.Admin || !sysOrgIDClaim) && config.AppID != appIDClaim {
claimsMatch = false
}
} else if !application.Admin {
return false, errors.ErrorData(logutils.StatusInvalid, model.TypeConfig, &logutils.FieldArgs{"app_id": authutils.AllApps, "app.admin": false})
}

return claimsMatch, nil
}
32 changes: 25 additions & 7 deletions core/interfaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ import (
"groups/driven/storage"
"groups/utils"
"time"

"github.com/rokwire/core-auth-library-go/v2/tokenauth"
)

// Services exposes APIs for the driver adapters
Expand Down Expand Up @@ -270,11 +272,11 @@ func (s *servicesImpl) GetResearchProfileUserCount(clientID string, current *mod
type Administration interface {
GetGroups(clientID string, filter model.GroupsFilter) ([]model.Group, error)

GetConfig(id string, appID string, orgID string, system bool) (*model.Config, error)
GetConfigs(configType *string, appID string, orgID string, system bool) ([]model.Config, error)
CreateConfig(config model.Config, appID string, orgID string, system bool) (*model.Config, error)
UpdateConfig(config model.Config, appID string, orgID string, system bool) error
DeleteConfig(id string, appID string, orgID string, system bool) error
GetConfig(id string, claims *tokenauth.Claims) (*model.Config, error)
GetConfigs(configType *string, claims *tokenauth.Claims) ([]model.Config, error)
CreateConfig(config model.Config, claims *tokenauth.Claims) (*model.Config, error)
UpdateConfig(config model.Config, claims *tokenauth.Claims) error
DeleteConfig(id string, claims *tokenauth.Claims) error

// GetManagedGroupConfigs(clientID string) ([]model.ManagedGroupConfig, error)
// CreateManagedGroupConfig(config model.ManagedGroupConfig) (*model.ManagedGroupConfig, error)
Expand Down Expand Up @@ -306,8 +308,24 @@ func (s *administrationImpl) GetGroups(clientID string, filter model.GroupsFilte
// return s.app.deleteManagedGroupConfig(id, clientID)
// }

func (s *administrationImpl) GetConfig(configType string, appID string, orgID string) (*model.Config, error) {
return s.app.getConfig(configType, appID, orgID)
func (s *administrationImpl) GetConfig(id string, claims *tokenauth.Claims) (*model.Config, error) {
return s.app.getConfig(id, claims)
}

func (s *administrationImpl) GetConfigs(configType *string, claims *tokenauth.Claims) ([]model.Config, error) {
return s.app.getConfigs(configType, claims)
}

func (s *administrationImpl) CreateConfig(config model.Config, claims *tokenauth.Claims) (*model.Config, error) {
return s.app.createConfig(config, claims)
}

func (s *administrationImpl) UpdateConfig(config model.Config, claims *tokenauth.Claims) error {
return s.app.updateConfig(config, claims)
}

func (s *administrationImpl) DeleteConfig(id string, claims *tokenauth.Claims) error {
return s.app.deleteConfig(id, claims)
}

// Storage is used by corebb to storage data - DB storage adapter, file storage adapter etc
Expand Down
10 changes: 5 additions & 5 deletions driver/web/adapter.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,11 +98,11 @@ func (we *Adapter) Start() {
adminSubrouter.HandleFunc("/sync-configs", we.adminIDTokenAuthWrapFunc(we.adminApisHandler.GetSyncConfig)).Methods("GET")
adminSubrouter.HandleFunc("/sync-configs", we.adminIDTokenAuthWrapFunc(we.adminApisHandler.SaveSyncConfig)).Methods("PUT")

adminSubrouter.HandleFunc("/configs/{id}", we.adminIDTokenAuthWrapFunc(we.adminApisHandler.getConfig)).Methods("GET")
adminSubrouter.HandleFunc("/configs", we.adminIDTokenAuthWrapFunc(we.adminApisHandler.getConfigs)).Methods("GET")
adminSubrouter.HandleFunc("/configs", we.adminIDTokenAuthWrapFunc(we.adminApisHandler.createConfig)).Methods("POST")
adminSubrouter.HandleFunc("/configs/{id}", we.adminIDTokenAuthWrapFunc(we.adminApisHandler.updateConfig)).Methods("PUT")
adminSubrouter.HandleFunc("/configs/{id}", we.adminIDTokenAuthWrapFunc(we.adminApisHandler.deleteConfig)).Methods("DELETE")
adminSubrouter.HandleFunc("/configs/{id}", we.adminIDTokenAuthWrapFunc(we.adminApisHandler.GetConfig)).Methods("GET")
adminSubrouter.HandleFunc("/configs", we.adminIDTokenAuthWrapFunc(we.adminApisHandler.GetConfigs)).Methods("GET")
adminSubrouter.HandleFunc("/configs", we.adminIDTokenAuthWrapFunc(we.adminApisHandler.CreateConfig)).Methods("POST")
adminSubrouter.HandleFunc("/configs/{id}", we.adminIDTokenAuthWrapFunc(we.adminApisHandler.UpdateConfig)).Methods("PUT")
adminSubrouter.HandleFunc("/configs/{id}", we.adminIDTokenAuthWrapFunc(we.adminApisHandler.DeleteConfig)).Methods("DELETE")

// Internal key protection
restSubrouter.HandleFunc("/int/user/{identifier}/groups", we.internalKeyAuthFunc(we.internalApisHandler.IntGetUserGroupMemberships)).Methods("GET")
Expand Down
6 changes: 3 additions & 3 deletions driver/web/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ func (auth *APIKeysAuth) check(apiKey *string, r *http.Request) bool {
//check if there is api key in the header
if apiKey == nil || len(*apiKey) == 0 {
if auth.coreTokenAuth != nil {
_, err := auth.coreTokenAuth.CheckRequestTokens(r)
_, err := auth.coreTokenAuth.CheckRequestToken(r)
if err == nil {
return true
}
Expand Down Expand Up @@ -322,7 +322,7 @@ func (auth *IDTokenAuth) check(clientID string, token *string, allowAnonymousCor
var coreErr error
if auth.coreTokenAuth != nil {
var claims *tokenauth.Claims
claims, coreErr = auth.coreTokenAuth.CheckRequestTokens(r)
claims, coreErr = auth.coreTokenAuth.CheckRequestToken(r)
if coreErr == nil && claims != nil && (allowAnonymousCoreToken || !claims.Anonymous) {
err := auth.coreTokenAuth.AuthorizeRequestScope(claims, r)
if err != nil {
Expand Down Expand Up @@ -521,7 +521,7 @@ func (auth *AdminAuth) check(clientID string, r *http.Request) (*model.User, boo
var coreErr error
if auth.coreTokenAuth != nil {
var claims *tokenauth.Claims
claims, coreErr = auth.coreTokenAuth.CheckRequestTokens(r)
claims, coreErr = auth.coreTokenAuth.CheckRequestToken(r)
if coreErr == nil && claims != nil && !claims.Anonymous {
err := auth.coreTokenAuth.AuthorizeRequestPermissions(claims, r)
if err != nil {
Expand Down
Loading

0 comments on commit 24fa2df

Please sign in to comment.