1
Fork 0

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:
Matei Adriel 2019-05-20 17:43:59 +03:00 committed by prescientmoon
parent 3740397789
commit 6fb7143528
Signed by: prescientmoon
SSH key fingerprint: SHA256:UUF9JT2s8Xfyv76b8ZuVL7XrmimH4o49p4b+iexbVH4
12 changed files with 140 additions and 2132 deletions

File diff suppressed because it is too large Load diff

View file

@ -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",

View file

@ -0,0 +1 @@
export * from "./preventGlobalError"

View file

@ -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)
}
}
}

View file

@ -0,0 +1 @@
export * from "./respond"

View 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)
}

View file

@ -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 => {

View file

@ -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();
}

View file

@ -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()
} }

View file

@ -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") //if already logged in return the uid
if (req.session.uid)
return respond(res, true, { uid: req.session.uid })
//get data from body
const { password, email, name } = req.body
//check if the email isnt used
if (await User.findOne({ email }))
return respond(res, false, { email }, ["email is already used"], 400)
//validate
req.check("email", "email isnt valid").isEmail()
const errors = req.validationErrors() as any[]
if (errors)
return respond(res, false, {}, errors, 400)
//generate an uid
const uid = await generateUid()
const user = new User({
email, name, uid,
friends: [],
photo: process.env.DEFAULTPROFILEPIC
} as UserDoc) //used for my editor to help me
//save things in session
req.session.uid = uid
req.session.save(() => { })
await Promise.all([
encodePassword(password).then(result => savePassword(uid, result)),
user.save()
])
//send uid back
return respond(res,true,{ uid })
}) })
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 (req.session.uid)
return res.redirect("auth/account")
//get data from body
const { password, email, name } = req.body
//check if the email isnt used
if (await User.findOne({ name }))
res.redirect("login")
//validate
req.check("email", "email isnt valid").isEmail()
const errors = req.validationErrors()
if (errors)
res.json({ error: `${req.body.email} is not a valid email` })
//generate an uid
const uid = await generateUid()
const user = new User({
email,
friends: [],
name,
photo: process.env.DEFAULTPROFILEPIC,
uid
} as UserDoc) //used for my editor to help me
encodePassword(password)
//save the password and the user in the db
await Promise.all([
encodePassword(password).then(result => savePassword(uid, result)),
user.save()
])
//save things in session
req.session.uid = uid
//save in the session
req.session.save(() => { })
//send uid back
res.json({
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

View file

@ -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"
} }

View file

@ -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()