Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OV-3: add sign up flow #30

Merged
merged 25 commits into from
Aug 28, 2024
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
c51398a
OV-3: + name column to users table, with mods into model and user ser…
JPjok3r Aug 19, 2024
9a3a62b
OV-3: * user repository, validations from shared
JPjok3r Aug 19, 2024
b881101
OV-3: - name from existing migration file, + name to users table in d…
JPjok3r Aug 20, 2024
09d597d
OV-3: - lint and prettier errors
JPjok3r Aug 20, 2024
b4dfe2b
OV-3: * fix lint errors, * drop field and not table in last migration…
JPjok3r Aug 20, 2024
eca26b8
OV-3: * user validation messages and user validation schema
JPjok3r Aug 21, 2024
6fe3503
OV-3: * changing name to fullName
JPjok3r Aug 21, 2024
53c0a6a
OV-3: * applying lint format
JPjok3r Aug 21, 2024
56d664e
OV-3: * validation rules
JPjok3r Aug 22, 2024
25d2f9e
OV-3: * validation messages
JPjok3r Aug 22, 2024
58895f3
OV-3: * validation messages
JPjok3r Aug 22, 2024
375b4f0
OV-3: * lint format
JPjok3r Aug 22, 2024
de12058
OV-3: * fullName in auth controller
JPjok3r Aug 22, 2024
a628e34
OV-3: * solve merge conficts
JPjok3r Aug 23, 2024
82d819d
OV-3: * validations
JPjok3r Aug 23, 2024
bef91bb
OV-3: * merge conflicts
JPjok3r Aug 23, 2024
3a962ad
OV-3: * solve merge conficts
JPjok3r Aug 24, 2024
0584350
Merge remote-tracking branch 'origin/next' into task/OV-3-add-sign-up…
JPjok3r Aug 24, 2024
59e9a0a
OV-3: - merge conflict solved
JPjok3r Aug 24, 2024
0bdf6b5
OV-3: * lint and prettier
JPjok3r Aug 24, 2024
afaea06
OV-3: * name to fullName
JPjok3r Aug 27, 2024
2ab3912
OV-3: * name to fullName
JPjok3r Aug 27, 2024
d3ac3eb
OV-3: * name to fullName
JPjok3r Aug 27, 2024
b5cdb0d
Merge branch 'origin/next' into task/OV-3-add-sign-up-flow
JPjok3r Aug 27, 2024
b8c0ee2
OV-3: * name to fullName, solve merge conflicts
JPjok3r Aug 27, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions backend/src/bundles/auth/auth.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ class AuthController extends BaseController {
* format: email
* password:
* type: string
* name:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also change it to full name here

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks Anton, it's done.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks like not resolved

* type: string
* responses:
* 201:
* description: Successful operation
Expand Down
15 changes: 15 additions & 0 deletions backend/src/bundles/users/user.entity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,58 +5,69 @@ class UserEntity implements Entity {

private 'email': string;

private 'name': string;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in design looks like we have Full Name


private 'passwordHash': string;

private 'passwordSalt': string;

private constructor({
id,
email,
name,
passwordHash,
passwordSalt,
}: {
id: number | null;
email: string;
name: string;
passwordHash: string;
passwordSalt: string;
}) {
this.id = id;
this.email = email;
this.name = name;
this.passwordHash = passwordHash;
this.passwordSalt = passwordSalt;
}

public static initialize({
id,
email,
name,
passwordHash,
passwordSalt,
}: {
id: number;
email: string;
name: string;
passwordHash: string;
passwordSalt: string;
}): UserEntity {
return new UserEntity({
id,
email,
name,
passwordHash,
passwordSalt,
});
}

public static initializeNew({
email,
name,
passwordHash,
passwordSalt,
}: {
email: string;
name: string;
passwordHash: string;
passwordSalt: string;
}): UserEntity {
return new UserEntity({
id: null,
email,
name,
passwordHash,
passwordSalt,
});
Expand All @@ -65,20 +76,24 @@ class UserEntity implements Entity {
public toObject(): {
id: number;
email: string;
name: string;
} {
return {
id: this.id as number,
email: this.email,
name: this.name,
};
}

public toNewObject(): {
email: string;
name: string;
passwordHash: string;
passwordSalt: string;
} {
return {
email: this.email,
name: this.name,
passwordHash: this.passwordHash,
passwordSalt: this.passwordSalt,
};
Expand Down
2 changes: 2 additions & 0 deletions backend/src/bundles/users/user.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import {
class UserModel extends AbstractModel {
public 'email': string;

public 'name': string;

public 'passwordHash': string;

public 'passwordSalt': string;
Expand Down
4 changes: 3 additions & 1 deletion backend/src/bundles/users/user.repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,14 @@ class UserRepository implements Repository {
}

public async create(entity: UserEntity): Promise<UserEntity> {
const { email, passwordSalt, passwordHash } = entity.toNewObject();
const { email, name, passwordSalt, passwordHash } =
entity.toNewObject();

const item = await this.userModel
.query()
.insert({
email,
name,
passwordSalt,
passwordHash,
})
Expand Down
5 changes: 3 additions & 2 deletions backend/src/bundles/users/user.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,9 @@ class UserService implements Service {
const user = await this.userRepository.create(
UserEntity.initializeNew({
email: payload.email,
passwordSalt: salt, // TODO
passwordHash: hash, // TODO
name: payload.name,
passwordSalt: salt,
passwordHash: hash,
}),
);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { type Knex } from 'knex';

const TABLE_NAME = 'users';

async function up(knex: Knex): Promise<void> {
await knex.schema.table(TABLE_NAME, (table) => {
table.string('name').notNullable();
});
}

async function down(knex: Knex): Promise<void> {
await knex.schema.table(TABLE_NAME, (table) => {
table.dropColumn('name');
});
}

export { down, up };
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import { type UserSignUpRequestDto } from '~/bundles/users/users.js';

const DEFAULT_SIGN_UP_PAYLOAD: UserSignUpRequestDto = {
name: '',
email: '',
password: '',
confirmPassword: '',
};

export { DEFAULT_SIGN_UP_PAYLOAD };
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
const UserValidationMessage = {
EMAIL_REQUIRE: 'Email is required',
EMAIL_WRONG: 'Email is wrong',
FIELD_IS_REQUIRE: 'Please fill out this field',
EMAIL_WRONG: 'Please enter a valid email',
PASS_DONT_MATCH: 'Passwords must be identical',
PASS_WRONG: 'Password must have from 6 to 12 characters',
USER_IS_NOT_AVAILABLE:
'User with this email already exists. Log in if it is you',
} as const;

export { UserValidationMessage };
3 changes: 3 additions & 0 deletions shared/src/bundles/users/enums/user-validation-rule.enum.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
const UserValidationRule = {
EMAIL_MINIMUM_LENGTH: 1,
EMAIL_MAXIMUM_LENGTH: 320,
PASSWORD_MINIMUM_LENGTH: 6,
PASSWORD_MAXIMUM_LENGTH: 12,
} as const;

export { UserValidationRule };
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
type UserSignUpRequestDto = {
name: string;
email: string;
password: string;
confirmPassword: string;
};

export { type UserSignUpRequestDto };
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
type UserSignUpResponseDto = {
id: number;
name: string;
email: string;
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,50 @@ import { z } from 'zod';
import { UserValidationMessage, UserValidationRule } from '../enums/enums.js';

type UserSignUpRequestValidationDto = {
name: z.ZodString;
email: z.ZodString;
password: z.ZodString;
confirmPassword: z.ZodString;
};

const userSignUp = z
.object<UserSignUpRequestValidationDto>({
name: z.string().trim(),
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should validate, that name have at least 2 words

email: z
.string()
.trim()
.min(UserValidationRule.EMAIL_MINIMUM_LENGTH, {
message: UserValidationMessage.EMAIL_REQUIRE,
message: UserValidationMessage.EMAIL_WRONG,
})
.max(UserValidationRule.EMAIL_MAXIMUM_LENGTH, {
message: UserValidationMessage.EMAIL_WRONG,
})
.email({
message: UserValidationMessage.EMAIL_WRONG,
}),
password: z.string().trim(),
password: z
.string()
.trim()
.min(UserValidationRule.PASSWORD_MINIMUM_LENGTH, {
message: UserValidationMessage.PASS_WRONG,
})
.max(UserValidationRule.PASSWORD_MAXIMUM_LENGTH, {
message: UserValidationMessage.PASS_WRONG,
}),
confirmPassword: z
.string()
.trim()
.min(UserValidationRule.PASSWORD_MINIMUM_LENGTH, {
message: UserValidationMessage.PASS_WRONG,
})
.max(UserValidationRule.PASSWORD_MAXIMUM_LENGTH, {
message: UserValidationMessage.PASS_WRONG,
}),
})
.required();
.required()
.refine((data) => data.password === data.confirmPassword, {
message: UserValidationMessage.PASS_DONT_MATCH,
path: ['confirmPassword'],
});

export { userSignUp };
Loading