Skip to content
Snippets Groups Projects
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
roleFileSystemStore.go 3.66 KiB
package rbac

import (
	"encoding/json"
	"io/ioutil"
	"sync"

	"code.fbi.h-da.de/danet/gosdn/controller/interfaces/rbac"
	"code.fbi.h-da.de/danet/gosdn/controller/nucleus/errors"
	"code.fbi.h-da.de/danet/gosdn/controller/store"
)

// FileSystemRoleStore is the filesystem implementation of the role store
type FileSystemRoleStore struct {
	fileMutex      sync.Mutex
	pathToRoleFile string
}

// NewFileSystemRoleStore returns a filesystem implementation for a role store.
func NewFileSystemRoleStore() rbac.RoleStore {
	store.EnsureFilesystemStorePathExists(store.RoleFilename)
	return &FileSystemRoleStore{
		fileMutex:      sync.Mutex{},
		pathToRoleFile: store.GetCompletePathToFileStore(store.RoleFilename),
	}
}

func (s *FileSystemRoleStore) readAllRolesFromFile() ([]rbac.LoadedRole, error) {
	var loadedRoles []rbac.LoadedRole
	content, err := ioutil.ReadFile(s.pathToRoleFile)
	if err != nil {
		return nil, err
	}

	err = json.Unmarshal(content, &loadedRoles)
	if err != nil {
		return nil, err
	}

	return loadedRoles, nil
}

func (s *FileSystemRoleStore) writeAllRolesToFile(Roles []rbac.LoadedRole) error {
	serializedData, err := json.Marshal(Roles)
	if err != nil {
		return err
	}

	err = ioutil.WriteFile(s.pathToRoleFile, serializedData, 0600)
	if err != nil {
		return err
	}

	return nil
}

// Add adds a Role to the Role store
func (s *FileSystemRoleStore) Add(RoleToAdd rbac.Role) error {
	s.fileMutex.Lock()
	defer s.fileMutex.Unlock()

	roles, err := s.readAllRolesFromFile()
	if err != nil {
		return err
	}

	var loadedRole rbac.LoadedRole
	loadedRole, err = store.TransformObjectToLoadedObject[rbac.Role, rbac.LoadedRole](RoleToAdd)
	if err != nil {
		return err
	}

	roles = append(roles, loadedRole)

	err = s.writeAllRolesToFile(roles)
	if err != nil {
		return err
	}

	return nil
}

//Delete deletes a Role from the Role store
func (s *FileSystemRoleStore) Delete(RoleToDelete rbac.Role) error {
	s.fileMutex.Lock()
	defer s.fileMutex.Unlock()

	roles, err := s.readAllRolesFromFile()
	if err != nil {
		return err
	}

	for i, role := range roles {
		if role.ID == RoleToDelete.ID().String() {
			//remove item from slice
			roles[i] = roles[len(roles)-1]
			roles = roles[:len(roles)-1]

			err = s.writeAllRolesToFile(roles)
			if err != nil {
				return err
			}

			return nil
		}
	}

	return &errors.ErrCouldNotFind{ID: RoleToDelete.ID(), Name: RoleToDelete.Name()}
}

//Get takes a Roles ID and return the Role if found
func (s *FileSystemRoleStore) Get(query store.Query) (rbac.LoadedRole, error) {
	s.fileMutex.Lock()
	defer s.fileMutex.Unlock()

	var role rbac.LoadedRole
	roles, err := s.readAllRolesFromFile()
	if err != nil {
		return role, err
	}

	for _, role := range roles {
		if role.ID == query.ID.String() || role.RoleName == query.Name {
			return role, nil
		}
	}

	return role, &errors.ErrCouldNotFind{ID: query.ID, Name: query.Name}
}

// GetAll returns all the Roles
func (s *FileSystemRoleStore) GetAll() ([]rbac.LoadedRole, error) {
	s.fileMutex.Lock()
	defer s.fileMutex.Unlock()

	Roles, err := s.readAllRolesFromFile()
	return Roles, err
}

//Update updates an exsisting Role
func (s *FileSystemRoleStore) Update(roleToUpdate rbac.Role) error {
	s.fileMutex.Lock()
	defer s.fileMutex.Unlock()

	loadedRole, err := store.TransformObjectToLoadedObject[rbac.Role, rbac.LoadedRole](roleToUpdate)
	if err != nil {
		return err
	}
	Roles, err := s.readAllRolesFromFile()
	if err != nil {
		return err
	}

	for i, Role := range Roles {
		if Role.ID == roleToUpdate.ID().String() {
			Roles[i] = loadedRole
			err = s.writeAllRolesToFile(Roles)
			if err != nil {
				return err
			}
			return nil
		}
	}

	return &errors.ErrCouldNotFind{ID: roleToUpdate.ID(), Name: roleToUpdate.Name()}
}