Skip to content

Commit a65c92a

Browse files
Alyaa242AmiraKhalid04MarioRaafat
authored
feat(profile): v3
* feat(profile): profile posts tabs endpoints * fix(profile): fix update user response * fix(profile): return user birthdate in profile response * fix(profile): clean unused files after update profile * refactor(profile): convert sql posts query to typeorm * feat(profile): add user data to user posts view * fix(profile): remove reply from user posts + fix repost type * feat(profile): add quote parent data in user posts * feat(profile): apply cursor pagination to profile endpoints * fix(profile): fix get media + liked posts * refactor(profile): change response pagination schema * docs(profile): edit swagger documentation for pagination * fix(profile): fix cursor pagination and created_at timezone * fix(profile): replace location with country in update user * fix(profile): delete profile, cover images after delete account * feat(user): get username recommendations * fix(auth): fix refresh token * feat(auth): confirm password --------- Co-authored-by: Amira Khalid <149877108+AmiraKhalid04@users.noreply.github.com> Co-authored-by: Mario Raafat <136023677+MarioRaafat@users.noreply.github.com>
1 parent f5a61f7 commit a65c92a

37 files changed

+1002
-1496
lines changed

src/auth/auth.controller.ts

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ import {
6262
captcha_swagger,
6363
change_password_swagger,
6464
check_identifier_swagger,
65+
confirm_password_swagger,
6566
facebook_callback_swagger,
6667
facebook_oauth_swagger,
6768
forget_password_swagger,
@@ -89,6 +90,7 @@ import {
8990
verify_reset_otp_swagger,
9091
verify_update_email_swagger,
9192
} from './auth.swagger';
93+
import { ConfirmPasswordDto } from './dto/confirm-password.dto';
9294

9395
@ApiTags('Authentication')
9496
@Controller('auth')
@@ -100,7 +102,7 @@ export class AuthController {
100102

101103
response.cookie('refresh_token', refresh, {
102104
httpOnly: true,
103-
secure: is_production,
105+
secure: true,
104106
sameSite: is_production ? 'strict' : 'none',
105107
maxAge: 7 * 24 * 60 * 60 * 1000,
106108
});
@@ -263,7 +265,6 @@ export class AuthController {
263265
return await this.auth_service.logoutAll(refresh_token, response);
264266
}
265267

266-
@ApiCookieAuth('refresh_token')
267268
@ApiOperation(refresh_token_swagger.operation)
268269
@ApiOkResponse(refresh_token_swagger.responses.success)
269270
@ApiBadRequestErrorResponse(ERROR_MESSAGES.NO_REFRESH_TOKEN_PROVIDED)
@@ -609,4 +610,21 @@ export class AuthController {
609610
this.httpOnlyRefreshToken(response, refresh_token);
610611
return { access_token, user };
611612
}
613+
614+
@ApiBearerAuth('JWT-auth')
615+
@UseGuards(JwtAuthGuard)
616+
@ApiOperation(confirm_password_swagger.operation)
617+
@ApiBody({ type: ConfirmPasswordDto })
618+
@ApiOkResponse(confirm_password_swagger.responses.success)
619+
@ApiUnauthorizedErrorResponse(ERROR_MESSAGES.WRONG_PASSWORD)
620+
@ApiUnauthorizedErrorResponse(ERROR_MESSAGES.SOCIAL_LOGIN_REQUIRED)
621+
@ApiNotFoundErrorResponse(ERROR_MESSAGES.USER_NOT_FOUND)
622+
@ResponseMessage(SUCCESS_MESSAGES.PASSWORD_CONFIRMED)
623+
@Post('confirm-password')
624+
async confirmPassword(
625+
@Body() confirm_password_dto: ConfirmPasswordDto,
626+
@GetUserId() user_id: string
627+
) {
628+
return this.auth_service.confirmPassword(confirm_password_dto, user_id);
629+
}
612630
}

src/auth/auth.module.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import { FacebookStrategy } from './strategies/facebook.strategy';
2222
import { UserRepository } from 'src/user/user.repository';
2323
import { BackgroundJobsModule } from 'src/background-jobs/background-jobs.module';
2424
import { BackgroundJobsService } from 'src/background-jobs/background-jobs.service';
25+
import { PaginationService } from 'src/shared/services/pagination/pagination.service';
2526

2627
@Module({
2728
imports: [
@@ -57,6 +58,7 @@ import { BackgroundJobsService } from 'src/background-jobs/background-jobs.servi
5758
UsernameService,
5859
GoogleStrategy,
5960
FacebookStrategy,
61+
PaginationService,
6062
],
6163
})
6264
export class AuthModule {}

src/auth/auth.service.ts

Lines changed: 25 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ import { StringValue } from 'ms'; // Add this import
4646
import { OAuth2Client } from 'google-auth-library';
4747
import axios from 'axios';
4848
import { UserRepository } from 'src/user/user.repository';
49+
import { ConfirmPasswordDto } from './dto/confirm-password.dto';
4950

5051
@Injectable()
5152
export class AuthService {
@@ -92,19 +93,6 @@ export class AuthService {
9293
};
9394
}
9495

95-
async getRecommendedUsernames(name: string): Promise<string[]> {
96-
const name_parts = name.split(' ');
97-
const first_name = name_parts[0];
98-
const last_name = name_parts.length > 1 ? name_parts.slice(1).join(' ') : '';
99-
100-
const recommendations = await this.username_service.generateUsernameRecommendations(
101-
first_name,
102-
last_name
103-
);
104-
105-
return recommendations;
106-
}
107-
10896
async validateUser(identifier: string, password: string, type: string): Promise<string> {
10997
const user =
11098
type === 'email'
@@ -207,7 +195,10 @@ export class AuthService {
207195
);
208196

209197
// generate username recommendations for step 3
210-
const recommendations = await this.getRecommendedUsernames(signup_session.name);
198+
const recommendations =
199+
await this.username_service.generateUsernameRecommendationsSingleName(
200+
signup_session.name
201+
);
211202

212203
return {
213204
isVerified: true,
@@ -978,7 +969,8 @@ export class AuthService {
978969
updated_session_data.ttl
979970
);
980971

981-
const recommendations = await this.getRecommendedUsernames(user_data.name);
972+
const recommendations =
973+
await this.username_service.generateUsernameRecommendationsSingleName(user_data.name);
982974

983975
return {
984976
usernames: recommendations,
@@ -1029,4 +1021,22 @@ export class AuthService {
10291021
refresh_token,
10301022
};
10311023
}
1024+
1025+
async confirmPassword(confirm_password_dto: ConfirmPasswordDto, user_id: string) {
1026+
const user = await this.user_repository.findById(user_id);
1027+
1028+
if (!user) throw new NotFoundException(ERROR_MESSAGES.USER_NOT_FOUND);
1029+
1030+
if (user.password) {
1031+
const is_password_valid = await bcrypt.compare(
1032+
confirm_password_dto.password,
1033+
user.password
1034+
);
1035+
if (!is_password_valid) throw new UnauthorizedException(ERROR_MESSAGES.WRONG_PASSWORD);
1036+
} else {
1037+
throw new UnauthorizedException(ERROR_MESSAGES.SOCIAL_LOGIN_REQUIRED);
1038+
}
1039+
1040+
return { valid: true };
1041+
}
10321042
}

src/auth/auth.swagger.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1140,3 +1140,25 @@ export const verify_update_email_swagger = {
11401140
},
11411141
},
11421142
};
1143+
1144+
export const confirm_password_swagger = {
1145+
operation: {
1146+
summary: 'Confirm password',
1147+
description: 'Confirm that the password is valid',
1148+
},
1149+
1150+
responses: {
1151+
success: {
1152+
description: 'Password confirmed successfully',
1153+
schema: {
1154+
example: {
1155+
data: {
1156+
valid: true,
1157+
},
1158+
count: 1,
1159+
message: SUCCESS_MESSAGES.PASSWORD_CONFIRMED,
1160+
},
1161+
},
1162+
},
1163+
},
1164+
};
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { IsNotEmpty, Matches, MaxLength, MinLength } from 'class-validator';
2+
import { ApiProperty } from '@nestjs/swagger';
3+
import { STRING_MAX_LENGTH } from 'src/constants/variables';
4+
5+
export class ConfirmPasswordDto {
6+
@ApiProperty({
7+
description: 'User password',
8+
example: 'Mario0o0o!#$@2252004',
9+
minLength: 8,
10+
})
11+
@IsNotEmpty()
12+
@MinLength(8)
13+
@MaxLength(STRING_MAX_LENGTH)
14+
password: string;
15+
}

