From 4d2fb157f9649ee19975a448c72312ff87a0838c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20=C5=A0ediv=C3=BD?= Date: Sun, 14 Mar 2021 14:44:32 +0100 Subject: [PATCH] API implement members. --- internal/api/members/controler.go | 91 ++++++++++++++++++++++--------- internal/api/members/handler.go | 31 +++++++---- internal/api/router.go | 5 +- neko.go | 16 +++--- 4 files changed, 97 insertions(+), 46 deletions(-) diff --git a/internal/api/members/controler.go b/internal/api/members/controler.go index 579f0e3b..3a52c7f7 100644 --- a/internal/api/members/controler.go +++ b/internal/api/members/controler.go @@ -1,6 +1,7 @@ package members import ( + "strconv" "net/http" "demodesk/neko/internal/types" @@ -12,12 +13,40 @@ type MemberDataPayload struct { *types.MemberProfile } +type MemberCreatePayload struct { + Username string `json:"username"` + Password string `json:"password"` + Profile types.MemberProfile `json:"profile"` +} + +type MemberPasswordPayload struct { + Password string `json:"password"` +} + func (h *MembersHandler) membersList(w http.ResponseWriter, r *http.Request) { + limit, err := strconv.Atoi(r.URL.Query().Get("limit")) + if err != nil { + // TODO: Default zero. + limit = 0 + } + + offset, err := strconv.Atoi(r.URL.Query().Get("offset")) + if err != nil { + // TODO: Default zero. + offset = 0 + } + + entries, err := h.members.SelectAll(limit, offset) + if err != nil { + utils.HttpInternalServerError(w, err) + return + } + members := []MemberDataPayload{} - for _, session := range h.sessions.List() { - profile := session.Profile() + for id, profile := range entries { + profile := profile members = append(members, MemberDataPayload{ - ID: session.ID(), + ID: id, MemberProfile: &profile, }) } @@ -26,9 +55,9 @@ func (h *MembersHandler) membersList(w http.ResponseWriter, r *http.Request) { } func (h *MembersHandler) membersCreate(w http.ResponseWriter, r *http.Request) { - data := &MemberDataPayload{ + data := &MemberCreatePayload{ // default values - MemberProfile: &types.MemberProfile{ + Profile: types.MemberProfile{ IsAdmin: false, CanLogin: true, CanConnect: true, @@ -37,56 +66,64 @@ func (h *MembersHandler) membersCreate(w http.ResponseWriter, r *http.Request) { CanAccessClipboard: true, }, } - + if !utils.HttpJsonRequest(w, r, data) { return } - if data.Name == "" { - utils.HttpBadRequest(w, "Name cannot be empty.") + if data.Username == "" { + utils.HttpBadRequest(w, "Username cannot be empty.") return } - if data.ID == "" { - var err error - if data.ID, err = utils.NewUID(32); err != nil { - utils.HttpInternalServerError(w, err) - return - } - } else { - if _, ok := h.sessions.Get(data.ID); ok { - utils.HttpBadRequest(w, "Member ID already exists.") - return - } + if data.Password == "" { + utils.HttpBadRequest(w, "Password cannot be empty.") + return } - session, _, err := h.sessions.Create(data.ID, *data.MemberProfile) + id, err := h.members.Insert(data.Username, data.Password, data.Profile) if err != nil { utils.HttpInternalServerError(w, err) return } - + utils.HttpSuccess(w, MemberDataPayload{ - ID: session.ID(), + ID: id, }) } func (h *MembersHandler) membersRead(w http.ResponseWriter, r *http.Request) { member := GetMember(r) - profile := member.Profile() + profile := member.Profile utils.HttpSuccess(w, profile) } -func (h *MembersHandler) membersUpdate(w http.ResponseWriter, r *http.Request) { +func (h *MembersHandler) membersUpdateProfile(w http.ResponseWriter, r *http.Request) { member := GetMember(r) - profile := member.Profile() + profile := member.Profile if !utils.HttpJsonRequest(w, r, &profile) { return } - if err := h.sessions.Update(member.ID(), profile); err != nil { + if err := h.members.UpdateProfile(member.ID, profile); err != nil { + utils.HttpInternalServerError(w, err) + return + } + + utils.HttpSuccess(w) +} + +func (h *MembersHandler) membersUpdatePassword(w http.ResponseWriter, r *http.Request) { + member := GetMember(r) + data := MemberPasswordPayload{} + + if !utils.HttpJsonRequest(w, r, &data) { + return + } + + if err := h.members.UpdatePassword(member.ID, data.Password); err != nil { utils.HttpInternalServerError(w, err) return } @@ -97,7 +134,7 @@ func (h *MembersHandler) membersUpdate(w http.ResponseWriter, r *http.Request) { func (h *MembersHandler) membersDelete(w http.ResponseWriter, r *http.Request) { member := GetMember(r) - if err := h.sessions.Delete(member.ID()); err != nil { + if err := h.members.Delete(member.ID); err != nil { utils.HttpInternalServerError(w, err) return } diff --git a/internal/api/members/handler.go b/internal/api/members/handler.go index 555058a7..0988f9b9 100644 --- a/internal/api/members/handler.go +++ b/internal/api/members/handler.go @@ -18,16 +18,16 @@ const ( ) type MembersHandler struct { - sessions types.SessionManager + members types.MemberManager } func New( - sessions types.SessionManager, + members types.MemberManager, ) *MembersHandler { // Init return &MembersHandler{ - sessions: sessions, + members: members, } } @@ -38,29 +38,38 @@ func (h *MembersHandler) Route(r chi.Router) { r.Post("/", h.membersCreate) r.With(h.ExtractMember).Route("/{memberId}", func(r chi.Router) { r.Get("/", h.membersRead) - r.Post("/", h.membersUpdate) + r.Post("/", h.membersUpdateProfile) + r.Post("/password", h.membersUpdatePassword) r.Delete("/", h.membersDelete) }) }) } -func SetMember(r *http.Request, session types.Session) *http.Request { +type MemberData struct { + ID string + Profile types.MemberProfile +} + +func SetMember(r *http.Request, session MemberData) *http.Request { ctx := context.WithValue(r.Context(), keyMemberCtx, session) return r.WithContext(ctx) } -func GetMember(r *http.Request) types.Session { - return r.Context().Value(keyMemberCtx).(types.Session) +func GetMember(r *http.Request) MemberData { + return r.Context().Value(keyMemberCtx).(MemberData) } func (h *MembersHandler) ExtractMember(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { memberId := chi.URLParam(r, "memberId") - session, ok := h.sessions.Get(memberId) - if !ok { - utils.HttpNotFound(w, "Member was not found.") + profile, err := h.members.Select(memberId) + if err != nil { + utils.HttpNotFound(w, err) } else { - next.ServeHTTP(w, SetMember(r, session)) + next.ServeHTTP(w, SetMember(r, MemberData{ + ID: memberId, + Profile: profile, + })) } }) } diff --git a/internal/api/router.go b/internal/api/router.go index b1fe988a..84a7b377 100644 --- a/internal/api/router.go +++ b/internal/api/router.go @@ -15,6 +15,7 @@ import ( type ApiManagerCtx struct { sessions types.SessionManager + members types.MemberManager desktop types.DesktopManager capture types.CaptureManager routers map[string]func(chi.Router) @@ -22,6 +23,7 @@ type ApiManagerCtx struct { func New( sessions types.SessionManager, + members types.MemberManager, desktop types.DesktopManager, capture types.CaptureManager, conf *config.Server, @@ -29,6 +31,7 @@ func New( return &ApiManagerCtx{ sessions: sessions, + members: members, desktop: desktop, capture: capture, routers: make(map[string]func(chi.Router)), @@ -45,7 +48,7 @@ func (api *ApiManagerCtx) Route(r chi.Router) { r.Post("/logout", api.Logout) r.Get("/whoami", api.Whoami) - membersHandler := members.New(api.sessions) + membersHandler := members.New(api.members) r.Route("/members", membersHandler.Route) roomHandler := room.New(api.sessions, api.desktop, api.capture) diff --git a/neko.go b/neko.go index 1dd41749..3b8c40fa 100644 --- a/neko.go +++ b/neko.go @@ -134,17 +134,18 @@ func (neko *Neko) Preflight() { } func (neko *Neko) Start() { - neko.memberManager = member.New( - neko.Configs.Member, - ) - if err := neko.memberManager.Connect(); err != nil { - neko.logger.Panic().Err(err).Msg("unable to connect to member manager") - } - neko.sessionManager = session.New( neko.Configs.Session, ) + neko.memberManager = member.New( + neko.Configs.Member, + ) + + if err := neko.memberManager.Connect(); err != nil { + neko.logger.Panic().Err(err).Msg("unable to connect to member manager") + } + neko.desktopManager = desktop.New( neko.Configs.Desktop, ) @@ -173,6 +174,7 @@ func (neko *Neko) Start() { neko.apiManager = api.New( neko.sessionManager, + neko.memberManager, neko.desktopManager, neko.captureManager, neko.Configs.Server,