Skip to content
Open
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
2 changes: 2 additions & 0 deletions clase-7/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
node_modules
db
5 changes: 5 additions & 0 deletions clase-7/config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export const {
PORT = 3000,
SALT_ROUND = 10,
SECRET_JWT_KEY = 'this-is-an-awesome-secret-key-mucho-mas-largo-y-muy-seguro'
} = process.env
81 changes: 81 additions & 0 deletions clase-7/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import express from 'express'
import { PORT, SECRET_JWT_KEY } from './config.js'
import cookieParser from 'cookie-parser'
import jwt from 'jsonwebtoken'
import { UserRepository } from './user-repository.js'

const app = express()

app.set('view engine', 'ejs')

app.use(express.json())
app.use(cookieParser())

app.use((req, res, next) => {
const token = req.cookies.access_token
req.session = { user: null }

try {
const data = jwt.verify(token, SECRET_JWT_KEY)
req.session.user = data
} catch (error) {
req.session.user = null
}

next()
})

app.get('/', (req, res) => {
const { user } = req.session
res.render('index', user)
})

app.post('/login', async (req, res) => {
const { username, password } = req.body
try {
const user = await UserRepository.login({ username, password })
const token = jwt.sign(
{ id: user._id, username: user.username },
SECRET_JWT_KEY,
{
expiresIn: '1h'
}
)
res
.cookie('access_token', token, {
httpOnly: true,
secure: process.env.NODE_ENV === 'production',
sameSite: 'strict',
maxAge: 1000 * 60 * 60
})
.status(200).send({ user, token })
} catch (error) {
res.status(401).send({ error: error.message })
}
})

app.post('/register', async (req, res) => {
const { username, password } = req.body
try {
const id = await UserRepository.create({
username,
password
})
res.send({ id })
} catch (error) {
res.status(400).send({ error: error.message })
}
})

app.post('/logout', (req, res) => {
res
.clearCookie('access_token')
.json({ message: 'Logout successful' })
})

app.get('/protected', (req, res) => {
const { user } = req.session
if (!user) return res.status(403).send('Access not authorized')
res.render('protected', user)
})
app.listen(PORT, () => { console.log(`Server is listen on port ${PORT}`) })
28 changes: 28 additions & 0 deletions clase-7/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"name": "6.-user-aouth-midu",
"version": "1.0.0",
"description": "",
"main": "index.js",
"type": "module",
"scripts": {
"dev": "node --watch index.js",
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"bcrypt": "^5.1.1",
"cookie-parser": "^1.4.7",
"db-local": "^3.1.0",
"ejs": "^3.1.10",
"express": "^4.21.2",
"jsonwebtoken": "^9.0.2"
},
"devDependencies": {
"standard": "^17.1.2"
},
"eslintConfig": {
"extends": "standard"
}
}
9 changes: 9 additions & 0 deletions clase-7/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
## To run this app download it and run the command npm i to install all denpendencies (Is required have node on you computer).

```bash
npm i
```
## screenshots:
![Image](https://github.com/user-attachments/assets/f91a1f7a-ba1c-418f-ade7-7b91264c5b67)
![Image](https://github.com/user-attachments/assets/0a65335a-33bb-41d6-8db6-25af541d8f04)
![Image](https://github.com/user-attachments/assets/eb071544-6c44-4e68-b6d4-7f1606278d8c)
54 changes: 54 additions & 0 deletions clase-7/user-repository.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import DBLocal from 'db-local'
import crypto from 'crypto'
import bcrypt from 'bcrypt'
import { SALT_ROUND } from './config.js'
const { Schema } = new DBLocal({ path: './db' })

const User = Schema('User', {
_id: { type: String, required: true },
username: { type: String, required: true },
password: { type: String, required: true }
})

export class UserRepository {
static async create ({ username, password }) {
Validatiton.password(password)
Validatiton.username(username)
const user = User.findOne({ username })
if (user) throw new Error(`The username: ${username} is already taken`)
const id = crypto.randomUUID()
const hashedPassword = await bcrypt.hash(password, SALT_ROUND)
User.create({
id,
username,
password: hashedPassword
}).save()

return id
}

static async login ({ username, password }) {
Validatiton.username(username)
Validatiton.password(password)

const user = User.findOne({ username })
if (!user) throw new Error('This user does not exist in our database')
const isValid = await bcrypt.compare(password, user.password)
if (!isValid) throw new Error('Incorrect password')
const { password: _, ...publicUser } = user
console.log(publicUser)
return publicUser
}
}

class Validatiton {
static password (password) {
if (typeof password !== 'string') throw new Error('Password must be a string')
if (password.length < 6) throw new Error('Password at leat must have 6 characters long')
}

static username (username) {
if (typeof username !== 'string') throw new Error('Username must be a string')
if (username.length < 3) throw new Error('Username at least must be have 3 characters long')
}
}
Loading