feat: implement privacy-aware profile visibility and activity status filtering using optional authentication guard
This commit is contained in:
@@ -16,6 +16,17 @@ export class MessagesService {
|
||||
private readonly eventEmitter: EventEmitter2,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Check if a user's activity status allows showing online status.
|
||||
* Connected users always see online status for 'connections' setting.
|
||||
*/
|
||||
private shouldShowOnlineStatus(privacyPreferences: any, isConnected = true): boolean {
|
||||
const activityStatus = (privacyPreferences as any)?.privacySettings?.activity_status || 'public';
|
||||
if (activityStatus === 'public') return true;
|
||||
if (activityStatus === 'connections' && isConnected) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate if a user can message an agent (must have ACCEPTED connection)
|
||||
*/
|
||||
@@ -87,6 +98,7 @@ export class MessagesService {
|
||||
select: {
|
||||
isOnline: true,
|
||||
lastSeenAt: true,
|
||||
privacyPreferences: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -96,6 +108,7 @@ export class MessagesService {
|
||||
id: true,
|
||||
isOnline: true,
|
||||
lastSeenAt: true,
|
||||
privacyPreferences: true,
|
||||
userProfile: {
|
||||
select: {
|
||||
firstName: true,
|
||||
@@ -130,8 +143,10 @@ export class MessagesService {
|
||||
}
|
||||
|
||||
// Transform to include otherParty based on caller role
|
||||
// Conversations only exist between connected users, so isConnected=true
|
||||
if (callerRole === UserRole.AGENT) {
|
||||
// Agent is viewing — other party is the user
|
||||
const showStatus = this.shouldShowOnlineStatus(conversation.user.privacyPreferences);
|
||||
return {
|
||||
...conversation,
|
||||
unreadCount: conversation.agentUnreadCount,
|
||||
@@ -139,12 +154,13 @@ export class MessagesService {
|
||||
id: conversation.user.id,
|
||||
name: `${conversation.user.userProfile?.firstName || ''} ${conversation.user.userProfile?.lastName || ''}`.trim() || 'User',
|
||||
avatar: conversation.user.userProfile?.avatar,
|
||||
isOnline: conversation.user.isOnline,
|
||||
lastSeenAt: conversation.user.lastSeenAt,
|
||||
isOnline: showStatus ? conversation.user.isOnline : false,
|
||||
lastSeenAt: showStatus ? conversation.user.lastSeenAt : null,
|
||||
},
|
||||
};
|
||||
} else {
|
||||
// User is viewing — other party is the agent
|
||||
const showStatus = this.shouldShowOnlineStatus(conversation.agentProfile.user?.privacyPreferences);
|
||||
return {
|
||||
...conversation,
|
||||
unreadCount: conversation.userUnreadCount,
|
||||
@@ -154,8 +170,8 @@ export class MessagesService {
|
||||
name: `${conversation.agentProfile.firstName || ''} ${conversation.agentProfile.lastName || ''}`.trim() || 'Agent',
|
||||
avatar: conversation.agentProfile.avatar,
|
||||
headline: conversation.agentProfile.headline,
|
||||
isOnline: conversation.agentProfile.user?.isOnline || false,
|
||||
lastSeenAt: conversation.agentProfile.user?.lastSeenAt || null,
|
||||
isOnline: showStatus ? (conversation.agentProfile.user?.isOnline || false) : false,
|
||||
lastSeenAt: showStatus ? (conversation.agentProfile.user?.lastSeenAt || null) : null,
|
||||
},
|
||||
};
|
||||
}
|
||||
@@ -306,6 +322,7 @@ export class MessagesService {
|
||||
id: true,
|
||||
isOnline: true,
|
||||
lastSeenAt: true,
|
||||
privacyPreferences: true,
|
||||
userProfile: {
|
||||
select: {
|
||||
firstName: true,
|
||||
@@ -324,17 +341,20 @@ export class MessagesService {
|
||||
});
|
||||
|
||||
// Map to include unread count from agent perspective
|
||||
return conversations.map((conv) => ({
|
||||
...conv,
|
||||
unreadCount: conv.agentUnreadCount,
|
||||
otherParty: {
|
||||
id: conv.user.id,
|
||||
name: `${conv.user.userProfile?.firstName || ''} ${conv.user.userProfile?.lastName || ''}`.trim() || 'User',
|
||||
avatar: conv.user.userProfile?.avatar,
|
||||
isOnline: conv.user.isOnline,
|
||||
lastSeenAt: conv.user.lastSeenAt,
|
||||
},
|
||||
}));
|
||||
return conversations.map((conv) => {
|
||||
const showStatus = this.shouldShowOnlineStatus(conv.user.privacyPreferences);
|
||||
return {
|
||||
...conv,
|
||||
unreadCount: conv.agentUnreadCount,
|
||||
otherParty: {
|
||||
id: conv.user.id,
|
||||
name: `${conv.user.userProfile?.firstName || ''} ${conv.user.userProfile?.lastName || ''}`.trim() || 'User',
|
||||
avatar: conv.user.userProfile?.avatar,
|
||||
isOnline: showStatus ? conv.user.isOnline : false,
|
||||
lastSeenAt: showStatus ? conv.user.lastSeenAt : null,
|
||||
},
|
||||
};
|
||||
});
|
||||
} else {
|
||||
// Regular user
|
||||
conversations = await this.prisma.conversation.findMany({
|
||||
@@ -352,6 +372,7 @@ export class MessagesService {
|
||||
select: {
|
||||
isOnline: true,
|
||||
lastSeenAt: true,
|
||||
privacyPreferences: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -365,19 +386,22 @@ export class MessagesService {
|
||||
});
|
||||
|
||||
// Map to include unread count from user perspective
|
||||
return conversations.map((conv) => ({
|
||||
...conv,
|
||||
unreadCount: conv.userUnreadCount,
|
||||
otherParty: {
|
||||
id: conv.agentProfile.id,
|
||||
userId: conv.agentProfile.userId,
|
||||
name: `${conv.agentProfile.firstName || ''} ${conv.agentProfile.lastName || ''}`.trim() || 'Agent',
|
||||
avatar: conv.agentProfile.avatar,
|
||||
headline: conv.agentProfile.headline,
|
||||
isOnline: conv.agentProfile.user.isOnline,
|
||||
lastSeenAt: conv.agentProfile.user.lastSeenAt,
|
||||
},
|
||||
}));
|
||||
return conversations.map((conv) => {
|
||||
const showStatus = this.shouldShowOnlineStatus(conv.agentProfile.user.privacyPreferences);
|
||||
return {
|
||||
...conv,
|
||||
unreadCount: conv.userUnreadCount,
|
||||
otherParty: {
|
||||
id: conv.agentProfile.id,
|
||||
userId: conv.agentProfile.userId,
|
||||
name: `${conv.agentProfile.firstName || ''} ${conv.agentProfile.lastName || ''}`.trim() || 'Agent',
|
||||
avatar: conv.agentProfile.avatar,
|
||||
headline: conv.agentProfile.headline,
|
||||
isOnline: showStatus ? conv.agentProfile.user.isOnline : false,
|
||||
lastSeenAt: showStatus ? conv.agentProfile.user.lastSeenAt : null,
|
||||
},
|
||||
};
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user