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

Ft google auth #187419170 #27

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
14 changes: 14 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
[*]
charset = utf-8
indent_style = space
indent_size = 2
insert_final_newline = true
trim_trailing_whitespace = true
max_line_length = 160

[*.ts]
quote_type = single

[*.md]
max_line_length = off
trim_trailing_whitespace = false
6 changes: 5 additions & 1 deletion .env.example
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
PORT = 3000
DB_CONNECTION = "" --> TODO: put your own connection string here
TEST_DB = ""-->TODO: put your own testing database connection string here
JWT_SECRET = ""-->TODO: put your own jsonwebtoken scret here
JWT_SECRET = ""-->TODO: put your own jsonwebtoken scret here

GOOGLE_CLIENT_ID="" use yours
GOOGLE_CLIENT_SECRET="" use yours
GOOGLE_CALLBACK_URL="" use yours
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
/node_modules
/.env
/package-lock.json
/coverage
/coverage
/.vscode
1 change: 1 addition & 0 deletions .husky/pre-commit
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
npm run test
10 changes: 10 additions & 0 deletions .prettierrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"tabWidth": 2,
"useTabs": false,
"singleQuote": false,
"semi": true,
"bracketSpacing": true,
"arrowParens": "always",
"bracketSameLine": true,
"endOfLine": "auto"
}
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
# eagles-ec-be

<div style="display: flex; justify-content: center;" align="center">

<img src="https://codecov.io/gh/soleil00/eagles-ec-be/branch/dev/graph/badge.svg?token=9c1e8e93-1062-4e49-a58d-b2777a75fb70" alt="Codecov" >
<img alt="GitHub Actions Workflow Status" src="https://img.shields.io/github/actions/workflow/status/atlp-rwanda/eagles-ec-be/deploy.yml" >
<a href="https://codeclimate.com/github/atlp-rwanda/eagles-ec-be/maintainability"><img src="https://api.codeclimate.com/v1/badges/dfe8454356fb9da65407/maintainability" /></a>
<img alt="Static Badge" src="https://img.shields.io/badge/Reviewed_By-HoundCI-blue?style=flat-square">

</div>

Expand Down
16 changes: 14 additions & 2 deletions __test__/home.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,23 @@ describe("Testing Home route", () => {
} catch (error) {
sequelize.close();
}
}, 20000);
}, 40000);

test("servr should return status code of 200 --> given'/'", async () => {
test("server should return status code of 200 --> given'/'", async () => {
const response = await request(app).get("/");

expect(response.status).toBe(200);
}, 40000);
test("server should return status code of 200 and link to log in with google --> given'/login'", async () => {
const response = await request(app).get("/login");
expect(response.text).toBe("<a href='/api/v1/users/login/google'>click to here to Login</a>")

expect(response.status).toBe(200);
}, 20000);
test("server should return status code of 200 and link to log in with google --> given'/login'", async () => {
const response = await request(app).get("/login");
expect(response.text).toBe("<a href='/api/v1/users/login/google'>click to here to Login</a>")

expect(response.status).toBe(200);
}, 20000);
});
118 changes: 74 additions & 44 deletions __test__/user.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,54 +4,67 @@ import app from "../src/utils/server";
import User from "../src/sequelize/models/users";
import * as userServices from "../src/services/user.service";
import sequelize, { connect } from "../src/config/dbConnection";
const userData: any = {
name: "yvanna",
username: "testuser",
email: "[email protected]",
password: "test1234",
};

const userData:any = {
name: 'yvanna',
username: 'testuser',
email: '[email protected]',
password:'test1234',
};
const userTestData = {
newPassword: "Test@123",
confirmPassword: "Test@123",
wrongPassword: "Test456",
};

const loginData:any = {
email:'[email protected]',
password:"test1234"
}
const loginData: any = {
email: "[email protected]",
password: "test1234",
};
describe("Testing user Routes", () => {
beforeAll(async () => {
try {
await connect();
await User.destroy({truncate:true})
await User.destroy({ truncate: true });
} catch (error) {
sequelize.close();
}
}, 20000);
}, 40000);

