feat: add im tenant db routing and chapter seven flows
This commit is contained in:
@@ -149,6 +149,13 @@ func tenantAuthAdapter(tenantID types.TenantID) (adapter.TenantAuthAdapter, erro
|
||||
if !tenantID.IsValid() {
|
||||
return nil, types.ErrMalformed
|
||||
}
|
||||
if routed, ok := adp.(adapter.TenantRoutedAdapter); ok {
|
||||
_, authAdp, err := routed.TenantAdapterFor(tenantID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return authAdp, nil
|
||||
}
|
||||
tenantAdp, ok := adp.(adapter.TenantAuthAdapter)
|
||||
if !ok {
|
||||
return nil, types.ErrUnsupported
|
||||
@@ -160,6 +167,17 @@ func tenantBusinessAdapter(tenantID types.TenantID) (adapter.TenantBusinessAdapt
|
||||
if !tenantID.IsValid() {
|
||||
return nil, types.ErrMalformed
|
||||
}
|
||||
if routed, ok := adp.(adapter.TenantRoutedAdapter); ok {
|
||||
businessAdp, _, err := routed.TenantAdapterFor(tenantID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !businessAdp.TenantBusinessReady() {
|
||||
return nil, types.ErrUnsupported
|
||||
}
|
||||
activeTenantIDs.Store(tenantID, struct{}{})
|
||||
return businessAdp, nil
|
||||
}
|
||||
tenantAdp, ok := adp.(adapter.TenantBusinessAdapter)
|
||||
if !ok {
|
||||
return nil, types.ErrUnsupported
|
||||
@@ -960,6 +978,7 @@ type MessagesPersistenceInterface interface {
|
||||
DeleteList(tenantID types.TenantID, topic string, delID int, forUser types.Uid, msgDelAge time.Duration, ranges []types.Range) error
|
||||
GetAll(tenantID types.TenantID, topic string, forUser types.Uid, opt *types.QueryOpt) ([]types.Message, error)
|
||||
GetDeleted(tenantID types.TenantID, topic string, forUser types.Uid, opt *types.QueryOpt) ([]types.Range, int, error)
|
||||
Search(tenantID types.TenantID, topic string, forUser types.Uid, query, messageType, cursor string, limit int) ([]types.Message, string, error)
|
||||
}
|
||||
|
||||
// messagesMapper is a concrete type implementing MessagesPersistenceInterface.
|
||||
@@ -1003,14 +1022,75 @@ type RelationsPersistenceInterface interface {
|
||||
GetRelationshipContext(tenantID types.TenantID, userID, peerID types.Uid, topic string) (*types.RelationshipContext, error)
|
||||
CanSendP2P(tenantID types.TenantID, userID, peerID types.Uid) (bool, string, error)
|
||||
BlockUser(tenantID types.TenantID, blockerID, blockedID types.Uid, now time.Time) (*types.UserBlock, error)
|
||||
ListBlocks(tenantID types.TenantID, blockerID types.Uid, cursor string, limit int) ([]types.BlockListItem, string, error)
|
||||
UnblockUser(tenantID types.TenantID, blockerID, blockedID types.Uid) error
|
||||
DeleteFriend(tenantID types.TenantID, userID, peerID types.Uid, now time.Time) error
|
||||
UpdateFriendRemark(tenantID types.TenantID, userID, peerID types.Uid, remark string, now time.Time) (*types.Friendship, error)
|
||||
SearchUsers(tenantID types.TenantID, viewer types.Uid, query, searchType, cursor string, limit int) ([]types.UserSearchItem, string, error)
|
||||
}
|
||||
|
||||
type relationsMapper struct{}
|
||||
|
||||
var Relations RelationsPersistenceInterface
|
||||
|
||||
type FavoritesPersistenceInterface interface {
|
||||
Create(tenantID types.TenantID, item *types.FavoriteItem) (*types.FavoriteItem, error)
|
||||
List(tenantID types.TenantID, uid types.Uid, itemType, query, cursor string, limit int) ([]types.FavoriteItem, string, error)
|
||||
Get(tenantID types.TenantID, uid types.Uid, favoriteID string) (*types.FavoriteItem, error)
|
||||
Delete(tenantID types.TenantID, uid types.Uid, favoriteID string) error
|
||||
}
|
||||
|
||||
type favoritesMapper struct{}
|
||||
|
||||
var Favorites FavoritesPersistenceInterface
|
||||
|
||||
func (favoritesMapper) Create(tenantID types.TenantID, item *types.FavoriteItem) (*types.FavoriteItem, error) {
|
||||
if item == nil || item.TenantID != tenantID || item.UserID.IsZero() || item.FavoriteID == "" {
|
||||
return nil, types.ErrMalformed
|
||||
}
|
||||
tenantAdp, err := tenantBusinessAdapter(tenantID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return tenantAdp.TenantFavoriteCreate(tenantID, item)
|
||||
}
|
||||
|
||||
func (favoritesMapper) List(tenantID types.TenantID, uid types.Uid, itemType, query, cursor string, limit int) ([]types.FavoriteItem, 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.TenantFavoriteList(tenantID, uid, itemType, query, cursor, limit)
|
||||
}
|
||||
|
||||
func (favoritesMapper) Get(tenantID types.TenantID, uid types.Uid, favoriteID string) (*types.FavoriteItem, error) {
|
||||
if uid.IsZero() || strings.TrimSpace(favoriteID) == "" {
|
||||
return nil, types.ErrMalformed
|
||||
}
|
||||
tenantAdp, err := tenantBusinessAdapter(tenantID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return tenantAdp.TenantFavoriteGet(tenantID, uid, favoriteID)
|
||||
}
|
||||
|
||||
func (favoritesMapper) Delete(tenantID types.TenantID, uid types.Uid, favoriteID string) error {
|
||||
if uid.IsZero() || strings.TrimSpace(favoriteID) == "" {
|
||||
return types.ErrMalformed
|
||||
}
|
||||
tenantAdp, err := tenantBusinessAdapter(tenantID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return tenantAdp.TenantFavoriteDelete(tenantID, uid, favoriteID)
|
||||
}
|
||||
|
||||
func (relationsMapper) CreateFriendRequest(tenantID types.TenantID, req *types.FriendRequest) (*types.FriendRequest, error) {
|
||||
if req == nil || req.TenantID != tenantID || req.ApplicantID.IsZero() || req.TargetID.IsZero() || req.ApplicantID == req.TargetID {
|
||||
return nil, types.ErrMalformed
|
||||
@@ -1111,6 +1191,20 @@ func (relationsMapper) BlockUser(tenantID types.TenantID, blockerID, blockedID t
|
||||
return tenantAdp.TenantUserBlockUpsert(tenantID, blockerID, blockedID, now)
|
||||
}
|
||||
|
||||
func (relationsMapper) ListBlocks(tenantID types.TenantID, blockerID types.Uid, cursor string, limit int) ([]types.BlockListItem, string, error) {
|
||||
if blockerID.IsZero() {
|
||||
return nil, "", types.ErrMalformed
|
||||
}
|
||||
if limit <= 0 || limit > 100 {
|
||||
limit = 50
|
||||
}
|
||||
tenantAdp, err := tenantBusinessAdapter(tenantID)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
return tenantAdp.TenantUserBlockList(tenantID, blockerID, cursor, limit)
|
||||
}
|
||||
|
||||
func (relationsMapper) UnblockUser(tenantID types.TenantID, blockerID, blockedID types.Uid) error {
|
||||
if blockerID.IsZero() || blockedID.IsZero() || blockerID == blockedID {
|
||||
return types.ErrMalformed
|
||||
@@ -1133,6 +1227,68 @@ func (relationsMapper) DeleteFriend(tenantID types.TenantID, userID, peerID type
|
||||
return tenantAdp.TenantFriendshipDeletePair(tenantID, userID, peerID, now)
|
||||
}
|
||||
|
||||
func (relationsMapper) UpdateFriendRemark(tenantID types.TenantID, userID, peerID types.Uid, remark string, now time.Time) (*types.Friendship, error) {
|
||||
if userID.IsZero() || peerID.IsZero() || userID == peerID || len([]rune(remark)) > 64 {
|
||||
return nil, types.ErrMalformed
|
||||
}
|
||||
tenantAdp, err := tenantBusinessAdapter(tenantID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return tenantAdp.TenantFriendshipUpdateRemark(tenantID, userID, peerID, remark, now)
|
||||
}
|
||||
|
||||
func (relationsMapper) SearchUsers(tenantID types.TenantID, viewer types.Uid, query, searchType, cursor string, limit int) ([]types.UserSearchItem, string, error) {
|
||||
if viewer.IsZero() || strings.TrimSpace(query) == "" {
|
||||
return nil, "", types.ErrMalformed
|
||||
}
|
||||
switch searchType {
|
||||
case "", "account", "exact_account", "phone":
|
||||
default:
|
||||
return nil, "", types.ErrMalformed
|
||||
}
|
||||
if limit <= 0 || limit > 50 {
|
||||
limit = 20
|
||||
}
|
||||
tenantAdp, err := tenantBusinessAdapter(tenantID)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
users, nextCursor, err := tenantAdp.TenantUserSearch(tenantID, viewer, query, searchType, cursor, limit)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
items := make([]types.UserSearchItem, 0, len(users))
|
||||
for i := range users {
|
||||
uid := users[i].Uid()
|
||||
ctx, err := relationshipContext(tenantAdp, tenantID, viewer, uid, viewer.P2PName(uid))
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
items = append(items, types.UserSearchItem{
|
||||
User: &users[i],
|
||||
Relationship: ctx.Relationship,
|
||||
RequestID: ctx.RequestID,
|
||||
CanAdd: ctx.Relationship == types.RelationshipNone,
|
||||
Action: relationshipAction(ctx.Relationship),
|
||||
})
|
||||
}
|
||||
return items, nextCursor, nil
|
||||
}
|
||||
|
||||
func relationshipAction(relationship string) string {
|
||||
switch relationship {
|
||||
case types.RelationshipFriend:
|
||||
return "chat"
|
||||
case types.RelationshipPendingInbound, types.RelationshipPendingOutbound:
|
||||
return "pending"
|
||||
case types.RelationshipBlockedByMe, types.RelationshipBlockedByPeer:
|
||||
return "none"
|
||||
default:
|
||||
return "add"
|
||||
}
|
||||
}
|
||||
|
||||
func relationshipContext(tenantAdp adapter.TenantBusinessAdapter, tenantID types.TenantID, userID, peerID types.Uid, topic string) (*types.RelationshipContext, error) {
|
||||
ctx := &types.RelationshipContext{
|
||||
TenantID: tenantID,
|
||||
@@ -1381,6 +1537,20 @@ func (messagesMapper) GetAll(tenantID types.TenantID, topic string, forUser type
|
||||
return tenantAdp.TenantMessageGetAll(tenantID, topic, forUser, opt)
|
||||
}
|
||||
|
||||
func (messagesMapper) Search(tenantID types.TenantID, topic string, forUser types.Uid, query, messageType, cursor string, limit int) ([]types.Message, string, error) {
|
||||
if topic == "" || forUser.IsZero() {
|
||||
return nil, "", types.ErrMalformed
|
||||
}
|
||||
if limit <= 0 || limit > 100 {
|
||||
limit = 50
|
||||
}
|
||||
tenantAdp, err := tenantBusinessAdapter(tenantID)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
return tenantAdp.TenantMessageSearch(tenantID, topic, forUser, query, messageType, cursor, limit)
|
||||
}
|
||||
|
||||
// GetDeleted returns the ranges of deleted messages and the largest DelId reported in the list.
|
||||
func (messagesMapper) GetDeleted(tenantID types.TenantID, topic string, forUser types.Uid, opt *types.QueryOpt) ([]types.Range, int, error) {
|
||||
tenantAdp, err := tenantBusinessAdapter(tenantID)
|
||||
@@ -1649,6 +1819,8 @@ type FilePersistenceInterface interface {
|
||||
// LinkAttachments connects earlier uploaded attachments to a message or topic to prevent it
|
||||
// from being garbage collected.
|
||||
LinkAttachments(tenantID types.TenantID, topic string, msgId types.Uid, attachments []string) error
|
||||
// UserHasAccess checks if user can download a file through an active upload, user, topic, or message reference.
|
||||
UserHasAccess(tenantID types.TenantID, fid string, uid types.Uid) (bool, error)
|
||||
}
|
||||
|
||||
// fileMapper is concrete type which implements FilePersistenceInterface.
|
||||
@@ -1738,6 +1910,17 @@ func (fileMapper) LinkAttachments(tenantID types.TenantID, topic string, msgId t
|
||||
return nil
|
||||
}
|
||||
|
||||
func (fileMapper) UserHasAccess(tenantID types.TenantID, fid string, uid types.Uid) (bool, error) {
|
||||
if fid == "" || uid.IsZero() {
|
||||
return false, types.ErrMalformed
|
||||
}
|
||||
tenantAdp, err := tenantBusinessAdapter(tenantID)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return tenantAdp.TenantFileUserHasAccess(tenantID, fid, uid)
|
||||
}
|
||||
|
||||
// PersistentCacheInterface is an interface which defines methods used for accessing persistent key-value cache.
|
||||
type PersistentCacheInterface interface {
|
||||
// Get reads a persistent cache entry.
|
||||
@@ -2004,4 +2187,5 @@ func init() {
|
||||
Verifications = verificationMapper{}
|
||||
Security = userSecurityMapper{}
|
||||
Relations = relationsMapper{}
|
||||
Favorites = favoritesMapper{}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user