feat: stabilize social backend contracts
هذا الالتزام موجود في:
@@ -99,6 +99,12 @@ export class User {
|
||||
@Prop({ default: false })
|
||||
isEmailVerified!: boolean;
|
||||
|
||||
@Prop({ default: false, index: true })
|
||||
isOnline!: boolean;
|
||||
|
||||
@Prop({ type: Date, default: null })
|
||||
lastSeenAt?: Date | null;
|
||||
|
||||
@Prop({ default: '', trim: true, maxlength: 120 })
|
||||
shopName!: string;
|
||||
|
||||
|
||||
@@ -288,11 +288,18 @@ export class UsersController {
|
||||
return this.usersService.getProfileOverview(id, user.sub);
|
||||
}
|
||||
|
||||
@ApiBearerAuth()
|
||||
@UseGuards(JwtAuthGuard)
|
||||
@Get(':id/presence')
|
||||
async getPresence(@Param('id') id: string) {
|
||||
return this.usersService.getPresence(id);
|
||||
}
|
||||
|
||||
@ApiBearerAuth()
|
||||
@UseGuards(JwtAuthGuard)
|
||||
@Get(':id')
|
||||
async findOne(@Param('id') id: string) {
|
||||
return this.usersService.findPublicByIdOrFail(id);
|
||||
async findOne(@CurrentUser() user: JwtPayload, @Param('id') id: string) {
|
||||
return this.usersService.findPublicByIdForViewer(id, user.sub);
|
||||
}
|
||||
|
||||
@ApiBearerAuth()
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { InjectModel } from '@nestjs/mongoose';
|
||||
import { ClientSession, FilterQuery, Model, UpdateQuery } from 'mongoose';
|
||||
import { ClientSession, FilterQuery, Model, Types, UpdateQuery } from 'mongoose';
|
||||
import { User, UserDocument } from './schemas/user.schema';
|
||||
|
||||
@Injectable()
|
||||
@@ -69,6 +69,12 @@ export class UsersRepository {
|
||||
await this.userModel.findByIdAndUpdate(userId, { followingCount }, { new: false }).exec();
|
||||
}
|
||||
|
||||
async setPresence(userId: string, isOnline: boolean, lastSeenAt: Date): Promise<void> {
|
||||
await this.userModel
|
||||
.findByIdAndUpdate(userId, { isOnline, lastSeenAt }, { new: false })
|
||||
.exec();
|
||||
}
|
||||
|
||||
async findMany(
|
||||
filter: FilterQuery<UserDocument>,
|
||||
skip: number,
|
||||
@@ -78,6 +84,16 @@ export class UsersRepository {
|
||||
return this.userModel.find(filter).sort(sort).skip(skip).limit(limit).exec();
|
||||
}
|
||||
|
||||
async findManyByIds(ids: string[]): Promise<UserDocument[]> {
|
||||
if (!ids.length) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return this.userModel
|
||||
.find({ _id: { $in: ids.map((id) => new Types.ObjectId(id)) } })
|
||||
.exec();
|
||||
}
|
||||
|
||||
async findByUsernames(usernames: string[]): Promise<UserDocument[]> {
|
||||
if (!usernames.length) {
|
||||
return [];
|
||||
|
||||
@@ -237,6 +237,40 @@ export class UsersService {
|
||||
return user;
|
||||
}
|
||||
|
||||
async findPublicByIdForViewer(userId: string, viewerUserId: string) {
|
||||
const user = await this.findPublicByIdOrFail(userId);
|
||||
const isFollowing =
|
||||
viewerUserId === userId
|
||||
? false
|
||||
: (await this.connection.collection('follows').countDocuments({
|
||||
followerId: new Types.ObjectId(viewerUserId),
|
||||
followingId: new Types.ObjectId(userId),
|
||||
})) > 0;
|
||||
|
||||
return {
|
||||
...user.toObject(),
|
||||
isFollowing,
|
||||
following: isFollowing,
|
||||
isOwnProfile: viewerUserId === userId,
|
||||
};
|
||||
}
|
||||
|
||||
async getPresence(userId: string) {
|
||||
const user = await this.findPublicByIdOrFail(userId);
|
||||
return {
|
||||
userId: user.id,
|
||||
isOnline: user.isOnline ?? false,
|
||||
lastSeenAt: user.lastSeenAt ?? null,
|
||||
};
|
||||
}
|
||||
|
||||
async setPresence(userId: string, isOnline: boolean): Promise<void> {
|
||||
if (!Types.ObjectId.isValid(userId)) {
|
||||
return;
|
||||
}
|
||||
await this.usersRepository.setPresence(userId, isOnline, new Date());
|
||||
}
|
||||
|
||||
async findByEmailWithPassword(email: string): Promise<UserDocument | null> {
|
||||
return this.usersRepository.findOneWithPassword({ email: email.toLowerCase() });
|
||||
}
|
||||
@@ -737,6 +771,7 @@ export class UsersService {
|
||||
viewerState: {
|
||||
isOwnProfile: viewerUserId === userId,
|
||||
following: followingState,
|
||||
isFollowing: followingState,
|
||||
canMessage: viewerUserId !== userId,
|
||||
},
|
||||
};
|
||||
@@ -749,6 +784,7 @@ export class UsersService {
|
||||
viewerState: {
|
||||
isOwnProfile: false,
|
||||
following: false,
|
||||
isFollowing: false,
|
||||
canMessage: false,
|
||||
},
|
||||
};
|
||||
|
||||
المرجع في مشكلة جديدة
حظر مستخدم