src/auth/username.service.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,16 @@ import { UserRepository } from 'src/user/user.repository';
55
export class UsernameService {
66
constructor(private readonly user_repository: UserRepository) {}
77

8+
async generateUsernameRecommendationsSingleName(name: string): Promise<string[]> {
9+
const name_parts = name.split(' ');
10+
const first_name = name_parts[0];
11+
const last_name = name_parts.length > 1 ? name_parts.slice(1).join(' ') : '';
12+
13+
const recommendations = await this.generateUsernameRecommendations(first_name, last_name);
14+
15+
return recommendations;
16+
}
17+
818
async generateUsernameRecommendations(
919
first_name: string,
1020
last_name: string

src/constants/swagger-messages.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,7 @@ export const SUCCESS_MESSAGES = {
134134
USERNAME_UPDATED: 'Username updated successfully',
135135
EMAIL_UPDATE_INITIATED: 'Email update process initiated. Check your new email for verification',
136136
EMAIL_UPDATED: 'Email updated successfully',
137+
PASSWORD_CONFIRMED: 'Password confirmed successfully',
137138

138139
// OAuth completion
139140
BIRTH_DATE_SET: 'Birth date set successfully',
@@ -182,6 +183,7 @@ export const SUCCESS_MESSAGES = {
182183
COVER_DELETED: 'Cover deleted successfully',
183184
INTERESTS_ASSIGNED: 'Interests assigned successfully',
184185
LANGUAGE_CHANGED: 'Language changed successfully',
186+
USERNAME_RECOMMENDATIONS_RETRIEVED: 'Username recommendations retrieved successfully',
185187

186188
// search
187189
SUGGESTIONS_RETRIEVED: 'Search suggestions retrieved successfully',

src/constants/variables.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ export const Y_LOGO_URL = 'https://iili.io/KUhrEyN.png';
22
export const Y_LOGO_HOST_URL = 'https://freeimage.host/';
33

44
export const STRING_MAX_LENGTH = 100;
5-
export const LARGE_MAX_LENGTH = 1500;
5+
export const LARGE_MAX_LENGTH = 3000;
66
export const POST_CONTENT_LENGTH = 280;
77
export const MESSAGE_CONTENT_LENGTH = 300;
88
export const OTP_LENGTH = 6;

src/main.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ async function bootstrap() {
1212
transform: true,
1313
transformOptions: {
1414
exposeDefaultValues: true,
15-
enableImplicitConversion: true,
15+
enableImplicitConversion: true, // should be removed
1616
},
1717
})
1818
);

src/migrations/1730356800000-AddConversationIdToTweets.ts

Lines changed: 0 additions & 51 deletions
This file was deleted.

0 commit comments

Comments
 (0)