diff --git a/packages/httpRequest/hubs.go b/packages/httpRequest/hubs.go index b80846a..18064a2 100644 --- a/packages/httpRequest/hubs.go +++ b/packages/httpRequest/hubs.go @@ -7,6 +7,8 @@ import ( "go-socket/packages/cache" "go-socket/packages/postgresql" "go-socket/packages/types" + + "github.com/google/uuid" ) 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.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) 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 } cache.SaveHub(hub) diff --git a/packages/postgresql/postgresql.go b/packages/postgresql/postgresql.go index 1341f24..92b723b 100644 --- a/packages/postgresql/postgresql.go +++ b/packages/postgresql/postgresql.go @@ -73,67 +73,81 @@ func Init(ctx context.Context) { } _, err = dbConn.Exec(ctx, ` - CREATE TABLE IF NOT EXISTS hubs () - id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + CREATE TABLE IF NOT EXISTS hubs ( + id UUID PRIMARY KEY, creator_id UUID NOT NULL REFERENCES users(id), 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), created_at TIMESTAMP NOT NULL DEFAULT NOW() + ) `) if err != nil { panic(err) } _, err = dbConn.Exec(ctx, ` - CREATE TABLE IF NOT EXISTS hub_channel_groups () - hub_id UUID PRIMARY KEY NOT NULL REFERENCES hubs(id) ON DELETE CASCADE, - channel_group_id UUID PRIMARY KEY DEFAULT gen_random_uuid(), - 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, + CREATE TABLE IF NOT EXISTS hub_roles ( + hub_id UUID NOT NULL REFERENCES hubs(id) ON DELETE CASCADE, + role_id SMALLINT NOT NULL, name TEXT NOT NULL, permissions INTEGER NOT NULL DEFAULT 0, 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 { panic(err) @@ -322,10 +336,10 @@ func ConnectionGetMessagesBefore(ctx context.Context, before time.Time, connecti } func HubSave(ctx context.Context, hub *types.Hub) error { - return dbConn.QueryRow(ctx, ` - INSERT INTO hubs (creator_id, name, allow_user_color, rgba, created_at) VALUES ($1, $2, $3, $4, $5) - RETURNING id - `, hub.Creator, hub.Name, hub.AllowUserColor, convertions.RgbaToUint32(hub.Color), hub.CreatedAt).Scan(&hub.Id) + _, err := dbConn.Exec(ctx, ` + INSERT INTO hubs (id, creator_id, name, allow_user_color, rgba, created_at) VALUES ($1, $2, $3, $4, $5, $6) + `, hub.Id, hub.Creator, hub.Name, hub.AllowUserColor, convertions.RgbaToUint32(hub.Color), hub.CreatedAt) + return err } 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, ` 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 - 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 GROUP BY hu.user_id, hu.name, hu.created_at `, hub.Id) @@ -442,17 +456,17 @@ func HubUserRemove(ctx context.Context, hubId uuid.UUID, userId uuid.UUID) error 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, ` - INSERT INTO hub_user_roles (user_id, role_id) VALUES ($1, $2) - `, userId, roleId) + INSERT INTO hub_user_roles (hub_id, user_id, role_id) VALUES ($1, $2, $3) + `, hubId, userId, roleId) 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, ` - DELETE FROM hub_user_roles WHERE user_id = $1 AND role_id = $2 - `, userId, roleId) + DELETE FROM hub_user_roles WHERE hub_id = $1 AND user_id = $2 AND role_id = $3 + `, hubId, userId, roleId) 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 { - return dbConn.QueryRow(ctx, ` - INSERT INTO hub_channel_groups (hub_id, name, rgba) VALUES ($1, $2, $3) - RETURNING channel_group_id - `, hubId, cg.Name, convertions.RgbaToUint32(cg.Color)).Scan(&cg.Id) + _, err := dbConn.Exec(ctx, ` + INSERT INTO hub_channel_groups (channel_group_id, hub_id, name, rgba, position) VALUES ($1, $2, $3, $4, $5) + `, cg.Id, hubId, cg.Name, convertions.RgbaToUint32(cg.Color), cg.Position) + return err } 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 { 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 - `, 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 { diff --git a/packages/types/types.go b/packages/types/types.go index f955177..e7dbd70 100644 --- a/packages/types/types.go +++ b/packages/types/types.go @@ -128,7 +128,7 @@ type RolePermission uint32 const ( // Hub permissions - PermissionSetHubName RolePermission = iota + PermissionSetHubName RolePermission = 1 << iota PermissionSetHubBg PermissionSetHubColor PermissionRemoveHub @@ -165,38 +165,43 @@ const ( ) type Hub struct { - Mu sync.RWMutex `json:"-"` - Id uuid.UUID `json:"id"` - CreatedAt time.Time `json:"createdAt"` - MessagesBuff []*Message `json:"-"` - NextBuffIdx uint32 `json:"-"` - HaveOverflowed bool `json:"-"` - Users map[uuid.UUID]*HubUser `json:"-"` - Roles map[uint8]*HubRole `json:"-"` - Creator uuid.UUID `json:"creator"` - Name string `json:"name"` - Color Rgba `json:"color"` - AllowUserColor bool `json:"allowUserColor"` + Mu sync.RWMutex `json:"-"` + Id uuid.UUID `json:"id"` + CreatedAt time.Time `json:"createdAt"` + MessagesBuff []*Message `json:"-"` + NextBuffIdx uint32 `json:"-"` + HaveOverflowed bool `json:"-"` + Users map[uuid.UUID]*HubUser `json:"-"` + Roles map[uint8]*HubRole `json:"-"` + ChannelGroups map[uuid.UUID]*HubChannelGroup `json:"-"` + Creator uuid.UUID `json:"creator"` + Name string `json:"name"` + Color Rgba `json:"color"` + AllowUserColor bool `json:"allowUserColor"` } func NewHub() *Hub { return &Hub{ - MessagesBuff: make([]*Message, config.MaxHubMsgCache), - Users: make(map[uuid.UUID]*HubUser), - Roles: make(map[uint8]*HubRole), + Id: uuid.New(), + MessagesBuff: make([]*Message, config.MaxHubMsgCache), + Users: make(map[uuid.UUID]*HubUser), + Roles: make(map[uint8]*HubRole), + ChannelGroups: make(map[uuid.UUID]*HubChannelGroup), } } type HubChannelGroup struct { - Id uuid.UUID `json:"id"` - Name string `json:"name"` - Color Rgba `json:"color"` + Id uuid.UUID `json:"id"` + Name string `json:"name"` + Color Rgba `json:"color"` + Position uint8 `json:"position"` } type HubChannel struct { Id uuid.UUID `json:"id"` Name uuid.UUID `json:"name"` ParentGroupId uuid.UUID `json:"parentGroupId"` + Position uint8 `json:"position"` } type HubUser struct { @@ -213,22 +218,22 @@ type HubRole struct { Color Rgba `json:"color"` } -func (h HubRole) GrantPermission(r RolePermission) { +func (h *HubRole) GrantPermission(r RolePermission) { h.RolePermission |= r } -func (h HubRole) GrantPermissions(rs []RolePermission) { +func (h *HubRole) GrantPermissions(rs []RolePermission) { for _, r := range rs { h.RolePermission |= r } } -func (h HubRole) RevokePermission(r RolePermission) { +func (h *HubRole) RevokePermission(r RolePermission) { h.RolePermission &^= r } -func (h HubRole) RevokePermissions(rs []RolePermission) { +func (h *HubRole) RevokePermissions(rs []RolePermission) { for _, r := range rs { h.RolePermission &^= r } } -func (h HubRole) HasPermission(r RolePermission) bool { +func (h *HubRole) HasPermission(r RolePermission) bool { return h.RolePermission&r != 0 }