move server to server directory.

This commit is contained in:
Miroslav Šedivý
2024-06-23 17:48:14 +02:00
parent da45f62ca8
commit 5b98344205
211 changed files with 18 additions and 10 deletions

98
server/pkg/auth/auth.go Normal file
View File

@ -0,0 +1,98 @@
package auth
import (
"context"
"fmt"
"net/http"
"github.com/demodesk/neko/pkg/types"
"github.com/demodesk/neko/pkg/utils"
)
type key int
const keySessionCtx key = iota
func SetSession(r *http.Request, session types.Session) context.Context {
return context.WithValue(r.Context(), keySessionCtx, session)
}
func GetSession(r *http.Request) (types.Session, bool) {
session, ok := r.Context().Value(keySessionCtx).(types.Session)
return session, ok
}
func AdminsOnly(w http.ResponseWriter, r *http.Request) (context.Context, error) {
session, ok := GetSession(r)
if !ok || !session.Profile().IsAdmin {
return nil, utils.HttpForbidden("session is not admin")
}
return nil, nil
}
func HostsOnly(w http.ResponseWriter, r *http.Request) (context.Context, error) {
session, ok := GetSession(r)
if !ok || !session.IsHost() {
return nil, utils.HttpForbidden("session is not host")
}
return nil, nil
}
func CanWatchOnly(w http.ResponseWriter, r *http.Request) (context.Context, error) {
session, ok := GetSession(r)
if !ok || !session.Profile().CanWatch {
return nil, utils.HttpForbidden("session cannot watch")
}
return nil, nil
}
func CanHostOnly(w http.ResponseWriter, r *http.Request) (context.Context, error) {
session, ok := GetSession(r)
if !ok || !session.Profile().CanHost {
return nil, utils.HttpForbidden("session cannot host")
}
if session.PrivateModeEnabled() {
return nil, utils.HttpUnprocessableEntity("private mode is enabled")
}
return nil, nil
}
func CanAccessClipboardOnly(w http.ResponseWriter, r *http.Request) (context.Context, error) {
session, ok := GetSession(r)
if !ok || !session.Profile().CanAccessClipboard {
return nil, utils.HttpForbidden("session cannot access clipboard")
}
return nil, nil
}
func PluginsGenericOnly[V comparable](key string, exp V) func(w http.ResponseWriter, r *http.Request) (context.Context, error) {
return func(w http.ResponseWriter, r *http.Request) (context.Context, error) {
session, ok := GetSession(r)
if !ok {
return nil, utils.HttpForbidden("session not found")
}
plugins := session.Profile().Plugins
if plugins[key] == nil {
return nil, utils.HttpForbidden(fmt.Sprintf("missing plugin permission: %s=%T", key, exp))
}
val, ok := plugins[key].(V)
if !ok {
return nil, utils.HttpForbidden(fmt.Sprintf("invalid plugin permission type: %s=%T expected %T", key, plugins[key], exp))
}
if val != exp {
return nil, utils.HttpForbidden(fmt.Sprintf("wrong plugin permission value for %s=%T", key, exp))
}
return nil, nil
}
}

View File

