diff --git a/controller/controller.go b/controller/controller.go index 8737c07ed754ffd80d9bd723594b37584b268ab6..77877b123fdc52b5e089c887504940783246a022 100644 --- a/controller/controller.go +++ b/controller/controller.go @@ -38,10 +38,8 @@ import ( "code.fbi.h-da.de/danet/gosdn/controller/config" "code.fbi.h-da.de/danet/gosdn/controller/conflict" eventservice "code.fbi.h-da.de/danet/gosdn/controller/eventService" - "code.fbi.h-da.de/danet/gosdn/controller/interfaces/rbac" "code.fbi.h-da.de/danet/gosdn/controller/northbound/server" nbi "code.fbi.h-da.de/danet/gosdn/controller/northbound/server" - rbacImpl "code.fbi.h-da.de/danet/gosdn/controller/rbac" "code.fbi.h-da.de/danet/gosdn/controller/store" "code.fbi.h-da.de/danet/gosdn/controller/topology" "code.fbi.h-da.de/danet/gosdn/controller/topology/nodes" @@ -61,8 +59,8 @@ type Core struct { pndService ports.PndService mneService ports.NetworkElementService - userService rbac.UserService - roleService rbac.RoleService + userService ports.UserService + roleService ports.RoleService topologyService topology.Service nodeService nodes.Service portService topoPorts.Service @@ -126,8 +124,8 @@ func initialize() error { pndService: service.NewPndService(pndStore), mneService: service.NewNetworkElementService(persistence.NewNetworkElementStore(), pluginService, eventService), changeStore: *changeStore, - userService: rbacImpl.NewUserService(rbacImpl.NewUserStore(), eventService), - roleService: rbacImpl.NewRoleService(rbacImpl.NewRoleStore(), eventService), + userService: service.NewUserService(persistence.NewUserStore(), eventService), + roleService: service.NewRoleService(persistence.NewRoleStore(), eventService), topologyService: topology.NewTopologyService( topology.NewDatabaseTopologyStore(), nodeService, @@ -201,7 +199,7 @@ func startGrpc() error { } log.Infof("listening to %v", lislisten.Addr()) - jwtManager := rbacImpl.NewJWTManager(config.JWTSecret, config.JWTDuration) + jwtManager := service.NewJWTManager(config.JWTSecret, config.JWTDuration) setupGRPCServerWithCorrectSecurityLevel(jwtManager, c.userService, c.roleService) c.nbi = nbi.NewNBI( @@ -274,8 +272,8 @@ func ensureDefaultRoleExists() error { log.Info(err) } - if adminRole == nil { - err := c.roleService.Add(rbacImpl.NewRole(uuid.New(), defaultAdminRoleName, "admin role", []string{ + if adminRole.RoleName == "" { + err := c.roleService.Add(model.NewRole(uuid.New(), defaultAdminRoleName, "admin role", []string{ "/gosdn.pnd.PndService/GetPnd", "/gosdn.pnd.PndService/GetPndList", "/gosdn.pnd.PndService/CreatePndList", @@ -332,7 +330,7 @@ func ensureDefaultUserExists() error { if err != nil { log.Info(err) } - if adminUser == nil { + if adminUser.Name() == "" { // Getting the password from the environment variable which is set in gosdn.clab.yaml. var preDefinedPassword = os.Getenv("GOSDN_ADMIN_PASSWORD") var usedPassword string @@ -357,7 +355,7 @@ func ensureDefaultUserExists() error { hashedPassword := base64.RawStdEncoding.EncodeToString(argon2.IDKey([]byte(usedPassword), []byte(salt), 1, 64*1024, 4, 32)) - err = c.userService.Add(rbacImpl.NewUser(uuid.New(), defaultUserName, map[string]string{config.BasePndUUID.String(): "admin"}, string(hashedPassword), "", salt, conflict.Metadata{ResourceVersion: 0})) + err = c.userService.Add(model.NewUser(uuid.New(), defaultUserName, map[string]string{config.BasePndUUID.String(): "admin"}, string(hashedPassword), "", salt, conflict.Metadata{ResourceVersion: 0})) if err != nil { return err } @@ -427,7 +425,7 @@ func callback(id uuid.UUID, ch chan model.Details) { // This allows users to operate on the controller without any authentication/authorization, // but they could still login if they want to. // Use insecure only for testing purposes and with caution. -func setupGRPCServerWithCorrectSecurityLevel(jwt *rbacImpl.JWTManager, userService rbac.UserService, roleService rbac.RoleService) { +func setupGRPCServerWithCorrectSecurityLevel(jwt *service.JWTManager, userService ports.UserService, roleService ports.RoleService) { securityLevel := viper.GetString("security") if securityLevel == "insecure" { c.grpcServer = grpc.NewServer() diff --git a/controller/interfaces/rbac/rbacService.go b/controller/interfaces/rbac/rbacService.go deleted file mode 100644 index 84862f715004c0bd9a7cb78bd6d4b6e3f02f0b38..0000000000000000000000000000000000000000 --- a/controller/interfaces/rbac/rbacService.go +++ /dev/null @@ -1,21 +0,0 @@ -package rbac - -import "code.fbi.h-da.de/danet/gosdn/controller/nucleus/domain/model" - -// UserService describes an interface for user service implementation. -type UserService interface { - Add(User) error - Delete(User) error - Update(User) error - Get(model.Query) (User, error) - GetAll() ([]User, error) -} - -// RoleService describes an interface for role service implementations. -type RoleService interface { - Add(Role) error - Delete(Role) error - Update(Role) error - Get(model.Query) (Role, error) - GetAll() ([]Role, error) -} diff --git a/controller/interfaces/rbac/role.go b/controller/interfaces/rbac/role.go deleted file mode 100644 index 85658265b7b931f84785cb6c92c6738793cffe94..0000000000000000000000000000000000000000 --- a/controller/interfaces/rbac/role.go +++ /dev/null @@ -1,20 +0,0 @@ -package rbac - -import "github.com/google/uuid" - -// Role represents a role with permissions. -type Role interface { - ID() uuid.UUID - Name() string - GetDescription() string - GetPermissions() []string - RemovePermissionsFromRole([]string) -} - -// LoadedRole represents a Role that was loaded. -type LoadedRole struct { - ID string `json:"_id" bson:"_id"` - RoleName string `json:"rolename"` - Description string `json:"description,omitempty"` - Permissions []string `json:"permissions,omitempty"` -} diff --git a/controller/interfaces/rbac/roleStore.go b/controller/interfaces/rbac/roleStore.go deleted file mode 100644 index a26e54d107d27a1148274a5d1c02282c4e57a827..0000000000000000000000000000000000000000 --- a/controller/interfaces/rbac/roleStore.go +++ /dev/null @@ -1,12 +0,0 @@ -package rbac - -import "code.fbi.h-da.de/danet/gosdn/controller/nucleus/domain/model" - -// RoleStore describes an interface for role store implementations. -type RoleStore interface { - Add(r Role) error - Update(r Role) error - Delete(Role) error - Get(model.Query) (LoadedRole, error) - GetAll() ([]LoadedRole, error) -} diff --git a/controller/interfaces/rbac/user.go b/controller/interfaces/rbac/user.go deleted file mode 100644 index 2116e73be7c3346c43281812e167bc33d2504a5b..0000000000000000000000000000000000000000 --- a/controller/interfaces/rbac/user.go +++ /dev/null @@ -1,30 +0,0 @@ -package rbac - -import ( - "github.com/google/uuid" - - "code.fbi.h-da.de/danet/gosdn/controller/conflict" -) - -// User represents an User which is managed by rbac. -type User interface { - ID() uuid.UUID - Name() string - GetRoles() map[string]string - GetPassword() string - GetToken() string - SetToken(string) - GetSalt() string - GetMetadata() conflict.Metadata -} - -// LoadedUser represents a User that was loaded. -type LoadedUser struct { - ID string `json:"_id" bson:"_id"` - UserName string `json:"username"` - Roles map[string]string `json:"roles,omitempty"` - Password string `json:"password"` - Token string `json:"token,omitempty"` - Salt string `json:"salt" bson:"salt"` - Metadata conflict.Metadata `json:"metadata" bson:"metadata"` -} diff --git a/controller/interfaces/rbac/userStore.go b/controller/interfaces/rbac/userStore.go deleted file mode 100644 index a69f7acb686b7afdd991ec836438ffd75cbd1121..0000000000000000000000000000000000000000 --- a/controller/interfaces/rbac/userStore.go +++ /dev/null @@ -1,12 +0,0 @@ -package rbac - -import "code.fbi.h-da.de/danet/gosdn/controller/nucleus/domain/model" - -// UserStore describes an interface for user store implementations. -type UserStore interface { - Add(u User) error - Update(u User) error - Delete(User) error - Get(model.Query) (LoadedUser, error) - GetAll() ([]LoadedUser, error) -} diff --git a/controller/northbound/server/auth.go b/controller/northbound/server/auth.go index e3283b738e7949e628990678359105d483d103f2..353631e781c2f3d1785c60df6c86f0ccde6c37ae 100644 --- a/controller/northbound/server/auth.go +++ b/controller/northbound/server/auth.go @@ -6,10 +6,10 @@ import ( "time" apb "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/rbac" - rbacInterfaces "code.fbi.h-da.de/danet/gosdn/controller/interfaces/rbac" "code.fbi.h-da.de/danet/gosdn/controller/metrics" + "code.fbi.h-da.de/danet/gosdn/controller/nucleus/domain/application/service" "code.fbi.h-da.de/danet/gosdn/controller/nucleus/domain/model" - "code.fbi.h-da.de/danet/gosdn/controller/rbac" + "code.fbi.h-da.de/danet/gosdn/controller/nucleus/domain/ports" "github.com/bufbuild/protovalidate-go" "github.com/prometheus/client_golang/prometheus" "golang.org/x/crypto/argon2" @@ -21,15 +21,15 @@ import ( // AuthServer holds a JWTManager and represents a AuthServiceServer. type AuthServer struct { apb.UnimplementedAuthServiceServer - jwtManager *rbac.JWTManager - userService rbacInterfaces.UserService + jwtManager *service.JWTManager + userService ports.UserService protoValidator *protovalidate.Validator } // NewAuthServer receives a JWTManager and a userService and returns a new Auth interface. func NewAuthServer( - jwtManager *rbac.JWTManager, - userService rbacInterfaces.UserService, + jwtManager *service.JWTManager, + userService ports.UserService, protoValidator *protovalidate.Validator, ) *AuthServer { return &AuthServer{ @@ -49,7 +49,7 @@ func (s AuthServer) Login(ctx context.Context, request *apb.LoginRequest) (*apb. return nil, status.Errorf(codes.Aborted, "%v", err) } - user := rbac.User{ + user := model.User{ UserName: request.Username, Password: request.Pwd, } @@ -107,7 +107,7 @@ func (s AuthServer) Logout(ctx context.Context, request *apb.LogoutRequest) (*ap } // isValidUser checks if the provided user name fits to a stored one and then checks if the provided password is correct. -func (s AuthServer) isValidUser(user rbac.User) error { +func (s AuthServer) isValidUser(user model.User) error { storedUser, err := s.userService.Get(model.Query{Name: user.Name()}) if err != nil { return err @@ -163,7 +163,7 @@ func (s AuthServer) handleLogout(ctx context.Context, userName string) error { return status.Errorf(codes.Aborted, "missing match of token provied for user") } - err = s.userService.Update(&rbac.User{UserID: storedUser.ID(), + err = s.userService.Update(model.User{UserID: storedUser.ID(), UserName: storedUser.Name(), Roles: storedUser.GetRoles(), Password: storedUser.GetPassword(), diff --git a/controller/northbound/server/auth_interceptor.go b/controller/northbound/server/auth_interceptor.go index 6a389b6dd88c0636837f999b4bd013edde5af6c1..02dd7c97ffc80a1156a88edd61f4b1f4a1ef70fe 100644 --- a/controller/northbound/server/auth_interceptor.go +++ b/controller/northbound/server/auth_interceptor.go @@ -4,12 +4,12 @@ import ( "context" "time" - rbacInterfaces "code.fbi.h-da.de/danet/gosdn/controller/interfaces/rbac" + "code.fbi.h-da.de/danet/gosdn/controller/nucleus/domain/application/service" "code.fbi.h-da.de/danet/gosdn/controller/nucleus/domain/model" + "code.fbi.h-da.de/danet/gosdn/controller/nucleus/domain/ports" csbipb "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/csbi" apb "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/rbac" - "code.fbi.h-da.de/danet/gosdn/controller/rbac" "google.golang.org/grpc" "google.golang.org/grpc/codes" "google.golang.org/grpc/metadata" @@ -18,16 +18,16 @@ import ( // AuthInterceptor provides an AuthInterceptor. type AuthInterceptor struct { - jwtManager *rbac.JWTManager - userService rbacInterfaces.UserService - roleService rbacInterfaces.RoleService + jwtManager *service.JWTManager + userService ports.UserService + roleService ports.RoleService } // NewAuthInterceptor receives a JWTManager and a rbacMand returns a new AuthInterceptor provding gRPC Interceptor functionality. func NewAuthInterceptor( - jwtManager *rbac.JWTManager, - userService rbacInterfaces.UserService, - roleService rbacInterfaces.RoleService, + jwtManager *service.JWTManager, + userService ports.UserService, + roleService ports.RoleService, ) *AuthInterceptor { return &AuthInterceptor{ jwtManager: jwtManager, diff --git a/controller/northbound/server/nbi.go b/controller/northbound/server/nbi.go index 6b4c95af7fb63886736c85d1219e3eb3232b5fbb..ec5784dce6d7b7707d561c2cd90951078984b9d5 100644 --- a/controller/northbound/server/nbi.go +++ b/controller/northbound/server/nbi.go @@ -4,10 +4,9 @@ import ( cpb "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/csbi" rpb "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/plugin-registry" "code.fbi.h-da.de/danet/gosdn/controller/app" - rbacInterfaces "code.fbi.h-da.de/danet/gosdn/controller/interfaces/rbac" + "code.fbi.h-da.de/danet/gosdn/controller/nucleus/domain/application/service" "code.fbi.h-da.de/danet/gosdn/controller/nucleus/domain/model" "code.fbi.h-da.de/danet/gosdn/controller/nucleus/domain/ports" - "code.fbi.h-da.de/danet/gosdn/controller/rbac" "code.fbi.h-da.de/danet/gosdn/controller/store" "code.fbi.h-da.de/danet/gosdn/controller/topology" "code.fbi.h-da.de/danet/gosdn/controller/topology/nodes" @@ -45,9 +44,9 @@ func NewNBI( pndService ports.PndService, mneService ports.NetworkElementService, changeStore store.ChangeStore, - users rbacInterfaces.UserService, - roles rbacInterfaces.RoleService, - jwt rbac.JWTManager, + users ports.UserService, + roles ports.RoleService, + jwt service.JWTManager, topologyService topology.Service, nodeService nodes.Service, portService topoPorts.Service, diff --git a/controller/northbound/server/role.go b/controller/northbound/server/role.go index 134fa30e0c7bec1e34604b4d4467be7f7791a3cc..1113d6449471db08134e760bfe13359780bfdd40 100644 --- a/controller/northbound/server/role.go +++ b/controller/northbound/server/role.go @@ -6,10 +6,10 @@ import ( "time" apb "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/rbac" - rbacInterfaces "code.fbi.h-da.de/danet/gosdn/controller/interfaces/rbac" "code.fbi.h-da.de/danet/gosdn/controller/metrics" + "code.fbi.h-da.de/danet/gosdn/controller/nucleus/domain/application/service" "code.fbi.h-da.de/danet/gosdn/controller/nucleus/domain/model" - "code.fbi.h-da.de/danet/gosdn/controller/rbac" + "code.fbi.h-da.de/danet/gosdn/controller/nucleus/domain/ports" "github.com/bufbuild/protovalidate-go" "github.com/google/uuid" "github.com/prometheus/client_golang/prometheus" @@ -21,15 +21,15 @@ import ( // RoleServer holds a JWTManager and represents a RoleServiceServer. type RoleServer struct { apb.UnimplementedRoleServiceServer - jwtManager *rbac.JWTManager - roleService rbacInterfaces.RoleService + jwtManager *service.JWTManager + roleService ports.RoleService protoValidator *protovalidate.Validator } // NewRoleServer receives a JWTManager and a RoleService and returns a new RoleServer. func NewRoleServer( - jwtManager *rbac.JWTManager, - roleService rbacInterfaces.RoleService, + jwtManager *service.JWTManager, + roleService ports.RoleService, protoValidator *protovalidate.Validator, ) *RoleServer { return &RoleServer{ @@ -50,7 +50,7 @@ func (r RoleServer) CreateRoles(ctx context.Context, request *apb.CreateRolesReq } for _, rrole := range request.Roles { - role := rbac.NewRole(uuid.New(), rrole.Name, rrole.Description, rrole.Permissions) + role := model.NewRole(uuid.New(), rrole.Name, rrole.Description, rrole.Permissions) err := r.roleService.Add(role) if err != nil { @@ -151,7 +151,7 @@ func (r RoleServer) UpdateRoles(ctx context.Context, request *apb.UpdateRolesReq return nil, status.Errorf(codes.Canceled, "role not found %v", err) } - roleToUpdate := rbac.NewRole(rid, role.Name, role.Description, role.Permissions) + roleToUpdate := model.NewRole(rid, role.Name, role.Description, role.Permissions) err = r.roleService.Update(roleToUpdate) if err != nil { return nil, status.Errorf(codes.Aborted, "could not update role %v", err) diff --git a/controller/northbound/server/user.go b/controller/northbound/server/user.go index 66864315fb68460979ef8d5dc1c9568433652c16..9ad4d02ee6613b2c9e6356d4fe1a0fb3f4ac4715 100644 --- a/controller/northbound/server/user.go +++ b/controller/northbound/server/user.go @@ -9,10 +9,10 @@ import ( cpb "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/conflict" apb "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/rbac" "code.fbi.h-da.de/danet/gosdn/controller/conflict" - rbacInterfaces "code.fbi.h-da.de/danet/gosdn/controller/interfaces/rbac" "code.fbi.h-da.de/danet/gosdn/controller/metrics" + "code.fbi.h-da.de/danet/gosdn/controller/nucleus/domain/application/service" "code.fbi.h-da.de/danet/gosdn/controller/nucleus/domain/model" - "code.fbi.h-da.de/danet/gosdn/controller/rbac" + "code.fbi.h-da.de/danet/gosdn/controller/nucleus/domain/ports" "github.com/bufbuild/protovalidate-go" "github.com/google/uuid" "github.com/prometheus/client_golang/prometheus" @@ -27,13 +27,13 @@ import ( // UserServer holds a JWTManager and represents a UserServiceServer. type UserServer struct { apb.UnimplementedUserServiceServer - jwtManager *rbac.JWTManager - userService rbacInterfaces.UserService + jwtManager *service.JWTManager + userService ports.UserService protoValidator *protovalidate.Validator } // NewUserServer receives a JWTManager and a UserService and returns a new UserServer. -func NewUserServer(jwtManager *rbac.JWTManager, userService rbacInterfaces.UserService, protoValidator *protovalidate.Validator) *UserServer { +func NewUserServer(jwtManager *service.JWTManager, userService ports.UserService, protoValidator *protovalidate.Validator) *UserServer { return &UserServer{ jwtManager: jwtManager, userService: userService, @@ -74,7 +74,7 @@ func (u UserServer) CreateUsers(ctx context.Context, request *apb.CreateUsersReq hashedPassword := base64.RawStdEncoding.EncodeToString(argon2.IDKey([]byte(user.Password), []byte(salt), 1, 64*1024, 4, 32)) - user := rbac.NewUser(uuid.New(), user.Name, roles, string(hashedPassword), user.Token, salt, conflict.Metadata{ResourceVersion: 0}) + user := model.NewUser(uuid.New(), user.Name, roles, string(hashedPassword), user.Token, salt, conflict.Metadata{ResourceVersion: 0}) err = u.userService.Add(user) if err != nil { log.Error(err) @@ -181,13 +181,12 @@ func (u UserServer) UpdateUsers(ctx context.Context, request *apb.UpdateUsersReq hashedPassword := base64.RawStdEncoding.EncodeToString(argon2.IDKey([]byte(user.Password), []byte(storedUser.GetSalt()), 1, 64*1024, 4, 32)) - userToUpdate := rbac.NewUser(uid, user.Name, user.Roles, string(hashedPassword), user.Token, storedUser.GetSalt(), conflict.Metadata{ + userToUpdate := model.NewUser(uid, user.Name, user.Roles, string(hashedPassword), user.Token, storedUser.GetSalt(), conflict.Metadata{ ResourceVersion: int(user.Metadata.ResourceVersion)}) - usr, _ := userToUpdate.(*rbac.User) - usr.Metadata.ResourceVersion = int(user.Metadata.ResourceVersion) + userToUpdate.Metadata.ResourceVersion = int(user.Metadata.ResourceVersion) - err = u.userService.Update(usr) + err = u.userService.Update(userToUpdate) if err != nil { return nil, status.Errorf(codes.Aborted, "could not update user %v", err) } diff --git a/controller/rbac/jwtManager.go b/controller/nucleus/domain/application/service/jwtManager.go similarity index 93% rename from controller/rbac/jwtManager.go rename to controller/nucleus/domain/application/service/jwtManager.go index 3e76ec03865c399bcd686a91772180b99e324eba..72e2a789d1d1aaebf92da83676d142e1a623b513 100644 --- a/controller/rbac/jwtManager.go +++ b/controller/nucleus/domain/application/service/jwtManager.go @@ -1,8 +1,9 @@ -package rbac +package service import ( "time" + "code.fbi.h-da.de/danet/gosdn/controller/nucleus/domain/model" "github.com/golang-jwt/jwt" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" @@ -28,7 +29,7 @@ type UserClaims struct { } // GenerateToken generate a jwt for the user to use for authorization purposes. -func (man *JWTManager) GenerateToken(user User) (string, error) { +func (man *JWTManager) GenerateToken(user model.User) (string, error) { claims := UserClaims{ StandardClaims: jwt.StandardClaims{ExpiresAt: time.Now().Add(man.tokenDuration).Unix()}, Username: user.Name(), diff --git a/controller/rbac/jwtManager_test.go b/controller/nucleus/domain/application/service/jwtManager_test.go similarity index 99% rename from controller/rbac/jwtManager_test.go rename to controller/nucleus/domain/application/service/jwtManager_test.go index dd91e1ffcdc5145f6e642378232ca1e1f8064bea..de019abd1d918e6538d7b00a992fd2379a852133 100644 --- a/controller/rbac/jwtManager_test.go +++ b/controller/nucleus/domain/application/service/jwtManager_test.go @@ -1,4 +1,4 @@ -package rbac +package service import ( "reflect" diff --git a/controller/rbac/rbacService.go b/controller/nucleus/domain/application/service/rbacService.go similarity index 75% rename from controller/rbac/rbacService.go rename to controller/nucleus/domain/application/service/rbacService.go index 58e776ba2f9e921f6c7b3d4765900103a8861119..a865d083310866f7b2c2f3e4492917be08db5e70 100644 --- a/controller/rbac/rbacService.go +++ b/controller/nucleus/domain/application/service/rbacService.go @@ -1,8 +1,7 @@ -package rbac +package service import ( "code.fbi.h-da.de/danet/gosdn/controller/event" - "code.fbi.h-da.de/danet/gosdn/controller/interfaces/rbac" "code.fbi.h-da.de/danet/gosdn/controller/nucleus/domain/model" "code.fbi.h-da.de/danet/gosdn/controller/nucleus/domain/ports" "github.com/google/uuid" @@ -19,12 +18,12 @@ const ( // UserService provides a user service implementation. type UserService struct { - userStore rbac.UserStore + userStore ports.UserStore eventService ports.EventService } // NewUserService creates a user service. -func NewUserService(userStore rbac.UserStore, eventService ports.EventService) rbac.UserService { +func NewUserService(userStore ports.UserStore, eventService ports.EventService) ports.UserService { userService := &UserService{ userStore: userStore, eventService: eventService, @@ -34,7 +33,7 @@ func NewUserService(userStore rbac.UserStore, eventService ports.EventService) r } // Add adds a user to the user store. -func (s *UserService) Add(userToAdd rbac.User) error { +func (s *UserService) Add(userToAdd model.User) error { err := s.userStore.Add(userToAdd) if err != nil { return err @@ -56,7 +55,7 @@ func (s *UserService) Add(userToAdd rbac.User) error { } // Delete deletes a user from the user store. -func (s *UserService) Delete(userToDelete rbac.User) error { +func (s *UserService) Delete(userToDelete model.User) error { err := s.userStore.Delete(userToDelete) if err != nil { return err @@ -78,7 +77,7 @@ func (s *UserService) Delete(userToDelete rbac.User) error { } // Update updates a existing user. -func (s *UserService) Update(userToUpdate rbac.User) error { +func (s *UserService) Update(userToUpdate model.User) error { err := s.userStore.Update(userToUpdate) if err != nil { return err @@ -100,18 +99,18 @@ func (s *UserService) Update(userToUpdate rbac.User) error { } // Get takes a user's UUID or name and returns the user. -func (s *UserService) Get(query model.Query) (rbac.User, error) { +func (s *UserService) Get(query model.Query) (model.User, error) { loadedUser, err := s.userStore.Get(query) if err != nil { - return nil, err + return model.User{}, err } return s.createUserFromStore(loadedUser), nil } // GetAll returns all stored users. -func (s *UserService) GetAll() ([]rbac.User, error) { - var users []rbac.User +func (s *UserService) GetAll() ([]model.User, error) { + var users []model.User loadedUsers, err := s.userStore.GetAll() if err != nil { @@ -125,18 +124,18 @@ func (s *UserService) GetAll() ([]rbac.User, error) { return users, nil } -func (s *UserService) createUserFromStore(loadedUser rbac.LoadedUser) rbac.User { - return NewUser(uuid.MustParse(loadedUser.ID), loadedUser.UserName, loadedUser.Roles, loadedUser.Password, loadedUser.Token, loadedUser.Salt, loadedUser.Metadata) +func (s *UserService) createUserFromStore(loadedUser model.LoadedUser) model.User { + return model.NewUser(uuid.MustParse(loadedUser.ID), loadedUser.UserName, loadedUser.Roles, loadedUser.Password, loadedUser.Token, loadedUser.Salt, loadedUser.Metadata) } // RoleService provides a role service implementation. type RoleService struct { - roleStore rbac.RoleStore + roleStore ports.RoleStore eventService ports.EventService } // NewRoleService creates a role service. -func NewRoleService(roleStore rbac.RoleStore, eventService ports.EventService) rbac.RoleService { +func NewRoleService(roleStore ports.RoleStore, eventService ports.EventService) ports.RoleService { return &RoleService{ roleStore: roleStore, eventService: eventService, @@ -144,7 +143,7 @@ func NewRoleService(roleStore rbac.RoleStore, eventService ports.EventService) r } // Add adds a role to the role store. -func (s *RoleService) Add(roleToAdd rbac.Role) error { +func (s *RoleService) Add(roleToAdd model.Role) error { err := s.roleStore.Add(roleToAdd) if err != nil { return err @@ -166,7 +165,7 @@ func (s *RoleService) Add(roleToAdd rbac.Role) error { } // Delete deletes a role from the role store. -func (s *RoleService) Delete(roleToDelete rbac.Role) error { +func (s *RoleService) Delete(roleToDelete model.Role) error { err := s.roleStore.Delete(roleToDelete) if err != nil { return err @@ -187,7 +186,7 @@ func (s *RoleService) Delete(roleToDelete rbac.Role) error { } // Update updates a existing role. -func (s *RoleService) Update(roleToUpdate rbac.Role) error { +func (s *RoleService) Update(roleToUpdate model.Role) error { err := s.roleStore.Update(roleToUpdate) if err != nil { return err @@ -209,18 +208,18 @@ func (s *RoleService) Update(roleToUpdate rbac.Role) error { } // Get takes a roles's UUID or name and returns the role. -func (s *RoleService) Get(query model.Query) (rbac.Role, error) { +func (s *RoleService) Get(query model.Query) (model.Role, error) { loadedRole, err := s.roleStore.Get(query) if err != nil { - return nil, err + return model.Role{}, err } return s.createRoleFromStore(loadedRole), nil } // GetAll returns all stored roles. -func (s *RoleService) GetAll() ([]rbac.Role, error) { - var roles []rbac.Role +func (s *RoleService) GetAll() ([]model.Role, error) { + var roles []model.Role loadedRoles, err := s.roleStore.GetAll() if err != nil { @@ -234,6 +233,6 @@ func (s *RoleService) GetAll() ([]rbac.Role, error) { return roles, nil } -func (s *RoleService) createRoleFromStore(loadedRole rbac.LoadedRole) rbac.Role { - return NewRole(uuid.MustParse(loadedRole.ID), loadedRole.RoleName, loadedRole.Description, loadedRole.Permissions) +func (s *RoleService) createRoleFromStore(loadedRole model.LoadedRole) model.Role { + return model.NewRole(uuid.MustParse(loadedRole.ID), loadedRole.RoleName, loadedRole.Description, loadedRole.Permissions) } diff --git a/controller/rbac/role.go b/controller/nucleus/domain/model/role.go similarity index 88% rename from controller/rbac/role.go rename to controller/nucleus/domain/model/role.go index 0e7c01b14367ce8fd154cd03afe29a4cf5e50cc0..c46dc09b2513cabf7502758ded68291ac3fd0bc9 100644 --- a/controller/rbac/role.go +++ b/controller/nucleus/domain/model/role.go @@ -1,9 +1,8 @@ -package rbac +package model import ( "encoding/json" - "code.fbi.h-da.de/danet/gosdn/controller/interfaces/rbac" "github.com/google/uuid" "go.mongodb.org/mongo-driver/bson" ) @@ -16,12 +15,20 @@ type Role struct { Permissions []string `json:"permissions,omitempty"` } +// LoadedRole represents a Role that was loaded. +type LoadedRole struct { + ID string `json:"_id" bson:"_id"` + RoleName string `json:"rolename"` + Description string `json:"description,omitempty"` + Permissions []string `json:"permissions,omitempty"` +} + // NewRole creates a new role. func NewRole(id uuid.UUID, name string, description string, - permissions []string) rbac.Role { - return &Role{ + permissions []string) Role { + return Role{ RoleID: id, RoleName: name, Description: description, diff --git a/controller/rbac/user.go b/controller/nucleus/domain/model/user.go similarity index 86% rename from controller/rbac/user.go rename to controller/nucleus/domain/model/user.go index d0b5ae14fa35d299db531500a0b0d286d127fc89..ed47d57b77450d5c26383bbfcd96c97dc3bc6e73 100644 --- a/controller/rbac/user.go +++ b/controller/nucleus/domain/model/user.go @@ -1,10 +1,9 @@ -package rbac +package model import ( "encoding/json" "code.fbi.h-da.de/danet/gosdn/controller/conflict" - "code.fbi.h-da.de/danet/gosdn/controller/interfaces/rbac" "github.com/google/uuid" "go.mongodb.org/mongo-driver/bson" ) @@ -20,6 +19,17 @@ type User struct { Salt string `json:"salt"` } +// LoadedUser represents a User that was loaded. +type LoadedUser struct { + ID string `json:"_id" bson:"_id"` + UserName string `json:"username"` + Roles map[string]string `json:"roles,omitempty"` + Password string `json:"password"` + Token string `json:"token,omitempty"` + Salt string `json:"salt" bson:"salt"` + Metadata conflict.Metadata `json:"metadata" bson:"metadata"` +} + // NewUser creates a new user. func NewUser(id uuid.UUID, name string, @@ -28,8 +38,8 @@ func NewUser(id uuid.UUID, token string, salt string, metadata conflict.Metadata, -) rbac.User { - return &User{ +) User { + return User{ UserID: id, UserName: name, Roles: roles, diff --git a/controller/nucleus/domain/ports/rbac.go b/controller/nucleus/domain/ports/rbac.go new file mode 100644 index 0000000000000000000000000000000000000000..82fb9383f8dfd845371c4811d841e69febf79dad --- /dev/null +++ b/controller/nucleus/domain/ports/rbac.go @@ -0,0 +1,27 @@ +package ports + +import ( + "code.fbi.h-da.de/danet/gosdn/controller/conflict" + "github.com/google/uuid" +) + +// Role represents a role with permissions. +type Role interface { + ID() uuid.UUID + Name() string + GetDescription() string + GetPermissions() []string + RemovePermissionsFromRole([]string) +} + +// User represents an User which is managed by rbac. +type User interface { + ID() uuid.UUID + Name() string + GetRoles() map[string]string + GetPassword() string + GetToken() string + SetToken(string) + GetSalt() string + GetMetadata() conflict.Metadata +} diff --git a/controller/nucleus/domain/ports/service.go b/controller/nucleus/domain/ports/service.go index b059e4a0cd3133718987985c7a1039b0b49fa473..8210dc85c24a458505c6932a4335db0bf66e4c97 100644 --- a/controller/nucleus/domain/ports/service.go +++ b/controller/nucleus/domain/ports/service.go @@ -44,3 +44,21 @@ type EventService interface { RetryPublish(topic string, event event.Event) error Reconnect() } + +// UserService describes an interface for user service implementation. +type UserService interface { + Add(model.User) error + Delete(model.User) error + Update(model.User) error + Get(model.Query) (model.User, error) + GetAll() ([]model.User, error) +} + +// RoleService describes an interface for role service implementations. +type RoleService interface { + Add(model.Role) error + Delete(model.Role) error + Update(model.Role) error + Get(model.Query) (model.Role, error) + GetAll() ([]model.Role, error) +} diff --git a/controller/nucleus/domain/ports/store.go b/controller/nucleus/domain/ports/store.go index d220dd8a960c7f57790d6da3f7e68a9b8d13318d..a355705629acbe7107fd63709e9e3e3c0a41a9c5 100644 --- a/controller/nucleus/domain/ports/store.go +++ b/controller/nucleus/domain/ports/store.go @@ -33,3 +33,21 @@ type PndStore interface { AddPendingChannel(id uuid.UUID, ch chan model.Details) RemovePendingChannel(id uuid.UUID) } + +// RoleStore describes an interface for role store implementations. +type RoleStore interface { + Add(r model.Role) error + Update(r model.Role) error + Delete(model.Role) error + Get(model.Query) (model.LoadedRole, error) + GetAll() ([]model.LoadedRole, error) +} + +// UserStore describes an interface for user store implementations. +type UserStore interface { + Add(u model.User) error + Update(u model.User) error + Delete(model.User) error + Get(model.Query) (model.LoadedUser, error) + GetAll() ([]model.LoadedUser, error) +} diff --git a/controller/rbac/rbacTestUtil_test.go b/controller/nucleus/pkg/persistence/filesystem/rbacTestUtil_test.go similarity index 96% rename from controller/rbac/rbacTestUtil_test.go rename to controller/nucleus/pkg/persistence/filesystem/rbacTestUtil_test.go index dd007e3b18472edf4c5089665c5417993bfb947e..737e9dcf610b2159ab041baa20863b054c0d38d7 100644 --- a/controller/rbac/rbacTestUtil_test.go +++ b/controller/nucleus/pkg/persistence/filesystem/rbacTestUtil_test.go @@ -1,4 +1,4 @@ -package rbac +package filesystem import ( "log" diff --git a/controller/rbac/roleFileSystemStore.go b/controller/nucleus/pkg/persistence/filesystem/roleFileSystemStore.go similarity index 76% rename from controller/rbac/roleFileSystemStore.go rename to controller/nucleus/pkg/persistence/filesystem/roleFileSystemStore.go index 5850e023af259bcf6ac1638ae8a4f6c6117ef247..89fe9ec0a651a591e34019c931c9901cd1591b50 100644 --- a/controller/rbac/roleFileSystemStore.go +++ b/controller/nucleus/pkg/persistence/filesystem/roleFileSystemStore.go @@ -1,4 +1,4 @@ -package rbac +package filesystem import ( "encoding/json" @@ -6,8 +6,8 @@ import ( "sync" "code.fbi.h-da.de/danet/gosdn/controller/customerrs" - "code.fbi.h-da.de/danet/gosdn/controller/interfaces/rbac" "code.fbi.h-da.de/danet/gosdn/controller/nucleus/domain/model" + "code.fbi.h-da.de/danet/gosdn/controller/nucleus/domain/ports" "code.fbi.h-da.de/danet/gosdn/controller/store" log "github.com/sirupsen/logrus" ) @@ -19,7 +19,7 @@ type FileSystemRoleStore struct { } // NewFileSystemRoleStore returns a filesystem implementation for a role store. -func NewFileSystemRoleStore() rbac.RoleStore { +func NewFileSystemRoleStore() ports.RoleStore { if err := store.EnsureFilesystemStorePathExists(store.RoleFilename); err != nil { log.Error(err) } @@ -30,8 +30,8 @@ func NewFileSystemRoleStore() rbac.RoleStore { } } -func (s *FileSystemRoleStore) readAllRolesFromFile() ([]rbac.LoadedRole, error) { - var loadedRoles []rbac.LoadedRole +func (s *FileSystemRoleStore) readAllRolesFromFile() ([]model.LoadedRole, error) { + var loadedRoles []model.LoadedRole content, err := os.ReadFile(s.pathToRoleFile) if err != nil { return nil, err @@ -45,7 +45,7 @@ func (s *FileSystemRoleStore) readAllRolesFromFile() ([]rbac.LoadedRole, error) return loadedRoles, nil } -func (s *FileSystemRoleStore) writeAllRolesToFile(roles []rbac.LoadedRole) error { +func (s *FileSystemRoleStore) writeAllRolesToFile(roles []model.LoadedRole) error { serializedData, err := json.Marshal(roles) if err != nil { return err @@ -60,7 +60,7 @@ func (s *FileSystemRoleStore) writeAllRolesToFile(roles []rbac.LoadedRole) error } // Add adds a Role to the Role store. -func (s *FileSystemRoleStore) Add(roleToAdd rbac.Role) error { +func (s *FileSystemRoleStore) Add(roleToAdd model.Role) error { s.fileMutex.Lock() defer s.fileMutex.Unlock() @@ -69,8 +69,8 @@ func (s *FileSystemRoleStore) Add(roleToAdd rbac.Role) error { return err } - var loadedRole rbac.LoadedRole - loadedRole, err = store.TransformObjectToLoadedObject[rbac.Role, rbac.LoadedRole](roleToAdd) + var loadedRole model.LoadedRole + loadedRole, err = store.TransformObjectToLoadedObject[model.Role, model.LoadedRole](roleToAdd) if err != nil { return err } @@ -86,7 +86,7 @@ func (s *FileSystemRoleStore) Add(roleToAdd rbac.Role) error { } // Delete deletes a Role from the Role store. -func (s *FileSystemRoleStore) Delete(roleToDelete rbac.Role) error { +func (s *FileSystemRoleStore) Delete(roleToDelete model.Role) error { s.fileMutex.Lock() defer s.fileMutex.Unlock() @@ -114,11 +114,11 @@ func (s *FileSystemRoleStore) Delete(roleToDelete rbac.Role) error { } // Get takes a Roles ID and return the Role if found. -func (s *FileSystemRoleStore) Get(query model.Query) (rbac.LoadedRole, error) { +func (s *FileSystemRoleStore) Get(query model.Query) (model.LoadedRole, error) { s.fileMutex.Lock() defer s.fileMutex.Unlock() - var role rbac.LoadedRole + var role model.LoadedRole roles, err := s.readAllRolesFromFile() if err != nil { return role, err @@ -134,7 +134,7 @@ func (s *FileSystemRoleStore) Get(query model.Query) (rbac.LoadedRole, error) { } // GetAll returns all the Roles. -func (s *FileSystemRoleStore) GetAll() ([]rbac.LoadedRole, error) { +func (s *FileSystemRoleStore) GetAll() ([]model.LoadedRole, error) { s.fileMutex.Lock() defer s.fileMutex.Unlock() @@ -143,11 +143,11 @@ func (s *FileSystemRoleStore) GetAll() ([]rbac.LoadedRole, error) { } // Update updates an exsisting Role. -func (s *FileSystemRoleStore) Update(roleToUpdate rbac.Role) error { +func (s *FileSystemRoleStore) Update(roleToUpdate model.Role) error { s.fileMutex.Lock() defer s.fileMutex.Unlock() - loadedRole, err := store.TransformObjectToLoadedObject[rbac.Role, rbac.LoadedRole](roleToUpdate) + loadedRole, err := store.TransformObjectToLoadedObject[model.Role, model.LoadedRole](roleToUpdate) if err != nil { return err } diff --git a/controller/rbac/roleFileSystemStore_test.go b/controller/nucleus/pkg/persistence/filesystem/roleFileSystemStore_test.go similarity index 99% rename from controller/rbac/roleFileSystemStore_test.go rename to controller/nucleus/pkg/persistence/filesystem/roleFileSystemStore_test.go index 0906f1e6b17a5fd117ec19f360d991204eded012..fd69440d8ea837fd75edd2d1a9a4076e7beea06f 100644 --- a/controller/rbac/roleFileSystemStore_test.go +++ b/controller/nucleus/pkg/persistence/filesystem/roleFileSystemStore_test.go @@ -1,4 +1,4 @@ -package rbac +package filesystem import ( "reflect" diff --git a/controller/rbac/userFileSystemStore.go b/controller/nucleus/pkg/persistence/filesystem/userFileSystemStore.go similarity index 76% rename from controller/rbac/userFileSystemStore.go rename to controller/nucleus/pkg/persistence/filesystem/userFileSystemStore.go index 2bd90fd7aaf1357c42f794f9411fa0b0b6a00f67..98258c5db67e11461435c422fa9d07debd977e02 100644 --- a/controller/rbac/userFileSystemStore.go +++ b/controller/nucleus/pkg/persistence/filesystem/userFileSystemStore.go @@ -1,4 +1,4 @@ -package rbac +package filesystem import ( "encoding/json" @@ -6,8 +6,8 @@ import ( "sync" "code.fbi.h-da.de/danet/gosdn/controller/customerrs" - "code.fbi.h-da.de/danet/gosdn/controller/interfaces/rbac" "code.fbi.h-da.de/danet/gosdn/controller/nucleus/domain/model" + "code.fbi.h-da.de/danet/gosdn/controller/nucleus/domain/ports" "code.fbi.h-da.de/danet/gosdn/controller/store" log "github.com/sirupsen/logrus" ) @@ -19,7 +19,7 @@ type FileSystemUserStore struct { } // NewFileSystemUserStore returns a filesystem implementation for a user store. -func NewFileSystemUserStore() rbac.UserStore { +func NewFileSystemUserStore() ports.UserStore { if err := store.EnsureFilesystemStorePathExists(store.UserFilename); err != nil { log.Error(err) } @@ -30,8 +30,8 @@ func NewFileSystemUserStore() rbac.UserStore { } } -func (s *FileSystemUserStore) readAllUsersFromFile() ([]rbac.LoadedUser, error) { - var loadedUsers []rbac.LoadedUser +func (s *FileSystemUserStore) readAllUsersFromFile() ([]model.LoadedUser, error) { + var loadedUsers []model.LoadedUser content, err := os.ReadFile(s.pathToUserFile) if err != nil { return nil, err @@ -45,7 +45,7 @@ func (s *FileSystemUserStore) readAllUsersFromFile() ([]rbac.LoadedUser, error) return loadedUsers, nil } -func (s *FileSystemUserStore) writeAllUsersToFile(users []rbac.LoadedUser) error { +func (s *FileSystemUserStore) writeAllUsersToFile(users []model.LoadedUser) error { serializedData, err := json.Marshal(users) if err != nil { return err @@ -60,7 +60,7 @@ func (s *FileSystemUserStore) writeAllUsersToFile(users []rbac.LoadedUser) error } // Add adds a User to the User store. -func (s *FileSystemUserStore) Add(UserToAdd rbac.User) error { +func (s *FileSystemUserStore) Add(UserToAdd model.User) error { s.fileMutex.Lock() defer s.fileMutex.Unlock() @@ -69,8 +69,8 @@ func (s *FileSystemUserStore) Add(UserToAdd rbac.User) error { return err } - var loadedUser rbac.LoadedUser - loadedUser, err = store.TransformObjectToLoadedObject[rbac.User, rbac.LoadedUser](UserToAdd) + var loadedUser model.LoadedUser + loadedUser, err = store.TransformObjectToLoadedObject[model.User, model.LoadedUser](UserToAdd) if err != nil { return err } @@ -86,7 +86,7 @@ func (s *FileSystemUserStore) Add(UserToAdd rbac.User) error { } // Delete deletes a User from the User store. -func (s *FileSystemUserStore) Delete(userToDelete rbac.User) error { +func (s *FileSystemUserStore) Delete(userToDelete model.User) error { s.fileMutex.Lock() defer s.fileMutex.Unlock() @@ -114,11 +114,11 @@ func (s *FileSystemUserStore) Delete(userToDelete rbac.User) error { } // Get takes a Users ID and return the User if found. -func (s *FileSystemUserStore) Get(query model.Query) (rbac.LoadedUser, error) { +func (s *FileSystemUserStore) Get(query model.Query) (model.LoadedUser, error) { s.fileMutex.Lock() defer s.fileMutex.Unlock() - var user rbac.LoadedUser + var user model.LoadedUser users, err := s.readAllUsersFromFile() if err != nil { @@ -134,7 +134,7 @@ func (s *FileSystemUserStore) Get(query model.Query) (rbac.LoadedUser, error) { } // GetAll returns all the Users. -func (s *FileSystemUserStore) GetAll() ([]rbac.LoadedUser, error) { +func (s *FileSystemUserStore) GetAll() ([]model.LoadedUser, error) { s.fileMutex.Lock() defer s.fileMutex.Unlock() @@ -143,11 +143,11 @@ func (s *FileSystemUserStore) GetAll() ([]rbac.LoadedUser, error) { } // Update updates an exsisting user. -func (s *FileSystemUserStore) Update(userToUpdate rbac.User) error { +func (s *FileSystemUserStore) Update(userToUpdate model.User) error { s.fileMutex.Lock() defer s.fileMutex.Unlock() - loadedUser, err := store.TransformObjectToLoadedObject[rbac.User, rbac.LoadedUser](userToUpdate) + loadedUser, err := store.TransformObjectToLoadedObject[model.User, model.LoadedUser](userToUpdate) if err != nil { return err } diff --git a/controller/rbac/userFileSystemStore_test.go b/controller/nucleus/pkg/persistence/filesystem/userFileSystemStore_test.go similarity index 99% rename from controller/rbac/userFileSystemStore_test.go rename to controller/nucleus/pkg/persistence/filesystem/userFileSystemStore_test.go index b7a1c6d71d238d67b8c98475b65f05e9afd16d6e..19830d77c29c119595979878affded07bdfbfe89 100644 --- a/controller/rbac/userFileSystemStore_test.go +++ b/controller/nucleus/pkg/persistence/filesystem/userFileSystemStore_test.go @@ -1,4 +1,4 @@ -package rbac +package filesystem import ( "reflect" diff --git a/controller/rbac/memoryRoleStore.go b/controller/nucleus/pkg/persistence/memory/memoryRoleStore.go similarity index 100% rename from controller/rbac/memoryRoleStore.go rename to controller/nucleus/pkg/persistence/memory/memoryRoleStore.go diff --git a/controller/rbac/memoryUserStore.go b/controller/nucleus/pkg/persistence/memory/memoryUserStore.go similarity index 100% rename from controller/rbac/memoryUserStore.go rename to controller/nucleus/pkg/persistence/memory/memoryUserStore.go diff --git a/controller/rbac/databaseRoleStore.go b/controller/nucleus/pkg/persistence/mongodb/databaseRoleStore.go similarity index 78% rename from controller/rbac/databaseRoleStore.go rename to controller/nucleus/pkg/persistence/mongodb/databaseRoleStore.go index bf45a8d0c624b2bd562545389f39cc848adb698a..7cb4ebb61df57e063e942e7d3ff0ef383c8e4fcb 100644 --- a/controller/rbac/databaseRoleStore.go +++ b/controller/nucleus/pkg/persistence/mongodb/databaseRoleStore.go @@ -1,12 +1,11 @@ -package rbac +package mongodb import ( "fmt" "code.fbi.h-da.de/danet/gosdn/controller/customerrs" - "code.fbi.h-da.de/danet/gosdn/controller/interfaces/rbac" "code.fbi.h-da.de/danet/gosdn/controller/nucleus/domain/model" - "code.fbi.h-da.de/danet/gosdn/controller/nucleus/pkg/persistence/mongodb" + "code.fbi.h-da.de/danet/gosdn/controller/nucleus/domain/ports" "github.com/google/uuid" log "github.com/sirupsen/logrus" "go.mongodb.org/mongo-driver/bson" @@ -20,9 +19,13 @@ type DatabaseRoleStore struct { roleStoreName string } +func NewDatabaseRoleStore() ports.RoleStore { + return &DatabaseRoleStore{roleStoreName: "role.json"} +} + // Add adds a Role. -func (s *DatabaseRoleStore) Add(roleToAdd rbac.Role) (err error) { - client, ctx, cancel := mongodb.GetMongoConnection() +func (s *DatabaseRoleStore) Add(roleToAdd model.Role) (err error) { + client, ctx, cancel := GetMongoConnection() defer cancel() defer func() { if ferr := client.Disconnect(ctx); ferr != nil { @@ -31,7 +34,7 @@ func (s *DatabaseRoleStore) Add(roleToAdd rbac.Role) (err error) { } }() - _, err = client.Database(mongodb.DatabaseName). + _, err = client.Database(DatabaseName). Collection(s.roleStoreName). InsertOne(ctx, roleToAdd) if err != nil { @@ -46,8 +49,8 @@ func (s *DatabaseRoleStore) Add(roleToAdd rbac.Role) (err error) { } // Delete deletes a Role. -func (s *DatabaseRoleStore) Delete(roleToDelete rbac.Role) (err error) { - client, ctx, cancel := mongodb.GetMongoConnection() +func (s *DatabaseRoleStore) Delete(roleToDelete model.Role) (err error) { + client, ctx, cancel := GetMongoConnection() defer cancel() defer func() { if ferr := client.Disconnect(ctx); ferr != nil { @@ -56,7 +59,7 @@ func (s *DatabaseRoleStore) Delete(roleToDelete rbac.Role) (err error) { } }() - _, err = client.Database(mongodb.DatabaseName). + _, err = client.Database(DatabaseName). Collection(s.roleStoreName). DeleteOne(ctx, bson.D{primitive.E{Key: "_id", Value: roleToDelete.ID().String()}}) if err != nil { @@ -68,8 +71,8 @@ func (s *DatabaseRoleStore) Delete(roleToDelete rbac.Role) (err error) { // Get takes a Roles's UUID or name and returns the Role. If the requested // Role does not exist an error is returned. -func (s *DatabaseRoleStore) Get(query model.Query) (rbac.LoadedRole, error) { - var loadedRole rbac.LoadedRole +func (s *DatabaseRoleStore) Get(query model.Query) (model.LoadedRole, error) { + var loadedRole model.LoadedRole if query.ID != uuid.Nil { loadedRole, err := s.getByID(query.ID) @@ -88,8 +91,8 @@ func (s *DatabaseRoleStore) Get(query model.Query) (rbac.LoadedRole, error) { return loadedRole, nil } -func (s *DatabaseRoleStore) getByID(idOfRole uuid.UUID) (loadedRole rbac.LoadedRole, err error) { - client, ctx, cancel := mongodb.GetMongoConnection() +func (s *DatabaseRoleStore) getByID(idOfRole uuid.UUID) (loadedRole model.LoadedRole, err error) { + client, ctx, cancel := GetMongoConnection() defer cancel() defer func() { if ferr := client.Disconnect(ctx); ferr != nil { @@ -98,7 +101,7 @@ func (s *DatabaseRoleStore) getByID(idOfRole uuid.UUID) (loadedRole rbac.LoadedR } }() - db := client.Database(mongodb.DatabaseName) + db := client.Database(DatabaseName) collection := db.Collection(s.roleStoreName) result := collection.FindOne(ctx, bson.D{primitive.E{Key: "_id", Value: idOfRole.String()}}) if result == nil { @@ -114,8 +117,8 @@ func (s *DatabaseRoleStore) getByID(idOfRole uuid.UUID) (loadedRole rbac.LoadedR return loadedRole, nil } -func (s *DatabaseRoleStore) getByName(nameOfRole string) (loadedRole rbac.LoadedRole, err error) { - client, ctx, cancel := mongodb.GetMongoConnection() +func (s *DatabaseRoleStore) getByName(nameOfRole string) (loadedRole model.LoadedRole, err error) { + client, ctx, cancel := GetMongoConnection() defer cancel() defer func() { if ferr := client.Disconnect(ctx); ferr != nil { @@ -124,7 +127,7 @@ func (s *DatabaseRoleStore) getByName(nameOfRole string) (loadedRole rbac.Loaded } }() - db := client.Database(mongodb.DatabaseName) + db := client.Database(DatabaseName) collection := db.Collection(s.roleStoreName) result := collection.FindOne(ctx, bson.D{primitive.E{Key: "rolename", Value: nameOfRole}}) if result == nil { @@ -141,8 +144,8 @@ func (s *DatabaseRoleStore) getByName(nameOfRole string) (loadedRole rbac.Loaded } // GetAll returns all Roles. -func (s *DatabaseRoleStore) GetAll() (loadedRoles []rbac.LoadedRole, err error) { - client, ctx, cancel := mongodb.GetMongoConnection() +func (s *DatabaseRoleStore) GetAll() (loadedRoles []model.LoadedRole, err error) { + client, ctx, cancel := GetMongoConnection() defer cancel() defer func() { if ferr := client.Disconnect(ctx); ferr != nil { @@ -151,7 +154,7 @@ func (s *DatabaseRoleStore) GetAll() (loadedRoles []rbac.LoadedRole, err error) } }() - db := client.Database(mongodb.DatabaseName) + db := client.Database(DatabaseName) collection := db.Collection(s.roleStoreName) cursor, err := collection.Find(ctx, bson.D{}) @@ -175,10 +178,10 @@ func (s *DatabaseRoleStore) GetAll() (loadedRoles []rbac.LoadedRole, err error) } // Update updates the role. -func (s *DatabaseRoleStore) Update(roleToUpdate rbac.Role) (err error) { - var updatedLoadedRole rbac.LoadedRole +func (s *DatabaseRoleStore) Update(roleToUpdate model.Role) (err error) { + var updatedLoadedRole model.LoadedRole - client, ctx, cancel := mongodb.GetMongoConnection() + client, ctx, cancel := GetMongoConnection() defer cancel() defer func() { if ferr := client.Disconnect(ctx); ferr != nil { @@ -195,7 +198,7 @@ func (s *DatabaseRoleStore) Update(roleToUpdate rbac.Role) (err error) { ReturnDocument: &after, } - err = client.Database(mongodb.DatabaseName). + err = client.Database(DatabaseName). Collection(s.roleStoreName). FindOneAndUpdate( ctx, bson.M{"_id": roleToUpdate.ID().String()}, update, &opt). diff --git a/controller/rbac/databaseUserStore.go b/controller/nucleus/pkg/persistence/mongodb/databaseUserStore.go similarity index 81% rename from controller/rbac/databaseUserStore.go rename to controller/nucleus/pkg/persistence/mongodb/databaseUserStore.go index bf1a9e18a3091320b02bceca5185f467a1973f78..5b72db57fb4da212f38dd16da5206828132be360 100644 --- a/controller/rbac/databaseUserStore.go +++ b/controller/nucleus/pkg/persistence/mongodb/databaseUserStore.go @@ -1,12 +1,11 @@ -package rbac +package mongodb import ( "fmt" "code.fbi.h-da.de/danet/gosdn/controller/customerrs" - "code.fbi.h-da.de/danet/gosdn/controller/interfaces/rbac" "code.fbi.h-da.de/danet/gosdn/controller/nucleus/domain/model" - "code.fbi.h-da.de/danet/gosdn/controller/nucleus/pkg/persistence/mongodb" + "code.fbi.h-da.de/danet/gosdn/controller/nucleus/domain/ports" "github.com/google/uuid" log "github.com/sirupsen/logrus" "go.mongodb.org/mongo-driver/bson" @@ -21,9 +20,13 @@ type DatabaseUserStore struct { userStoreName string } +func NewDatabaseUserStore() ports.UserStore { + return &DatabaseUserStore{userStoreName: "user.json"} +} + // Add adds an User. -func (s *DatabaseUserStore) Add(userToAdd rbac.User) (err error) { - client, ctx, cancel := mongodb.GetMongoConnection() +func (s *DatabaseUserStore) Add(userToAdd model.User) (err error) { + client, ctx, cancel := GetMongoConnection() defer cancel() defer func() { if ferr := client.Disconnect(ctx); ferr != nil { @@ -32,7 +35,7 @@ func (s *DatabaseUserStore) Add(userToAdd rbac.User) (err error) { } }() - _, err = client.Database(mongodb.DatabaseName). + _, err = client.Database(DatabaseName). Collection(s.userStoreName). InsertOne(ctx, userToAdd) if err != nil { @@ -47,8 +50,8 @@ func (s *DatabaseUserStore) Add(userToAdd rbac.User) (err error) { } // Delete deletes an User. -func (s *DatabaseUserStore) Delete(userToDelete rbac.User) (err error) { - client, ctx, cancel := mongodb.GetMongoConnection() +func (s *DatabaseUserStore) Delete(userToDelete model.User) (err error) { + client, ctx, cancel := GetMongoConnection() defer cancel() defer func() { if ferr := client.Disconnect(ctx); ferr != nil { @@ -57,7 +60,7 @@ func (s *DatabaseUserStore) Delete(userToDelete rbac.User) (err error) { } }() - _, err = client.Database(mongodb.DatabaseName). + _, err = client.Database(DatabaseName). Collection(s.userStoreName). DeleteOne(ctx, bson.D{primitive.E{Key: "_id", Value: userToDelete.ID().String()}}) if err != nil { @@ -69,8 +72,8 @@ func (s *DatabaseUserStore) Delete(userToDelete rbac.User) (err error) { // Get takes a User's UUID or name and returns the User. If the requested // User does not exist an error is returned. -func (s *DatabaseUserStore) Get(query model.Query) (rbac.LoadedUser, error) { - var loadedUser rbac.LoadedUser +func (s *DatabaseUserStore) Get(query model.Query) (model.LoadedUser, error) { + var loadedUser model.LoadedUser if query.ID != uuid.Nil { loadedUser, err := s.getByID(query.ID) @@ -89,8 +92,8 @@ func (s *DatabaseUserStore) Get(query model.Query) (rbac.LoadedUser, error) { return loadedUser, nil } -func (s *DatabaseUserStore) getByID(idOfUser uuid.UUID) (loadedUser rbac.LoadedUser, err error) { - client, ctx, cancel := mongodb.GetMongoConnection() +func (s *DatabaseUserStore) getByID(idOfUser uuid.UUID) (loadedUser model.LoadedUser, err error) { + client, ctx, cancel := GetMongoConnection() defer cancel() defer func() { if ferr := client.Disconnect(ctx); ferr != nil { @@ -99,7 +102,7 @@ func (s *DatabaseUserStore) getByID(idOfUser uuid.UUID) (loadedUser rbac.LoadedU } }() - db := client.Database(mongodb.DatabaseName) + db := client.Database(DatabaseName) collection := db.Collection(s.userStoreName) result := collection.FindOne(ctx, bson.D{primitive.E{Key: "_id", Value: idOfUser.String()}}) if result == nil { @@ -115,8 +118,8 @@ func (s *DatabaseUserStore) getByID(idOfUser uuid.UUID) (loadedUser rbac.LoadedU return loadedUser, nil } -func (s *DatabaseUserStore) getByName(nameOfUser string) (loadedUser rbac.LoadedUser, err error) { - client, ctx, cancel := mongodb.GetMongoConnection() +func (s *DatabaseUserStore) getByName(nameOfUser string) (loadedUser model.LoadedUser, err error) { + client, ctx, cancel := GetMongoConnection() defer cancel() defer func() { if ferr := client.Disconnect(ctx); ferr != nil { @@ -125,7 +128,7 @@ func (s *DatabaseUserStore) getByName(nameOfUser string) (loadedUser rbac.Loaded } }() - db := client.Database(mongodb.DatabaseName) + db := client.Database(DatabaseName) collection := db.Collection(s.userStoreName) result := collection.FindOne(ctx, bson.D{primitive.E{Key: "username", Value: nameOfUser}}) if result == nil { @@ -142,8 +145,8 @@ func (s *DatabaseUserStore) getByName(nameOfUser string) (loadedUser rbac.Loaded } // GetAll returns all Users. -func (s *DatabaseUserStore) GetAll() (loadedUsers []rbac.LoadedUser, err error) { - client, ctx, cancel := mongodb.GetMongoConnection() +func (s *DatabaseUserStore) GetAll() (loadedUsers []model.LoadedUser, err error) { + client, ctx, cancel := GetMongoConnection() defer cancel() defer func() { if ferr := client.Disconnect(ctx); ferr != nil { @@ -152,7 +155,7 @@ func (s *DatabaseUserStore) GetAll() (loadedUsers []rbac.LoadedUser, err error) } }() - db := client.Database(mongodb.DatabaseName) + db := client.Database(DatabaseName) collection := db.Collection(s.userStoreName) cursor, err := collection.Find(ctx, bson.D{}) @@ -176,10 +179,10 @@ func (s *DatabaseUserStore) GetAll() (loadedUsers []rbac.LoadedUser, err error) } // Update updates the User. -func (s *DatabaseUserStore) Update(userToUpdate rbac.User) (err error) { - var updatedLoadedUser rbac.LoadedUser +func (s *DatabaseUserStore) Update(userToUpdate model.User) (err error) { + var updatedLoadedUser model.LoadedUser - client, ctx, cancel := mongodb.GetMongoConnection() + client, ctx, cancel := GetMongoConnection() defer cancel() defer func() { if ferr := client.Disconnect(ctx); ferr != nil { @@ -191,7 +194,7 @@ func (s *DatabaseUserStore) Update(userToUpdate rbac.User) (err error) { // 1. Start Transaction wcMajority := writeconcern.Majority() wcMajorityCollectionOpts := options.Collection().SetWriteConcern(wcMajority) - userCollection := client.Database(mongodb.DatabaseName).Collection(s.userStoreName, wcMajorityCollectionOpts) + userCollection := client.Database(DatabaseName).Collection(s.userStoreName, wcMajorityCollectionOpts) session, err := client.StartSession() if err != nil { @@ -222,7 +225,7 @@ func (s *DatabaseUserStore) Update(userToUpdate rbac.User) (err error) { // Important: You must pass sessCtx as the Context parameter to the operations for them to be executed in the // transaction. - u, _ := userToUpdate.(*User) + u := userToUpdate u.Metadata.ResourceVersion = u.Metadata.ResourceVersion + 1 update := bson.D{primitive.E{Key: "$set", Value: u}} diff --git a/controller/nucleus/pkg/persistence/roleStore.go b/controller/nucleus/pkg/persistence/roleStore.go new file mode 100644 index 0000000000000000000000000000000000000000..4a00aaf3eaec5d4af26aad108821c7391542ce97 --- /dev/null +++ b/controller/nucleus/pkg/persistence/roleStore.go @@ -0,0 +1,21 @@ +package persistence + +import ( + "code.fbi.h-da.de/danet/gosdn/controller/nucleus/domain/ports" + "code.fbi.h-da.de/danet/gosdn/controller/nucleus/pkg/persistence/filesystem" + "code.fbi.h-da.de/danet/gosdn/controller/nucleus/pkg/persistence/mongodb" + "code.fbi.h-da.de/danet/gosdn/controller/store" +) + +// NewRoleStore returns a roleStore. +func NewRoleStore() ports.RoleStore { + storeMode := store.GetStoreMode() + + switch storeMode { + case store.Database: + return mongodb.NewDatabaseRoleStore() + default: + store := filesystem.NewFileSystemRoleStore() + return store + } +} diff --git a/controller/nucleus/pkg/persistence/userStore.go b/controller/nucleus/pkg/persistence/userStore.go new file mode 100644 index 0000000000000000000000000000000000000000..a451a9d4e932c65b9a92bb31c4bfc0c4149c42a6 --- /dev/null +++ b/controller/nucleus/pkg/persistence/userStore.go @@ -0,0 +1,21 @@ +package persistence + +import ( + "code.fbi.h-da.de/danet/gosdn/controller/nucleus/domain/ports" + "code.fbi.h-da.de/danet/gosdn/controller/nucleus/pkg/persistence/filesystem" + "code.fbi.h-da.de/danet/gosdn/controller/nucleus/pkg/persistence/mongodb" + "code.fbi.h-da.de/danet/gosdn/controller/store" +) + +// NewUserStore returns a userStore. +func NewUserStore() ports.UserStore { + storeMode := store.GetStoreMode() + + switch storeMode { + case store.Database: + return mongodb.NewDatabaseUserStore() + default: + store := filesystem.NewFileSystemUserStore() + return store + } +} diff --git a/controller/rbac/roleStore.go b/controller/rbac/roleStore.go deleted file mode 100644 index ad76beaa75e173ff92cddcb0d80c69597a29f401..0000000000000000000000000000000000000000 --- a/controller/rbac/roleStore.go +++ /dev/null @@ -1,19 +0,0 @@ -package rbac - -import ( - "code.fbi.h-da.de/danet/gosdn/controller/interfaces/rbac" - "code.fbi.h-da.de/danet/gosdn/controller/store" -) - -// NewRoleStore returns a roleStore. -func NewRoleStore() rbac.RoleStore { - storeMode := store.GetStoreMode() - - switch storeMode { - case store.Database: - return &DatabaseRoleStore{"role.json"} - default: - store := NewFileSystemRoleStore() - return store - } -} diff --git a/controller/rbac/userStore.go b/controller/rbac/userStore.go deleted file mode 100644 index 48e6c861802f09382cd9e196dedefc418c48e05b..0000000000000000000000000000000000000000 --- a/controller/rbac/userStore.go +++ /dev/null @@ -1,19 +0,0 @@ -package rbac - -import ( - "code.fbi.h-da.de/danet/gosdn/controller/interfaces/rbac" - "code.fbi.h-da.de/danet/gosdn/controller/store" -) - -// NewUserStore returns a userStore. -func NewUserStore() rbac.UserStore { - storeMode := store.GetStoreMode() - - switch storeMode { - case store.Database: - return &DatabaseUserStore{"user.json"} - default: - store := NewFileSystemUserStore() - return store - } -}