Skip to content

Commit

Permalink
Merge pull request #603 from hackforla/update-validation-schemas
Browse files Browse the repository at this point in the history
Update validation schemas
  • Loading branch information
erikguntner authored Apr 18, 2024
2 parents e0100a9 + 9629608 commit cc4c495
Show file tree
Hide file tree
Showing 5 changed files with 40 additions and 57 deletions.
38 changes: 10 additions & 28 deletions api/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

## Overview

This is the *Home Unite Us* web API server.
This is the _Home Unite Us_ web API server.

This server uses the [Connexion](https://github.com/zalando/connexion) framework on top of Flask.

Expand All @@ -24,12 +24,12 @@ Run `python -V` to check the Python version.

The API application configuration must be specified before running the application. Configuration variables can be specified either as environment variables, or as entries within a `.env` file located within the `api` directory. To get started, copy the values from one of these configurations into a `.env` file:

* `.env.dev.example`
* [Recommended] This is the easiest configuration to use. It enables debugging, and mocks third party API calls so no secrets are needed to run the API.
* `.env.staging.example`
* This configuration strips all mocking from the application, but allows debugging and other testing related features.
* `.env.prod.example`
* This configuration strips all mocking and strictly validates the configuration to ensure that debugging is disabled and that the deployment is production-ready.
- `.env.dev.example`
- [Recommended] This is the easiest configuration to use. It enables debugging, and mocks third party API calls so no secrets are needed to run the API.
- `.env.staging.example`
- This configuration strips all mocking from the application, but allows debugging and other testing related features.
- `.env.prod.example`
- This configuration strips all mocking and strictly validates the configuration to ensure that debugging is disabled and that the deployment is production-ready.

Using the `staging` or `production` configurations will require access to deployment secrets. If access to these secrets are needed to test a feature locally then you can request the secrets in the HUU slack channel.

Expand Down Expand Up @@ -92,8 +92,8 @@ Core dependencies of this project are listed in `pyproject.toml` under the `[pro

To aid in testing and building a reproducible, predictable, and deterministic API, this project also includes auto-generated requirements files that contains a list of all core and transitive dependencies with pinned versions. These files are:

* `requirements.txt` for a base set dependencies
* `requirements-dev.txt` that also includes developer dependencies
- `requirements.txt` for a base set dependencies
- `requirements-dev.txt` that also includes developer dependencies

Developers will use `pip install -r requirements-dev.txt` in their own Python virtual environment when working on this API.

Expand Down Expand Up @@ -196,26 +196,8 @@ docker exec `docker ps -qf "ancestor=homeuniteus-api"` pytest

Debugging is enabled when using the `development` configuration. It can also be enabled on the `staging` configuration by setting the `FLASK_DEBUG` environment variable to `True`, or adding a `FLASK_DEBUG=True` to your local `.env` file. When debugging is enabled, the API server will automatically reload each time you save a change to the source code.

For Visual Studio Code users:

* Set breakpoint(s).
* Add the following config below to your `/.vscode/launch.json` configuration.

```json
{
"name": "Openapi_server module",
"type": "python",
"request": "launch",
"module": "openapi_server",
"justMyCode": false,
"cwd": "${workspaceFolder}/api"
}
```

With this configuration selecting "Run" -> "Start with Debugging" will start the API with the debugger enabled.

## Usage - Production

A WSGI server is needed to run our application. A WSGI (Web Server Gateway Interface) server is a bridge between a web server and web applications. The server handles requests, invokes the web application, translates responses back to HTTP, and also manages concurrency to ensure the server can handle multiple requests simultaneously.

While Flask does provide a built-in development server, it is not intended for production use. Therefore, we utilize a third-party, production-grade WSGI server to manage our application. Various options exist, but we've chosen `gunicorn`. `gunicorn` does not support Windows, but you can use another WSGI server like `waitress` if Windows support is needed.
Expand Down
17 changes: 1 addition & 16 deletions app/src/components/authentication/SignInForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,22 +21,7 @@ interface SignInFormProps {

const validationSchema = object({
email: string().email().required('email is required'),
password: string()
.required('password is required')
.matches(/^(?=.*[0-9])/, 'password must contain at least one number')
.min(8, 'password must be at least 8 characters')
.matches(
/^(?=.*[a-z])/,
'password must contain at least one lowercase character',
)
.matches(
/^(?=.*[A-Z])/,
'password must contain at least one uppercase character',
)
.matches(
/^(?=.*[!@#%&])/,
'password must contain at least one special character',
),
password: string().required('password is required'),
});

export const SignInForm = ({
Expand Down
11 changes: 0 additions & 11 deletions app/src/components/authentication/__tests__/SignInForm.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,15 +39,4 @@ describe('<SignInForm />', () => {
expect(emailInput).toHaveValue('[email protected]');
expect(passwordInput).toHaveValue('password');
});

it('should display error text', async () => {
const {emailInput, passwordInput, submitButton} = prepare();

fireEvent.change(emailInput, {target: {value: 'invalid'}});
fireEvent.change(passwordInput, {target: {value: 'password'}});
fireEvent.click(submitButton);

await screen.findByText('email must be a valid email');
await screen.findByText(/password must contain/i);
});
});
29 changes: 28 additions & 1 deletion app/src/components/authentication/__tests__/SignUpForm.test.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {BrowserRouter} from 'react-router-dom';
import {describe, vi} from 'vitest';
import {render, screen, userEvent} from '../../../utils/test/test-utils';
import {render, screen, userEvent, fireEvent} from '../../../utils/test/test-utils';
import {SignUpForm, SignUpFormProps} from '../SignUpForm';
import {faker} from '@faker-js/faker';

Expand Down Expand Up @@ -38,6 +38,33 @@ const prepare = (initialProps: Partial<SignUpFormProps> = {}) => {
};

describe('<SignUpForm />', () => {
// what it should render
it('should render', () => {
const {emailInput, passwordInput} = prepare();
expect(emailInput).toBeInTheDocument();
expect(passwordInput).toBeInTheDocument();
});

// when correct special characters are added, it should pass validation form
it('should pass password validation form with correct special characters', () => {
const {passwordInput, submitButton} = prepare();
fireEvent.change(passwordInput, {target: {value: 'Test123!'}});
expect(submitButton).not.toBeDisabled;
});

// when special character not valid, password validation should be present
it('should display error text when special character not present', () => {
const {passwordInput, submitButton} = prepare();
fireEvent.change(passwordInput, {target: {value: 'test123'}});
expect(submitButton).toBeDisabled;
});

// test for unusual special characters
it('should pass password validation form with unusual special characters', () => {
const {passwordInput, submitButton} = prepare();
fireEvent.change(passwordInput, {target: {value: '7væVPj¼±mó5÷ÙÞW'}});
expect(submitButton).not.toBeDisabled;
});
it('submits all necessary information', async () => {
const user = {
firstName: faker.person.firstName(),
Expand Down
2 changes: 1 addition & 1 deletion app/src/utils/PasswordValidationSchema.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export const validationSchema = object().shape({
.matches(/^(?=.*[A-Z])/, {
message: {uppercase: 'Must contain at least one uppercase character'},
})
.matches(/\W|_/g, {
.matches(/\W|_/, {
message: {
// add specificity into message
special: 'password must contain at least one special character',
Expand Down

0 comments on commit cc4c495

Please sign in to comment.