@ -0,0 +1,358 @@
package auth
import (
"fmt"
"net/http"
"reflect"
"testing"
"github.com/demodesk/neko/internal/config"
"github.com/demodesk/neko/internal/session"
"github.com/demodesk/neko/pkg/types"
)
var i = 0
var sessionManager = session.New(&config.Session{})
func rWithSession(profile types.MemberProfile) (*http.Request, types.Session, error) {
i++
r := &http.Request{}
session, _, err := sessionManager.Create(fmt.Sprintf("id-%d", i), profile)
ctx := SetSession(r, session)
r = r.WithContext(ctx)
return r, session, err
}
func TestSessionCtx(t *testing.T) {
r, session, err := rWithSession(types.MemberProfile{})
if err != nil {
t.Errorf("could not create session %s", err.Error())
return
}
sess, ok := GetSession(r)
if !ok {
t.Errorf("session not found")
return
}
if !reflect.DeepEqual(sess, session) {
t.Errorf("sessions not equal")
return
}
}
func TestAdminsOnly(t *testing.T) {
r1, _, err := rWithSession(types.MemberProfile{IsAdmin: false})
if err != nil {
t.Errorf("could not create session %s", err.Error())
return
}
r2, _, err := rWithSession(types.MemberProfile{IsAdmin: true})
if err != nil {
t.Errorf("could not create session %s", err.Error())
return
}
tests := []struct {
name string
r *http.Request
wantErr bool
}{
{
name: "is not admin",
r: r1,
wantErr: true,
},
{
name: "is admin",
r: r2,
wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
_, err := AdminsOnly(nil, tt.r)
if (err != nil) != tt.wantErr {
t.Errorf("AdminsOnly() error = %v, wantErr %v", err, tt.wantErr)
return
}
})
}
}
func TestHostsOnly(t *testing.T) {
r1, _, err := rWithSession(types.MemberProfile{CanHost: true})
if err != nil {
t.Errorf("could not create session %s", err.Error())
return
}
r2, session, err := rWithSession(types.MemberProfile{CanHost: true})
if err != nil {
t.Errorf("could not create session %s", err.Error())
return
}
// r2 is host
session.SetAsHost()
r3, _, err := rWithSession(types.MemberProfile{CanHost: false})
if err != nil {
t.Errorf("could not create session %s", err.Error())
return
}
tests := []struct {
name string
r *http.Request
wantErr bool
}{
{
name: "is not hosting",
r: r1,
wantErr: true,
},
{
name: "is hosting",
r: r2,
wantErr: false,
},
{
name: "cannot host",
r: r3,
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
_, err := HostsOnly(nil, tt.r)
if (err != nil) != tt.wantErr {
t.Errorf("HostsOnly() error = %v, wantErr %v", err, tt.wantErr)
return
}
})
}
}
func TestCanWatchOnly(t *testing.T) {
r1, _, err := rWithSession(types.MemberProfile{CanWatch: false})
if err != nil {
t.Errorf("could not create session %s", err.Error())
return
}
r2, _, err := rWithSession(types.MemberProfile{CanWatch: true})
if err != nil {
t.Errorf("could not create session %s", err.Error())
return
}
tests := []struct {
name string
r *http.Request
wantErr bool
}{
{
name: "can not watch",
r: r1,
wantErr: true,
},
{
name: "can watch",
r: r2,
wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
_, err := CanWatchOnly(nil, tt.r)
if (err != nil) != tt.wantErr {
t.Errorf("CanWatchOnly() error = %v, wantErr %v", err, tt.wantErr)
return
}
})
}
}
func TestCanHostOnly(t *testing.T) {
r1, _, err := rWithSession(types.MemberProfile{CanHost: false})
if err != nil {
t.Errorf("could not create session %s", err.Error())
return
}
r2, _, err := rWithSession(types.MemberProfile{CanHost: true})
if err != nil {
t.Errorf("could not create session %s", err.Error())
return
}
tests := []struct {
name string
r *http.Request
wantErr bool
privateMode bool
}{
{
name: "can not host",
r: r1,
wantErr: true,
},
{
name: "can host",
r: r2,
wantErr: false,
},
{
name: "private mode enabled: can not host",
r: r1,
wantErr: true,
privateMode: true,
},
{
name: "private mode enabled: can host",
r: r2,
wantErr: true,
privateMode: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
session, _ := GetSession(tt.r)
sessionManager.UpdateSettingsFunc(session, func(s *types.Settings) bool {
s.PrivateMode = tt.privateMode
return true
})
_, err := CanHostOnly(nil, tt.r)
if (err != nil) != tt.wantErr {
t.Errorf("CanHostOnly() error = %v, wantErr %v", err, tt.wantErr)
return
}
})
}
}
func TestCanAccessClipboardOnly(t *testing.T) {
r1, _, err := rWithSession(types.MemberProfile{CanAccessClipboard: false})
if err != nil {
t.Errorf("could not create session %s", err.Error())
return
}
r2, _, err := rWithSession(types.MemberProfile{CanAccessClipboard: true})
if err != nil {
t.Errorf("could not create session %s", err.Error())
return
}
tests := []struct {
name string
r *http.Request
wantErr bool
}{
{
name: "can not access clipboard",
r: r1,
wantErr: true,
},
{
name: "can access clipboard",
r: r2,
wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
_, err := CanAccessClipboardOnly(nil, tt.r)
if (err != nil) != tt.wantErr {
t.Errorf("CanAccessClipboardOnly() error = %v, wantErr %v", err, tt.wantErr)
return
}
})
}
}
func TestPluginsGenericOnly(t *testing.T) {
r1, _, err := rWithSession(types.MemberProfile{
Plugins: map[string]any{
"foo.bar": 1,
},
})
if err != nil {
t.Errorf("could not create session %s", err.Error())
return
}
t.Run("test if exists", func(t *testing.T) {
key := "foo.bar"
val := 1
wantErr := false
handler := PluginsGenericOnly(key, val)
_, err := handler(nil, r1)
if (err != nil) != wantErr {
t.Errorf("PluginsGenericOnly(%q, %v) error = %v, wantErr %v", key, val, err, wantErr)
return
}
})
t.Run("test when gets different value", func(t *testing.T) {
key := "foo.bar"
val := 2
wantErr := true
handler := PluginsGenericOnly(key, val)
_, err := handler(nil, r1)
if (err != nil) != wantErr {
t.Errorf("PluginsGenericOnly(%q, %v) error = %v, wantErr %v", key, val, err, wantErr)
return
}
})
t.Run("test when gets different type", func(t *testing.T) {
key := "foo.bar"
val := "1"
wantErr := true
handler := PluginsGenericOnly(key, val)
_, err := handler(nil, r1)
if (err != nil) != wantErr {
t.Errorf("PluginsGenericOnly(%q, %v) error = %v, wantErr %v", key, val, err, wantErr)
return
}
})
t.Run("test if does not exists", func(t *testing.T) {
key := "foo.bar_not_extist"
val := 1
wantErr := true
handler := PluginsGenericOnly(key, val)
_, err := handler(nil, r1)
if (err != nil) != wantErr {
t.Errorf("PluginsGenericOnly(%q, %v) error = %v, wantErr %v", key, val, err, wantErr)
return
}
})
t.Run("test if session does not exists", func(t *testing.T) {
key := "foo.bar_not_extist"
val := 1
wantErr := true
handler := PluginsGenericOnly(key, val)
_, err := handler(nil, &http.Request{})
if (err != nil) != wantErr {
t.Errorf("PluginsGenericOnly(%q, %v) error = %v, wantErr %v", key, val, err, wantErr)
return
}
})
}