|
|
|
@@ -1045,6 +1045,114 @@ func (messagesMapper) Edit(tenantID types.TenantID, topic string, seq int, actor
|
|
|
|
|
return tenantAdp.TenantMessageEdit(tenantID, topic, seq, actor, expectedVersion, head, content, reason, editedAt)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type ConversationsPersistenceInterface interface {
|
|
|
|
|
EnsureP2P(tenantID types.TenantID, uid, peer types.Uid) (string, error)
|
|
|
|
|
GetSettings(tenantID types.TenantID, uid types.Uid, topic string) (*types.ConversationSettings, error)
|
|
|
|
|
UpdateSettings(tenantID types.TenantID, uid types.Uid, topic string, patch types.ConversationSettingsPatch) (*types.ConversationSettings, error)
|
|
|
|
|
GetDraft(tenantID types.TenantID, uid types.Uid, topic string) (*types.TopicDraft, error)
|
|
|
|
|
PutDraft(tenantID types.TenantID, uid types.Uid, topic, content string, entities []byte, version int) (*types.TopicDraft, error)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type conversationsMapper struct{}
|
|
|
|
|
|
|
|
|
|
var Conversations ConversationsPersistenceInterface
|
|
|
|
|
|
|
|
|
|
func (conversationsMapper) EnsureP2P(tenantID types.TenantID, uid, peer types.Uid) (string, error) {
|
|
|
|
|
if uid.IsZero() || peer.IsZero() || uid == peer {
|
|
|
|
|
return "", types.ErrMalformed
|
|
|
|
|
}
|
|
|
|
|
canSend, _, err := Relations.CanSendP2P(tenantID, uid, peer)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return "", err
|
|
|
|
|
}
|
|
|
|
|
if !canSend {
|
|
|
|
|
return "", types.ErrPermissionDenied
|
|
|
|
|
}
|
|
|
|
|
topic := uid.P2PName(peer)
|
|
|
|
|
if topic == "" {
|
|
|
|
|
return "", types.ErrMalformed
|
|
|
|
|
}
|
|
|
|
|
now := types.TimeNow()
|
|
|
|
|
initiator := &types.Subscription{
|
|
|
|
|
ObjHeader: types.ObjHeader{CreatedAt: now, UpdatedAt: now},
|
|
|
|
|
TenantID: tenantID,
|
|
|
|
|
User: uid.String(),
|
|
|
|
|
Topic: topic,
|
|
|
|
|
ModeWant: types.ModeCP2P,
|
|
|
|
|
ModeGiven: types.ModeCP2P,
|
|
|
|
|
Private: map[string]any{"peer": peer.UserId(), "created_by": "http"},
|
|
|
|
|
}
|
|
|
|
|
invited := &types.Subscription{
|
|
|
|
|
ObjHeader: types.ObjHeader{CreatedAt: now, UpdatedAt: now},
|
|
|
|
|
TenantID: tenantID,
|
|
|
|
|
User: peer.String(),
|
|
|
|
|
Topic: topic,
|
|
|
|
|
ModeWant: types.ModeCP2P,
|
|
|
|
|
ModeGiven: types.ModeCP2P,
|
|
|
|
|
Private: map[string]any{"peer": uid.UserId(), "created_by": "http"},
|
|
|
|
|
}
|
|
|
|
|
if err = Topics.CreateP2P(tenantID, initiator, invited); err != nil {
|
|
|
|
|
return "", err
|
|
|
|
|
}
|
|
|
|
|
return topic, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (conversationsMapper) GetSettings(tenantID types.TenantID, uid types.Uid, topic string) (*types.ConversationSettings, error) {
|
|
|
|
|
if uid.IsZero() || strings.TrimSpace(topic) == "" {
|
|
|
|
|
return nil, types.ErrMalformed
|
|
|
|
|
}
|
|
|
|
|
if _, err := Subs.Get(tenantID, strings.TrimSpace(topic), uid, false); err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
tenantAdp, err := tenantBusinessAdapter(tenantID)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
return tenantAdp.TenantConversationSettingsGet(tenantID, uid, strings.TrimSpace(topic))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (conversationsMapper) UpdateSettings(tenantID types.TenantID, uid types.Uid, topic string, patch types.ConversationSettingsPatch) (*types.ConversationSettings, error) {
|
|
|
|
|
if uid.IsZero() || strings.TrimSpace(topic) == "" || patch.Version <= 0 {
|
|
|
|
|
return nil, types.ErrMalformed
|
|
|
|
|
}
|
|
|
|
|
if _, err := Subs.Get(tenantID, strings.TrimSpace(topic), uid, false); err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
tenantAdp, err := tenantBusinessAdapter(tenantID)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
return tenantAdp.TenantConversationSettingsUpdate(tenantID, uid, strings.TrimSpace(topic), patch)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (conversationsMapper) GetDraft(tenantID types.TenantID, uid types.Uid, topic string) (*types.TopicDraft, error) {
|
|
|
|
|
if uid.IsZero() || strings.TrimSpace(topic) == "" {
|
|
|
|
|
return nil, types.ErrMalformed
|
|
|
|
|
}
|
|
|
|
|
if _, err := Subs.Get(tenantID, strings.TrimSpace(topic), uid, false); err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
tenantAdp, err := tenantBusinessAdapter(tenantID)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
return tenantAdp.TenantTopicDraftGet(tenantID, uid, strings.TrimSpace(topic))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (conversationsMapper) PutDraft(tenantID types.TenantID, uid types.Uid, topic, content string, entities []byte, version int) (*types.TopicDraft, error) {
|
|
|
|
|
if uid.IsZero() || strings.TrimSpace(topic) == "" || version < 0 {
|
|
|
|
|
return nil, types.ErrMalformed
|
|
|
|
|
}
|
|
|
|
|
if _, err := Subs.Get(tenantID, strings.TrimSpace(topic), uid, false); err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
tenantAdp, err := tenantBusinessAdapter(tenantID)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
return tenantAdp.TenantTopicDraftPut(tenantID, uid, strings.TrimSpace(topic), content, entities, version)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type CallsPersistenceInterface interface {
|
|
|
|
|
Create(tenantID types.TenantID, record *types.CallRecord) error
|
|
|
|
|
Accept(tenantID types.TenantID, callID string, seq int, acceptedAt time.Time) error
|
|
|
|
@@ -1120,6 +1228,7 @@ type GroupBusinessPersistenceInterface interface {
|
|
|
|
|
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)
|
|
|
|
|
AcceptInvitation(types.TenantID, string, types.Uid, any, time.Time) (*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, any, time.Time) (*types.GroupJoinRequest, error)
|
|
|
|
@@ -1129,6 +1238,9 @@ type GroupBusinessPersistenceInterface interface {
|
|
|
|
|
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
|
|
|
|
|
ListFiles(types.TenantID, string, string, string, string, int) ([]types.GroupFile, string, error)
|
|
|
|
|
CreateFile(types.TenantID, *types.GroupFile) (*types.GroupFile, error)
|
|
|
|
|
DeleteFile(types.TenantID, string, string, types.Uid, bool, time.Time) (*types.GroupFile, error)
|
|
|
|
|
InviteMember(types.TenantID, string, types.Uid, types.Uid, string, string, any, time.Time) (bool, error)
|
|
|
|
|
Leave(types.TenantID, string, types.Uid, time.Time) error
|
|
|
|
|
UpdateRole(types.TenantID, string, types.Uid, types.Uid, string, types.AccessMode, time.Time) error
|
|
|
|
@@ -1248,6 +1360,17 @@ func (groupBusinessMapper) CreateInvitation(tenantID types.TenantID, invitation
|
|
|
|
|
return tenantAdp.TenantGroupInvitationCreate(tenantID, invitation)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (groupBusinessMapper) AcceptInvitation(tenantID types.TenantID, invitationID string, uid types.Uid, memberPrivate any, now time.Time) (*types.GroupInvitation, error) {
|
|
|
|
|
if strings.TrimSpace(invitationID) == "" || uid.IsZero() || now.IsZero() {
|
|
|
|
|
return nil, types.ErrMalformed
|
|
|
|
|
}
|
|
|
|
|
tenantAdp, err := tenantBusinessAdapter(tenantID)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
return tenantAdp.TenantGroupInvitationAccept(tenantID, strings.TrimSpace(invitationID), uid, memberPrivate, now)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
@@ -1353,6 +1476,42 @@ func (groupBusinessMapper) DeleteMute(tenantID types.TenantID, topic string, uid
|
|
|
|
|
return tenantAdp.TenantGroupMuteDelete(tenantID, strings.TrimSpace(topic), uid, actor, now)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (groupBusinessMapper) ListFiles(tenantID types.TenantID, topic, fileType, query, cursor string, limit int) ([]types.GroupFile, 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.TenantGroupFileList(tenantID, strings.TrimSpace(topic), strings.TrimSpace(fileType), strings.TrimSpace(query), strings.TrimSpace(cursor), limit)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (groupBusinessMapper) CreateFile(tenantID types.TenantID, file *types.GroupFile) (*types.GroupFile, error) {
|
|
|
|
|
if file == nil || strings.TrimSpace(file.Topic) == "" || strings.TrimSpace(file.FileID) == "" || file.UploaderID.IsZero() {
|
|
|
|
|
return nil, types.ErrMalformed
|
|
|
|
|
}
|
|
|
|
|
tenantAdp, err := tenantBusinessAdapter(tenantID)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
return tenantAdp.TenantGroupFileCreate(tenantID, file)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (groupBusinessMapper) DeleteFile(tenantID types.TenantID, topic, groupFileID string, actor types.Uid, canManage bool, now time.Time) (*types.GroupFile, error) {
|
|
|
|
|
if strings.TrimSpace(topic) == "" || strings.TrimSpace(groupFileID) == "" || actor.IsZero() || now.IsZero() {
|
|
|
|
|
return nil, types.ErrMalformed
|
|
|
|
|
}
|
|
|
|
|
tenantAdp, err := tenantBusinessAdapter(tenantID)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
return tenantAdp.TenantGroupFileDelete(tenantID, strings.TrimSpace(topic), strings.TrimSpace(groupFileID), actor, canManage, now)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (groupBusinessMapper) InviteMember(tenantID types.TenantID, topic string, inviter, target types.Uid,
|
|
|
|
|
message, idempotencyKey string, private any, now time.Time) (bool, error) {
|
|
|
|
|
if strings.TrimSpace(topic) == "" || inviter.IsZero() || target.IsZero() || now.IsZero() {
|
|
|
|
@@ -1456,6 +1615,7 @@ func (workbenchMapper) Get(tenantID types.TenantID, uid types.Uid) ([]types.Work
|
|
|
|
|
type OrganizationPersistenceInterface interface {
|
|
|
|
|
ListDepartments(tenantID types.TenantID, uid types.Uid, parentID, cursor string, limit int) ([]types.OrganizationDepartment, string, error)
|
|
|
|
|
ListMembers(tenantID types.TenantID, uid types.Uid, departmentID, cursor string, limit int) ([]types.OrganizationMember, string, error)
|
|
|
|
|
ListAllMembers(tenantID types.TenantID, uid types.Uid, departmentID, queryText, cursor string, limit int) ([]types.OrganizationMember, string, error)
|
|
|
|
|
Search(tenantID types.TenantID, uid types.Uid, queryText, resultTypes, cursor string, limit int) ([]types.OrganizationSearchItem, string, error)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -1491,6 +1651,20 @@ func (organizationMapper) ListMembers(tenantID types.TenantID, uid types.Uid, de
|
|
|
|
|
return tenantAdp.TenantOrganizationMembers(tenantID, uid, strings.TrimSpace(departmentID), strings.TrimSpace(cursor), limit)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (organizationMapper) ListAllMembers(tenantID types.TenantID, uid types.Uid, departmentID, queryText, cursor string, limit int) ([]types.OrganizationMember, string, error) {
|
|
|
|
|
if uid.IsZero() {
|
|
|
|
|
return nil, "", types.ErrMalformed
|
|
|
|
|
}
|
|
|
|
|
if limit <= 0 || limit > 100 {
|
|
|
|
|
limit = 50
|
|
|
|
|
}
|
|
|
|
|
tenantAdp, err := tenantBusinessAdapter(tenantID)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, "", err
|
|
|
|
|
}
|
|
|
|
|
return tenantAdp.TenantOrganizationMembersAll(tenantID, uid, strings.TrimSpace(departmentID), strings.TrimSpace(queryText), strings.TrimSpace(cursor), limit)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (organizationMapper) Search(tenantID types.TenantID, uid types.Uid, queryText, resultTypes, cursor string, limit int) ([]types.OrganizationSearchItem, string, error) {
|
|
|
|
|
if uid.IsZero() || strings.TrimSpace(queryText) == "" {
|
|
|
|
|
return nil, "", types.ErrMalformed
|
|
|
|
@@ -1714,6 +1888,7 @@ type MonthlyReportsPersistenceInterface interface {
|
|
|
|
|
Get(tenantID types.TenantID, uid types.Uid, reportID string) (*types.MonthlyReport, error)
|
|
|
|
|
SaveDraft(tenantID types.TenantID, uid types.Uid, reportID, workSummary, nextPlan string, attachments []string, version int) (*types.MonthlyReport, error)
|
|
|
|
|
Submit(tenantID types.TenantID, uid types.Uid, reportID string, version int) (*types.MonthlyReport, error)
|
|
|
|
|
Reopen(tenantID types.TenantID, uid types.Uid, reportID string, version int) (*types.MonthlyReport, error)
|
|
|
|
|
Stats(tenantID types.TenantID, uid types.Uid, month, departmentID string) (*types.MonthlyReportStats, error)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -1779,6 +1954,17 @@ func (monthlyReportsMapper) Submit(tenantID types.TenantID, uid types.Uid, repor
|
|
|
|
|
return tenantAdp.TenantMonthlyReportSubmit(tenantID, uid, strings.TrimSpace(reportID), version)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (monthlyReportsMapper) Reopen(tenantID types.TenantID, uid types.Uid, reportID string, version int) (*types.MonthlyReport, error) {
|
|
|
|
|
if uid.IsZero() || strings.TrimSpace(reportID) == "" || version <= 0 {
|
|
|
|
|
return nil, types.ErrMalformed
|
|
|
|
|
}
|
|
|
|
|
tenantAdp, err := tenantBusinessAdapter(tenantID)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
return tenantAdp.TenantMonthlyReportReopen(tenantID, uid, strings.TrimSpace(reportID), version)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (monthlyReportsMapper) Stats(tenantID types.TenantID, uid types.Uid, month, departmentID string) (*types.MonthlyReportStats, error) {
|
|
|
|
|
if uid.IsZero() || strings.TrimSpace(month) == "" {
|
|
|
|
|
return nil, types.ErrMalformed
|
|
|
|
@@ -3118,6 +3304,7 @@ type UserSecurityPersistenceInterface interface {
|
|
|
|
|
BumpAuthVersion(tenantID types.TenantID, uid types.Uid, updatedAt time.Time) (int, error)
|
|
|
|
|
GetRealName(tenantID types.TenantID, uid types.Uid) (*types.RealNameVerification, error)
|
|
|
|
|
CreateRealNameSubmission(tenantID types.TenantID, rv *types.RealNameVerification) error
|
|
|
|
|
CreateRealNameAppeal(tenantID types.TenantID, appeal *types.RealNameAppeal) (*types.RealNameAppeal, error)
|
|
|
|
|
CreateActionToken(tenantID types.TenantID, token *types.ActionToken) error
|
|
|
|
|
ConsumeActionToken(tenantID types.TenantID, uid types.Uid, token, action, target string, now time.Time) (*types.ActionToken, error)
|
|
|
|
|
GetIndependentPassword(tenantID types.TenantID, uid types.Uid, purpose string) (*types.IndependentPassword, error)
|
|
|
|
@@ -3171,6 +3358,17 @@ func (userSecurityMapper) CreateRealNameSubmission(tenantID types.TenantID, rv *
|
|
|
|
|
return tenantAdp.TenantRealNameCreate(tenantID, rv)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (userSecurityMapper) CreateRealNameAppeal(tenantID types.TenantID, appeal *types.RealNameAppeal) (*types.RealNameAppeal, error) {
|
|
|
|
|
if appeal == nil || appeal.TenantID != tenantID || appeal.UserID.IsZero() || strings.TrimSpace(appeal.AppealID) == "" {
|
|
|
|
|
return nil, types.ErrMalformed
|
|
|
|
|
}
|
|
|
|
|
tenantAdp, err := tenantBusinessAdapter(tenantID)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
return tenantAdp.TenantRealNameAppealCreate(tenantID, appeal)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (userSecurityMapper) CreateActionToken(tenantID types.TenantID, token *types.ActionToken) error {
|
|
|
|
|
if token == nil || token.TenantID != tenantID {
|
|
|
|
|
return types.ErrMalformed
|
|
|
|
@@ -3481,6 +3679,7 @@ func init() {
|
|
|
|
|
Topics = topicsMapper{}
|
|
|
|
|
Subs = subsMapper{}
|
|
|
|
|
Messages = messagesMapper{}
|
|
|
|
|
Conversations = conversationsMapper{}
|
|
|
|
|
Calls = callsMapper{}
|
|
|
|
|
GroupBusiness = groupBusinessMapper{}
|
|
|
|
|
Workbench = workbenchMapper{}
|
|
|
|
|