afterAll(async () => {
afterAll(async () => {
await User.destroy({ truncate: true });
await sequelize.close();
});
describe("Testing user authentication", () => {
test('should return 201 and create a new user when registering successfully', async () => {
const response = await request(app)
.post('/api/v1/users/register')
.send(userData);
expect(response.status).toBe(201); }, 20000);
await sequelize.close();
});
let token: any;
describe("Testing user authentication", () => {
test("should return 201 and create a new user when registering successfully", async () => {
const response = await request(app)
.post("/api/v1/users/register")
.send(userData);
expect(response.status).toBe(201);
}, 20000);

test('should return 409 when registering with an existing email', async () => {
User.create(userData)
const response = await request(app)
.post('/api/v1/users/register')
.send(userData);
expect(response.status).toBe(409); }, 20000);
test("should return 409 when registering with an existing email", async () => {
User.create(userData);
const response = await request(app)
.post("/api/v1/users/register")
.send(userData);
expect(response.status).toBe(409);
}, 20000);

test('should return 400 when registering with an invalid credential', async () => {
const userData = {
email: '[email protected]', name: "", username: 'existinguser', };
const response = await request(app)
.post('/api/v1/users/register')
.send(userData);

expect(response.status).toBe(400); }, 20000); });
test("should return 400 when registering with an invalid credential", async () => {
const userData = {
email: "[email protected]",
name: "",
username: "existinguser",
};
const response = await request(app)
.post("/api/v1/users/register")
.send(userData);

expect(response.status).toBe(400);
}, 20000);
});

