add session delete and disconnect to API.

This commit is contained in:
Miroslav Šedivý 2024-05-09 10:28:58 +02:00
parent 416faa3df4
commit 0e8108e9a4
7 changed files with 214 additions and 25 deletions

View File

@ -7,6 +7,7 @@ import (
"github.com/demodesk/neko/internal/api/members" "github.com/demodesk/neko/internal/api/members"
"github.com/demodesk/neko/internal/api/room" "github.com/demodesk/neko/internal/api/room"
"github.com/demodesk/neko/internal/api/sessions"
"github.com/demodesk/neko/pkg/auth" "github.com/demodesk/neko/pkg/auth"
"github.com/demodesk/neko/pkg/types" "github.com/demodesk/neko/pkg/types"
"github.com/demodesk/neko/pkg/utils" "github.com/demodesk/neko/pkg/utils"
@ -45,7 +46,9 @@ func (api *ApiManagerCtx) Route(r types.Router) {
r.Post("/logout", api.Logout) r.Post("/logout", api.Logout)
r.Get("/whoami", api.Whoami) r.Get("/whoami", api.Whoami)
r.Get("/sessions", api.Sessions)
sessionsHandler := sessions.New(api.sessions)
r.Route("/sessions", sessionsHandler.Route)
membersHandler := members.New(api.members) membersHandler := members.New(api.members)
r.Route("/members", membersHandler.Route) r.Route("/members", membersHandler.Route)

View File

@ -83,16 +83,3 @@ func (api *ApiManagerCtx) Whoami(w http.ResponseWriter, r *http.Request) error {
State: session.State(), State: session.State(),
}) })
} }
func (api *ApiManagerCtx) Sessions(w http.ResponseWriter, r *http.Request) error {
sessions := []SessionDataPayload{}
for _, session := range api.sessions.List() {
sessions = append(sessions, SessionDataPayload{
ID: session.ID(),
Profile: session.Profile(),
State: session.State(),
})
}
return utils.HttpSuccess(w, sessions)
}

View File

@ -0,0 +1,80 @@
package sessions
import (
"errors"
"net/http"
"github.com/demodesk/neko/pkg/auth"
"github.com/demodesk/neko/pkg/types"
"github.com/demodesk/neko/pkg/utils"
"github.com/go-chi/chi"
)
type SessionDataPayload struct {
ID string `json:"id"`
Profile types.MemberProfile `json:"profile"`
State types.SessionState `json:"state"`
}
func (h *SessionsHandler) sessionsList(w http.ResponseWriter, r *http.Request) error {
sessions := []SessionDataPayload{}
for _, session := range h.sessions.List() {
sessions = append(sessions, SessionDataPayload{
ID: session.ID(),
Profile: session.Profile(),
State: session.State(),
})
}
return utils.HttpSuccess(w, sessions)
}
func (h *SessionsHandler) sessionsRead(w http.ResponseWriter, r *http.Request) error {
sessionId := chi.URLParam(r, "sessionId")
session, ok := h.sessions.Get(sessionId)
if !ok {
return utils.HttpNotFound("session not found")
}
return utils.HttpSuccess(w, SessionDataPayload{
ID: session.ID(),
Profile: session.Profile(),
State: session.State(),
})
}
func (h *SessionsHandler) sessionsDelete(w http.ResponseWriter, r *http.Request) error {
session, _ := auth.GetSession(r)
sessionId := chi.URLParam(r, "sessionId")
if sessionId == session.ID() {
return utils.HttpBadRequest("cannot delete own session")
}
err := h.sessions.Delete(sessionId)
if err != nil {
if errors.Is(err, types.ErrSessionNotFound) {
return utils.HttpBadRequest("session not found")
} else {
return utils.HttpInternalServerError().WithInternalErr(err)
}
}
return utils.HttpSuccess(w)
}
func (h *SessionsHandler) sessionsDisconnect(w http.ResponseWriter, r *http.Request) error {
sessionId := chi.URLParam(r, "sessionId")
err := h.sessions.Disconnect(sessionId)
if err != nil {
if errors.Is(err, types.ErrSessionNotFound) {
return utils.HttpBadRequest("session not found")
} else {
return utils.HttpInternalServerError().WithInternalErr(err)
}
}
return utils.HttpSuccess(w)
}

View File

