764 lines
24 KiB
Go
764 lines
24 KiB
Go
package postgresql
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"strings"
|
|
"time"
|
|
|
|
"go-socket/packages/convertions"
|
|
"go-socket/packages/types"
|
|
|
|
"github.com/google/uuid"
|
|
"github.com/jackc/pgx/v5/pgxpool"
|
|
)
|
|
|
|
var dbConn *pgxpool.Pool
|
|
|
|
func Init(ctx context.Context) {
|
|
var err error
|
|
dbConn, err = pgxpool.New(ctx, "postgres://master:secret@localhost:5432") // TODO change to env in production
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
_, err = dbConn.Exec(ctx, `CREATE EXTENSION IF NOT EXISTS "pgcrypto";`)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
_, err = dbConn.Exec(ctx, `
|
|
CREATE TABLE IF NOT EXISTS users (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
name TEXT UNIQUE NOT NULL,
|
|
pass_hash TEXT NOT NULL,
|
|
pronouns TEXT DEFAULT NULL,
|
|
description TEXT DEFAULT NULL,
|
|
avatar TEXT DEFAULT NULL,
|
|
profile_bg TEXT DEFAULT 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 user_connections (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
requestor_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
|
recipient_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
|
state SMALLINT NOT NULL DEFAULT 0,
|
|
created_at TIMESTAMP NOT NULL DEFAULT NOW()
|
|
)
|
|
`)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
_, err = dbConn.Exec(ctx, `
|
|
CREATE TABLE IF NOT EXISTS direct_messages (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
sender_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
|
receiver_id UUID NOT NULL REFERENCES user_connections(id) ON DELETE CASCADE,
|
|
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
|
|
content TEXT NOT NULL,
|
|
attached_file TEXT NOT NULL DEFAULT ''
|
|
)
|
|
`)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
_, err = dbConn.Exec(ctx, `
|
|
CREATE TABLE IF NOT EXISTS hubs (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
name TEXT NOT NULL,
|
|
icon_url TEXT,
|
|
background_url TEXT,
|
|
creator UUID NOT NULL REFERENCES users(id),
|
|
join_role SMALLINT,
|
|
rgba BIGINT NOT NULL DEFAULT 0 CHECK (rgba BETWEEN 0 AND 4294967295),
|
|
user_color_allowed BOOLEAN NOT NULL DEFAULT FALSE,
|
|
created_at TIMESTAMP NOT NULL DEFAULT NOW()
|
|
)
|
|
`)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
_, err = dbConn.Exec(ctx, `
|
|
CREATE TABLE IF NOT EXISTS hub_roles (
|
|
id SMALLINT NOT NULL,
|
|
hub_id UUID NOT NULL REFERENCES hubs(id) ON DELETE CASCADE,
|
|
name TEXT NOT NULL,
|
|
permissions BIGINT NOT NULL DEFAULT 0,
|
|
rgba BIGINT NOT NULL DEFAULT 0 CHECK (rgba BETWEEN 0 AND 4294967295),
|
|
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
|
|
PRIMARY KEY (id, hub_id)
|
|
)
|
|
`)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
_, err = dbConn.Exec(ctx, `
|
|
CREATE TABLE IF NOT EXISTS hub_channel (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
hub_id UUID NOT NULL REFERENCES hubs(id) ON DELETE CASCADE,
|
|
name TEXT NOT NULL,
|
|
description TEXT,
|
|
icon_url TEXT,
|
|
position SMALLINT NOT NULL DEFAULT 0,
|
|
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
|
|
roles_can_view_0 BIGINT NOT NULL DEFAULT 0,
|
|
roles_can_view_1 BIGINT NOT NULL DEFAULT 0,
|
|
roles_can_view_2 BIGINT NOT NULL DEFAULT 0,
|
|
roles_can_message_0 BIGINT NOT NULL DEFAULT 0,
|
|
roles_can_message_1 BIGINT NOT NULL DEFAULT 0,
|
|
roles_can_message_2 BIGINT NOT NULL DEFAULT 0,
|
|
roles_can_read_history_0 BIGINT NOT NULL DEFAULT 0,
|
|
roles_can_read_history_1 BIGINT NOT NULL DEFAULT 0,
|
|
roles_can_read_history_2 BIGINT NOT NULL DEFAULT 0
|
|
)
|
|
`)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
_, err = dbConn.Exec(ctx, `
|
|
CREATE TABLE IF NOT EXISTS hub_users (
|
|
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
|
hub_id UUID NOT NULL REFERENCES hubs(id) ON DELETE CASCADE,
|
|
name TEXT NOT NULL DEFAULT '',
|
|
roles_0 BIGINT NOT NULL DEFAULT 0,
|
|
roles_1 BIGINT NOT NULL DEFAULT 0,
|
|
roles_2 BIGINT NOT NULL DEFAULT 0,
|
|
is_muted BOOLEAN NOT NULL DEFAULT FALSE,
|
|
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
|
|
PRIMARY KEY (user_id, hub_id)
|
|
)
|
|
`)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
_, err = dbConn.Exec(ctx, `
|
|
CREATE TABLE IF NOT EXISTS hub_channel_messages (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
sender_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
|
receiver_id UUID NOT NULL REFERENCES hub_channel(id) ON DELETE CASCADE,
|
|
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
|
|
content TEXT NOT NULL,
|
|
attached_file TEXT NOT NULL DEFAULT ''
|
|
)
|
|
`)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
}
|
|
|
|
func UserSave(ctx context.Context, user *types.User) error {
|
|
err := dbConn.QueryRow(ctx, `
|
|
INSERT INTO users (name, pass_hash, pronouns, rgba, created_at)
|
|
VALUES ($1, $2, $3, $4, $5)
|
|
RETURNING id
|
|
`, user.Name, user.PasswordHash, user.Pronouns, convertions.RgbaToUint32(user.Color), user.CreatedAt).
|
|
Scan(&user.Id)
|
|
return err
|
|
}
|
|
|
|
func UserDelete(ctx context.Context, id uuid.UUID) error {
|
|
_, err := dbConn.Exec(ctx, `
|
|
DELETE FROM users WHERE id = $1
|
|
`, id)
|
|
return err
|
|
}
|
|
|
|
func UserGetStandardInfoByName(ctx context.Context, user *types.User) error {
|
|
var rgba int64
|
|
err := dbConn.QueryRow(ctx, `
|
|
SELECT id, name, pass_hash, COALESCE(pronouns, ''), rgba, created_at, COALESCE(avatar, ''), COALESCE(profile_bg, '') FROM users WHERE name = $1
|
|
`, user.Name).Scan(&user.Id, &user.Name, &user.PasswordHash, &user.Pronouns, &rgba, &user.CreatedAt, &user.AvatarKey, &user.ProfileBgKey)
|
|
if err == nil {
|
|
user.Color = convertions.Uint32ToRgba(uint32(rgba))
|
|
}
|
|
return err
|
|
}
|
|
|
|
func UserGetById(ctx context.Context, user *types.User) error {
|
|
var rgba int64
|
|
err := dbConn.QueryRow(ctx, `
|
|
SELECT name, pass_hash, COALESCE(pronouns, ''), rgba, created_at, COALESCE(avatar, ''), COALESCE(profile_bg, '') FROM users WHERE id = $1
|
|
`, user.Id).Scan(&user.Name, &user.PasswordHash, &user.Pronouns, &rgba, &user.CreatedAt, &user.AvatarKey, &user.ProfileBgKey)
|
|
if err == nil {
|
|
user.Color = convertions.Uint32ToRgba(uint32(rgba))
|
|
}
|
|
return err
|
|
}
|
|
|
|
func UserUpdateProfile(ctx context.Context, user *types.User, updateList *types.UserProfileUpdate) error {
|
|
setClauses := make([]string, 0, 3)
|
|
args := make([]any, 0, 4)
|
|
argIdx := 1
|
|
|
|
if updateList.Pronouns {
|
|
setClauses = append(setClauses, fmt.Sprintf("pronouns = $%d", argIdx))
|
|
args = append(args, user.Pronouns)
|
|
argIdx++
|
|
}
|
|
if updateList.Description {
|
|
setClauses = append(setClauses, fmt.Sprintf("description = $%d", argIdx))
|
|
args = append(args, user.Description)
|
|
argIdx++
|
|
}
|
|
if updateList.Color {
|
|
setClauses = append(setClauses, fmt.Sprintf("rgba = $%d", argIdx))
|
|
args = append(args, convertions.RgbaToUint32(user.Color))
|
|
argIdx++
|
|
}
|
|
if updateList.Avatar {
|
|
setClauses = append(setClauses, fmt.Sprintf("avatar = $%d", argIdx))
|
|
args = append(args, user.AvatarKey)
|
|
argIdx++
|
|
}
|
|
if updateList.ProfileBg {
|
|
setClauses = append(setClauses, fmt.Sprintf("profile_bg = $%d", argIdx))
|
|
args = append(args, user.ProfileBgKey)
|
|
argIdx++
|
|
}
|
|
|
|
if len(setClauses) == 0 {
|
|
return nil
|
|
}
|
|
|
|
query := "UPDATE users SET " + strings.Join(setClauses, ", ") + fmt.Sprintf(" WHERE id = $%d", argIdx)
|
|
args = append(args, user.Id)
|
|
|
|
_, err := dbConn.Exec(ctx, query, args...)
|
|
return err
|
|
}
|
|
|
|
func UserGetBelongingHubs(ctx context.Context, user *types.User) error {
|
|
rows, err := dbConn.Query(ctx, `
|
|
SELECT h.id, h.name, COALESCE(h.icon_url, ''), COALESCE(h.background_url, ''), h.creator, h.join_role, h.rgba, h.user_color_allowed, h.created_at
|
|
FROM hubs h
|
|
INNER JOIN hub_users hu ON hu.hub_id = h.id
|
|
WHERE hu.user_id = $1
|
|
`, user.Id)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer rows.Close()
|
|
|
|
if user.Hubs == nil {
|
|
user.Hubs = make(map[uuid.UUID]*types.Hub)
|
|
}
|
|
|
|
for rows.Next() {
|
|
hub := types.NewHub()
|
|
var joinRoleId *int16
|
|
var rgba int64
|
|
if err = rows.Scan(&hub.Id, &hub.Name, &hub.IconUrl, &hub.BgUrl, &hub.Creator, &joinRoleId, &rgba, &hub.UserColorAllowed, &hub.CreatedAt); err != nil {
|
|
return fmt.Errorf("scanning hub row: %w", err)
|
|
}
|
|
hub.Color = convertions.Uint32ToRgba(uint32(rgba))
|
|
if joinRoleId != nil {
|
|
hub.JoinRole = &types.HubRole{Id: uint8(*joinRoleId)}
|
|
}
|
|
user.Hubs[hub.Id] = hub
|
|
}
|
|
return rows.Err()
|
|
}
|
|
|
|
func UserGetWhole(ctx context.Context, user *types.User) error {
|
|
if err := UserGetById(ctx, user); err != nil {
|
|
return err
|
|
}
|
|
if err := ConnectionsGetBelongingToUser(ctx, user); err != nil {
|
|
return err
|
|
}
|
|
if err := UserGetBelongingHubs(ctx, user); err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func ConnectionSave(ctx context.Context, conn *types.Connection) error {
|
|
return dbConn.QueryRow(ctx, `
|
|
INSERT INTO user_connections (requestor_id, recipient_id, state, created_at) VALUES ($1, $2, $3, $4)
|
|
RETURNING id
|
|
`, conn.RequestorId, conn.RecipientId, conn.State, conn.CreatedAt).Scan(&conn.Id)
|
|
}
|
|
|
|
func ConnectionDelete(ctx context.Context, conn *types.Connection) error {
|
|
_, err := dbConn.Exec(ctx, `
|
|
DELETE FROM user_connections WHERE id = $1
|
|
`, conn.Id)
|
|
return err
|
|
}
|
|
|
|
func ConnectionGetById(ctx context.Context, id uuid.UUID) (*types.Connection, error) {
|
|
conn := types.NewConn()
|
|
err := dbConn.QueryRow(ctx, `
|
|
SELECT id, requestor_id, recipient_id, state, created_at
|
|
FROM user_connections
|
|
WHERE id = $1
|
|
`, id).Scan(&conn.Id, &conn.RequestorId, &conn.RecipientId, &conn.State, &conn.CreatedAt)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return conn, nil
|
|
}
|
|
|
|
func ConnectionsGetBelongingToUser(ctx context.Context, user *types.User) error {
|
|
rows, err := dbConn.Query(ctx, `
|
|
SELECT id, requestor_id, recipient_id, state, created_at
|
|
FROM user_connections
|
|
WHERE requestor_id = $1 OR recipient_id = $1
|
|
`, user.Id)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer rows.Close()
|
|
|
|
if user.Connections == nil {
|
|
user.Connections = make(map[uuid.UUID]*types.Connection)
|
|
}
|
|
|
|
for rows.Next() {
|
|
conn := types.NewConn()
|
|
if err = rows.Scan(&conn.Id, &conn.RequestorId, &conn.RecipientId, &conn.State, &conn.CreatedAt); err != nil {
|
|
return fmt.Errorf("scanning connection row: %w", err)
|
|
}
|
|
user.Connections[conn.Id] = conn
|
|
}
|
|
return rows.Err()
|
|
}
|
|
|
|
func ConnectionUpdateState(ctx context.Context, conn *types.Connection) error {
|
|
_, err := dbConn.Exec(ctx, `
|
|
UPDATE user_connections SET state = $1 WHERE id = $2
|
|
`, conn.State, conn.Id)
|
|
return err
|
|
}
|
|
|
|
func ConnectionMessageSave(ctx context.Context, message *types.Message) error {
|
|
if message.Id != (uuid.UUID{}) {
|
|
_, err := dbConn.Exec(ctx, `
|
|
INSERT INTO direct_messages (id, sender_id, receiver_id, created_at, content, attached_file) VALUES ($1, $2, $3, $4, $5, $6)
|
|
`, message.Id, message.Sender, message.Receiver, message.CreatedAt, message.Content, message.AttachedFile)
|
|
return err
|
|
}
|
|
return dbConn.QueryRow(ctx, `
|
|
INSERT INTO direct_messages (sender_id, receiver_id, created_at, content, attached_file) VALUES ($1, $2, $3, $4, $5)
|
|
RETURNING id
|
|
`, message.Sender, message.Receiver, message.CreatedAt, message.Content, message.AttachedFile).Scan(&message.Id)
|
|
}
|
|
|
|
func ConnectionGetMessagesBefore(ctx context.Context, before time.Time, connection uuid.UUID, cap uint32) ([]*types.Message, error) {
|
|
rows, err := dbConn.Query(ctx, `
|
|
SELECT id, sender_id, receiver_id, created_at, content, attached_file
|
|
FROM (
|
|
SELECT id, sender_id, receiver_id, created_at, content, attached_file
|
|
FROM direct_messages
|
|
WHERE receiver_id = $1
|
|
AND created_at < $2
|
|
ORDER BY created_at DESC
|
|
LIMIT $3
|
|
) sub
|
|
ORDER BY created_at ASC
|
|
`, connection, before, cap)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
|
|
messages := make([]*types.Message, 0, cap)
|
|
for rows.Next() {
|
|
msg := &types.Message{}
|
|
if err = rows.Scan(&msg.Id, &msg.Sender, &msg.Receiver, &msg.CreatedAt, &msg.Content, &msg.AttachedFile); err != nil {
|
|
return nil, err
|
|
}
|
|
messages = append(messages, msg)
|
|
}
|
|
return messages, rows.Err()
|
|
}
|
|
|
|
func HubGet(ctx context.Context, hub *types.Hub) error {
|
|
var joinRoleId *int16
|
|
var rgba int64
|
|
err := dbConn.QueryRow(ctx, `
|
|
SELECT name, COALESCE(icon_url, ''), COALESCE(background_url, ''), creator, join_role, rgba, user_color_allowed, created_at
|
|
FROM hubs WHERE id = $1
|
|
`, hub.Id).Scan(&hub.Name, &hub.IconUrl, &hub.BgUrl, &hub.Creator, &joinRoleId, &rgba, &hub.UserColorAllowed, &hub.CreatedAt)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
hub.Color = convertions.Uint32ToRgba(uint32(rgba))
|
|
if joinRoleId != nil {
|
|
hub.JoinRole = &types.HubRole{Id: uint8(*joinRoleId)}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func HubGetWhole(ctx context.Context, hub *types.Hub) error {
|
|
if err := HubGet(ctx, hub); err != nil {
|
|
return err
|
|
}
|
|
if err := HubRolesGet(ctx, hub); err != nil {
|
|
return err
|
|
}
|
|
if err := HubChannelsGet(ctx, hub); err != nil {
|
|
return err
|
|
}
|
|
if err := HubUsersGet(ctx, hub); err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func HubRolesGet(ctx context.Context, hub *types.Hub) error {
|
|
rows, err := dbConn.Query(ctx, `
|
|
SELECT id, name, permissions, rgba, created_at FROM hub_roles WHERE hub_id = $1
|
|
`, hub.Id)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer rows.Close()
|
|
|
|
for rows.Next() {
|
|
role := &types.HubRole{}
|
|
var id int16
|
|
var permissions, rgba int64
|
|
if err = rows.Scan(&id, &role.Name, &permissions, &rgba, &role.CreatedAt); err != nil {
|
|
return fmt.Errorf("scanning hub_role row: %w", err)
|
|
}
|
|
role.Id = uint8(id)
|
|
role.Permissions = types.Permissions(uint32(permissions))
|
|
role.Color = convertions.Uint32ToRgba(uint32(rgba))
|
|
hub.Roles[role.Id] = role
|
|
}
|
|
return rows.Err()
|
|
}
|
|
|
|
func HubUsersGet(ctx context.Context, hub *types.Hub) error {
|
|
rows, err := dbConn.Query(ctx, `
|
|
SELECT user_id, name, roles_0, roles_1, roles_2, is_muted, created_at FROM hub_users WHERE hub_id = $1
|
|
`, hub.Id)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer rows.Close()
|
|
|
|
if hub.Users == nil {
|
|
hub.Users = make(map[uuid.UUID]*types.HubUser)
|
|
}
|
|
|
|
for rows.Next() {
|
|
user := types.NewHubUser()
|
|
var r0, r1, r2 int64
|
|
if err = rows.Scan(&user.OriginalId, &user.Name, &r0, &r1, &r2, &user.IsMuted, &user.CreatedAt); err != nil {
|
|
return fmt.Errorf("scanning hub_user row: %w", err)
|
|
}
|
|
user.Roles[0] = uint64(r0)
|
|
user.Roles[1] = uint64(r1)
|
|
user.Roles[2] = uint64(r2)
|
|
hub.Users[user.OriginalId] = user
|
|
}
|
|
return rows.Err()
|
|
}
|
|
|
|
func HubChannelsGet(ctx context.Context, hub *types.Hub) error {
|
|
rows, err := dbConn.Query(ctx, `
|
|
SELECT id, name, COALESCE(description, ''), COALESCE(icon_url, ''), position, created_at,
|
|
roles_can_view_0, roles_can_view_1, roles_can_view_2,
|
|
roles_can_message_0, roles_can_message_1, roles_can_message_2,
|
|
roles_can_read_history_0, roles_can_read_history_1, roles_can_read_history_2
|
|
FROM hub_channel WHERE hub_id = $1
|
|
`, hub.Id)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer rows.Close()
|
|
|
|
if hub.Channels == nil {
|
|
hub.Channels = make(map[uuid.UUID]*types.HubChannel)
|
|
}
|
|
|
|
for rows.Next() {
|
|
channel := types.NewHubChannel()
|
|
var pos int16
|
|
var v0, v1, v2, m0, m1, m2, rh0, rh1, rh2 int64
|
|
if err = rows.Scan(
|
|
&channel.Id, &channel.Name, &channel.Description, &channel.IconUrl, &pos, &channel.CreatedAt,
|
|
&v0, &v1, &v2, &m0, &m1, &m2, &rh0, &rh1, &rh2,
|
|
); err != nil {
|
|
return fmt.Errorf("scanning hub_channel row: %w", err)
|
|
}
|
|
channel.Position = uint8(pos)
|
|
channel.RolesCanView = types.HubBoundRoles{uint64(v0), uint64(v1), uint64(v2)}
|
|
channel.RolesCanMessage = types.HubBoundRoles{uint64(m0), uint64(m1), uint64(m2)}
|
|
channel.RolesCanReadHistory = types.HubBoundRoles{uint64(rh0), uint64(rh1), uint64(rh2)}
|
|
hub.Channels[channel.Id] = channel
|
|
}
|
|
return rows.Err()
|
|
}
|
|
|
|
func HubSave(ctx context.Context, hub *types.Hub) error {
|
|
var joinRoleId *int16
|
|
if hub.JoinRole != nil {
|
|
id := int16(hub.JoinRole.Id)
|
|
joinRoleId = &id
|
|
}
|
|
_, err := dbConn.Exec(ctx, `
|
|
INSERT INTO hubs (id, name, icon_url, background_url, creator, join_role, rgba, user_color_allowed, created_at)
|
|
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)
|
|
`, hub.Id, hub.Name, hub.IconUrl, hub.BgUrl, hub.Creator, joinRoleId,
|
|
convertions.RgbaToUint32(hub.Color), hub.UserColorAllowed, hub.CreatedAt)
|
|
return err
|
|
}
|
|
|
|
func HubRoleSave(ctx context.Context, hubId uuid.UUID, role *types.HubRole) error {
|
|
_, err := dbConn.Exec(ctx, `
|
|
INSERT INTO hub_roles (id, hub_id, name, permissions, rgba, created_at)
|
|
VALUES ($1, $2, $3, $4, $5, $6)
|
|
`, int16(role.Id), hubId, role.Name, int64(role.Permissions),
|
|
convertions.RgbaToUint32(role.Color), role.CreatedAt)
|
|
return err
|
|
}
|
|
|
|
func HubChannelSave(ctx context.Context, hubId uuid.UUID, channel *types.HubChannel) error {
|
|
_, err := dbConn.Exec(ctx, `
|
|
INSERT INTO hub_channel (
|
|
id, hub_id, name, description, icon_url, position, created_at,
|
|
roles_can_view_0, roles_can_view_1, roles_can_view_2,
|
|
roles_can_message_0, roles_can_message_1, roles_can_message_2,
|
|
roles_can_read_history_0, roles_can_read_history_1, roles_can_read_history_2
|
|
) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16)
|
|
`, channel.Id, hubId, channel.Name, channel.Description, channel.IconUrl, channel.Position, channel.CreatedAt,
|
|
int64(channel.RolesCanView[0]), int64(channel.RolesCanView[1]), int64(channel.RolesCanView[2]),
|
|
int64(channel.RolesCanMessage[0]), int64(channel.RolesCanMessage[1]), int64(channel.RolesCanMessage[2]),
|
|
int64(channel.RolesCanReadHistory[0]), int64(channel.RolesCanReadHistory[1]), int64(channel.RolesCanReadHistory[2]))
|
|
return err
|
|
}
|
|
|
|
func HubUserSave(ctx context.Context, hubId uuid.UUID, hubUser *types.HubUser) error {
|
|
_, err := dbConn.Exec(ctx, `
|
|
INSERT INTO hub_users (user_id, hub_id, name, roles_0, roles_1, roles_2, is_muted, created_at)
|
|
VALUES ($1, $2, $3, $4, $5, $6, $7, $8)
|
|
`, hubUser.OriginalId, hubId, hubUser.Name,
|
|
int64(hubUser.Roles[0]), int64(hubUser.Roles[1]), int64(hubUser.Roles[2]),
|
|
hubUser.IsMuted, hubUser.CreatedAt)
|
|
return err
|
|
}
|
|
|
|
func HubChannelMessageSave(ctx context.Context, message *types.Message) error {
|
|
if message.Id != (uuid.UUID{}) {
|
|
_, err := dbConn.Exec(ctx, `
|
|
INSERT INTO hub_channel_messages (id, sender_id, receiver_id, created_at, content, attached_file)
|
|
VALUES ($1, $2, $3, $4, $5, $6)
|
|
`, message.Id, message.Sender, message.Receiver, message.CreatedAt, message.Content, message.AttachedFile)
|
|
return err
|
|
}
|
|
return dbConn.QueryRow(ctx, `
|
|
INSERT INTO hub_channel_messages (sender_id, receiver_id, created_at, content, attached_file)
|
|
VALUES ($1, $2, $3, $4, $5)
|
|
RETURNING id
|
|
`, message.Sender, message.Receiver, message.CreatedAt, message.Content, message.AttachedFile).Scan(&message.Id)
|
|
}
|
|
|
|
func HubChannelMessageGet(ctx context.Context, message *types.Message) error {
|
|
return dbConn.QueryRow(ctx, `
|
|
SELECT sender_id, receiver_id, created_at, content, attached_file
|
|
FROM hub_channel_messages
|
|
WHERE id = $1
|
|
`, message.Id).Scan(&message.Sender, &message.Receiver, &message.CreatedAt, &message.Content, &message.AttachedFile)
|
|
}
|
|
|
|
func HubUpdate(ctx context.Context, hub *types.Hub, updateList *types.HubUpdate) error {
|
|
setClauses := make([]string, 0, 6)
|
|
args := make([]any, 0, 7)
|
|
argIdx := 1
|
|
|
|
if updateList.Name {
|
|
setClauses = append(setClauses, fmt.Sprintf("name = $%d", argIdx))
|
|
args = append(args, hub.Name)
|
|
argIdx++
|
|
}
|
|
if updateList.IconUrl {
|
|
setClauses = append(setClauses, fmt.Sprintf("icon_url = $%d", argIdx))
|
|
args = append(args, hub.IconUrl)
|
|
argIdx++
|
|
}
|
|
if updateList.BgUrl {
|
|
setClauses = append(setClauses, fmt.Sprintf("background_url = $%d", argIdx))
|
|
args = append(args, hub.BgUrl)
|
|
argIdx++
|
|
}
|
|
if updateList.JoinRole {
|
|
var joinRoleId *int16
|
|
if hub.JoinRole != nil {
|
|
id := int16(hub.JoinRole.Id)
|
|
joinRoleId = &id
|
|
}
|
|
setClauses = append(setClauses, fmt.Sprintf("join_role = $%d", argIdx))
|
|
args = append(args, joinRoleId)
|
|
argIdx++
|
|
}
|
|
if updateList.Color {
|
|
setClauses = append(setClauses, fmt.Sprintf("rgba = $%d", argIdx))
|
|
args = append(args, convertions.RgbaToUint32(hub.Color))
|
|
argIdx++
|
|
}
|
|
if updateList.UserColorAllowed {
|
|
setClauses = append(setClauses, fmt.Sprintf("user_color_allowed = $%d", argIdx))
|
|
args = append(args, hub.UserColorAllowed)
|
|
argIdx++
|
|
}
|
|
|
|
if len(setClauses) == 0 {
|
|
return nil
|
|
}
|
|
|
|
query := "UPDATE hubs SET " + strings.Join(setClauses, ", ") + fmt.Sprintf(" WHERE id = $%d", argIdx)
|
|
args = append(args, hub.Id)
|
|
_, err := dbConn.Exec(ctx, query, args...)
|
|
return err
|
|
}
|
|
|
|
func HubRoleUpdate(ctx context.Context, hubId uuid.UUID, role *types.HubRole, updateList *types.HubRoleUpdate) error {
|
|
setClauses := make([]string, 0, 3)
|
|
args := make([]any, 0, 5)
|
|
argIdx := 1
|
|
|
|
if updateList.Name {
|
|
setClauses = append(setClauses, fmt.Sprintf("name = $%d", argIdx))
|
|
args = append(args, role.Name)
|
|
argIdx++
|
|
}
|
|
if updateList.Permissions {
|
|
setClauses = append(setClauses, fmt.Sprintf("permissions = $%d", argIdx))
|
|
args = append(args, int64(role.Permissions))
|
|
argIdx++
|
|
}
|
|
if updateList.Color {
|
|
setClauses = append(setClauses, fmt.Sprintf("rgba = $%d", argIdx))
|
|
args = append(args, convertions.RgbaToUint32(role.Color))
|
|
argIdx++
|
|
}
|
|
|
|
if len(setClauses) == 0 {
|
|
return nil
|
|
}
|
|
|
|
query := "UPDATE hub_roles SET " + strings.Join(setClauses, ", ") + fmt.Sprintf(" WHERE id = $%d AND hub_id = $%d", argIdx, argIdx+1)
|
|
args = append(args, int16(role.Id), hubId)
|
|
_, err := dbConn.Exec(ctx, query, args...)
|
|
return err
|
|
}
|
|
|
|
func HubChannelUpdate(ctx context.Context, channel *types.HubChannel, updateList *types.HubChannelUpdate) error {
|
|
setClauses := make([]string, 0, 13)
|
|
args := make([]any, 0, 15)
|
|
argIdx := 1
|
|
|
|
if updateList.Name {
|
|
setClauses = append(setClauses, fmt.Sprintf("name = $%d", argIdx))
|
|
args = append(args, channel.Name)
|
|
argIdx++
|
|
}
|
|
if updateList.Description {
|
|
setClauses = append(setClauses, fmt.Sprintf("description = $%d", argIdx))
|
|
args = append(args, channel.Description)
|
|
argIdx++
|
|
}
|
|
if updateList.IconUrl {
|
|
setClauses = append(setClauses, fmt.Sprintf("icon_url = $%d", argIdx))
|
|
args = append(args, channel.IconUrl)
|
|
argIdx++
|
|
}
|
|
if updateList.Position {
|
|
setClauses = append(setClauses, fmt.Sprintf("position = $%d", argIdx))
|
|
args = append(args, channel.Position)
|
|
argIdx++
|
|
}
|
|
if updateList.RolesCanView {
|
|
setClauses = append(setClauses, fmt.Sprintf("roles_can_view_0 = $%d, roles_can_view_1 = $%d, roles_can_view_2 = $%d", argIdx, argIdx+1, argIdx+2))
|
|
args = append(args, int64(channel.RolesCanView[0]), int64(channel.RolesCanView[1]), int64(channel.RolesCanView[2]))
|
|
argIdx += 3
|
|
}
|
|
if updateList.RolesCanMessage {
|
|
setClauses = append(setClauses, fmt.Sprintf("roles_can_message_0 = $%d, roles_can_message_1 = $%d, roles_can_message_2 = $%d", argIdx, argIdx+1, argIdx+2))
|
|
args = append(args, int64(channel.RolesCanMessage[0]), int64(channel.RolesCanMessage[1]), int64(channel.RolesCanMessage[2]))
|
|
argIdx += 3
|
|
}
|
|
if updateList.RolesCanReadHistory {
|
|
setClauses = append(setClauses, fmt.Sprintf("roles_can_read_history_0 = $%d, roles_can_read_history_1 = $%d, roles_can_read_history_2 = $%d", argIdx, argIdx+1, argIdx+2))
|
|
args = append(args, int64(channel.RolesCanReadHistory[0]), int64(channel.RolesCanReadHistory[1]), int64(channel.RolesCanReadHistory[2]))
|
|
argIdx += 3
|
|
}
|
|
|
|
if len(setClauses) == 0 {
|
|
return nil
|
|
}
|
|
|
|
query := "UPDATE hub_channel SET " + strings.Join(setClauses, ", ") + fmt.Sprintf(" WHERE id = $%d", argIdx)
|
|
args = append(args, channel.Id)
|
|
_, err := dbConn.Exec(ctx, query, args...)
|
|
return err
|
|
}
|
|
|
|
func HubUserUpdate(ctx context.Context, hubId uuid.UUID, hubUser *types.HubUser, updateList *types.HubUserUpdate) error {
|
|
setClauses := make([]string, 0, 5)
|
|
args := make([]any, 0, 7)
|
|
argIdx := 1
|
|
|
|
if updateList.Name {
|
|
setClauses = append(setClauses, fmt.Sprintf("name = $%d", argIdx))
|
|
args = append(args, hubUser.Name)
|
|
argIdx++
|
|
}
|
|
if updateList.Roles {
|
|
setClauses = append(setClauses, fmt.Sprintf("roles_0 = $%d, roles_1 = $%d, roles_2 = $%d", argIdx, argIdx+1, argIdx+2))
|
|
args = append(args, int64(hubUser.Roles[0]), int64(hubUser.Roles[1]), int64(hubUser.Roles[2]))
|
|
argIdx += 3
|
|
}
|
|
if updateList.IsMuted {
|
|
setClauses = append(setClauses, fmt.Sprintf("is_muted = $%d", argIdx))
|
|
args = append(args, hubUser.IsMuted)
|
|
argIdx++
|
|
}
|
|
|
|
if len(setClauses) == 0 {
|
|
return nil
|
|
}
|
|
|
|
query := "UPDATE hub_users SET " + strings.Join(setClauses, ", ") + fmt.Sprintf(" WHERE user_id = $%d AND hub_id = $%d", argIdx, argIdx+1)
|
|
args = append(args, hubUser.OriginalId, hubId)
|
|
_, err := dbConn.Exec(ctx, query, args...)
|
|
return err
|
|
}
|
|
|
|
func HubDelete(ctx context.Context, hubId uuid.UUID) error {
|
|
_, err := dbConn.Exec(ctx, `DELETE FROM hubs WHERE id = $1`, hubId)
|
|
return err
|
|
}
|
|
|
|
func HubUserDelete(ctx context.Context, hubId uuid.UUID, userId uuid.UUID) error {
|
|
_, err := dbConn.Exec(ctx, `DELETE FROM hub_users WHERE user_id = $1 AND hub_id = $2`, userId, hubId)
|
|
return err
|
|
}
|
|
|
|
func HubRoleDelete(ctx context.Context, hubId uuid.UUID, roleId uint8) error {
|
|
_, err := dbConn.Exec(ctx, `DELETE FROM hub_roles WHERE id = $1 AND hub_id = $2`, int16(roleId), hubId)
|
|
return err
|
|
}
|
|
|
|
func HubChannelDelete(ctx context.Context, channelId uuid.UUID) error {
|
|
_, err := dbConn.Exec(ctx, `DELETE FROM hub_channel WHERE id = $1`, channelId)
|
|
return err
|
|
}
|