feat: persist group business state in tables
This commit is contained in:
@@ -1079,6 +1079,226 @@ func (callsMapper) List(tenantID types.TenantID, uid types.Uid, topic, cursor st
|
||||
return tenantAdp.TenantCallList(tenantID, uid, strings.TrimSpace(topic), strings.TrimSpace(cursor), limit)
|
||||
}
|
||||
|
||||
type GroupBusinessPersistenceInterface interface {
|
||||
CreateSettings(types.TenantID, *types.GroupSettings) (*types.GroupSettings, error)
|
||||
GetSettings(types.TenantID, string) (*types.GroupSettings, error)
|
||||
UpdateSettings(types.TenantID, string, types.GroupSettingsPatch) (*types.GroupSettings, error)
|
||||
UpsertMember(types.TenantID, *types.GroupMember) (*types.GroupMember, error)
|
||||
GetMember(types.TenantID, string, types.Uid) (*types.GroupMember, error)
|
||||
ListMembers(types.TenantID, string, types.GroupMemberListOptions) ([]types.GroupMember, string, error)
|
||||
UpdateMember(types.TenantID, string, types.Uid, types.GroupMemberPatch) (*types.GroupMember, error)
|
||||
CreateInvitation(types.TenantID, *types.GroupInvitation) (*types.GroupInvitation, error)
|
||||
CreateJoinRequest(types.TenantID, *types.GroupJoinRequest) (*types.GroupJoinRequest, error)
|
||||
ListJoinRequests(types.TenantID, string, string, string, int) ([]types.GroupJoinRequest, string, error)
|
||||
ResolveJoinRequest(types.TenantID, string, string, types.Uid, string, string, int, time.Time) (*types.GroupJoinRequest, error)
|
||||
LatestAnnouncement(types.TenantID, string) (*types.GroupAnnouncement, error)
|
||||
PutAnnouncement(types.TenantID, *types.GroupAnnouncement, int) (*types.GroupAnnouncement, error)
|
||||
ReadAnnouncement(types.TenantID, string, string, types.Uid, time.Time) error
|
||||
ListMutes(types.TenantID, string, string, int) ([]types.GroupMute, string, error)
|
||||
UpsertMute(types.TenantID, *types.GroupMute) (*types.GroupMute, error)
|
||||
DeleteMute(types.TenantID, string, types.Uid, types.Uid, time.Time) error
|
||||
}
|
||||
|
||||
type groupBusinessMapper struct{}
|
||||
|
||||
var GroupBusiness GroupBusinessPersistenceInterface
|
||||
|
||||
func (groupBusinessMapper) CreateSettings(tenantID types.TenantID, settings *types.GroupSettings) (*types.GroupSettings, error) {
|
||||
if settings == nil || settings.Topic == "" || settings.OwnerUserID.IsZero() || settings.CreatedBy.IsZero() {
|
||||
return nil, types.ErrMalformed
|
||||
}
|
||||
tenantAdp, err := tenantBusinessAdapter(tenantID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return tenantAdp.TenantGroupSettingsCreate(tenantID, settings)
|
||||
}
|
||||
|
||||
func (groupBusinessMapper) GetSettings(tenantID types.TenantID, topic string) (*types.GroupSettings, error) {
|
||||
if strings.TrimSpace(topic) == "" {
|
||||
return nil, types.ErrMalformed
|
||||
}
|
||||
tenantAdp, err := tenantBusinessAdapter(tenantID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return tenantAdp.TenantGroupSettingsGet(tenantID, strings.TrimSpace(topic))
|
||||
}
|
||||
|
||||
func (groupBusinessMapper) UpdateSettings(tenantID types.TenantID, topic string, patch types.GroupSettingsPatch) (*types.GroupSettings, error) {
|
||||
if strings.TrimSpace(topic) == "" {
|
||||
return nil, types.ErrMalformed
|
||||
}
|
||||
tenantAdp, err := tenantBusinessAdapter(tenantID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return tenantAdp.TenantGroupSettingsUpdate(tenantID, strings.TrimSpace(topic), patch)
|
||||
}
|
||||
|
||||
func (groupBusinessMapper) UpsertMember(tenantID types.TenantID, member *types.GroupMember) (*types.GroupMember, error) {
|
||||
if member == nil || member.Topic == "" || member.UserID.IsZero() {
|
||||
return nil, types.ErrMalformed
|
||||
}
|
||||
tenantAdp, err := tenantBusinessAdapter(tenantID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return tenantAdp.TenantGroupMemberUpsert(tenantID, member)
|
||||
}
|
||||
|
||||
func (groupBusinessMapper) GetMember(tenantID types.TenantID, topic string, uid types.Uid) (*types.GroupMember, error) {
|
||||
if strings.TrimSpace(topic) == "" || uid.IsZero() {
|
||||
return nil, types.ErrMalformed
|
||||
}
|
||||
tenantAdp, err := tenantBusinessAdapter(tenantID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return tenantAdp.TenantGroupMemberGet(tenantID, strings.TrimSpace(topic), uid)
|
||||
}
|
||||
|
||||
func (groupBusinessMapper) ListMembers(tenantID types.TenantID, topic string, opts types.GroupMemberListOptions) ([]types.GroupMember, string, error) {
|
||||
if strings.TrimSpace(topic) == "" {
|
||||
return nil, "", types.ErrMalformed
|
||||
}
|
||||
if opts.Limit <= 0 || opts.Limit > 100 {
|
||||
opts.Limit = 30
|
||||
}
|
||||
tenantAdp, err := tenantBusinessAdapter(tenantID)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
return tenantAdp.TenantGroupMemberList(tenantID, strings.TrimSpace(topic), opts)
|
||||
}
|
||||
|
||||
func (groupBusinessMapper) UpdateMember(tenantID types.TenantID, topic string, uid types.Uid, patch types.GroupMemberPatch) (*types.GroupMember, error) {
|
||||
if strings.TrimSpace(topic) == "" || uid.IsZero() {
|
||||
return nil, types.ErrMalformed
|
||||
}
|
||||
tenantAdp, err := tenantBusinessAdapter(tenantID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return tenantAdp.TenantGroupMemberUpdate(tenantID, strings.TrimSpace(topic), uid, patch)
|
||||
}
|
||||
|
||||
func (groupBusinessMapper) CreateInvitation(tenantID types.TenantID, invitation *types.GroupInvitation) (*types.GroupInvitation, error) {
|
||||
if invitation == nil || invitation.Topic == "" || invitation.InviterUserID.IsZero() || invitation.TargetUserID.IsZero() {
|
||||
return nil, types.ErrMalformed
|
||||
}
|
||||
tenantAdp, err := tenantBusinessAdapter(tenantID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return tenantAdp.TenantGroupInvitationCreate(tenantID, invitation)
|
||||
}
|
||||
|
||||
func (groupBusinessMapper) CreateJoinRequest(tenantID types.TenantID, req *types.GroupJoinRequest) (*types.GroupJoinRequest, error) {
|
||||
if req == nil || req.Topic == "" || req.ApplicantUserID.IsZero() || req.RequestID == "" {
|
||||
return nil, types.ErrMalformed
|
||||
}
|
||||
tenantAdp, err := tenantBusinessAdapter(tenantID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return tenantAdp.TenantGroupJoinRequestCreate(tenantID, req)
|
||||
}
|
||||
|
||||
func (groupBusinessMapper) ListJoinRequests(tenantID types.TenantID, topic, status, cursor string, limit int) ([]types.GroupJoinRequest, string, error) {
|
||||
if strings.TrimSpace(topic) == "" {
|
||||
return nil, "", types.ErrMalformed
|
||||
}
|
||||
if limit <= 0 || limit > 100 {
|
||||
limit = 50
|
||||
}
|
||||
tenantAdp, err := tenantBusinessAdapter(tenantID)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
return tenantAdp.TenantGroupJoinRequestList(tenantID, strings.TrimSpace(topic), strings.TrimSpace(status), strings.TrimSpace(cursor), limit)
|
||||
}
|
||||
|
||||
func (groupBusinessMapper) ResolveJoinRequest(tenantID types.TenantID, topic, requestID string, actor types.Uid, action, rejectReason string, version int, now time.Time) (*types.GroupJoinRequest, error) {
|
||||
if strings.TrimSpace(topic) == "" || strings.TrimSpace(requestID) == "" || actor.IsZero() || now.IsZero() {
|
||||
return nil, types.ErrMalformed
|
||||
}
|
||||
tenantAdp, err := tenantBusinessAdapter(tenantID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return tenantAdp.TenantGroupJoinRequestResolve(tenantID, strings.TrimSpace(topic), strings.TrimSpace(requestID), actor, strings.TrimSpace(action), strings.TrimSpace(rejectReason), version, now)
|
||||
}
|
||||
|
||||
func (groupBusinessMapper) LatestAnnouncement(tenantID types.TenantID, topic string) (*types.GroupAnnouncement, error) {
|
||||
if strings.TrimSpace(topic) == "" {
|
||||
return nil, types.ErrMalformed
|
||||
}
|
||||
tenantAdp, err := tenantBusinessAdapter(tenantID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return tenantAdp.TenantGroupAnnouncementLatest(tenantID, strings.TrimSpace(topic))
|
||||
}
|
||||
|
||||
func (groupBusinessMapper) PutAnnouncement(tenantID types.TenantID, ann *types.GroupAnnouncement, expectedVersion int) (*types.GroupAnnouncement, error) {
|
||||
if ann == nil || ann.Topic == "" || ann.AuthorUserID.IsZero() || ann.Content == "" {
|
||||
return nil, types.ErrMalformed
|
||||
}
|
||||
tenantAdp, err := tenantBusinessAdapter(tenantID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return tenantAdp.TenantGroupAnnouncementPut(tenantID, ann, expectedVersion)
|
||||
}
|
||||
|
||||
func (groupBusinessMapper) ReadAnnouncement(tenantID types.TenantID, topic, announcementID string, uid types.Uid, readAt time.Time) error {
|
||||
if strings.TrimSpace(topic) == "" || strings.TrimSpace(announcementID) == "" || uid.IsZero() || readAt.IsZero() {
|
||||
return types.ErrMalformed
|
||||
}
|
||||
tenantAdp, err := tenantBusinessAdapter(tenantID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return tenantAdp.TenantGroupAnnouncementRead(tenantID, strings.TrimSpace(topic), strings.TrimSpace(announcementID), uid, readAt)
|
||||
}
|
||||
|
||||
func (groupBusinessMapper) ListMutes(tenantID types.TenantID, topic, cursor string, limit int) ([]types.GroupMute, string, error) {
|
||||
if strings.TrimSpace(topic) == "" {
|
||||
return nil, "", types.ErrMalformed
|
||||
}
|
||||
if limit <= 0 || limit > 100 {
|
||||
limit = 50
|
||||
}
|
||||
tenantAdp, err := tenantBusinessAdapter(tenantID)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
return tenantAdp.TenantGroupMuteList(tenantID, strings.TrimSpace(topic), strings.TrimSpace(cursor), limit)
|
||||
}
|
||||
|
||||
func (groupBusinessMapper) UpsertMute(tenantID types.TenantID, mute *types.GroupMute) (*types.GroupMute, error) {
|
||||
if mute == nil || mute.Topic == "" || mute.UserID.IsZero() || mute.MutedBy.IsZero() {
|
||||
return nil, types.ErrMalformed
|
||||
}
|
||||
tenantAdp, err := tenantBusinessAdapter(tenantID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return tenantAdp.TenantGroupMuteUpsert(tenantID, mute)
|
||||
}
|
||||
|
||||
func (groupBusinessMapper) DeleteMute(tenantID types.TenantID, topic string, uid, actor types.Uid, now time.Time) error {
|
||||
if strings.TrimSpace(topic) == "" || uid.IsZero() || actor.IsZero() || now.IsZero() {
|
||||
return types.ErrMalformed
|
||||
}
|
||||
tenantAdp, err := tenantBusinessAdapter(tenantID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return tenantAdp.TenantGroupMuteDelete(tenantID, strings.TrimSpace(topic), uid, actor, now)
|
||||
}
|
||||
|
||||
type WorkbenchPersistenceInterface interface {
|
||||
Get(tenantID types.TenantID, uid types.Uid) ([]types.WorkbenchModule, int, error)
|
||||
}
|
||||
@@ -2861,6 +3081,7 @@ func init() {
|
||||
Subs = subsMapper{}
|
||||
Messages = messagesMapper{}
|
||||
Calls = callsMapper{}
|
||||
GroupBusiness = groupBusinessMapper{}
|
||||
Workbench = workbenchMapper{}
|
||||
Organization = organizationMapper{}
|
||||
Meetings = meetingsMapper{}
|
||||
|
||||
@@ -0,0 +1,182 @@
|
||||
package types
|
||||
|
||||
import "time"
|
||||
|
||||
const (
|
||||
GroupStatusActive = "active"
|
||||
|
||||
GroupMemberRoleOwner = "owner"
|
||||
GroupMemberRoleAdmin = "admin"
|
||||
GroupMemberRoleMember = "member"
|
||||
|
||||
GroupMemberStatusActive = "active"
|
||||
GroupMemberStatusLeft = "left"
|
||||
|
||||
GroupInvitationStatusJoined = "joined"
|
||||
|
||||
GroupJoinRequestStatusPending = "pending"
|
||||
GroupJoinRequestStatusAccepted = "accepted"
|
||||
GroupJoinRequestStatusRejected = "rejected"
|
||||
|
||||
GroupAnnouncementStatusCurrent = "current"
|
||||
GroupAnnouncementStatusSuperseded = "superseded"
|
||||
|
||||
GroupMuteStatusActive = "active"
|
||||
GroupMuteStatusRevoked = "revoked"
|
||||
)
|
||||
|
||||
type GroupSettings struct {
|
||||
Topic string `db:"topic"`
|
||||
OwnerUserID Uid `db:"-"`
|
||||
Name string `db:"name"`
|
||||
AvatarFileID string `db:"avatar_file_id"`
|
||||
Description string `db:"description"`
|
||||
GroupStatus string `db:"group_status"`
|
||||
JoinApproval bool `db:"join_approval"`
|
||||
MuteAll bool `db:"mute_all"`
|
||||
MemberUploadFiles bool `db:"member_upload_files"`
|
||||
MemberPrivateChat bool `db:"member_private_chat"`
|
||||
MemberInvite bool `db:"member_invite"`
|
||||
MaxMemberCount int `db:"max_member_count"`
|
||||
MaxAdminCount int `db:"max_admin_count"`
|
||||
MemberCount int `db:"member_count"`
|
||||
Version int `db:"version"`
|
||||
CreatedBy Uid `db:"-"`
|
||||
DissolvedBy Uid `db:"-"`
|
||||
DissolvedAt *time.Time `db:"dissolved_at"`
|
||||
CreatedAt time.Time `db:"created_at"`
|
||||
UpdatedAt time.Time `db:"updated_at"`
|
||||
OwnerUserIDRaw int64 `db:"owner_user_id"`
|
||||
CreatedByRaw int64 `db:"created_by"`
|
||||
DissolvedByRaw *int64 `db:"dissolved_by"`
|
||||
}
|
||||
|
||||
type GroupSettingsPatch struct {
|
||||
Name *string
|
||||
AvatarFileID *string
|
||||
Description *string
|
||||
OwnerUserID *Uid
|
||||
JoinApproval *bool
|
||||
MuteAll *bool
|
||||
MemberUploadFiles *bool
|
||||
MemberPrivateChat *bool
|
||||
MemberInvite *bool
|
||||
MemberCountDelta int
|
||||
Version int
|
||||
}
|
||||
|
||||
type GroupMember struct {
|
||||
ID int64 `db:"id"`
|
||||
Topic string `db:"topic"`
|
||||
UserID Uid `db:"-"`
|
||||
Role string `db:"role"`
|
||||
MemberStatus string `db:"member_status"`
|
||||
Nickname string `db:"nickname"`
|
||||
Pinned bool `db:"pinned"`
|
||||
MuteNotifications bool `db:"mute_notifications"`
|
||||
JoinSource string `db:"join_source"`
|
||||
JoinedBy Uid `db:"-"`
|
||||
JoinedAt time.Time `db:"joined_at"`
|
||||
LeftAt *time.Time `db:"left_at"`
|
||||
RemovedBy Uid `db:"-"`
|
||||
Version int `db:"version"`
|
||||
CreatedAt time.Time `db:"created_at"`
|
||||
UpdatedAt time.Time `db:"updated_at"`
|
||||
UserIDRaw int64 `db:"user_id"`
|
||||
JoinedByRaw *int64 `db:"joined_by"`
|
||||
RemovedByRaw *int64 `db:"removed_by"`
|
||||
}
|
||||
|
||||
type GroupMemberPatch struct {
|
||||
Role *string
|
||||
MemberStatus *string
|
||||
Nickname *string
|
||||
Pinned *bool
|
||||
MuteNotifications *bool
|
||||
LeftAt *time.Time
|
||||
RemovedBy *Uid
|
||||
Version int
|
||||
}
|
||||
|
||||
type GroupMemberListOptions struct {
|
||||
Role string
|
||||
EligibleRole string
|
||||
Query string
|
||||
Cursor string
|
||||
Limit int
|
||||
}
|
||||
|
||||
type GroupInvitation struct {
|
||||
ID int64 `db:"id"`
|
||||
InvitationID string `db:"invitation_id"`
|
||||
Topic string `db:"topic"`
|
||||
InviterUserID Uid `db:"-"`
|
||||
TargetUserID Uid `db:"-"`
|
||||
Message string `db:"message"`
|
||||
Status string `db:"status"`
|
||||
Result string `db:"result"`
|
||||
JoinRequestID string `db:"join_request_id"`
|
||||
IdempotencyKey string `db:"idempotency_key"`
|
||||
ExpiresAt time.Time `db:"expires_at"`
|
||||
HandledAt *time.Time `db:"handled_at"`
|
||||
CreatedAt time.Time `db:"created_at"`
|
||||
UpdatedAt time.Time `db:"updated_at"`
|
||||
InviterUserRaw int64 `db:"inviter_user_id"`
|
||||
TargetUserRaw int64 `db:"target_user_id"`
|
||||
}
|
||||
|
||||
type GroupJoinRequest struct {
|
||||
ID int64 `db:"id"`
|
||||
RequestID string `db:"request_id"`
|
||||
Topic string `db:"topic"`
|
||||
ApplicantUserID Uid `db:"-"`
|
||||
InviterUserID Uid `db:"-"`
|
||||
Source string `db:"source"`
|
||||
QRTokenHash string `db:"qr_token_hash"`
|
||||
Message string `db:"message"`
|
||||
Status string `db:"status"`
|
||||
RejectReason string `db:"reject_reason"`
|
||||
HandledBy Uid `db:"-"`
|
||||
HandledAt *time.Time `db:"handled_at"`
|
||||
ExpiresAt *time.Time `db:"expires_at"`
|
||||
IdempotencyKey string `db:"idempotency_key"`
|
||||
Version int `db:"version"`
|
||||
CreatedAt time.Time `db:"created_at"`
|
||||
UpdatedAt time.Time `db:"updated_at"`
|
||||
ApplicantUserRaw int64 `db:"applicant_user_id"`
|
||||
InviterUserRaw *int64 `db:"inviter_user_id"`
|
||||
HandledByRaw *int64 `db:"handled_by"`
|
||||
}
|
||||
|
||||
type GroupAnnouncement struct {
|
||||
ID int64 `db:"id"`
|
||||
AnnouncementID string `db:"announcement_id"`
|
||||
Topic string `db:"topic"`
|
||||
AuthorUserID Uid `db:"-"`
|
||||
Content string `db:"content"`
|
||||
Status string `db:"status"`
|
||||
Version int `db:"version"`
|
||||
PublishedAt time.Time `db:"published_at"`
|
||||
IdempotencyKey string `db:"idempotency_key"`
|
||||
CreatedAt time.Time `db:"created_at"`
|
||||
UpdatedAt time.Time `db:"updated_at"`
|
||||
AuthorUserIDRaw int64 `db:"author_user_id"`
|
||||
}
|
||||
|
||||
type GroupMute struct {
|
||||
Topic string `db:"topic"`
|
||||
UserID Uid `db:"-"`
|
||||
MutedBy Uid `db:"-"`
|
||||
MutedAt time.Time `db:"muted_at"`
|
||||
ExpiresAt *time.Time `db:"expires_at"`
|
||||
Reason string `db:"reason"`
|
||||
Status string `db:"status"`
|
||||
RevokedBy Uid `db:"-"`
|
||||
RevokedAt *time.Time `db:"revoked_at"`
|
||||
Version int `db:"version"`
|
||||
CreatedAt time.Time `db:"created_at"`
|
||||
UpdatedAt time.Time `db:"updated_at"`
|
||||
UserIDRaw int64 `db:"user_id"`
|
||||
MutedByRaw int64 `db:"muted_by"`
|
||||
RevokedRaw *int64 `db:"revoked_by"`
|
||||
}
|
||||
Reference in New Issue
Block a user