complete hub save endpoint

This commit is contained in:
2026-04-23 20:07:09 +02:00
parent c0d7e53884
commit 8aaa27a6dc
3 changed files with 151 additions and 90 deletions
+43 -1
View File
@@ -7,6 +7,8 @@ import (
"go-socket/packages/cache" "go-socket/packages/cache"
"go-socket/packages/postgresql" "go-socket/packages/postgresql"
"go-socket/packages/types" "go-socket/packages/types"
"github.com/google/uuid"
) )
func HandleHubCreate(response http.ResponseWriter, request *http.Request) { func HandleHubCreate(response http.ResponseWriter, request *http.Request) {
@@ -33,9 +35,49 @@ func HandleHubCreate(response http.ResponseWriter, request *http.Request) {
hub.Color = types.Rgba{}.GetRandom() hub.Color = types.Rgba{}.GetRandom()
hub.CreatedAt = time.Now() hub.CreatedAt = time.Now()
rootGrp := &types.HubChannelGroup{
Id: uuid.New(),
Name: "root",
Color: types.Rgba{6, 2, 1, 255},
Position: uint8(0),
}
hub.ChannelGroups[rootGrp.Id] = rootGrp
rootRole := &types.HubRole{
Id: 0,
Name: "root",
Color: types.Rgba{255, 0, 0, 255},
RolePermission: ^types.RolePermission(0),
}
hub.Roles[rootRole.Id] = rootRole
rootUser := &types.HubUser{
Id: user.Id,
Username: user.Name,
Roles: []uint8{rootRole.Id},
CreatedAt: hub.CreatedAt,
}
hub.Users[rootUser.Id] = rootUser
err = postgresql.HubSave(ctx, hub) err = postgresql.HubSave(ctx, hub)
if err != nil { if err != nil {
http.Error(response, "failed to save hub", http.StatusInternalServerError) http.Error(response, "internal server error", http.StatusInternalServerError)
return
}
if err = postgresql.HubRoleSave(ctx, hub.Id, rootRole); err != nil {
http.Error(response, "internal server error", http.StatusInternalServerError)
return
}
if err = postgresql.HubChannelGroupSave(ctx, hub.Id, rootGrp); err != nil {
http.Error(response, "internal server error", http.StatusInternalServerError)
return
}
if err = postgresql.HubUserAdd(ctx, hub.Id, rootUser); err != nil {
http.Error(response, "internal server error", http.StatusInternalServerError)
return
}
if err = postgresql.HubUserRoleAdd(ctx, hub.Id, user.Id, rootRole.Id); err != nil {
http.Error(response, "internal server error", http.StatusInternalServerError)
return return
} }
cache.SaveHub(hub) cache.SaveHub(hub)
+79 -65
View File
@@ -73,67 +73,81 @@ func Init(ctx context.Context) {
} }
_, err = dbConn.Exec(ctx, ` _, err = dbConn.Exec(ctx, `
CREATE TABLE IF NOT EXISTS hubs () CREATE TABLE IF NOT EXISTS hubs (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(), id UUID PRIMARY KEY,
creator_id UUID NOT NULL REFERENCES users(id), creator_id UUID NOT NULL REFERENCES users(id),
name TEXT NOT NULL, name TEXT NOT NULL,
allow_user_color BOOLEAN DEFAULT TRUE, allow_user_color BOOLEAN NOT NULL DEFAULT TRUE,
rgba BIGINT NOT NULL DEFAULT 0 CHECK (rgba BETWEEN 0 AND 4294967295), rgba BIGINT NOT NULL DEFAULT 0 CHECK (rgba BETWEEN 0 AND 4294967295),
created_at TIMESTAMP NOT NULL DEFAULT NOW() created_at TIMESTAMP NOT NULL DEFAULT NOW()
)
`) `)
if err != nil { if err != nil {
panic(err) panic(err)
} }
_, err = dbConn.Exec(ctx, ` _, err = dbConn.Exec(ctx, `
CREATE TABLE IF NOT EXISTS hub_channel_groups () CREATE TABLE IF NOT EXISTS hub_roles (
hub_id UUID PRIMARY KEY NOT NULL REFERENCES hubs(id) ON DELETE CASCADE, hub_id UUID NOT NULL REFERENCES hubs(id) ON DELETE CASCADE,
channel_group_id UUID PRIMARY KEY DEFAULT gen_random_uuid(), role_id SMALLINT NOT NULL,
name TEXT NOT NULL,
rgba BIGINT NOT NULL DEFAULT 0 CHECK (rgba BETWEEN 0 AND 4294967295),
`)
if err != nil {
panic(err)
}
_, err = dbConn.Exec(ctx, `
CREATE TABLE IF NOT EXISTS hub_channels ()
hub_id UUID PRIMARY KEY NOT NULL REFERENCES hubs(id) ON DELETE CASCADE,
channel_id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
name TEXT NOT NULL,
parent_group_id UUID REFERENCES hub_channel_groups(id) ON DELETE CASCADE,
`)
if err != nil {
panic(err)
}
_, err = dbConn.Exec(ctx, `
CREATE TABLE IF NOT EXISTS hub_users ()
hub_id UUID PRIMARY KEY NOT NULL REFERENCES hubs(id) ON DELETE CASCADE,
user_id UUID PRIMARY KEY NOT NULL REFERENCES users(id) ON DELETE CASCADE,
name TEXT NOT NULL,
rgba BIGINT NOT NULL DEFAULT 0 CHECK (rgba BETWEEN 0 AND 4294967295),
created_at TIMESTAMP NOT NULL DEFAULT NOW()
`)
if err != nil {
panic(err)
}
_, err = dbConn.Exec(ctx, `
CREATE TABLE IF NOT EXISTS hub_user_roles ()
user_id UUID PRIMARY KEY NOT NULL REFERENCES users(id) ON DELETE CASCADE,
role_id SMALLINT NOT NULL REFERENCES hub_roles(role_id) ON DELETE CASCADE
`)
if err != nil {
panic(err)
}
_, err = dbConn.Exec(ctx, `
CREATE TABLE IF NOT EXISTS hub_roles ()
hub_id UUID PRIMARY KEY NOT NULL REFERENCES hubs(id) ON DELETE CASCADE,
role_id SMALLINT NOT NULL DEFAULT 0,
name TEXT NOT NULL, name TEXT NOT NULL,
permissions INTEGER NOT NULL DEFAULT 0, permissions INTEGER NOT NULL DEFAULT 0,
rgba BIGINT NOT NULL DEFAULT 0 CHECK (rgba BETWEEN 0 AND 4294967295), rgba BIGINT NOT NULL DEFAULT 0 CHECK (rgba BETWEEN 0 AND 4294967295),
PRIMARY KEY (hub_id, role_id)
)
`)
if err != nil {
panic(err)
}
_, err = dbConn.Exec(ctx, `
CREATE TABLE IF NOT EXISTS hub_channel_groups (
channel_group_id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
hub_id UUID NOT NULL REFERENCES hubs(id) ON DELETE CASCADE,
name TEXT NOT NULL,
rgba BIGINT NOT NULL DEFAULT 0 CHECK (rgba BETWEEN 0 AND 4294967295),
position SMALLINT NOT NULL DEFAULT 0
)
`)
if err != nil {
panic(err)
}
_, err = dbConn.Exec(ctx, `
CREATE TABLE IF NOT EXISTS hub_channels (
channel_id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
hub_id UUID NOT NULL REFERENCES hubs(id) ON DELETE CASCADE,
name TEXT NOT NULL,
parent_group_id UUID REFERENCES hub_channel_groups(channel_group_id) ON DELETE CASCADE,
position SMALLINT NOT NULL DEFAULT 0
)
`)
if err != nil {
panic(err)
}
_, err = dbConn.Exec(ctx, `
CREATE TABLE IF NOT EXISTS hub_users (
hub_id UUID NOT NULL REFERENCES hubs(id) ON DELETE CASCADE,
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
name TEXT NOT NULL,
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
PRIMARY KEY (hub_id, user_id)
)
`)
if err != nil {
panic(err)
}
_, err = dbConn.Exec(ctx, `
CREATE TABLE IF NOT EXISTS hub_user_roles (
hub_id UUID NOT NULL,
user_id UUID NOT NULL,
role_id SMALLINT NOT NULL,
PRIMARY KEY (hub_id, user_id, role_id),
FOREIGN KEY (hub_id, user_id) REFERENCES hub_users(hub_id, user_id) ON DELETE CASCADE,
FOREIGN KEY (hub_id, role_id) REFERENCES hub_roles(hub_id, role_id) ON DELETE CASCADE
)
`) `)
if err != nil { if err != nil {
panic(err) panic(err)
@@ -322,10 +336,10 @@ func ConnectionGetMessagesBefore(ctx context.Context, before time.Time, connecti
} }
func HubSave(ctx context.Context, hub *types.Hub) error { func HubSave(ctx context.Context, hub *types.Hub) error {
return dbConn.QueryRow(ctx, ` _, err := dbConn.Exec(ctx, `
INSERT INTO hubs (creator_id, name, allow_user_color, rgba, created_at) VALUES ($1, $2, $3, $4, $5) INSERT INTO hubs (id, creator_id, name, allow_user_color, rgba, created_at) VALUES ($1, $2, $3, $4, $5, $6)
RETURNING id `, hub.Id, hub.Creator, hub.Name, hub.AllowUserColor, convertions.RgbaToUint32(hub.Color), hub.CreatedAt)
`, hub.Creator, hub.Name, hub.AllowUserColor, convertions.RgbaToUint32(hub.Color), hub.CreatedAt).Scan(&hub.Id) return err
} }
func HubDelete(ctx context.Context, hub *types.Hub) error { func HubDelete(ctx context.Context, hub *types.Hub) error {
@@ -373,7 +387,7 @@ func HubGetUsers(ctx context.Context, hub *types.Hub) error {
rows, err := dbConn.Query(ctx, ` rows, err := dbConn.Query(ctx, `
SELECT hu.user_id, hu.name, hu.created_at, COALESCE(array_agg(hur.role_id) FILTER (WHERE hur.role_id IS NOT NULL), '{}') SELECT hu.user_id, hu.name, hu.created_at, COALESCE(array_agg(hur.role_id) FILTER (WHERE hur.role_id IS NOT NULL), '{}')
FROM hub_users hu FROM hub_users hu
LEFT JOIN hub_user_roles hur ON hu.user_id = hur.user_id LEFT JOIN hub_user_roles hur ON hu.hub_id = hur.hub_id AND hu.user_id = hur.user_id
WHERE hu.hub_id = $1 WHERE hu.hub_id = $1
GROUP BY hu.user_id, hu.name, hu.created_at GROUP BY hu.user_id, hu.name, hu.created_at
`, hub.Id) `, hub.Id)
@@ -442,17 +456,17 @@ func HubUserRemove(ctx context.Context, hubId uuid.UUID, userId uuid.UUID) error
return err return err
} }
func HubUserRoleAdd(ctx context.Context, userId uuid.UUID, roleId uint8) error { func HubUserRoleAdd(ctx context.Context, hubId uuid.UUID, userId uuid.UUID, roleId uint8) error {
_, err := dbConn.Exec(ctx, ` _, err := dbConn.Exec(ctx, `
INSERT INTO hub_user_roles (user_id, role_id) VALUES ($1, $2) INSERT INTO hub_user_roles (hub_id, user_id, role_id) VALUES ($1, $2, $3)
`, userId, roleId) `, hubId, userId, roleId)
return err return err
} }
func HubUserRoleRemove(ctx context.Context, userId uuid.UUID, roleId uint8) error { func HubUserRoleRemove(ctx context.Context, hubId uuid.UUID, userId uuid.UUID, roleId uint8) error {
_, err := dbConn.Exec(ctx, ` _, err := dbConn.Exec(ctx, `
DELETE FROM hub_user_roles WHERE user_id = $1 AND role_id = $2 DELETE FROM hub_user_roles WHERE hub_id = $1 AND user_id = $2 AND role_id = $3
`, userId, roleId) `, hubId, userId, roleId)
return err return err
} }
@@ -478,10 +492,10 @@ func HubRoleUpdate(ctx context.Context, hubId uuid.UUID, role *types.HubRole) er
} }
func HubChannelGroupSave(ctx context.Context, hubId uuid.UUID, cg *types.HubChannelGroup) error { func HubChannelGroupSave(ctx context.Context, hubId uuid.UUID, cg *types.HubChannelGroup) error {
return dbConn.QueryRow(ctx, ` _, err := dbConn.Exec(ctx, `
INSERT INTO hub_channel_groups (hub_id, name, rgba) VALUES ($1, $2, $3) INSERT INTO hub_channel_groups (channel_group_id, hub_id, name, rgba, position) VALUES ($1, $2, $3, $4, $5)
RETURNING channel_group_id `, cg.Id, hubId, cg.Name, convertions.RgbaToUint32(cg.Color), cg.Position)
`, hubId, cg.Name, convertions.RgbaToUint32(cg.Color)).Scan(&cg.Id) return err
} }
func HubChannelGroupDelete(ctx context.Context, cgId uuid.UUID) error { func HubChannelGroupDelete(ctx context.Context, cgId uuid.UUID) error {
@@ -491,9 +505,9 @@ func HubChannelGroupDelete(ctx context.Context, cgId uuid.UUID) error {
func HubChannelSave(ctx context.Context, hubId uuid.UUID, ch *types.HubChannel) error { func HubChannelSave(ctx context.Context, hubId uuid.UUID, ch *types.HubChannel) error {
return dbConn.QueryRow(ctx, ` return dbConn.QueryRow(ctx, `
INSERT INTO hub_channels (hub_id, name, parent_group_id) VALUES ($1, $2, $3) INSERT INTO hub_channels (hub_id, name, parent_group_id, position) VALUES ($1, $2, $3, $4)
RETURNING channel_id RETURNING channel_id
`, hubId, ch.Name, ch.ParentGroupId).Scan(&ch.Id) `, hubId, ch.Name, ch.ParentGroupId, ch.Position).Scan(&ch.Id)
} }
func HubChannelDelete(ctx context.Context, chId uuid.UUID) error { func HubChannelDelete(ctx context.Context, chId uuid.UUID) error {
+11 -6
View File
@@ -128,7 +128,7 @@ type RolePermission uint32
const ( const (
// Hub permissions // Hub permissions
PermissionSetHubName RolePermission = iota PermissionSetHubName RolePermission = 1 << iota
PermissionSetHubBg PermissionSetHubBg
PermissionSetHubColor PermissionSetHubColor
PermissionRemoveHub PermissionRemoveHub
@@ -173,6 +173,7 @@ type Hub struct {
HaveOverflowed bool `json:"-"` HaveOverflowed bool `json:"-"`
Users map[uuid.UUID]*HubUser `json:"-"` Users map[uuid.UUID]*HubUser `json:"-"`
Roles map[uint8]*HubRole `json:"-"` Roles map[uint8]*HubRole `json:"-"`
ChannelGroups map[uuid.UUID]*HubChannelGroup `json:"-"`
Creator uuid.UUID `json:"creator"` Creator uuid.UUID `json:"creator"`
Name string `json:"name"` Name string `json:"name"`
Color Rgba `json:"color"` Color Rgba `json:"color"`
@@ -181,9 +182,11 @@ type Hub struct {
func NewHub() *Hub { func NewHub() *Hub {
return &Hub{ return &Hub{
Id: uuid.New(),
MessagesBuff: make([]*Message, config.MaxHubMsgCache), MessagesBuff: make([]*Message, config.MaxHubMsgCache),
Users: make(map[uuid.UUID]*HubUser), Users: make(map[uuid.UUID]*HubUser),
Roles: make(map[uint8]*HubRole), Roles: make(map[uint8]*HubRole),
ChannelGroups: make(map[uuid.UUID]*HubChannelGroup),
} }
} }
@@ -191,12 +194,14 @@ type HubChannelGroup struct {
Id uuid.UUID `json:"id"` Id uuid.UUID `json:"id"`
Name string `json:"name"` Name string `json:"name"`
Color Rgba `json:"color"` Color Rgba `json:"color"`
Position uint8 `json:"position"`
} }
type HubChannel struct { type HubChannel struct {
Id uuid.UUID `json:"id"` Id uuid.UUID `json:"id"`
Name uuid.UUID `json:"name"` Name uuid.UUID `json:"name"`
ParentGroupId uuid.UUID `json:"parentGroupId"` ParentGroupId uuid.UUID `json:"parentGroupId"`
Position uint8 `json:"position"`
} }
type HubUser struct { type HubUser struct {
@@ -213,22 +218,22 @@ type HubRole struct {
Color Rgba `json:"color"` Color Rgba `json:"color"`
} }
func (h HubRole) GrantPermission(r RolePermission) { func (h *HubRole) GrantPermission(r RolePermission) {
h.RolePermission |= r h.RolePermission |= r
} }
func (h HubRole) GrantPermissions(rs []RolePermission) { func (h *HubRole) GrantPermissions(rs []RolePermission) {
for _, r := range rs { for _, r := range rs {
h.RolePermission |= r h.RolePermission |= r
} }
} }
func (h HubRole) RevokePermission(r RolePermission) { func (h *HubRole) RevokePermission(r RolePermission) {
h.RolePermission &^= r h.RolePermission &^= r
} }
func (h HubRole) RevokePermissions(rs []RolePermission) { func (h *HubRole) RevokePermissions(rs []RolePermission) {
for _, r := range rs { for _, r := range rs {
h.RolePermission &^= r h.RolePermission &^= r
} }
} }
func (h HubRole) HasPermission(r RolePermission) bool { func (h *HubRole) HasPermission(r RolePermission) bool {
return h.RolePermission&r != 0 return h.RolePermission&r != 0
} }