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
3 changes: 2 additions & 1 deletion backend/.gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
node_modules
package-lock.json
package-lock.json
.env
7 changes: 5 additions & 2 deletions backend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,12 @@
"@babel/core": "^7.17.9",
"@babel/node": "^7.16.8",
"@babel/preset-env": "^7.16.11",
"bcrypt": "^5.1.1",
"cors": "^2.8.5",
"dotenv": "^16.4.5",
"express": "^4.17.3",
"mongoose": "^8.0.0",
"nodemon": "^3.0.1"
"express-list-endpoints": "^7.1.0",
"mongoose": "^8.4.0",
"nodemon": "^3.1.1"
}
}
98 changes: 93 additions & 5 deletions backend/server.js
Original file line number Diff line number Diff line change
@@ -1,24 +1,112 @@
import cors from "cors";
import crypto from "crypto";
import bcrypt from "bcrypt";
import express from "express";
import mongoose from "mongoose";
import expressListEndpoints from "express-list-endpoints";

const mongoUrl = process.env.MONGO_URL || "mongodb://localhost/project-mongo";
// const mongoUrl = process.env.MONGO_URL || "mongodb://localhost/auth";
const mongoUrl = "mongodb://localhost/auth";
mongoose.connect(mongoUrl);
mongoose.Promise = Promise;

const User = mongoose.model("User", {
name: {
type: String,
unique: true,
},
email: {
type: String,
unique: true,
},
password: {
type: String,
required: true,
},
accessToken: {
type: String,
default: () => crypto.randomBytes(128).toString("hex"),
},
});

// Middleware function
const authenticateUser = async (req, res, next) => {
const user = await User.findOne({ accessToken: req.header("Authorization") });
if (user) {
req.user = user;
next();
} else {
res.status(401).json({ loggedOut: true });
}
};

// Defines the port the app will run on. Defaults to 8080, but can be overridden
// when starting the server. Example command to overwrite PORT env variable value:
// PORT=9000 npm start
const port = process.env.PORT || 8080;
const app = express();

// Add middlewares to enable cors and json body parsing
app.use(cors());
app.use(express.json());

// Start defining your routes here
// Documentation endpoint
app.get("/", (req, res) => {
res.send("Hello Technigo!");
const endpoints = expressListEndpoints(app);
const documentation = {
Welcome: "This is the Authentication API!",
Endpoints: {
"/": "Get API documentation",
"/users": {
POST: "Create a new user",
},
"/sessions": {
POST: "Authenticate a returning user",
},
"/secrets": {
GET: "Get secret content (requires authentication)",
},
},
};
res.json(documentation);
});
Comment on lines 52 to +70
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you're not really listing the endpoints urls, try with:

app.get("/", (req, res) => {
  const endpoints = expressListEndpoints(app);
  const documentation = {
    Welcome: "This is the Authentication API!",
    Endpoints: endpoints.map((endpoint) => ({
      method: endpoint.methods.join(", "),
      path: endpoint.path
    }))
  };
  res.json(documentation);
});

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry Antonella, I forgot to tell that I couldn't finish the auth project. I got stuck first on getting the endpoints to work on postman and later trying to deploy to Netlify, so I had no time to connect the FE to the BE. I will try to work on it in another moment. Just now I'm working on the FP.


app.post("/users", async (req, res) => {
try {
const { name, email, password } = req.body;
// DO NOT STORE PLAINTEXT PASSWORD
const salt = bcrypt.genSaltSync();
const user = new User({
name,
email,
password: bcrypt.hashSync(password, salt),
});
await user.save(); // Await the save operation
res.status(201).json({
success: true,
message: "User created",
id: user._id,
accessToken: user.accessToken,
});
} catch (error) {
res.status(400).json({ success: false, message: "Could not create user", errors: error });
}
});

app.post("/sessions", async (req, res) => {
const user = await User.findOne({ email: req.body.email });
if (user && bcrypt.compareSync(req.body.password, user.password)) {
res.status(200).json({
success: true,
message: "User authenticated",
id: user._id,
accessToken: user.accessToken,
});
} else {
res.status(401).json({ success: false, message: "Invalid email or password" });
}
});

app.get("/secrets", authenticateUser, (req, res) => {
res.json({ secret: "This is a super secret!" });
});

// Start the server
Expand Down
4 changes: 3 additions & 1 deletion frontend/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite + React</title>
<title>Auth Vite + React</title>
<link href='https://unpkg.com/boxicons@2.1.4/css/boxicons.min.css' rel='stylesheet'>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.jsx"></script>
</body>
</html>

