typescript(multiplayer-backend): 😁 Fixed the auth route!
typescript(multiplayer-backend): (the login one is still broken) typescript(multiplayer-backend): typescript(multiplayer-backend): Started refactoring the auth and fixing the folder structure! Signed-off-by: prescientmoon <git@moonythm.dev>
This commit is contained in:
parent
3740397789
commit
6fb7143528
2017
typescript/multiplayer-backend/package-lock.json
generated
2017
typescript/multiplayer-backend/package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
@ -18,7 +18,7 @@
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/bcryptjs": "^2.4.2",
|
"@types/bcryptjs": "^2.4.2",
|
||||||
"@types/chalk": "^2.2.0",
|
"@types/chalk": "^2.2.0",
|
||||||
"@types/connect-mongo": "0.0.41",
|
"@types/cors": "^2.8.5",
|
||||||
"@types/dotenv": "^6.1.1",
|
"@types/dotenv": "^6.1.1",
|
||||||
"@types/express": "^4.16.1",
|
"@types/express": "^4.16.1",
|
||||||
"@types/express-session": "^1.15.12",
|
"@types/express-session": "^1.15.12",
|
||||||
|
@ -32,13 +32,10 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"bcryptjs": "^2.4.3",
|
"bcryptjs": "^2.4.3",
|
||||||
"chalk": "^2.4.2",
|
"chalk": "^2.4.2",
|
||||||
"connect-mongo": "^2.0.3",
|
"cors": "^2.8.5",
|
||||||
"dotenv": "^7.0.0",
|
"dotenv": "^7.0.0",
|
||||||
"express": "^4.16.4",
|
"express": "^4.16.4",
|
||||||
"express-session": "^1.16.1",
|
|
||||||
"express-validator": "^5.3.1",
|
"express-validator": "^5.3.1",
|
||||||
"firebase-admin": "^7.2.0",
|
|
||||||
"firestore-store": "^1.0.0",
|
|
||||||
"lodash": "^4.17.11",
|
"lodash": "^4.17.11",
|
||||||
"mongoose": "^5.5.7",
|
"mongoose": "^5.5.7",
|
||||||
"morgan": "^1.9.1",
|
"morgan": "^1.9.1",
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
export * from "./preventGlobalError"
|
|
@ -0,0 +1,15 @@
|
||||||
|
import { Request, Response } from "express";
|
||||||
|
|
||||||
|
export const preventGlobalErrors = (func: (req: Request, res: Response) => any) => {
|
||||||
|
return async (req: Request, res: Response) => {
|
||||||
|
try {
|
||||||
|
await func(req,res)
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
res.json({
|
||||||
|
succes: false,
|
||||||
|
errors: [err]
|
||||||
|
}).status(400)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
export * from "./respond"
|
10
typescript/multiplayer-backend/src/common/respond/respond.ts
Normal file
10
typescript/multiplayer-backend/src/common/respond/respond.ts
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
import { Response } from "express";
|
||||||
|
|
||||||
|
export const respond = (res:Response, succes = true, data: any = {},
|
||||||
|
errors:any[] = [], status = 200) => {
|
||||||
|
res.json({
|
||||||
|
succes,
|
||||||
|
data,
|
||||||
|
errors
|
||||||
|
}).status(status)
|
||||||
|
}
|
|
@ -1,9 +1,10 @@
|
||||||
import * as express from "express"
|
import * as express from "express"
|
||||||
import chalk from "chalk";
|
import chalk from "chalk";
|
||||||
|
import * as cors from "cors"
|
||||||
|
|
||||||
import { staticRoutes } from "../config";
|
import { staticRoutes } from "../config";
|
||||||
import { routes } from "./routes"
|
import { routes } from "./routes"
|
||||||
import { urlencoded } from "body-parser";
|
import { json } from "body-parser";
|
||||||
import { morganChalk } from "./middleware/morgan";
|
import { morganChalk } from "./middleware/morgan";
|
||||||
import { sessionMiddleware } from "./middleware/sessions"
|
import { sessionMiddleware } from "./middleware/sessions"
|
||||||
|
|
||||||
|
@ -18,7 +19,12 @@ export const setupServer = (): Promise<serverSetupResults> =>
|
||||||
//create express app
|
//create express app
|
||||||
const app = express()
|
const app = express()
|
||||||
|
|
||||||
app.use(urlencoded({ extended: true }), morganChalk, sessionMiddleware)
|
app.use(
|
||||||
|
cors(),
|
||||||
|
json(),
|
||||||
|
morganChalk,
|
||||||
|
sessionMiddleware
|
||||||
|
)
|
||||||
|
|
||||||
//load static routes
|
//load static routes
|
||||||
staticRoutes.forEach(route => {
|
staticRoutes.forEach(route => {
|
||||||
|
|
|
@ -1,28 +0,0 @@
|
||||||
import { Request, Response } from "express"
|
|
||||||
import { whiteList } from "../../config"
|
|
||||||
import { includes } from "lodash"
|
|
||||||
|
|
||||||
const urls = whiteList.map(urlObject => urlObject.url)
|
|
||||||
|
|
||||||
//TODO: remove from here
|
|
||||||
const defaultMethods = "GET, POST, OPTIONS, PUT, PATCH, DELETE"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* used to fix the cors errors things
|
|
||||||
* @param url the url to allow
|
|
||||||
* @param methods the methods to allow the url to do
|
|
||||||
*/
|
|
||||||
export const corsErrorFixer = (req: Request, res: Response, next: any) => {
|
|
||||||
const host = req.get("host")
|
|
||||||
const methods: any = whiteList.find(value => value.url == host) || { methods: undefined }
|
|
||||||
|
|
||||||
if (!includes(urls, host))
|
|
||||||
return next()
|
|
||||||
|
|
||||||
res.setHeader('Access-Control-Allow-Origin', host) // Website you wish to allow to connect
|
|
||||||
res.setHeader('Access-Control-Allow-Methods', methods.methods || defaultMethods) //// Request methods you wish to allow
|
|
||||||
res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type') // Request headers you wish to allow
|
|
||||||
|
|
||||||
// Pass to next layer of middleware
|
|
||||||
next();
|
|
||||||
}
|
|
|
@ -12,6 +12,7 @@ const getToken = (req: Request) => {
|
||||||
// Handle token presented as a cookie parameter
|
// Handle token presented as a cookie parameter
|
||||||
return req.cookies.token;
|
return req.cookies.token;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we return null, we couldn't find a token.
|
// If we return null, we couldn't find a token.
|
||||||
// In this case, the JWT middleware will return a 401 (unauthorized) to the client for this request
|
// In this case, the JWT middleware will return a 401 (unauthorized) to the client for this request
|
||||||
return null;
|
return null;
|
||||||
|
@ -60,11 +61,5 @@ export const sessionMiddleware = async (req: Request, res: Response, next: Funct
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
req.session.rainbow = "unicorn"
|
|
||||||
|
|
||||||
//TODO: remove types for express-session
|
|
||||||
//@ts-ignore expects callback
|
|
||||||
req.session.save()
|
|
||||||
|
|
||||||
next()
|
next()
|
||||||
}
|
}
|
|
@ -1,134 +1,66 @@
|
||||||
import { Router, Response, Request } from "express"
|
import { Router, Response, Request } from "express"
|
||||||
import { reddirect } from "../../middleware/reddirect";
|
|
||||||
import * as validator from "express-validator"
|
import * as validator from "express-validator"
|
||||||
import { generateUid, encodePassword } from "../../services/auth/signup";
|
import { generateUid, encodePassword } from "../../services/auth/signup";
|
||||||
import { savePassword } from "../../services/auth/signup";
|
import { savePassword } from "../../services/auth/signup";
|
||||||
import { corsErrorFixer } from "../../middleware/corsErrorMiddleware";
|
|
||||||
import { config } from "dotenv"
|
import { config } from "dotenv"
|
||||||
import { compare } from "bcryptjs";
|
import { compare } from "bcryptjs";
|
||||||
import { User, UserDoc } from "../../models/User";
|
import { User, UserDoc } from "../../models/User";
|
||||||
import { Passsord } from "../../models/Password";
|
import { Passsord } from "../../models/Password";
|
||||||
|
import { preventGlobalErrors } from "../../common/preventGlobalError";
|
||||||
|
import { respond } from "../../common/respond";
|
||||||
|
|
||||||
//extract env variables
|
//extract env variables
|
||||||
config()
|
config()
|
||||||
|
|
||||||
const router = Router()
|
const router = Router()
|
||||||
|
|
||||||
router.get("/test", (req, res) => {
|
const authHandler = preventGlobalErrors(async (req: Request, res: Response) => {
|
||||||
res.send("just a test")
|
|
||||||
})
|
|
||||||
|
|
||||||
const loginHtml = (req: Request, res: Response) => {
|
|
||||||
res.send(`
|
|
||||||
<form action="/auth/login" method=post>
|
|
||||||
<div>
|
|
||||||
<label for=email>email</label>
|
|
||||||
<input type=text id=email name=email>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label for=password>password</label>
|
|
||||||
<input type=password id=password name=password>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label for=name>name</label>
|
|
||||||
<input type=name id=name name=name>
|
|
||||||
</div>
|
|
||||||
<button type=submit>Submit</button>
|
|
||||||
</form>
|
|
||||||
<button onclick="
|
|
||||||
fetch('/',{
|
|
||||||
headers: {
|
|
||||||
authorization: 'do u see this?'
|
|
||||||
}
|
|
||||||
})">send</button>
|
|
||||||
`)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const sayHello = (req: Request, res: Response) => {
|
|
||||||
res.send(`
|
|
||||||
<form action="/auth" method=post>
|
|
||||||
<div>
|
|
||||||
<label for=email>email</label>
|
|
||||||
<input type=text id=email name=email>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label for=password>password</label>
|
|
||||||
<input type=password id=password name=password>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label for=name>name</label>
|
|
||||||
<input type=name id=name name=name>
|
|
||||||
</div>
|
|
||||||
<button type=submit>Submit</button>
|
|
||||||
</form>
|
|
||||||
`)
|
|
||||||
}
|
|
||||||
|
|
||||||
const authHandler = async (req: Request, res: Response) => {
|
|
||||||
try {
|
|
||||||
//if already logged in return the uid
|
//if already logged in return the uid
|
||||||
if (req.session.uid)
|
if (req.session.uid)
|
||||||
return res.redirect("auth/account")
|
return respond(res, true, { uid: req.session.uid })
|
||||||
|
|
||||||
//get data from body
|
//get data from body
|
||||||
const { password, email, name } = req.body
|
const { password, email, name } = req.body
|
||||||
|
|
||||||
//check if the email isnt used
|
//check if the email isnt used
|
||||||
if (await User.findOne({ name }))
|
if (await User.findOne({ email }))
|
||||||
res.redirect("login")
|
return respond(res, false, { email }, ["email is already used"], 400)
|
||||||
|
|
||||||
//validate
|
//validate
|
||||||
req.check("email", "email isnt valid").isEmail()
|
req.check("email", "email isnt valid").isEmail()
|
||||||
const errors = req.validationErrors()
|
const errors = req.validationErrors() as any[]
|
||||||
|
|
||||||
if (errors)
|
if (errors)
|
||||||
res.json({ error: `${req.body.email} is not a valid email` })
|
return respond(res, false, {}, errors, 400)
|
||||||
|
|
||||||
//generate an uid
|
//generate an uid
|
||||||
const uid = await generateUid()
|
const uid = await generateUid()
|
||||||
|
|
||||||
const user = new User({
|
const user = new User({
|
||||||
email,
|
email, name, uid,
|
||||||
friends: [],
|
friends: [],
|
||||||
name,
|
photo: process.env.DEFAULTPROFILEPIC
|
||||||
photo: process.env.DEFAULTPROFILEPIC,
|
|
||||||
uid
|
|
||||||
} as UserDoc) //used for my editor to help me
|
} as UserDoc) //used for my editor to help me
|
||||||
|
|
||||||
encodePassword(password)
|
//save things in session
|
||||||
|
req.session.uid = uid
|
||||||
|
req.session.save(() => { })
|
||||||
|
|
||||||
//save the password and the user in the db
|
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
encodePassword(password).then(result => savePassword(uid, result)),
|
encodePassword(password).then(result => savePassword(uid, result)),
|
||||||
user.save()
|
user.save()
|
||||||
])
|
])
|
||||||
|
|
||||||
//save things in session
|
|
||||||
req.session.uid = uid
|
|
||||||
|
|
||||||
//save in the session
|
|
||||||
req.session.save(() => { })
|
|
||||||
|
|
||||||
//send uid back
|
//send uid back
|
||||||
res.json({
|
return respond(res,true,{ uid })
|
||||||
succes: true,
|
})
|
||||||
data: {
|
|
||||||
uid
|
|
||||||
}
|
|
||||||
}).status(200)
|
|
||||||
}
|
|
||||||
catch (errors) {
|
|
||||||
//send erros to clinet
|
|
||||||
res.json({ errors })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const account = async (req: Request, res: Response) => {
|
const account = async (req: Request, res: Response) => {
|
||||||
try {
|
try {
|
||||||
if (!req.session.uid)
|
if (!req.session.uid)
|
||||||
res.json({
|
res.json({
|
||||||
succes: false,
|
succes: false,
|
||||||
|
data: {},
|
||||||
errors: ["uid doesnt exist"]
|
errors: ["uid doesnt exist"]
|
||||||
}).status(203)
|
}).status(203)
|
||||||
|
|
||||||
|
@ -139,9 +71,9 @@ const account = async (req: Request, res: Response) => {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
catch (errors) {
|
catch (err) {
|
||||||
//send erros to clinet
|
//send erros to clinet
|
||||||
res.json({ errors })
|
res.json({ succes: false, errors: [err] })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -202,12 +134,10 @@ const logout = async (req: Request, res: Response) => {
|
||||||
res.send({ succes: true })
|
res.send({ succes: true })
|
||||||
}
|
}
|
||||||
|
|
||||||
router.use("*", validator(), corsErrorFixer)
|
router.use("*", validator())
|
||||||
|
|
||||||
router
|
router
|
||||||
.get("/", sayHello)
|
|
||||||
.post("/", authHandler)
|
.post("/", authHandler)
|
||||||
.get("/login", loginHtml)
|
|
||||||
.post("/login", login)
|
.post("/login", login)
|
||||||
.get("/account", account)
|
.get("/account", account)
|
||||||
.get("/logout", logout)
|
.get("/logout", logout)
|
||||||
|
@ -218,6 +148,4 @@ router
|
||||||
res.send(await generateUid())
|
res.send(await generateUid())
|
||||||
})
|
})
|
||||||
|
|
||||||
router.use("/*", reddirect("/auth"))
|
|
||||||
|
|
||||||
export const auth = router
|
export const auth = router
|
|
@ -1,7 +1,6 @@
|
||||||
import * as bcrypt from "bcryptjs"
|
import * as bcrypt from "bcryptjs"
|
||||||
import { promisify } from "util";
|
import { promisify } from "util";
|
||||||
import { randomBytes } from "crypto";
|
import { randomBytes } from "crypto";
|
||||||
import { database } from "../db/firestore";
|
|
||||||
import { Passsord, PasswordDoc } from "../../models/Password";
|
import { Passsord, PasswordDoc } from "../../models/Password";
|
||||||
import { User } from "../../models/User";
|
import { User } from "../../models/User";
|
||||||
|
|
||||||
|
@ -38,8 +37,9 @@ export function savePassword(uid: string, password: string) {
|
||||||
|
|
||||||
export async function getPassword(uid: string) {
|
export async function getPassword(uid: string) {
|
||||||
//get doc
|
//get doc
|
||||||
const doc = await database.doc(`passwords/${uid}`).get()
|
// const doc = await database.doc(`passwords/${uid}`).get()
|
||||||
|
|
||||||
//return result
|
//return result
|
||||||
return doc.data()
|
// return doc.data()
|
||||||
|
return "train"
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +0,0 @@
|
||||||
import * as admin from "firebase-admin"
|
|
||||||
|
|
||||||
export const firebase = admin.initializeApp({
|
|
||||||
credential: admin.credential.cert('firebase-admin.json'),
|
|
||||||
databaseURL: 'https://planets-io.firebaseio.com'
|
|
||||||
});
|
|
||||||
|
|
||||||
export const database = firebase.firestore()
|
|
Loading…
Reference in a new issue