Skip to content

Commit

Permalink
Merge branch 'next' into task/OV-5-JWT-token
Browse files Browse the repository at this point in the history
  • Loading branch information
stefano-lacorazza authored Aug 22, 2024
2 parents f07ba3b + 009d04a commit b4fe14c
Show file tree
Hide file tree
Showing 47 changed files with 848 additions and 98 deletions.
46 changes: 43 additions & 3 deletions backend/src/bundles/auth/auth.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,9 @@ class AuthController extends BaseController {

/**
* @swagger
* /auth/sign-up:
* /auth/sign-in:
* post:
* description: Sign up user into the application
* description: Sign in user into the application
* requestBody:
* description: User auth data
* required: true
Expand All @@ -72,7 +72,7 @@ class AuthController extends BaseController {
* password:
* type: string
* responses:
* 201:
* 200:
* description: Successful operation
* content:
* application/json:
Expand All @@ -82,7 +82,15 @@ class AuthController extends BaseController {
* message:
* type: object
* $ref: '#/components/schemas/User'
* 400:
* description: Failed operation
* content:
* application/json:
* schema:
* type: object
* $ref: '#/components/schemas/Error'
*/

private async signIn(
options: ApiHandlerOptions<{
body: UserSignInRequestDto;
Expand All @@ -94,6 +102,38 @@ class AuthController extends BaseController {
};
}

/**
* @swagger
* /auth/sign-up:
* post:
* description: Sign up user into the application
* requestBody:
* description: User auth data
* required: true
* content:
* application/json:
* schema:
* type: object
* properties:
* email:
* type: string
* format: email
* password:
* type: string
* responses:
* 201:
* description: Successful operation
* content:
* application/json:
* schema:
* type: object
* properties:
* message:
* type: object
* $ref: '#/components/schemas/User'
*/


private async signUp(
options: ApiHandlerOptions<{
body: UserSignUpRequestDto;
Expand Down
3 changes: 3 additions & 0 deletions backend/src/bundles/auth/auth.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@ import {
type UserSignInResponseDto,
} from '~/bundles/users/users.js';
import { HttpCode, HttpError } from '~/common/http/http.js';

import { cryptService, tokenService } from '~/common/services/services.js';


import { UserValidationMessage } from './enums/enums.js';

class AuthService {
Expand Down Expand Up @@ -45,6 +47,7 @@ class AuthService {
status: HttpCode.BAD_REQUEST,
});
}

const id = user.toObject().id;
const token = await tokenService.createToken(id);
return { ...user.toObject(), token };
Expand Down
20 changes: 18 additions & 2 deletions backend/src/common/server-application/base-server-app-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,27 @@ class BaseServerAppApi implements ServerAppApi {
definition: {
openapi: '3.0.0',
info: {
title: 'Hello World',
title: 'OutreachVids API documentation',
version: `${this.version}.0.0`,
},
components: {
schemas: {
Error: {
type: 'object',
properties: {
errorType: {
type: 'string',
enum: ['COMMON', 'VALIDATION'],
},
message: {
type: 'string',
},
},
},
},
},
},
apis: [`src/packages/**/*.controller.${controllerExtension}`],
apis: [`src/bundles/**/*.controller.${controllerExtension}`],
});
}
}
Expand Down
3 changes: 3 additions & 0 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,12 @@
"vite": "5.4.0"
},
"dependencies": {
"@chakra-ui/icons": "2.1.1",
"@chakra-ui/react": "2.8.2",
"@emotion/react": "11.13.0",
"@emotion/styled": "11.13.0",
"@fortawesome/free-solid-svg-icons": "6.6.0",
"@fortawesome/react-fontawesome": "0.2.2",
"@reduxjs/toolkit": "2.2.7",
"formik": "2.4.6",
"framer-motion": "11.3.24",
Expand Down
56 changes: 2 additions & 54 deletions frontend/src/app/app.tsx
Original file line number Diff line number Diff line change
@@ -1,61 +1,9 @@
import reactLogo from '~/assets/img/react.svg';
import { Link, RouterOutlet } from '~/bundles/common/components/components.js';
import { AppRoute } from '~/bundles/common/enums/enums.js';
import {
useAppDispatch,
useAppSelector,
useEffect,
useLocation,
} from '~/bundles/common/hooks/hooks.js';
import { actions as userActions } from '~/bundles/users/store/users.js';
import { RouterOutlet } from '~/bundles/common/components/components.js';

const App: React.FC = () => {
const { pathname } = useLocation();
const dispatch = useAppDispatch();
const { users, dataStatus } = useAppSelector(({ users }) => ({
users: users.users,
dataStatus: users.dataStatus,
}));

const isRoot = pathname === AppRoute.ROOT;

useEffect(() => {
if (isRoot) {
void dispatch(userActions.loadAll());
}
}, [isRoot, dispatch]);

return (
<>
<img src={reactLogo} width="30" alt="logo" />

<ul>
<li>
<Link to={AppRoute.ROOT}>Root</Link>
</li>
<li>
<Link to={AppRoute.SIGN_IN}>Sign in</Link>
</li>
<li>
<Link to={AppRoute.SIGN_UP}>Sign up</Link>
</li>
</ul>
<p>Current path: {pathname}</p>

<div>
<RouterOutlet />
</div>
{isRoot && (
<>
<h2>Users:</h2>
<h3>Status: {dataStatus}</h3>
<ul>
{users.map((it) => (
<li key={it.id}>{it.email}</li>
))}
</ul>
</>
)}
<RouterOutlet />
</>
);
};
Expand Down
18 changes: 18 additions & 0 deletions frontend/src/bundles/auth/auth-api.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { ApiPath, ContentType } from '~/bundles/common/enums/enums.js';
import {
type UserSignInRequestDto,
type UserSignInResponseDto,
type UserSignUpRequestDto,
type UserSignUpResponseDto,
} from '~/bundles/users/users.js';
Expand All @@ -20,6 +22,22 @@ class AuthApi extends BaseHttpApi {
super({ path: ApiPath.AUTH, baseUrl, http, storage });
}

public async signIn(
payload: UserSignInRequestDto,
): Promise<UserSignInResponseDto> {
const response = await this.load(
this.getFullEndpoint(AuthApiPath.SIGN_IN, {}),
{
method: 'POST',
contentType: ContentType.JSON,
payload: JSON.stringify(payload),
hasAuth: false,
},
);

return await response.json<UserSignInResponseDto>();
}

public async signUp(
payload: UserSignUpRequestDto,
): Promise<UserSignUpResponseDto> {
Expand Down
3 changes: 3 additions & 0 deletions frontend/src/bundles/auth/components/common/components.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export { FormError } from './form-error/form-error.js';
export { FormHeader } from './form-header/form-header.js';
export { PasswordInput } from './password-input/password-input.js';
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import {
FormControl,
FormErrorMessage,
} from '~/bundles/common/components/components.js';

type Properties = {
isVisible: boolean;
message: string;
};

const FormError: React.FC<Properties> = ({ isVisible, message }) => {
return (
<FormControl isInvalid={isVisible}>
<FormErrorMessage>{message}</FormErrorMessage>
</FormControl>
);
};

export { FormError };
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { Heading, Text } from '~/bundles/common/components/components.js';

type Properties = {
headerText: string;
subheader: React.ReactNode;
};

const FormHeader: React.FC<Properties> = ({ headerText, subheader }) => {
return (
<>
{/* TODO: Add logo */}
<h2 style={{ marginBottom: '50px' }}>LOGO</h2>
<Heading as="h1" color="white" mb="6px" fontSize="30px">
{headerText}
</Heading>
<Text mb="24px" fontSize="14px">
{subheader}
</Text>
</>
);
};

export { FormHeader };
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import {
IconButton,
Input,
InputGroup,
InputRightElement,
ViewIcon,
ViewOffIcon,
} from '~/bundles/common/components/components.js';
import { useCallback, useState } from '~/bundles/common/hooks/hooks.js';

type Properties = {
label: string;
name: string;
hasError: boolean;
};

const PasswordInput: React.FC<Properties> = ({ label, name, hasError }) => {
const [isPasswordVisible, setIsPasswordVisible] = useState<boolean>(false);

const handlePasswordIconClick = useCallback((): void => {
setIsPasswordVisible(
(previousIsPasswordVisible) => !previousIsPasswordVisible,
);
}, []);

return (
<InputGroup size="md">
<Input
type={isPasswordVisible ? 'text' : 'password'}
label={label}
placeholder="••••••••"
name={name}
icon="right"
/>
<InputRightElement top="unset" bottom={hasError ? '25px' : 0}>
<IconButton
aria-label={
isPasswordVisible ? 'Hide password' : 'Show password'
}
icon={isPasswordVisible ? <ViewIcon /> : <ViewOffIcon />}
onClick={handlePasswordIconClick}
variant="ghostIcon"
/>
</InputRightElement>
</InputGroup>
);
};

export { PasswordInput };
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { type UserSignInRequestDto } from '~/bundles/users/users.js';

const DEFAULT_SIGN_IN_PAYLOAD: UserSignInRequestDto = {
email: '',
password: '',
};

export { DEFAULT_SIGN_IN_PAYLOAD };
Loading

0 comments on commit b4fe14c

Please sign in to comment.