mirror of
https://github.com/opencloud-eu/opencloud.git
synced 2025-12-30 09:38:26 -05:00
129 lines
3.5 KiB
Go
129 lines
3.5 KiB
Go
package roles
|
|
|
|
import (
|
|
"context"
|
|
"time"
|
|
|
|
"github.com/opencloud-eu/opencloud/pkg/log"
|
|
settingsmsg "github.com/opencloud-eu/opencloud/protogen/gen/opencloud/messages/settings/v0"
|
|
settingssvc "github.com/opencloud-eu/opencloud/protogen/gen/opencloud/services/settings/v0"
|
|
"github.com/opencloud-eu/reva/v2/pkg/store"
|
|
microstore "go-micro.dev/v4/store"
|
|
"google.golang.org/protobuf/encoding/protojson"
|
|
)
|
|
|
|
const (
|
|
cacheDatabase = "opencloud-pkg"
|
|
cacheTableName = "roles"
|
|
cacheTTL = time.Hour
|
|
)
|
|
|
|
// Manager manages a cache of roles by fetching unknown roles from the settings.RoleService.
|
|
type Manager struct {
|
|
logger log.Logger
|
|
roleCache microstore.Store
|
|
roleService settingssvc.RoleService
|
|
}
|
|
|
|
// NewManager returns a new instance of Manager.
|
|
func NewManager(o ...Option) Manager {
|
|
opts := newOptions(o...)
|
|
|
|
nStore := store.Create(opts.storeOptions...)
|
|
return Manager{
|
|
roleCache: nStore,
|
|
roleService: opts.roleService,
|
|
}
|
|
}
|
|
|
|
// List returns all roles that match the given roleIDs.
|
|
func (m *Manager) List(ctx context.Context, roleIDs []string) []*settingsmsg.Bundle {
|
|
// get from cache
|
|
result := make([]*settingsmsg.Bundle, 0)
|
|
lookup := make([]string, 0)
|
|
for _, roleID := range roleIDs {
|
|
if records, err := m.roleCache.Read(roleID, microstore.ReadFrom(cacheDatabase, cacheTableName)); err != nil {
|
|
lookup = append(lookup, roleID)
|
|
} else {
|
|
role := &settingsmsg.Bundle{}
|
|
found := false
|
|
for _, record := range records {
|
|
if record.Key == roleID {
|
|
if err := protojson.Unmarshal(record.Value, role); err == nil {
|
|
// if we can unmarshal the role, append it to the result
|
|
// otherwise assume the role wasn't found (data was damaged and
|
|
// we need to get the role again)
|
|
result = append(result, role)
|
|
found = true
|
|
break
|
|
}
|
|
}
|
|
}
|
|
if !found {
|
|
lookup = append(lookup, roleID)
|
|
}
|
|
}
|
|
}
|
|
|
|
// if there are roles missing, fetch them from the RoleService
|
|
if len(lookup) > 0 {
|
|
request := &settingssvc.ListBundlesRequest{
|
|
BundleIds: lookup,
|
|
}
|
|
res, err := m.roleService.ListRoles(ctx, request)
|
|
if err != nil {
|
|
m.logger.Debug().Err(err).Msg("failed to fetch roles by roleIDs")
|
|
return nil
|
|
}
|
|
for _, role := range res.Bundles {
|
|
jsonbytes, _ := protojson.Marshal(role)
|
|
record := µstore.Record{
|
|
Key: role.Id,
|
|
Value: jsonbytes,
|
|
Expiry: cacheTTL,
|
|
}
|
|
err := m.roleCache.Write(
|
|
record,
|
|
microstore.WriteTo(cacheDatabase, cacheTableName),
|
|
microstore.WriteTTL(cacheTTL),
|
|
)
|
|
if err != nil {
|
|
m.logger.Debug().Err(err).Msg("failed to cache roles")
|
|
}
|
|
result = append(result, role)
|
|
}
|
|
}
|
|
|
|
return result
|
|
}
|
|
|
|
// FindPermissionByID searches for a permission-setting by the permissionID, but limited to the given roleIDs
|
|
func (m *Manager) FindPermissionByID(ctx context.Context, roleIDs []string, permissionID string) *settingsmsg.Setting {
|
|
for _, role := range m.List(ctx, roleIDs) {
|
|
for _, setting := range role.Settings {
|
|
if setting.Id == permissionID {
|
|
return setting
|
|
}
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// FindRoleIdsForUser returns all roles that are assigned to the supplied userid
|
|
func (m *Manager) FindRoleIDsForUser(ctx context.Context, userID string) ([]string, error) {
|
|
req := &settingssvc.ListRoleAssignmentsRequest{AccountUuid: userID}
|
|
assignmentResponse, err := m.roleService.ListRoleAssignments(ctx, req)
|
|
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
roleIDs := make([]string, 0, len(assignmentResponse.Assignments))
|
|
|
|
for _, assignment := range assignmentResponse.Assignments {
|
|
roleIDs = append(roleIDs, assignment.RoleId)
|
|
}
|
|
|
|
return roleIDs, nil
|
|
}
|