From e44d66d33467d7fddffff3afeaa758789b9e56a0 Mon Sep 17 00:00:00 2001 From: Samuel Lorch Date: Sun, 14 May 2023 03:23:38 +0200 Subject: [PATCH] Add User Backend --- internal/api/system/system.go | 9 ++ internal/api/system/user.go | 139 ++++++++++++++++++++++++++ internal/definitions/config/config.go | 2 + internal/definitions/system/system.go | 5 + internal/definitions/system/user.go | 7 ++ main.go | 2 + 6 files changed, 164 insertions(+) create mode 100644 internal/api/system/system.go create mode 100644 internal/api/system/user.go create mode 100644 internal/definitions/system/system.go create mode 100644 internal/definitions/system/user.go diff --git a/internal/api/system/system.go b/internal/api/system/system.go new file mode 100644 index 0000000..4c004cb --- /dev/null +++ b/internal/api/system/system.go @@ -0,0 +1,9 @@ +package system + +import ( + "nfsense.net/nfsense/internal/config" +) + +type System struct { + ConfigManager *config.ConfigManager +} diff --git a/internal/api/system/user.go b/internal/api/system/user.go new file mode 100644 index 0000000..e2b06c0 --- /dev/null +++ b/internal/api/system/user.go @@ -0,0 +1,139 @@ +package system + +import ( + "context" + "fmt" + + "nfsense.net/nfsense/internal/auth" + "nfsense.net/nfsense/internal/definitions/system" +) + +type User struct { + Comment string `json:"comment"` +} + +type GetUserParameters struct { + ID string +} + +type GetUserResult struct { + Name string `json:"name"` + User +} + +func (f *System) GetUser(ctx context.Context, params GetUserParameters) (GetUserResult, error) { + _, ok := f.ConfigManager.GetPendingConfig().System.Users[params.ID] + if !ok { + return GetUserResult{}, fmt.Errorf("User does not Exist") + } + + return GetUserResult{ + Name: params.ID, + User: User{ + Comment: f.ConfigManager.GetPendingConfig().System.Users[params.ID].Comment, + }, + }, nil +} + +type GetUsersResult struct { + Users map[string]User +} + +func (f *System) GetUsers(ctx context.Context, params struct{}) (GetUsersResult, error) { + users := map[string]User{} + for n, u := range f.ConfigManager.GetPendingConfig().System.Users { + users[n] = User{Comment: u.Comment} + } + return GetUsersResult{ + Users: users, + }, nil +} + +type CreateUserParameters struct { + Name string `json:"name"` + Password string `json:"password"` + User +} + +func (f *System) CreateUser(ctx context.Context, params CreateUserParameters) (struct{}, error) { + _, ok := f.ConfigManager.GetPendingConfig().System.Users[params.Name] + if ok { + return struct{}{}, fmt.Errorf("User already Exists") + } + + if params.Name == "" { + return struct{}{}, fmt.Errorf("Name Cannot be empty") + } + + if params.Password == "" { + return struct{}{}, fmt.Errorf("Password Cannot be empty") + } + + hash, salt, err := auth.GenerateHash(params.Password) + if err != nil { + return struct{}{}, fmt.Errorf("Generate Hash: %w", err) + } + + t, conf := f.ConfigManager.StartTransaction() + defer t.Discard() + + conf.System.Users[params.Name] = system.User{ + Hash: hash, + Salt: salt, + Comment: params.User.Comment, + } + return struct{}{}, t.Commit() +} + +type UpdateUserParameters struct { + Name string `json:"name"` + Password string `json:"password"` + User +} + +func (f *System) UpdateUser(ctx context.Context, params UpdateUserParameters) (struct{}, error) { + _, ok := f.ConfigManager.GetPendingConfig().System.Users[params.Name] + if !ok { + return struct{}{}, fmt.Errorf("User does not Exist") + } + + if params.Name == "" { + return struct{}{}, fmt.Errorf("Name Cannot be empty") + } + user := f.ConfigManager.GetPendingConfig().System.Users[params.Name] + + if params.Password != "" { + hash, salt, err := auth.GenerateHash(params.Password) + if err != nil { + return struct{}{}, fmt.Errorf("Generate Hash: %w", err) + } + + user.Hash = hash + user.Salt = salt + } + + user.Comment = params.User.Comment + + t, conf := f.ConfigManager.StartTransaction() + defer t.Discard() + + conf.System.Users[params.Name] = user + return struct{}{}, t.Commit() +} + +type DeleteUserParameters struct { + Name string +} + +func (f *System) DeleteUser(ctx context.Context, params DeleteUserParameters) (struct{}, error) { + _, ok := f.ConfigManager.GetPendingConfig().System.Users[params.Name] + if !ok { + return struct{}{}, fmt.Errorf("User does not Exist") + } + + t, conf := f.ConfigManager.StartTransaction() + defer t.Discard() + + delete(conf.System.Users, params.Name) + return struct{}{}, t.Commit() +} diff --git a/internal/definitions/config/config.go b/internal/definitions/config/config.go index 489d2c8..18e970e 100644 --- a/internal/definitions/config/config.go +++ b/internal/definitions/config/config.go @@ -10,6 +10,7 @@ import ( "nfsense.net/nfsense/internal/definitions/network" "nfsense.net/nfsense/internal/definitions/object" "nfsense.net/nfsense/internal/definitions/service" + "nfsense.net/nfsense/internal/definitions/system" "nfsense.net/nfsense/internal/definitions/vpn" ) @@ -20,6 +21,7 @@ type Config struct { Network network.Network `json:"network" validate:"required,dive"` Service service.Service `json:"service" validate:"required,dive"` VPN vpn.VPN `json:"vpn" validate:"required,dive"` + System system.System `json:"system" validate:"required,dive"` } // Clone TODO find a better way to deep copy diff --git a/internal/definitions/system/system.go b/internal/definitions/system/system.go new file mode 100644 index 0000000..94b3479 --- /dev/null +++ b/internal/definitions/system/system.go @@ -0,0 +1,5 @@ +package system + +type System struct { + Users map[string]User `json:"users" validate:"required,dive"` +} diff --git a/internal/definitions/system/user.go b/internal/definitions/system/user.go new file mode 100644 index 0000000..c8e0081 --- /dev/null +++ b/internal/definitions/system/user.go @@ -0,0 +1,7 @@ +package system + +type User struct { + Comment string `json:"comment"` + Hash string `json:"hash"` + Salt string `json:"salt"` +} diff --git a/main.go b/main.go index e452613..e5c3474 100644 --- a/main.go +++ b/main.go @@ -16,6 +16,7 @@ import ( "nfsense.net/nfsense/internal/api/network" "nfsense.net/nfsense/internal/api/object" "nfsense.net/nfsense/internal/api/service" + "nfsense.net/nfsense/internal/api/system" "nfsense.net/nfsense/internal/api/vpn" "nfsense.net/nfsense/internal/chrony" "nfsense.net/nfsense/internal/config" @@ -104,6 +105,7 @@ func RegisterAPIMethods(apiHandler *jsonrpc.Handler, configManager *config.Confi apiHandler.Register("Object", &object.Object{ConfigManager: configManager}) apiHandler.Register("Service", &service.Service{ConfigManager: configManager, DbusConn: dbusConn}) apiHandler.Register("VPN", &vpn.VPN{ConfigManager: configManager, DbusConn: dbusConn}) + apiHandler.Register("System", &system.System{ConfigManager: configManager}) } func RegisterApplyFunctions(configManager *config.ConfigManager) {