diff --git a/internal/api/members/crud.go b/internal/api/members/crud.go index 4be4cb89..a338ef1d 100644 --- a/internal/api/members/crud.go +++ b/internal/api/members/crud.go @@ -43,7 +43,7 @@ func (h *MembersHandler) membersCreate(w http.ResponseWriter, r *http.Request) { } // TODO: Join structs? - session := h.sessions.Create(data.ID, types.MemberProfile{ + session, err := h.sessions.Create(data.ID, types.MemberProfile{ Secret: data.Secret, Name: data.Name, IsAdmin: data.IsAdmin, @@ -54,6 +54,11 @@ func (h *MembersHandler) membersCreate(w http.ResponseWriter, r *http.Request) { CanAccessClipboard: data.CanAccessClipboard, }) + if err != nil { + utils.HttpInternalServerError(w, err) + return + } + utils.HttpSuccess(w, MemberCreatePayload{ ID: session.ID(), }) diff --git a/internal/session/database/manager.go b/internal/session/database/manager.go new file mode 100644 index 00000000..f26701b1 --- /dev/null +++ b/internal/session/database/manager.go @@ -0,0 +1,67 @@ +package database + +import ( + "fmt" + "sync" + + "demodesk/neko/internal/types" +) + +func New() *MembersDatabaseCtx { + return &MembersDatabaseCtx{ + profiles: make(map[string]types.MemberProfile), + mu: sync.Mutex{}, + } +} + +type MembersDatabaseCtx struct { + profiles map[string]types.MemberProfile + mu sync.Mutex +} + +func (manager *MembersDatabaseCtx) Insert(id string, profile types.MemberProfile) error { + manager.mu.Lock() + defer manager.mu.Unlock() + + _, ok := manager.profiles[id] + if ok { + return fmt.Errorf("Member ID already exists.") + } + + manager.profiles[id] = profile + return nil +} + +func (manager *MembersDatabaseCtx) Update(id string, profile types.MemberProfile) error { + manager.mu.Lock() + defer manager.mu.Unlock() + + _, ok := manager.profiles[id] + if !ok { + return fmt.Errorf("Member ID does not exist.") + } + + manager.profiles[id] = profile + return nil +} + +func (manager *MembersDatabaseCtx) Delete(id string) error { + manager.mu.Lock() + defer manager.mu.Unlock() + + _, ok := manager.profiles[id] + if !ok { + return fmt.Errorf("Member ID does not exist.") + } + + delete(manager.profiles, id) + return nil +} + +func (manager *MembersDatabaseCtx) Select(id string) (types.MemberProfile, bool) { + manager.mu.Lock() + defer manager.mu.Unlock() + + profile, ok := manager.profiles[id] + return profile, ok +} diff --git a/internal/session/manager.go b/internal/session/manager.go index eafbb472..ea6efbda 100644 --- a/internal/session/manager.go +++ b/internal/session/manager.go @@ -8,6 +8,7 @@ import ( "github.com/rs/zerolog" "github.com/rs/zerolog/log" + "demodesk/neko/internal/session/database" "demodesk/neko/internal/types" "demodesk/neko/internal/config" "demodesk/neko/internal/utils" @@ -19,20 +20,23 @@ func New(config *config.Session) *SessionManagerCtx { host: nil, hostMu: sync.Mutex{}, config: config, + database: database.New(), members: make(map[string]*SessionCtx), membersMu: sync.Mutex{}, emmiter: events.New(), } + // TODO: Import from Database at startup. + // create default admin account at startup - _ = manager.Create("admin", types.MemberProfile{ + _, _ = manager.Create("admin", types.MemberProfile{ Secret: config.AdminPassword, Name: "Administrator", IsAdmin: true, }) // create default user account at startup - _ = manager.Create("user", types.MemberProfile{ + _, _ = manager.Create("user", types.MemberProfile{ Secret: config.Password, Name: "User", IsAdmin: false, @@ -46,35 +50,56 @@ type SessionManagerCtx struct { host types.Session hostMu sync.Mutex config *config.Session + database *database.MembersDatabaseCtx members map[string]*SessionCtx membersMu sync.Mutex emmiter events.EventEmmiter } -func (manager *SessionManagerCtx) Create(id string, profile types.MemberProfile) types.Session { +func (manager *SessionManagerCtx) Create(id string, profile types.MemberProfile) (types.Session, error) { session := &SessionCtx{ - id: id, - manager: manager, - logger: manager.logger.With().Str("id", id).Logger(), - profile: profile, + id: id, + manager: manager, + logger: manager.logger.With().Str("id", id).Logger(), + profile: profile, } manager.membersMu.Lock() + + _, ok := manager.members[id] + if ok { + manager.membersMu.Unlock() + return nil, fmt.Errorf("Member ID already exists.") + } + + err := manager.database.Insert(id, profile) + if err != nil { + manager.membersMu.Unlock() + return nil, err + } + manager.members[id] = session manager.membersMu.Unlock() manager.emmiter.Emit("created", session) - return session + return session, nil } func (manager *SessionManagerCtx) Update(id string, profile types.MemberProfile) error { manager.membersMu.Lock() + session, ok := manager.members[id] if !ok { manager.membersMu.Unlock() return fmt.Errorf("Member not found.") } + err := manager.database.Update(id, profile) + if err != nil { + manager.membersMu.Unlock() + return err + } + session.profile = profile manager.membersMu.Unlock() @@ -82,14 +107,6 @@ func (manager *SessionManagerCtx) Update(id string, profile types.MemberProfile) return nil } -func (manager *SessionManagerCtx) Get(id string) (types.Session, bool) { - manager.membersMu.Lock() - session, ok := manager.members[id] - manager.membersMu.Unlock() - - return session, ok -} - func (manager *SessionManagerCtx) Delete(id string) error { manager.membersMu.Lock() session, ok := manager.members[id] @@ -98,10 +115,15 @@ func (manager *SessionManagerCtx) Delete(id string) error { return fmt.Errorf("Member not found.") } + err := manager.database.Delete(id) + if err != nil { + manager.membersMu.Unlock() + return err + } + delete(manager.members, id) manager.membersMu.Unlock() - var err error if session.IsConnected() { err = session.Disconnect("member deleted") } @@ -110,6 +132,14 @@ func (manager *SessionManagerCtx) Delete(id string) error { return err } +func (manager *SessionManagerCtx) Get(id string) (types.Session, bool) { + manager.membersMu.Lock() + defer manager.membersMu.Unlock() + + session, ok := manager.members[id] + return session, ok +} + // --- // host // --- diff --git a/internal/types/session.go b/internal/types/session.go index 28085d82..79e01a73 100644 --- a/internal/types/session.go +++ b/internal/types/session.go @@ -41,7 +41,7 @@ type Session interface { } type SessionManager interface { - Create(id string, profile MemberProfile) Session + Create(id string, profile MemberProfile) (Session, error) Update(id string, profile MemberProfile) error Get(id string) (Session, bool) Delete(id string) error