test("should return all users in db --> given '/api/v1/users'", async () => {
const spy = jest.spyOn(User, "findAll");
Expand All @@ -60,19 +73,36 @@ test('should return 400 when registering with an invalid credential', async () =
expect(spy).toHaveBeenCalled();
expect(spy2).toHaveBeenCalled();
}, 20000);
test("Should return status 401 to indicate Unauthorized user",async() =>{
const loggedInUser ={
email:userData.email,
password:"test",
test("Should return status 401 to indicate Unauthorized user", async () => {
const loggedInUser = {
email: userData.email,
password: "test",
};
const spyonOne = jest.spyOn(User,"findOne").mockResolvedValueOnce({
const spyonOne = jest.spyOn(User, "findOne").mockResolvedValueOnce({
//@ts-ignore
email:userData.email,
password:loginData.password,
email: userData.email,
password: loginData.password,
});
const response = await request(app).post("/api/v1/users/login")
.send(loggedInUser)
const response = await request(app)
.post("/api/v1/users/login")
.send(loggedInUser);
expect(response.body.status).toBe(401);
spyonOne.mockRestore();
});
})


describe("Testing Google auth", () => {
test('It should return Google login page with redirect status code (302), correct headers,', async () => {
const response = await request(app).get('/api/v1/users/login/google');
expect(response.status).toBe(302);
expect(response.headers).toHaveProperty('location');
}, 20000);

test('Callback endpoint should redirect to success route after successful authentication', async () => {
const response = await request(app).get('/api/v1/users/auth/google/callback');
expect(response.status).toBe(302);
expect(response.header['location']).toContain("redirect_uri");
});

});
51 changes: 51 additions & 0 deletions eslint.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
const eslint = require("@eslint/js");
Copy link

Choose a reason for hiding this comment

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

'const' is available in ES6 (use 'esversion: 6') or Mozilla JS extensions (use moz).

Copy link

Choose a reason for hiding this comment

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

'const' is available in ES6 (use 'esversion: 6') or Mozilla JS extensions (use moz).

Copy link

Choose a reason for hiding this comment

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

'const' is available in ES6 (use 'esversion: 6') or Mozilla JS extensions (use moz).

Copy link

Choose a reason for hiding this comment

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

'const' is available in ES6 (use 'esversion: 6') or Mozilla JS extensions (use moz).

Copy link

Choose a reason for hiding this comment

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

'const' is available in ES6 (use 'esversion: 6') or Mozilla JS extensions (use moz).

const tseslint = require("typescript-eslint");
Copy link

Choose a reason for hiding this comment

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

'const' is available in ES6 (use 'esversion: 6') or Mozilla JS extensions (use moz).

Copy link

Choose a reason for hiding this comment

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

'const' is available in ES6 (use 'esversion: 6') or Mozilla JS extensions (use moz).

Copy link

Choose a reason for hiding this comment

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

'const' is available in ES6 (use 'esversion: 6') or Mozilla JS extensions (use moz).

Copy link

Choose a reason for hiding this comment

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

'const' is available in ES6 (use 'esversion: 6') or Mozilla JS extensions (use moz).

Copy link

Choose a reason for hiding this comment

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

'const' is available in ES6 (use 'esversion: 6') or Mozilla JS extensions (use moz).


module.exports = tseslint.config(
{
ignores: ["**/__test__", "**/*.json"],
},
eslint.configs.recommended,
...tseslint.configs.recommended,
Copy link

Choose a reason for hiding this comment

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

'spread/rest operator' is only available in ES6 (use 'esversion: 6').

Copy link

Choose a reason for hiding this comment

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

'spread/rest operator' is only available in ES6 (use 'esversion: 6').

Copy link

Choose a reason for hiding this comment

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

'spread/rest operator' is only available in ES6 (use 'esversion: 6').

Copy link

Choose a reason for hiding this comment

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

'spread/rest operator' is only available in ES6 (use 'esversion: 6').

Copy link

Choose a reason for hiding this comment

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

'spread/rest operator' is only available in ES6 (use 'esversion: 6').

{
languageOptions: {
parserOptions: {
project: true,
ecmaVersion: 2020,
},
},
},
{
files: ["*.ts", "*.js"],
...tseslint.configs.disableTypeChecked,
Copy link

Choose a reason for hiding this comment

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

Expected ')' and instead saw 'tseslint'.
Expected '}' to match '{' from line 18 and instead saw '...'.
Expected an assignment or function call and instead saw an expression.
Missing semicolon.
Unrecoverable syntax error. (39% scanned).

Copy link

Choose a reason for hiding this comment

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

Expected ')' and instead saw 'tseslint'.
Expected '}' to match '{' from line 18 and instead saw '...'.
Expected an assignment or function call and instead saw an expression.
Missing semicolon.
Unrecoverable syntax error. (39% scanned).

Copy link

Choose a reason for hiding this comment

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

Expected ')' and instead saw 'tseslint'.
Expected '}' to match '{' from line 18 and instead saw '...'.
Expected an assignment or function call and instead saw an expression.
Missing semicolon.
Unrecoverable syntax error. (39% scanned).

Copy link

Choose a reason for hiding this comment

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

Expected ')' and instead saw 'tseslint'.
Expected '}' to match '{' from line 18 and instead saw '...'.
Expected an assignment or function call and instead saw an expression.
Missing semicolon.
Unrecoverable syntax error. (39% scanned).

Copy link

Choose a reason for hiding this comment

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

Expected ')' and instead saw 'tseslint'.
Expected '}' to match '{' from line 18 and instead saw '...'.
Expected an assignment or function call and instead saw an expression.
Missing semicolon.
Unrecoverable syntax error. (39% scanned).

},
Copy link

Choose a reason for hiding this comment

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

Unexpected '}'.

Copy link

Choose a reason for hiding this comment

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

Unexpected '}'.

Copy link

Choose a reason for hiding this comment

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

Unexpected '}'.

Copy link

Choose a reason for hiding this comment

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

Unexpected '}'.

Copy link

Choose a reason for hiding this comment

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

Unexpected '}'.

{
files: ["*.test *.js"],
rules: {
"@typescript-eslint/no-unused-vars": 0,
"@typescript-eslint/no-unsafe-call": 0,
languageOptions: {
globals: {
it: "readonly",
describe: "readonly",
},
},
},
},
{
rules: {
semi: "error",
"@typescript-eslint/no-unused-vars": 2,
"@typescript-eslint/no-explicit-any": 0,
"@typescript-eslint/no-var-requires": 0,
"no-shadow": [2, { allow: ["req", "res", "err"] }],
"new-cap": 0,
"one-var-declaration-per-line": 0,
"consistent-return": 0,
"no-param-reassign": 0,
"comma-dangle": 0,
"no-undef": 0,
curly: ["error", "multi-line"],
},
},
);
9 changes: 9 additions & 0 deletions hound.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
eslint:
enabled: true
file_patterns:
- "*.js"
- "*.ts"
enabled_plugins:
- eslint-plugin-import
- eslint-plugin-prettier
- eslint-plugin:@typescript-eslint
2 changes: 1 addition & 1 deletion index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ app.listen(env.port, async () => {
await sequelize
.sync()
.then(() => {
console.log(` db synced and server is running on port ${env.port}`);
console.log(" db synced and server is running");
})
.catch((error: any) => {
console.log(error.message);
Expand Down
41 changes: 36 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,28 +5,53 @@
"main": "index.ts",
"scripts": {
"start": "",
"pre-commit": "prettier . --write && eslint .",
"lint": "eslint .",
"dev": "nodemon index.ts",
"build": "tsc",
"migrate": "npx sequelize-cli db:migrate",
"unmigrate": "npx sequelize-cli db:migrate:undo",
"seed": "npx sequelize-cli db:seed:all",
"lint": "npx eslint .",
"lint:fix": "npx eslint --fix .",
"test": "cross-env NODE_ENV=test jest --detectOpenHandles --coverage"
"test": "cross-env NODE_ENV=test jest --detectOpenHandles --coverage",
"prepare": "husky",
"prettier": "prettier . --write"
},
"lint-staged": {
".ts": [
"npm run lint:fix"
],
"**/*": "prettier --write"
},
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest",
"prettier"
]
},
"husky": {
"hooks": {
"pre-commit": "npm run lint-staged && npm run test"
}
},
"author": "atlp",
"license": "MIT",
"devDependencies": {
"@eslint/js": "^9.0.0",
"@eslint/js": "^9.1.1",
"@types/bcryptjs": "^2.4.6",
"@types/cors": "^2.8.17",
"@types/dotenv": "^8.2.0",
"@types/express": "^4.17.21",
"@types/express-session": "^1.18.0",
"@types/jest": "^29.5.12",
"@types/jsonwebtoken": "^9.0.6",
"@types/node": "^20.12.7",
"@types/passport": "^1.0.16",
"@types/passport-google-oauth20": "^2.0.14",
"@types/supertest": "^6.0.2",
"@types/swagger-ui-express": "^4.1.6",
"@typescript-eslint/eslint-plugin": "^7.6.0",
"@typescript-eslint/eslint-plugin": "^7.7.1",
"@typescript-eslint/parser": "^7.6.0",
"eslint": "^8.57.0",
"eslint-config-airbnb-base": "^15.0.0",
Expand All @@ -36,6 +61,7 @@
"globals": "^15.0.0",
"jest": "^29.7.0",
"nodemon": "^3.1.0",
"pre-commit": "^1.2.2",
"prettier": "^3.2.5",
"sequelize-cli": "^6.6.2",
"supertest": "^6.3.4",
Expand All @@ -54,8 +80,13 @@
"dotenv": "^16.4.5",
"email-validator": "^2.0.4",
"express": "^4.19.2",
"joi": "^17.12.3",
"husky": "^9.0.11",
"joi": "^17.13.0",
"express-session": "^1.18.0",
"jsonwebtoken": "^9.0.2",
"lint-staged": "^15.2.2",
"passport": "^0.7.0",
"passport-google-oauth20": "^2.0.0",
"path": "^0.12.7",
"pg": "^8.11.5",
"pg-hstore": "^2.3.4",
Expand Down
Loading