Skip to content

Commit d89c63c

Browse files
committed
docker init
1 parent 717af05 commit d89c63c

14 files changed

Lines changed: 8224 additions & 0 deletions

File tree

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
node_modules
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
FROM node:16
2+
WORKDIR /app
3+
COPY . .
4+
RUN npm install
5+
EXPOSE 5000
6+
ENTRYPOINT ["node", "./src/app.js"]

examples_new/docker/auth/package-lock.json

Lines changed: 7661 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
{
2+
"name": "auth",
3+
"version": "1.0.0",
4+
"description": "",
5+
"main": "index.js",
6+
"scripts": {
7+
"start": "ts-node-dev ./src/index.ts",
8+
"test": "jest --watchAll --no-cache"
9+
},
10+
"jest": {
11+
"preset": "ts-jest",
12+
"testEnvironment": "node",
13+
"setupFilesAfterEnv": [
14+
"./src/test/setup.ts"
15+
]
16+
},
17+
"keywords": [],
18+
"author": "",
19+
"license": "ISC",
20+
"dependencies": {
21+
"@chronosmicro/tracker": "^12.0.2",
22+
"@chronosrx/common": "^1.0.4",
23+
"axios": "^1.6.2",
24+
"bcryptjs": "^2.4.3",
25+
"cookie-parser": "^1.4.6",
26+
"cors": "^2.8.5",
27+
"dotenv": "^16.3.1",
28+
"express": "^4.18.2",
29+
"express-async-errors": "^3.1.1",
30+
"jsonwebtoken": "^9.0.2",
31+
"mongoose": "^8.0.3",
32+
"ts-node-dev": "^2.0.0"
33+
},
34+
"devDependencies": {
35+
"@types/bcryptjs": "^2.4.6",
36+
"@types/cookie-parser": "^1.4.6",
37+
"@types/cors": "^2.8.17",
38+
"@types/express": "^4.17.21",
39+
"@types/jest": "^29.5.11",
40+
"@types/jsonwebtoken": "^9.0.5",
41+
"@types/supertest": "^2.0.16",
42+
"jest": "^29.7.0",
43+
"mongodb-memory-server": "^9.1.1",
44+
"supertest": "^6.3.3",
45+
"ts-jest": "^29.1.1"
46+
}
47+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import path from 'path';
2+
import express from 'express';
3+
import 'express-async-errors';
4+
// import dotenv from 'dotenv';
5+
// dotenv.config({ path: path.resolve(__dirname + '../../.env') });
6+
import { NotFoundError, errorHandler } from '@chronosrx/common';
7+
import authRouter from './routes/auth-router';
8+
import eventRouter from './routes/event-router';
9+
import cookieParser from 'cookie-parser';
10+
import cors from 'cors';
11+
12+
import chronosConfig from './chronos-config';
13+
const Chronos = require('@chronosmicro/tracker');
14+
const chronos = new Chronos(chronosConfig);
15+
chronos.propagate();
16+
17+
const app = express();
18+
19+
const trackingMiddleware = chronos.track();
20+
app.use(trackingMiddleware);
21+
22+
app.use(
23+
cors({
24+
credentials: true,
25+
origin: 'http://localhost:5000',
26+
})
27+
);
28+
app.use(express.json());
29+
app.use(cookieParser());
30+
31+
// app.get('/', (req, res) => {
32+
// console.log('💥 Test Route');
33+
// res.status(200).send({ msg: '💥 Test route' });
34+
// });
35+
36+
app.use('/api/auth', authRouter);
37+
app.use('/events', eventRouter);
38+
39+
app.use('*', (req, res) => {
40+
throw new NotFoundError();
41+
});
42+
43+
app.use(errorHandler);
44+
45+
export { app };
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
const path = require('path');
2+
require('dotenv').config({
3+
path: path.resolve(__dirname, '../../.env'),
4+
});
5+
6+
const chronosConfig = {
7+
// General configuration
8+
microservice: 'auth',
9+
interval: 5000,
10+
11+
// Mode Specific
12+
mode: 'microservices',
13+
dockerized: false,
14+
15+
database: {
16+
connection: 'REST',
17+
type: process.env.CHRONOS_DB,
18+
URI: process.env.CHRONOS_URI,
19+
},
20+
21+
notifications: [],
22+
};
23+
export default chronosConfig;
Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
import { Request, Response } from 'express';
2+
import axios, { AxiosError } from 'axios';
3+
import { BadRequestError, CurrentUserRequest, EventTypes, Events } from '@chronosrx/common';
4+
import { User } from '../models/user';
5+
import { attachCookie } from '../util/attachCookie';
6+
7+
export const signup = async (req: Request, res: Response) => {
8+
// console.log('💥 authController signup');
9+
const { username, password } = req.body;
10+
11+
// Validate inputs
12+
if (!username || !password || password.length < 4) {
13+
throw new BadRequestError('Invalid inputs');
14+
}
15+
16+
// Check to see if user with supplied username already exists
17+
const existingUser = await User.findOne({ username });
18+
if (existingUser) {
19+
throw new BadRequestError('User with that username exists');
20+
}
21+
22+
// create the user document
23+
const newUser = User.build({
24+
username,
25+
password,
26+
});
27+
// save newly created user document to the database
28+
await newUser.save();
29+
30+
// TODO PUBLISH AN EVENT TO THE EVENT BUS - type USER_CREATED, with data of user - user.id & username
31+
// console.log('Publishing event USER_CREATED');
32+
33+
const event: Events = {
34+
type: EventTypes.USER_CREATED,
35+
payload: {
36+
id: newUser.id,
37+
username: newUser.username,
38+
},
39+
};
40+
try {
41+
await axios.post('http://localhost:3005/', {
42+
event,
43+
});
44+
} catch (err) {
45+
console.log(
46+
`Failed to emit event USER_CREATED from auth: ${
47+
(err as AxiosError).message || 'unknown error'
48+
} `
49+
);
50+
}
51+
52+
// create a JWT w/ userId store on it
53+
// note: createJwt method created on the userSchema
54+
const token = newUser.createJwt();
55+
// set cookie on response object with name 'token' and value of the jwt
56+
// attachCookie method - defined in util folder
57+
attachCookie(res, token);
58+
59+
//
60+
res.status(201).send(newUser);
61+
};
62+
63+
export const login = async (req: Request, res: Response) => {
64+
// console.log('💥 authController login');
65+
// pull username and password off request body
66+
const { username, password } = req.body;
67+
// validate username and password - they exist
68+
if (!username || !password) {
69+
throw new BadRequestError('Must provide username and password');
70+
}
71+
// query database for user with that username
72+
const existingUser = await User.findOne({ username });
73+
// handle case where no user exists with that username
74+
if (!existingUser) {
75+
throw new BadRequestError('Invalid credentials');
76+
}
77+
78+
// if user does exist - compare provided password to user's password in DB
79+
// * we defined a comparePassword method on the userSchema -> accepts provided password as argument
80+
// handle case when passwords do not match
81+
const passwordsMatch = await existingUser.comparePassword(password);
82+
if (!passwordsMatch) {
83+
throw new BadRequestError('Invalid credentials');
84+
}
85+
86+
// if passwords do match - create a JWT
87+
// * we created a method createJwt on the userSchema that returns the jwt (aka token)
88+
const token = existingUser.createJwt();
89+
// attach the jwt to the cookie
90+
// * we defined an attachCookie helper function (in util folder) - is already imported for us
91+
// accepts the response object and jwt/token as arguments
92+
attachCookie(res, token);
93+
// send back the found user with status code 200
94+
res.status(200).send(existingUser);
95+
};
96+
97+
export const logout = async (req: Request, res: Response) => {
98+
// console.log('💥 authController logout');
99+
100+
// Set cookie on response object with name 'token' to null
101+
// make the cookie httpOnly
102+
// set cookie expiration to 500ms from now
103+
res.cookie('token', null, {
104+
httpOnly: true,
105+
secure: false,
106+
expires: new Date(Date.now() + 500),
107+
});
108+
109+
res.status(200).send({ message: 'success' });
110+
};
111+
112+
export const getCurrentUser = async (req: CurrentUserRequest, res: Response) => {
113+
// check request object for currentUser property
114+
if (!req.currentUser) {
115+
// if it doesn't exist send back status 200 with object with currentUser property set to null
116+
return res.status(200).send({ currentUser: null });
117+
}
118+
119+
// if it does exist - use req.currentUser to find user in database by id
120+
const user = await User.findById(req.currentUser);
121+
// send back 200 with object with property currentUser set to the user from the database
122+
res.status(200).send({ currentUser: user });
123+
};
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import { DbConnectionError } from '@chronosrx/common';
2+
import { app } from './app';
3+
import mongoose from 'mongoose';
4+
import { User } from './models/user';
5+
import path from 'path';
6+
import dotenv from 'dotenv';
7+
dotenv.config({ path: path.resolve(__dirname + '../../.env') });
8+
9+
const PORT = 3000;
10+
11+
const start = async () => {
12+
if (!process.env.MONGO_URI_AUTH) throw new Error('MONGO_URI_AUTH must be defined');
13+
if (!process.env.JWT_KEY) throw new Error('JWT_KEY must be defined');
14+
if (!process.env.JWT_LIFETIME) throw new Error('JWT_LIFETIME must be defined');
15+
16+
try {
17+
await mongoose.connect(process.env.MONGO_URI_AUTH, {});
18+
console.log('🍃 Connected to MongoDB');
19+
20+
await User.deleteMany();
21+
const testUser = User.build({
22+
username: 'ScrumLord',
23+
password: 'McKenzie',
24+
});
25+
await testUser.save();
26+
} catch (err) {
27+
throw new DbConnectionError();
28+
}
29+
30+
app.listen(PORT, async () => {
31+
console.log(`💥 Auth listening on ${PORT}`);
32+
});
33+
};
34+
35+
start();

0 commit comments

Comments
 (0)