-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathexpress_server.js
209 lines (185 loc) · 6.3 KB
/
express_server.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
//Required packages
const express = require("express");
const cookieSession = require("cookie-session");
const bcrypt = require("bcryptjs");
const { getUserByEmail } = require("./helpers");
const app = express();
const PORT = 8080; // defines the default port 8080 the app will listen to
//databases import
const users = require('./data/users');
const urlDatabase = require('./data/urls');
//Middleware
app.set("view engine", "ejs"); // sets up EJS as the templating engine
app.use(
cookieSession({
name: 'session',
keys: ['key1', 'key2'],
})
);
app.use(express.urlencoded({ extended: true })); // Middleware to parse form data
///Helpers function
// Function to generate 6-character random alphanumeric string
const generateRandomString = () => {
const chars =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
return Array.from({ length: 6 }, () =>
chars[Math.floor(Math.random() * chars.length)]).join("");
};
// helper function that Filters the URL database to return only the URLs that belong to the logged-in user.
const urlsForUser = (id) => {
const filteredURLs = {};
for (const urlId in urlDatabase) {
if (urlDatabase[urlId].userID === id) {
filteredURLs[urlId] = urlDatabase[urlId];
}
}
return filteredURLs;
};
//------> Routes <-------//
// Homepage redirect
app.get("/", (req, res) => {
res.redirect("/urls");
});
// GET /urls: Display all URLs for the logged-in user
app.get("/urls", (req, res) => {
const userId = req.session.user_id; // Retrieves the user ID from the cookies
if (!userId) {
return res.status(401).send("Please log in to view your URLs.");
}
// Retrieves the URLs specific to the logged-in user
const userURLs = urlsForUser(userId);
const templateVars = { user: users[userId], urls: userURLs };
res.render("urls_index", templateVars);
});
// GET /urls/new: Show form to create a new URL (restricted to users that are logged in)
app.get("/urls/new", (req, res) => {
const userId = req.session.user_id;
if (!userId) {
return res.redirect("/login"); //Redirects to login if not logged in
}
const templateVars = { user: users[userId] };
res.render("urls_new", templateVars);
});
// GET /urls/:id: Show details for a specific URL
app.get("/urls/:id", (req, res) => {
const { id } = req.params;
const userId = req.session.user_id;
const url = urlDatabase[id];
if (!url) {
return res.status(404).send("Short URL not found.");
}
if (!userId) {
return res.status(401).send("Please log in to view this URL.");
}
// Check if the logged-in user is the owner of the URL
if (url.userID !== userId) {
return res.status(403).send("You do not have permission to access this URL.");
}
const templateVars = {
user: users[userId],
shortURL:
id, longURL:
url.longURL };
res.render("urls_show", templateVars);
});
// /u/:id: Redirect to the long URL corresponding to the short URL
app.get("/u/:id", (req, res) => {
const shortURL = req.params.id;
const longURL = urlDatabase[shortURL];
if (!longURL) {
return res.status(404).send("Short URL not found."); // Handle missing URL
}
res.redirect(longURL.longURL); // Redirects to the original long URL
});
// POST /urls: Creates a new short URL
app.post("/urls", (req, res) => {
const userId = req.session.user_id;
if (!userId) {
return res.status(401).send("Please log in to create URLs.");
}
const shortURL = generateRandomString(); // Generate a new random short URL
urlDatabase[shortURL] = { // Store the URL with the userID
longURL: req.body.longURL,
userID: userId };
res.redirect(`/urls/${shortURL}`);
});
// POST /urls/:id/delete: Delete a URL (restricted to creator of the URLs)
app.post("/urls/:id/delete", (req, res) => {
const { id } = req.params;
const userId = req.session.user_id;
const url = urlDatabase[id];
if (!url) {
return res.status(404).send("Short URL not found.");
}
// Ensure the logged-in user is the owner
if (url.userID !== userId) {
return res.status(403).send("You do not have permission to delete this URL.");
}
delete urlDatabase[id]; //deletes the URL from database
res.redirect("/urls");
});
// POST /urls/:id: Update a URL
app.post("/urls/:id", (req, res) => {
const { id } = req.params;
const userId = req.session.user_id;
const url = urlDatabase[id];
if (!url) {
return res.status(404).send("Short URL not found.");
}
// Ensure the logged-in user is the owner
if (url.userID !== userId) {
return res.status(403).send("You do not have permission to edit this URL.");
}
urlDatabase[id].longURL = req.body.longURL;
res.redirect("/urls");
});
// GET route to serve the registration page
app.get("/register", (req, res) => {
const userId = req.session.user_id;
const templateVars = { user: users[userId] };
res.render("register", templateVars);
});
// POST route to handle user registration
app.post("/register", (req, res) => {
const { email, password } = req.body;
if (!email || !password) {
return res.status(400).send("Email and password cannot be empty!");
}
if (getUserByEmail(email, users)) {
return res.status(400).send("Email is already registered.");
}
const userId = generateRandomString(); // Generate a unique user ID
const hashedPassword = bcrypt.hashSync(password, 10); // Hash the password for security
users[userId] = { // Add new user to the database
id: userId,
email,
password: hashedPassword
};
req.session.user_id = userId;
res.redirect("/urls");
});
//GET route to handle login (Show login page)
app.get("/login", (req, res) => {
const userId = req.session.user_id;
const templateVars = { user: users[userId] };
res.render("login", templateVars);
});
// POST /login: Handle login
app.post("/login", (req, res) => {
const { email, password } = req.body;
const user = getUserByEmail(email, users);
if (!user || !bcrypt.compareSync(password, user.password)) {
return res.status(403).send("Invalid email or password.");
}
req.session.user_id = user.id; // Set the user's ID in the cookie
res.redirect("/urls");
});
// Updated POST /logout: Handle logout
app.post("/logout", (req, res) => {
req.session = null;
res.redirect("/login"); // Redirect the user to the login page after logout
});
// Start the server
app.listen(PORT, () => {
console.log(`TinyApp listening on port ${PORT}!`);
});