Skip to content

Commit

Permalink
Finish node
Browse files Browse the repository at this point in the history
  • Loading branch information
Auguxto committed Oct 20, 2021
0 parents commit 2f63143
Show file tree
Hide file tree
Showing 24 changed files with 1,477 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
node_modules
# Keep environment variables out of version control
.env
28 changes: 28 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"name": "nlw-heat-backend",
"version": "1.0.0",
"main": "index.js",
"license": "MIT",
"scripts": {
"dev": "ts-node-dev --exit-child --transpile-only --ignore-watch node_modules src/server.ts"
},
"devDependencies": {
"@types/axios": "^0.14.0",
"@types/express": "^4.17.13",
"@types/jsonwebtoken": "^8.5.5",
"@types/socket.io": "^3.0.2",
"prisma": "3.3.0",
"ts-node-dev": "^1.1.8",
"typescript": "^4.4.4"
},
"dependencies": {
"@prisma/client": "3.3.0",
"@types/cors": "^2.8.12",
"axios": "^0.23.0",
"cors": "^2.8.5",
"dotenv": "^10.0.0",
"express": "^4.17.1",
"jsonwebtoken": "^8.5.1",
"socket.io": "^4.3.1"
}
}
Binary file added prisma/dev.db
Binary file not shown.
8 changes: 8 additions & 0 deletions prisma/migrations/20211019225649_create_user/migration.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
-- CreateTable
CREATE TABLE "users" (
"id" TEXT NOT NULL PRIMARY KEY,
"name" TEXT NOT NULL,
"github_id" INTEGER NOT NULL,
"avatar_url" TEXT NOT NULL,
"login" TEXT NOT NULL
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
-- CreateTable
CREATE TABLE "messages" (
"id" TEXT NOT NULL PRIMARY KEY,
"text" TEXT NOT NULL,
"created_at" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
"user_id" TEXT NOT NULL,
CONSTRAINT "messages_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "users" ("id") ON DELETE RESTRICT ON UPDATE CASCADE
);
3 changes: 3 additions & 0 deletions prisma/migrations/migration_lock.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Please do not edit this file manually
# It should be added in your version-control system (i.e. Git)
provider = "sqlite"
34 changes: 34 additions & 0 deletions prisma/schema.prisma
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// This is your Prisma schema file,
// learn more about it in the docs: https://pris.ly/d/prisma-schema

generator client {
provider = "prisma-client-js"
}

datasource db {
provider = "sqlite"
url = "file:./dev.db"
}

model User {
id String @id @default(uuid())
name String
github_id Int
avatar_url String
login String
messages Message[]
@@map("users")
}

model Message {
id String @id @default(uuid())
text String
created_at DateTime @default(now())
user User @relation(fields: [user_id], references: [id])
user_id String
@@map("messages")
}
24 changes: 24 additions & 0 deletions public/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Nlw Heat</title>
</head>
<body>
<script
src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.0.1/socket.io.min.js"
integrity="sha512-eVL5Lb9al9FzgR63gDs1MxcDS2wFu3loYAgjIH0+Hg38tCS8Ag62dwKyH+wzDb+QauDpEZjXbMn11blw8cbTJQ=="
crossorigin="anonymous"
></script>

<script>
const socket = io("http://localhost:4000");

socket.on("new_message", (data) => {
console.log(data);
});
</script>
</body>
</html>
5 changes: 5 additions & 0 deletions src/@types/express/index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
declare namespace Express {
export interface Request {
user_id: string;
}
}
40 changes: 40 additions & 0 deletions src/app.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import "dotenv/config";
import express from "express";
import http from "http";
import cors from "cors";
import { Server } from "socket.io";

import { router } from "./routes";

const app = express();
app.use(cors());

const serverHttp = http.createServer(app);

const io = new Server(serverHttp, {
cors: {
origin: "*",
},
});

io.on("connection", (socket) => {
console.log(`Usuario conectado no socket ${socket.id}`);
});

app.use(express.json());

app.use(router);

app.get("/github", (request, response) => {
response.redirect(
`https://github.com/login/oauth/authorize?client_id=${process.env.GITHUB_CLIENT_ID}`
);
});

app.get("/signin/callback", (request, response) => {
const { code } = request.query;

response.json({ code });
});

export { serverHttp, io };
19 changes: 19 additions & 0 deletions src/controllers/AuthenticateUserController.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { Request, Response } from "express";
import { AuthenticateUserService } from "../services/AuthenticateUserService";

class AuthenticateUserController {
async handle(request: Request, response: Response) {
const { code } = request.body;

const service = new AuthenticateUserService();
try {
const result = await service.execute(code);

return response.json(result);
} catch (err) {
return response.json({ error: err.message });
}
}
}

export { AuthenticateUserController };
16 changes: 16 additions & 0 deletions src/controllers/CreateMessageController.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { Request, Response } from "express";
import { CreateMessageService } from "../services/CreateMessageService";

class CreateMessageController {
async handle(request: Request, response: Response) {
const { message } = request.body;
const { user_id } = request;

const service = new CreateMessageService();
const result = await service.execute(message, user_id);

return response.json(result);
}
}

export { CreateMessageController };
14 changes: 14 additions & 0 deletions src/controllers/GetLast3MessagesController.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { Request, Response } from "express";
import { GetLast3MessagesService } from "../services/GetLast3MessagesService";

class GetLast3MessagesController {
async handle(request: Request, response: Response) {
const service = new GetLast3MessagesService();

const result = await service.execute();

return response.json(result);
}
}

export { GetLast3MessagesController };
16 changes: 16 additions & 0 deletions src/controllers/ProfileUserController.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { Request, Response } from "express";
import { ProfileUserService } from "../services/ProfileUserService";

class ProfileUserController {
async handle(request: Request, response: Response) {
const { user_id } = request;

const service = new ProfileUserService();

const result = await service.execute(user_id);

return response.json(result);
}
}

export { ProfileUserController };
29 changes: 29 additions & 0 deletions src/middleware/ensureAuthenticated.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { Request, Response, NextFunction } from "express";
import { verify } from "jsonwebtoken";

interface IPayload {
sub: string;
}

export function ensureAuthenticated(
request: Request,
response: Response,
next: NextFunction
) {
const authToken = request.headers.authorization;

if (!authToken)
return response.status(401).json({ errorCode: "token.invalid" });

const [, token] = authToken.split(" ");

try {
const { sub } = verify(token, process.env.JWT_SECRET) as IPayload;

request.user_id = sub;

return next();
} catch (err) {
return response.status(401).json({ errorCode: "token.expired" });
}
}
5 changes: 5 additions & 0 deletions src/prisma/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { PrismaClient } from "@prisma/client";

const prismaClient = new PrismaClient();

export default prismaClient;
24 changes: 24 additions & 0 deletions src/routes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { Router } from "express";

import { AuthenticateUserController } from "./controllers/AuthenticateUserController";
import { CreateMessageController } from "./controllers/CreateMessageController";
import { GetLast3MessagesController } from "./controllers/GetLast3MessagesController";
import { ProfileUserController } from "./controllers/ProfileUserController";

import { ensureAuthenticated } from "./middleware/ensureAuthenticated";

const router = Router();

router.post("/authenticate", new AuthenticateUserController().handle);

router.post(
"/messages",
ensureAuthenticated,
new CreateMessageController().handle
);

router.get("/messages/last3", new GetLast3MessagesController().handle);

router.get("/profile", ensureAuthenticated, new ProfileUserController().handle);

export { router };
3 changes: 3 additions & 0 deletions src/server.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { serverHttp } from "./app";

serverHttp.listen(4000, () => console.log("Server is running"));
80 changes: 80 additions & 0 deletions src/services/AuthenticateUserService.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import axios from "axios";
import { sign } from "jsonwebtoken";

import prismaClient from "../prisma";

interface IAccessTokenResponse {
access_token: string;
}

interface IUserResponse {
avatar_url: string;
login: string;
id: number;
name: string;
}

class AuthenticateUserService {
async execute(code: string) {
const url = "https://github.com/login/oauth/access_token";

const { data: accessTokenResponse } =
await axios.post<IAccessTokenResponse>(url, null, {
params: {
client_id: process.env.GITHUB_CLIENT_ID,
client_secret: process.env.GITHUB_CLIENT_SECRET,
code,
},
headers: {
Accept: "application/json",
},
});

const response = await axios.get<IUserResponse>(
"https://api.github.com/user",
{
headers: {
authorization: `Bearer ${accessTokenResponse.access_token}`,
},
}
);

const { login, id, avatar_url, name } = response.data;

let user = await prismaClient.user.findFirst({
where: {
github_id: id,
},
});

if (!user) {
user = await prismaClient.user.create({
data: {
github_id: id,
avatar_url,
login,
name,
},
});
}

const token = sign(
{
user: {
name: user.name,
avatar_url: user.avatar_url,
id: user.id,
},
},
process.env.JWT_SECRET,
{
subject: user.id,
expiresIn: "1d",
}
);

return { token, user };
}
}

export { AuthenticateUserService };
Loading

0 comments on commit 2f63143

Please sign in to comment.