3 changes: 2 additions & 1 deletion frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@
},
"dependencies": {
"react": "^18.2.0",
"react-dom": "^18.2.0"
"react-dom": "^18.2.0",
"zustand": "^4.5.2"
},
"devDependencies": {
"@types/react": "^18.2.15",
Expand Down
Binary file added frontend/public/keys-wall.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added frontend/public/solo.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
31 changes: 31 additions & 0 deletions frontend/public/technigo-logo.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 6 additions & 0 deletions frontend/src/App.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
.app-container {
display: flex;
flex-direction: column;
align-items: center;
width: 100%;
}
13 changes: 12 additions & 1 deletion frontend/src/App.jsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,14 @@
import { Footer } from "./Components/Footer";
import { HomePage } from "./Components/HomePage";
import { Header } from "./Components/Header";
import "./App.css"

export const App = () => {
return <div>Find me in src/app.jsx!</div>;
return (
<div className="app-container">
<Header />
<HomePage />
<Footer />
</div>
)
};
14 changes: 14 additions & 0 deletions frontend/src/Components/Buttons.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
.button-container button {
padding: 8px 16px;
background-color: #007bff;
color: #fff;
border: none;
border-radius: 6px;
cursor: pointer;
margin: 5px 0;
width: 100%;
}

.button-container button:hover {
background-color: #0056b3;
}
31 changes: 31 additions & 0 deletions frontend/src/Components/Buttons.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import "./Buttons.css";

export const BtnSignIn = ({ onClick }) => {
return (
<div className="button-container">
<button onClick={onClick} type="button">
Sign In
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sign in and Login are synonyms, it's sign up or register if you prefer :)

</button>
</div>
);
};

export const BtnLogin = ({ onClick }) => {
return (
<div className="button-container">
<button onClick={onClick} type="button">
Login
</button>
</div>
);
};

export const BtnSubmit = ({ onClick }) => {
return (
<div className="button-container">
<button onClick={onClick} type="submit">
Submit
</button>
</div>
);
};
22 changes: 22 additions & 0 deletions frontend/src/Components/Footer.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
.footer-container {
position: fixed;
bottom: 0;
margin-top: auto;
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
padding: 5px;
background-color: #303030;
color: rgb(255, 255, 255);
width: 100%;
}

.footer-container p {
margin: 10px;
font-size: 0.85rem;
}

.logo {
height: 30px;
}
10 changes: 10 additions & 0 deletions frontend/src/Components/Footer.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import "./Footer.css"

export const Footer = () => {
return (
<footer className="footer-container">
<p>2024 by Arnau Vidal </p>
<img src="/technigo-logo.svg" alt="Technigo logo" className="logo" />
</footer>
)
}
32 changes: 32 additions & 0 deletions frontend/src/Components/Header.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
.header-container {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
color: white;
font-size: 1.5rem;
width: 100%;
margin-bottom: 20px;
}

.header-container h1 {
text-align: center;
font-size: 2rem;
backdrop-filter: blur(2px);
margin: 20px;
padding: 0px 15px;
border-radius: 15px;
}

/* TABLET SCREENS min 745px ------------------------------------------------------------ */

@media (min-width: 745px) {
.header-container {
min-height: 300px;
}

.header-container h1 {
font-size: 4rem;
backdrop-filter: blur(5px);
}
}
9 changes: 9 additions & 0 deletions frontend/src/Components/Header.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import "./Header.css";

export const Header = () => {
return (
<div className="header-container">
<h1>Arnau's Authentication Project</h1>
</div>
);
};
49 changes: 49 additions & 0 deletions frontend/src/Components/HomePage.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
.home-page-container {
text-align: center;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
width: 95%;
color: white;
background-color: rgba(0, 0, 0, 0.443);
box-shadow: 2px 2px 20px 10px rgba(0, 0, 0, 0.15);
padding: 10px;
backdrop-filter: blur(4px);
border-radius: 12px;
top: 0;
left: 0;
border: 2px solid white;
padding-bottom: 45px;
}

.nav {
position: relative;
display: flex;
flex-direction: column;
justify-content: space-between;
width: 100%;
}

.button-container button {
padding: 8px 16px;
background-color: #007bff;
color: #fff;
border: none;
border-radius: 6px;
cursor: pointer;
margin: 5px 0;
width: 100%;
}

.button-container button:hover {
background-color: #0056b3;
}

/* TABLET SCREENS min 745px ------------------------------------------------------------ */

@media (min-width:745px){
.home-page-container {
width: 500px;
}
}
Loading