Files
r3/request/request_clientEvent.go
2025-02-27 17:58:53 +01:00

130 lines
3.5 KiB
Go

package request
import (
"context"
"encoding/json"
"fmt"
"r3/cache"
"r3/cluster"
"r3/handler"
"r3/login/login_clientEvent"
"r3/schema/clientEvent"
"r3/types"
"strings"
"github.com/gofrs/uuid"
"github.com/jackc/pgx/v5"
)
func clientEventDel_tx(ctx context.Context, tx pgx.Tx, reqJson json.RawMessage) (interface{}, error) {
var req struct {
Id uuid.UUID `json:"id"`
}
if err := json.Unmarshal(reqJson, &req); err != nil {
return nil, err
}
return nil, clientEvent.Del_tx(ctx, tx, req.Id)
}
func clientEventSet_tx(ctx context.Context, tx pgx.Tx, reqJson json.RawMessage) (interface{}, error) {
var req types.ClientEvent
if err := json.Unmarshal(reqJson, &req); err != nil {
return nil, err
}
return nil, clientEvent.Set_tx(ctx, tx, req)
}
// fat client requests
func clientEventGetFatClient_tx(ctx context.Context, tx pgx.Tx, loginId int64) (interface{}, error) {
var err error
var res struct {
ClientEvents []types.ClientEvent `json:"clientEvents"`
ClientEventIdMapLogin map[uuid.UUID]types.LoginClientEvent `json:"clientEventIdMapLogin"`
}
res.ClientEvents = make([]types.ClientEvent, 0)
res.ClientEventIdMapLogin = make(map[uuid.UUID]types.LoginClientEvent)
// collect login client events for login (currently only used to enable and overwrite hotkeys)
res.ClientEventIdMapLogin, err = login_clientEvent.Get_tx(ctx, tx, loginId)
if err != nil {
return nil, err
}
// collect client events for login
access, err := cache.GetAccessById(loginId)
if err != nil {
return nil, err
}
cache.Schema_mx.RLock()
for id, ce := range cache.ClientEventIdMap {
if _, exists := access.ClientEvent[id]; !exists {
continue // login has no access, ignore
}
if ce.Event == "onHotkey" {
if _, exists := res.ClientEventIdMapLogin[id]; !exists {
continue // login has not enabled hotkey, ignore
}
}
res.ClientEvents = append(res.ClientEvents, ce)
}
cache.Schema_mx.RUnlock()
return res, nil
}
func clientEventExecFatClient_tx(ctx context.Context, tx pgx.Tx, reqJson json.RawMessage, loginId int64, address string) (interface{}, error) {
var req struct {
Id uuid.UUID `json:"id"`
Arguments []interface{} `json:"arguments"`
}
if err := json.Unmarshal(reqJson, &req); err != nil {
return nil, err
}
cache.Schema_mx.RLock()
ce, exists := cache.ClientEventIdMap[req.Id]
cache.Schema_mx.RUnlock()
if !exists {
return nil, handler.ErrSchemaUnknownClientEvent(req.Id)
}
// execute valid actions
if ce.Action == "callJsFunction" && ce.JsFunctionId.Valid {
return nil, cluster.JsFunctionCalled_tx(ctx, tx, true, address, loginId, ce.JsFunctionId.Bytes, req.Arguments)
}
if ce.Action == "callPgFunction" && ce.PgFunctionId.Valid {
cache.Schema_mx.RLock()
fnc, exists := cache.PgFunctionIdMap[ce.PgFunctionId.Bytes]
cache.Schema_mx.RUnlock()
if !exists {
return nil, handler.ErrSchemaUnknownPgFunction(ce.PgFunctionId.Bytes)
}
if fnc.IsTrigger {
return nil, handler.ErrSchemaTriggerPgFunctionCall(ce.PgFunctionId.Bytes)
}
cache.Schema_mx.RLock()
mod := cache.ModuleIdMap[fnc.ModuleId]
cache.Schema_mx.RUnlock()
placeholders := make([]string, 0)
for i := range req.Arguments {
placeholders = append(placeholders, fmt.Sprintf("$%d", i+1))
}
var returnIf interface{}
err := tx.QueryRow(ctx, fmt.Sprintf(`SELECT "%s"."%s"(%s)`, mod.Name, fnc.Name, strings.Join(placeholders, ",")),
req.Arguments...).Scan(&returnIf)
return nil, err
}
return nil, fmt.Errorf("invalid client event action")
}