@ -0,0 +1,30 @@
package sessions
import (
"github.com/demodesk/neko/pkg/auth"
"github.com/demodesk/neko/pkg/types"
)
type SessionsHandler struct {
sessions types.SessionManager
}
func New(
sessions types.SessionManager,
) *SessionsHandler {
// Init
return &SessionsHandler{
sessions: sessions,
}
}
func (h *SessionsHandler) Route(r types.Router) {
r.Get("/", h.sessionsList)
r.With(auth.AdminsOnly).Route("/{sessionId}", func(r types.Router) {
r.Get("/", h.sessionsRead)
r.Delete("/", h.sessionsDelete)
r.Post("/disconnect", h.sessionsDisconnect)
})
}

View File

@ -158,6 +158,26 @@ func (manager *SessionManagerCtx) Delete(id string) error {
return nil return nil
} }
func (manager *SessionManagerCtx) Disconnect(id string) error {
manager.sessionsMu.Lock()
session, ok := manager.sessions[id]
if !ok {
manager.sessionsMu.Unlock()
return types.ErrSessionNotFound
}
manager.sessionsMu.Unlock()
if session.State().IsConnected {
session.DestroyWebSocketPeer("session disconnected")
}
if session.State().IsWatching {
session.GetWebRTCPeer().Destroy()
}
return nil
}
func (manager *SessionManagerCtx) Get(id string) (types.Session, bool) { func (manager *SessionManagerCtx) Get(id string) (types.Session, bool) {
manager.sessionsMu.Lock() manager.sessionsMu.Lock()
defer manager.sessionsMu.Unlock() defer manager.sessionsMu.Unlock()

View File

@ -13,8 +13,8 @@ servers:
url: http://localhost:3000 url: http://localhost:3000
tags: tags:
- name: session - name: sessions
description: Session management. description: Sessions management.
- name: room - name: room
description: Room releated operations. description: Room releated operations.
- name: members - name: members
@ -61,13 +61,11 @@ paths:
required: true required: true
# #
# session # current session
# #
/api/login: /api/login:
post: post:
tags:
- session
summary: login summary: login
operationId: login operationId: login
security: [] security: []
@ -90,8 +88,6 @@ paths:
required: true required: true
/api/logout: /api/logout:
post: post:
tags:
- session
summary: logout summary: logout
operationId: logout operationId: logout
responses: responses:
@ -101,8 +97,6 @@ paths:
$ref: '#/components/responses/Unauthorized' $ref: '#/components/responses/Unauthorized'
/api/whoami: /api/whoami:
get: get:
tags:
- session
summary: whoami summary: whoami
operationId: whoami operationId: whoami
responses: responses:
@ -116,10 +110,15 @@ paths:
$ref: '#/components/responses/Unauthorized' $ref: '#/components/responses/Unauthorized'
'403': '403':
$ref: '#/components/responses/Forbidden' $ref: '#/components/responses/Forbidden'
#
# sessions
#
/api/sessions: /api/sessions:
get: get:
tags: tags:
- session - sessions
summary: get sessions summary: get sessions
operationId: sessionsGet operationId: sessionsGet
responses: responses:
@ -135,6 +134,75 @@ paths:
$ref: '#/components/responses/Unauthorized' $ref: '#/components/responses/Unauthorized'
'403': '403':
$ref: '#/components/responses/Forbidden' $ref: '#/components/responses/Forbidden'
/api/sessions/{sessionId}:
get:
tags:
- sessions
summary: get session
operationId: sessionGet
parameters:
- in: path
name: sessionId
description: session identifier
required: true
schema:
type: string
responses:
'200':
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/SessionData'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'404':
$ref: '#/components/responses/NotFound'
delete:
tags:
- sessions
summary: remove session
operationId: sessionRemove
parameters:
- in: path
name: sessionId
description: session identifier
required: true
schema:
type: string
responses:
'204':
description: OK
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'404':
$ref: '#/components/responses/NotFound'
/api/sessions/{sessionId}/disconnect:
post:
tags:
- sessions
summary: disconnect session
operationId: sessionDisconnect
parameters:
- in: path
name: sessionId
description: session identifier
required: true
schema:
type: string
responses:
'204':
description: OK
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'404':
$ref: '#/components/responses/NotFound'
# #
# room # room
@ -1023,7 +1091,7 @@ components:
type: integer type: integer
# #
# session # sessions
# #
SessionLogin: SessionLogin:

View File

@ -81,6 +81,7 @@ type SessionManager interface {
Create(id string, profile MemberProfile) (Session, string, error) Create(id string, profile MemberProfile) (Session, string, error)
Update(id string, profile MemberProfile) error Update(id string, profile MemberProfile) error
Delete(id string) error Delete(id string) error
Disconnect(id string) error
Get(id string) (Session, bool) Get(id string) (Session, bool)
GetByToken(token string) (Session, bool) GetByToken(token string) (Session, bool)
List() []Session List() []Session