mirror of
https://gh-proxy.org/https://github.com/klinsmaya/multica.git
synced 2026-11-08 01:16:45 +08:00
* fix(realtime): revoke workspace access on membership removal Close removed members' sockets, revalidate registration, and gate captured write batches with fresh coalesced membership queries. Cover relay failure, replay, queue races, and transactional removal/rollback (MUL-8014). Co-authored-by: multica-agent <[email protected]> * fix(realtime): keep registration free of database waits Co-authored-by: multica-agent <[email protected]> * perf(realtime): narrow removal event prefilter Co-authored-by: multica-agent <[email protected]> * test(wakeup): avoid global backfill in workspace default test Co-authored-by: multica-agent <[email protected]> * fix(realtime): bound concurrent authorization and defer relay revocation Co-authored-by: multica-agent <[email protected]> * test(realtime): check caller budget without waiting for expiry Co-authored-by: multica-agent <[email protected]> * fix(realtime): decouple member-list invalidation from revocation Co-authored-by: multica-agent <[email protected]> * perf(realtime): skip removal decoding for member actor metadata Co-authored-by: multica-agent <[email protected]> --------- Co-authored-by: Sol-Boy <[email protected]> Co-authored-by: multica-agent <[email protected]>
259 lines
6.3 KiB
Go
259 lines
6.3 KiB
Go
// Code generated by sqlc. DO NOT EDIT.
|
|
// versions:
|
|
// sqlc v1.31.1
|
|
// source: member.sql
|
|
|
|
package db
|
|
|
|
import (
|
|
"context"
|
|
|
|
"github.com/jackc/pgx/v5/pgtype"
|
|
)
|
|
|
|
const createMember = `-- name: CreateMember :one
|
|
INSERT INTO member (workspace_id, user_id, role)
|
|
VALUES ($1, $2, $3)
|
|
RETURNING id, workspace_id, user_id, role, created_at
|
|
`
|
|
|
|
type CreateMemberParams struct {
|
|
WorkspaceID pgtype.UUID `json:"workspace_id"`
|
|
UserID pgtype.UUID `json:"user_id"`
|
|
Role string `json:"role"`
|
|
}
|
|
|
|
func (q *Queries) CreateMember(ctx context.Context, arg CreateMemberParams) (Member, error) {
|
|
row := q.db.QueryRow(ctx, createMember, arg.WorkspaceID, arg.UserID, arg.Role)
|
|
var i Member
|
|
err := row.Scan(
|
|
&i.ID,
|
|
&i.WorkspaceID,
|
|
&i.UserID,
|
|
&i.Role,
|
|
&i.CreatedAt,
|
|
)
|
|
return i, err
|
|
}
|
|
|
|
const deleteMember = `-- name: DeleteMember :exec
|
|
DELETE FROM member WHERE id = $1
|
|
`
|
|
|
|
func (q *Queries) DeleteMember(ctx context.Context, id pgtype.UUID) error {
|
|
_, err := q.db.Exec(ctx, deleteMember, id)
|
|
return err
|
|
}
|
|
|
|
const getMember = `-- name: GetMember :one
|
|
SELECT id, workspace_id, user_id, role, created_at FROM member
|
|
WHERE id = $1
|
|
`
|
|
|
|
func (q *Queries) GetMember(ctx context.Context, id pgtype.UUID) (Member, error) {
|
|
row := q.db.QueryRow(ctx, getMember, id)
|
|
var i Member
|
|
err := row.Scan(
|
|
&i.ID,
|
|
&i.WorkspaceID,
|
|
&i.UserID,
|
|
&i.Role,
|
|
&i.CreatedAt,
|
|
)
|
|
return i, err
|
|
}
|
|
|
|
const getMemberByUserAndWorkspace = `-- name: GetMemberByUserAndWorkspace :one
|
|
SELECT id, workspace_id, user_id, role, created_at FROM member
|
|
WHERE user_id = $1 AND workspace_id = $2
|
|
`
|
|
|
|
type GetMemberByUserAndWorkspaceParams struct {
|
|
UserID pgtype.UUID `json:"user_id"`
|
|
WorkspaceID pgtype.UUID `json:"workspace_id"`
|
|
}
|
|
|
|
func (q *Queries) GetMemberByUserAndWorkspace(ctx context.Context, arg GetMemberByUserAndWorkspaceParams) (Member, error) {
|
|
row := q.db.QueryRow(ctx, getMemberByUserAndWorkspace, arg.UserID, arg.WorkspaceID)
|
|
var i Member
|
|
err := row.Scan(
|
|
&i.ID,
|
|
&i.WorkspaceID,
|
|
&i.UserID,
|
|
&i.Role,
|
|
&i.CreatedAt,
|
|
)
|
|
return i, err
|
|
}
|
|
|
|
const getRealtimeMemberships = `-- name: GetRealtimeMemberships :many
|
|
SELECT m.user_id, m.workspace_id
|
|
FROM member m
|
|
JOIN (
|
|
SELECT unnest($1::uuid[]) AS user_id,
|
|
unnest($2::uuid[]) AS workspace_id
|
|
) AS requested
|
|
ON m.user_id = requested.user_id AND m.workspace_id = requested.workspace_id
|
|
`
|
|
|
|
type GetRealtimeMembershipsParams struct {
|
|
UserIds []pgtype.UUID `json:"user_ids"`
|
|
WorkspaceIds []pgtype.UUID `json:"workspace_ids"`
|
|
}
|
|
|
|
type GetRealtimeMembershipsRow struct {
|
|
UserID pgtype.UUID `json:"user_id"`
|
|
WorkspaceID pgtype.UUID `json:"workspace_id"`
|
|
}
|
|
|
|
func (q *Queries) GetRealtimeMemberships(ctx context.Context, arg GetRealtimeMembershipsParams) ([]GetRealtimeMembershipsRow, error) {
|
|
rows, err := q.db.Query(ctx, getRealtimeMemberships, arg.UserIds, arg.WorkspaceIds)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
items := []GetRealtimeMembershipsRow{}
|
|
for rows.Next() {
|
|
var i GetRealtimeMembershipsRow
|
|
if err := rows.Scan(&i.UserID, &i.WorkspaceID); err != nil {
|
|
return nil, err
|
|
}
|
|
items = append(items, i)
|
|
}
|
|
if err := rows.Err(); err != nil {
|
|
return nil, err
|
|
}
|
|
return items, nil
|
|
}
|
|
|
|
const listMembers = `-- name: ListMembers :many
|
|
SELECT id, workspace_id, user_id, role, created_at FROM member
|
|
WHERE workspace_id = $1
|
|
ORDER BY created_at ASC
|
|
`
|
|
|
|
func (q *Queries) ListMembers(ctx context.Context, workspaceID pgtype.UUID) ([]Member, error) {
|
|
rows, err := q.db.Query(ctx, listMembers, workspaceID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
items := []Member{}
|
|
for rows.Next() {
|
|
var i Member
|
|
if err := rows.Scan(
|
|
&i.ID,
|
|
&i.WorkspaceID,
|
|
&i.UserID,
|
|
&i.Role,
|
|
&i.CreatedAt,
|
|
); err != nil {
|
|
return nil, err
|
|
}
|
|
items = append(items, i)
|
|
}
|
|
if err := rows.Err(); err != nil {
|
|
return nil, err
|
|
}
|
|
return items, nil
|
|
}
|
|
|
|
const listMembersWithUser = `-- name: ListMembersWithUser :many
|
|
SELECT m.id, m.workspace_id, m.user_id, m.role, m.created_at,
|
|
u.name as user_name, u.email as user_email, u.avatar_url as user_avatar_url
|
|
FROM member m
|
|
JOIN "user" u ON u.id = m.user_id
|
|
WHERE m.workspace_id = $1
|
|
ORDER BY m.created_at ASC
|
|
`
|
|
|
|
type ListMembersWithUserRow struct {
|
|
ID pgtype.UUID `json:"id"`
|
|
WorkspaceID pgtype.UUID `json:"workspace_id"`
|
|
UserID pgtype.UUID `json:"user_id"`
|
|
Role string `json:"role"`
|
|
CreatedAt pgtype.Timestamptz `json:"created_at"`
|
|
UserName string `json:"user_name"`
|
|
UserEmail string `json:"user_email"`
|
|
UserAvatarUrl pgtype.Text `json:"user_avatar_url"`
|
|
}
|
|
|
|
func (q *Queries) ListMembersWithUser(ctx context.Context, workspaceID pgtype.UUID) ([]ListMembersWithUserRow, error) {
|
|
rows, err := q.db.Query(ctx, listMembersWithUser, workspaceID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
items := []ListMembersWithUserRow{}
|
|
for rows.Next() {
|
|
var i ListMembersWithUserRow
|
|
if err := rows.Scan(
|
|
&i.ID,
|
|
&i.WorkspaceID,
|
|
&i.UserID,
|
|
&i.Role,
|
|
&i.CreatedAt,
|
|
&i.UserName,
|
|
&i.UserEmail,
|
|
&i.UserAvatarUrl,
|
|
); err != nil {
|
|
return nil, err
|
|
}
|
|
items = append(items, i)
|
|
}
|
|
if err := rows.Err(); err != nil {
|
|
return nil, err
|
|
}
|
|
return items, nil
|
|
}
|
|
|
|
const listWorkspaceManagerUserIDs = `-- name: ListWorkspaceManagerUserIDs :many
|
|
SELECT user_id FROM member
|
|
WHERE workspace_id = $1 AND role IN ('owner', 'admin')
|
|
ORDER BY created_at ASC
|
|
`
|
|
|
|
func (q *Queries) ListWorkspaceManagerUserIDs(ctx context.Context, workspaceID pgtype.UUID) ([]pgtype.UUID, error) {
|
|
rows, err := q.db.Query(ctx, listWorkspaceManagerUserIDs, workspaceID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
items := []pgtype.UUID{}
|
|
for rows.Next() {
|
|
var user_id pgtype.UUID
|
|
if err := rows.Scan(&user_id); err != nil {
|
|
return nil, err
|
|
}
|
|
items = append(items, user_id)
|
|
}
|
|
if err := rows.Err(); err != nil {
|
|
return nil, err
|
|
}
|
|
return items, nil
|
|
}
|
|
|
|
const updateMemberRole = `-- name: UpdateMemberRole :one
|
|
UPDATE member SET role = $2
|
|
WHERE id = $1
|
|
RETURNING id, workspace_id, user_id, role, created_at
|
|
`
|
|
|
|
type UpdateMemberRoleParams struct {
|
|
ID pgtype.UUID `json:"id"`
|
|
Role string `json:"role"`
|
|
}
|
|
|
|
func (q *Queries) UpdateMemberRole(ctx context.Context, arg UpdateMemberRoleParams) (Member, error) {
|
|
row := q.db.QueryRow(ctx, updateMemberRole, arg.ID, arg.Role)
|
|
var i Member
|
|
err := row.Scan(
|
|
&i.ID,
|
|
&i.WorkspaceID,
|
|
&i.UserID,
|
|
&i.Role,
|
|
&i.CreatedAt,
|
|
)
|
|
return i, err
|
|
}
|