diff --git a/.gitea/workflows/deploy.yml b/.gitea/workflows/deploy.yml
index b5ee22b..3b1acda 100644
--- a/.gitea/workflows/deploy.yml
+++ b/.gitea/workflows/deploy.yml
@@ -6,7 +6,7 @@ on:
env:
IMAGE_NAME: costco-grocery-list
- REGISTRY: gitea.nicosaya.com
+ REGISTRY: git.nicosaya.com
jobs:
build:
diff --git a/.vscode/settings.json b/.vscode/settings.json
index 5fff71a..c39bd96 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -1,65 +1,65 @@
-{
- // ============================
- // Editor basics
- // ============================
- "editor.tabSize": 2,
- "editor.insertSpaces": true,
- "editor.formatOnSave": true,
- "editor.codeActionsOnSave": {
- "source.fixAll": "explicit",
- "source.organizeImports": "explicit"
- },
- "editor.defaultFormatter": "esbenp.prettier-vscode",
-
- // ============================
- // JS / TS behavior
- // ============================
- "javascript.updateImportsOnFileMove.enabled": "always",
- "typescript.updateImportsOnFileMove.enabled": "always",
- "javascript.suggest.autoImports": true,
- "typescript.suggest.autoImports": true,
-
- // Fix annoying "JSX not allowed" issues in js files
- "javascript.validate.enable": false,
-
- // ============================
- // React specific
- // ============================
- "emmet.includeLanguages": {
- "javascript": "javascriptreact",
- "typescript": "typescriptreact"
- },
- "emmet.triggerExpansionOnTab": true,
-
- // ============================
- // Terminal
- // ============================
- "terminal.integrated.defaultProfile.windows": "Git Bash",
-
- // ============================
- // Prettier
- // ============================
- "[javascript]": { "editor.defaultFormatter": "vscode.typescript-language-features" },
- "[javascriptreact]": { "editor.defaultFormatter": "vscode.typescript-language-features" },
- "[typescript]": { "editor.defaultFormatter": "vscode.typescript-language-features" },
- "[typescriptreact]": { "editor.defaultFormatter": "vscode.typescript-language-features" },
-
- // ============================
- // File Icons
- // ============================
- "workbench.iconTheme": "material-icon-theme",
- "material-icon-theme.folders.associations": {
- "gitea/workflows": "repository",
- },
-
- // ============================
- // Explorer cleanup
- // ============================
- "files.exclude": {
- "**/.git": true,
- "**/.DS_Store": true,
- "**/node_modules": false,
- "**/*.log": true,
- "**/dist": true
- }
+{
+ // ============================
+ // Editor basics
+ // ============================
+ "editor.tabSize": 2,
+ "editor.insertSpaces": true,
+ "editor.formatOnSave": true,
+ "editor.codeActionsOnSave": {
+ "source.fixAll": "explicit",
+ "source.organizeImports": "explicit"
+ },
+ "editor.defaultFormatter": "esbenp.prettier-vscode",
+
+ // ============================
+ // JS / TS behavior
+ // ============================
+ "javascript.updateImportsOnFileMove.enabled": "always",
+ "typescript.updateImportsOnFileMove.enabled": "always",
+ "javascript.suggest.autoImports": true,
+ "typescript.suggest.autoImports": true,
+
+ // Fix annoying "JSX not allowed" issues in js files
+ "javascript.validate.enable": false,
+
+ // ============================
+ // React specific
+ // ============================
+ "emmet.includeLanguages": {
+ "javascript": "javascriptreact",
+ "typescript": "typescriptreact"
+ },
+ "emmet.triggerExpansionOnTab": true,
+
+ // ============================
+ // Terminal
+ // ============================
+ "terminal.integrated.defaultProfile.windows": "Git Bash",
+
+ // ============================
+ // Prettier
+ // ============================
+ "[javascript]": { "editor.defaultFormatter": "vscode.typescript-language-features" },
+ "[javascriptreact]": { "editor.defaultFormatter": "vscode.typescript-language-features" },
+ "[typescript]": { "editor.defaultFormatter": "vscode.typescript-language-features" },
+ "[typescriptreact]": { "editor.defaultFormatter": "vscode.typescript-language-features" },
+
+ // ============================
+ // File Icons
+ // ============================
+ "workbench.iconTheme": "material-icon-theme",
+ "material-icon-theme.folders.associations": {
+ "gitea/workflows": "repository",
+ },
+
+ // ============================
+ // Explorer cleanup
+ // ============================
+ "files.exclude": {
+ "**/.git": true,
+ "**/.DS_Store": true,
+ "**/node_modules": false,
+ "**/*.log": true,
+ "**/dist": true
+ }
}
\ No newline at end of file
diff --git a/backend/app.js b/backend/app.js
index 10e0306..752aee7 100644
--- a/backend/app.js
+++ b/backend/app.js
@@ -1,43 +1,43 @@
-const express = require("express");
-const cors = require("cors");
-const User = require("./models/user.model");
-
-const app = express();
-app.use(express.json());
-
-const allowedOrigins = process.env.ALLOWED_ORIGINS.split(",").map(origin => origin.trim());
-console.log("Allowed Origins:", allowedOrigins);
-app.use(
- cors({
- origin: function (origin, callback) {
- if (!origin) return callback(null, true);
- if (allowedOrigins.includes(origin)) return callback(null, true);
- if (/^http:\/\/192\.168\.\d+\.\d+/.test(origin)) return callback(null, true);
- if (/^https:\/\/192\.168\.\d+\.\d+/.test(origin)) return callback(null, true);
- callback(new Error("Not allowed by CORS"));
- },
- methods: ["GET", "POST", "PUT", "DELETE"],
- })
-);
-
-app.get('/', async (req, res) => {
- resText = `Grocery List API is running.\n` +
- `Roles available: ${Object.values(User.ROLES).join(', ')}`
-
- res.status(200).type("text/plain").send(resText);
-});
-
-
-const authRoutes = require("./routes/auth.routes");
-app.use("/auth", authRoutes);
-
-const listRoutes = require("./routes/list.routes");
-app.use("/list", listRoutes);
-
-const adminRoutes = require("./routes/admin.routes");
-app.use("/admin", adminRoutes);
-
-const usersRoutes = require("./routes/users.routes");
-app.use("/users", usersRoutes);
-
+const express = require("express");
+const cors = require("cors");
+const User = require("./models/user.model");
+
+const app = express();
+app.use(express.json());
+
+const allowedOrigins = process.env.ALLOWED_ORIGINS.split(",").map(origin => origin.trim());
+console.log("Allowed Origins:", allowedOrigins);
+app.use(
+ cors({
+ origin: function (origin, callback) {
+ if (!origin) return callback(null, true);
+ if (allowedOrigins.includes(origin)) return callback(null, true);
+ if (/^http:\/\/192\.168\.\d+\.\d+/.test(origin)) return callback(null, true);
+ if (/^https:\/\/192\.168\.\d+\.\d+/.test(origin)) return callback(null, true);
+ callback(new Error("Not allowed by CORS"));
+ },
+ methods: ["GET", "POST", "PUT", "DELETE"],
+ })
+);
+
+app.get('/', async (req, res) => {
+ resText = `Grocery List API is running.\n` +
+ `Roles available: ${Object.values(User.ROLES).join(', ')}`
+
+ res.status(200).type("text/plain").send(resText);
+});
+
+
+const authRoutes = require("./routes/auth.routes");
+app.use("/auth", authRoutes);
+
+const listRoutes = require("./routes/list.routes");
+app.use("/list", listRoutes);
+
+const adminRoutes = require("./routes/admin.routes");
+app.use("/admin", adminRoutes);
+
+const usersRoutes = require("./routes/users.routes");
+app.use("/users", usersRoutes);
+
module.exports = app;
\ No newline at end of file
diff --git a/backend/controllers/auth.controller.js b/backend/controllers/auth.controller.js
index 222acd8..bc52c48 100644
--- a/backend/controllers/auth.controller.js
+++ b/backend/controllers/auth.controller.js
@@ -1,44 +1,44 @@
-const bcrypt = require("bcryptjs");
-const jwt = require("jsonwebtoken");
-const User = require("../models/user.model");
-
-exports.register = async (req, res) => {
- let { username, password, name } = req.body;
- username = username.toLowerCase();
- console.log(`🆕 Registration attempt for ${name} => username:${username}, password:${password}`);
-
- try {
- const hash = await bcrypt.hash(password, 10);
- const user = await User.createUser(username, hash, name);
- console.log(`✅ User registered: ${username}`);
-
- res.json({ message: "User registered", user });
- } catch (err) {
- res.status(400).json({ message: "Registration failed", error: err });
- }
-};
-
-exports.login = async (req, res) => {
- let { username, password } = req.body;
-
- username = username.toLowerCase();
- const user = await User.findByUsername(username);
- if (!user) {
- console.log(`⚠️ Login attempt -> No user found: ${username}`);
- return res.status(401).json({ message: "User not found" });
- }
-
- const valid = await bcrypt.compare(password, user.password);
- if (!valid) {
- console.log(`⛔ Login attempt for user ${username} with password ${password}`);
- return res.status(401).json({ message: "Invalid credentials" });
- }
-
- const token = jwt.sign(
- { id: user.id, role: user.role },
- process.env.JWT_SECRET,
- { expiresIn: "1d" }
- );
-
- res.json({ token, username, role: user.role });
-};
+const bcrypt = require("bcryptjs");
+const jwt = require("jsonwebtoken");
+const User = require("../models/user.model");
+
+exports.register = async (req, res) => {
+ let { username, password, name } = req.body;
+ username = username.toLowerCase();
+ console.log(`🆕 Registration attempt for ${name} => username:${username}, password:${password}`);
+
+ try {
+ const hash = await bcrypt.hash(password, 10);
+ const user = await User.createUser(username, hash, name);
+ console.log(`✅ User registered: ${username}`);
+
+ res.json({ message: "User registered", user });
+ } catch (err) {
+ res.status(400).json({ message: "Registration failed", error: err });
+ }
+};
+
+exports.login = async (req, res) => {
+ let { username, password } = req.body;
+
+ username = username.toLowerCase();
+ const user = await User.findByUsername(username);
+ if (!user) {
+ console.log(`⚠️ Login attempt -> No user found: ${username}`);
+ return res.status(401).json({ message: "User not found" });
+ }
+
+ const valid = await bcrypt.compare(password, user.password);
+ if (!valid) {
+ console.log(`⛔ Login attempt for user ${username} with password ${password}`);
+ return res.status(401).json({ message: "Invalid credentials" });
+ }
+
+ const token = jwt.sign(
+ { id: user.id, role: user.role },
+ process.env.JWT_SECRET,
+ { expiresIn: "1d" }
+ );
+
+ res.json({ token, username, role: user.role });
+};
diff --git a/backend/controllers/lists.controller.js b/backend/controllers/lists.controller.js
index 348f0f8..3667c2d 100644
--- a/backend/controllers/lists.controller.js
+++ b/backend/controllers/lists.controller.js
@@ -1,37 +1,37 @@
-const List = require("../models/list.model");
-
-
-exports.getList = async (req, res) => {
- const items = await List.getUnboughtItems();
- res.json(items);
-};
-
-exports.getItemByName = async (req, res) => {
- const { itemName } = req.query;
- const item = await List.getItemByName(itemName);
- res.json(item);
-}
-
-
-exports.addItem = async (req, res) => {
- const { itemName, quantity } = req.body;
-
- const id = await List.addOrUpdateItem(itemName, quantity);
-
- await List.addHistoryRecord(id, quantity);
-
- res.json({ message: "Item added/updated" });
-};
-
-
-exports.markBought = async (req, res) => {
- await List.setBought(req.body.id);
- res.json({ message: "Item marked bought" });
-};
-
-
-exports.getSuggestions = async (req, res) => {
- const { query } = req.query || "";
- const suggestions = await List.getSuggestions(query);
- res.json(suggestions);
+const List = require("../models/list.model");
+
+
+exports.getList = async (req, res) => {
+ const items = await List.getUnboughtItems();
+ res.json(items);
+};
+
+exports.getItemByName = async (req, res) => {
+ const { itemName } = req.query;
+ const item = await List.getItemByName(itemName);
+ res.json(item);
+}
+
+
+exports.addItem = async (req, res) => {
+ const { itemName, quantity } = req.body;
+
+ const id = await List.addOrUpdateItem(itemName, quantity);
+
+ await List.addHistoryRecord(id, quantity);
+
+ res.json({ message: "Item added/updated" });
+};
+
+
+exports.markBought = async (req, res) => {
+ await List.setBought(req.body.id);
+ res.json({ message: "Item marked bought" });
+};
+
+
+exports.getSuggestions = async (req, res) => {
+ const { query } = req.query || "";
+ const suggestions = await List.getSuggestions(query);
+ res.json(suggestions);
};
\ No newline at end of file
diff --git a/backend/controllers/users.controller.js b/backend/controllers/users.controller.js
index ef9bc1d..0ef8399 100644
--- a/backend/controllers/users.controller.js
+++ b/backend/controllers/users.controller.js
@@ -1,55 +1,55 @@
-const User = require("../models/user.model");
-
-exports.test = async (req, res) => {
- console.log("User route is working");
- res.json({ message: "User route is working" });
-};
-
-exports.getAllUsers = async (req, res) => {
- console.log(req);
- const users = await User.getAllUsers();
- res.json(users);
-};
-
-
-exports.updateUserRole = async (req, res) => {
- try {
- const { id, role } = req.body;
-
- console.log(`Updating user ${id} to role ${role}`);
- if (!Object.values(User.ROLES).includes(role))
- return res.status(400).json({ error: "Invalid role" });
-
- const updated = await User.updateUserRole(id, role);
- if (!updated)
- return res.status(404).json({ error: "User not found" });
-
- res.json({ message: "Role updated", id, role });
- } catch (err) {
- res.status(500).json({ error: "Failed to update role" });
- }
-};
-
-exports.deleteUser = async (req, res) => {
- try {
- const { id } = req.params;
-
- const deleted = await User.deleteUser(id);
- if (!deleted)
- return res.status(404).json({ error: "User not found" });
-
-
- res.json({ message: "User deleted", id });
- } catch (err) {
- res.status(500).json({ error: "Failed to delete user" });
- }
-};
-
-
-
-
-exports.checkIfUserExists = async (req, res) => {
- const { username } = req.query;
- const users = await User.checkIfUserExists(username);
- res.json(users);
-};
+const User = require("../models/user.model");
+
+exports.test = async (req, res) => {
+ console.log("User route is working");
+ res.json({ message: "User route is working" });
+};
+
+exports.getAllUsers = async (req, res) => {
+ console.log(req);
+ const users = await User.getAllUsers();
+ res.json(users);
+};
+
+
+exports.updateUserRole = async (req, res) => {
+ try {
+ const { id, role } = req.body;
+
+ console.log(`Updating user ${id} to role ${role}`);
+ if (!Object.values(User.ROLES).includes(role))
+ return res.status(400).json({ error: "Invalid role" });
+
+ const updated = await User.updateUserRole(id, role);
+ if (!updated)
+ return res.status(404).json({ error: "User not found" });
+
+ res.json({ message: "Role updated", id, role });
+ } catch (err) {
+ res.status(500).json({ error: "Failed to update role" });
+ }
+};
+
+exports.deleteUser = async (req, res) => {
+ try {
+ const { id } = req.params;
+
+ const deleted = await User.deleteUser(id);
+ if (!deleted)
+ return res.status(404).json({ error: "User not found" });
+
+
+ res.json({ message: "User deleted", id });
+ } catch (err) {
+ res.status(500).json({ error: "Failed to delete user" });
+ }
+};
+
+
+
+
+exports.checkIfUserExists = async (req, res) => {
+ const { username } = req.query;
+ const users = await User.checkIfUserExists(username);
+ res.json(users);
+};
diff --git a/backend/models/list.model.js b/backend/models/list.model.js
index 565d73b..328b383 100644
--- a/backend/models/list.model.js
+++ b/backend/models/list.model.js
@@ -1,73 +1,73 @@
-const pool = require("../db/pool");
-
-
-exports.getUnboughtItems = async () => {
- const result = await pool.query(
- "SELECT * FROM grocery_list WHERE bought = FALSE ORDER BY id ASC"
- );
- return result.rows;
-};
-
-exports.getItemByName = async (itemName) => {
- const result = await pool.query(
- "SELECT * FROM grocery_list WHERE item_name ILIKE $1",
- [itemName]
- );
-
- return result.rows[0] || null;
-};
-
-
-exports.addOrUpdateItem = async (itemName, quantity) => {
- const result = await pool.query(
- "SELECT id, bought FROM grocery_list WHERE item_name ILIKE $1",
- [itemName]
- );
-
- if (result.rowCount > 0) {
- await pool.query(
- `UPDATE grocery_list
- SET quantity = $1,
- bought = FALSE
- WHERE id = $2`,
- [quantity, result.rows[0].id]
- );
- return result.rows[0].id;
- } else {
- const insert = await pool.query(
- `INSERT INTO grocery_list
- (item_name, quantity)
- VALUES ($1, $2) RETURNING id`,
- [itemName, quantity]
- );
- return insert.rows[0].id;
- }
-};
-
-
-exports.setBought = async (id) => {
- await pool.query("UPDATE grocery_list SET bought = TRUE WHERE id = $1", [id]);
-};
-
-
-exports.addHistoryRecord = async (itemId, quantity) => {
- await pool.query(
- `INSERT INTO grocery_history (list_item_id, quantity, added_on)
- VALUES ($1, $2, NOW())`,
- [itemId, quantity]
- );
-};
-
-
-exports.getSuggestions = async (query) => {
- const result = await pool.query(
- `SELECT DISTINCT item_name
- FROM grocery_list
- WHERE item_name ILIKE $1
- LIMIT 10`,
- [`%${query}%`]
- );
- res = result.rows;
- return result.rows;
-};
-
+const pool = require("../db/pool");
+
+
+exports.getUnboughtItems = async () => {
+ const result = await pool.query(
+ "SELECT * FROM grocery_list WHERE bought = FALSE ORDER BY id ASC"
+ );
+ return result.rows;
+};
+
+exports.getItemByName = async (itemName) => {
+ const result = await pool.query(
+ "SELECT * FROM grocery_list WHERE item_name ILIKE $1",
+ [itemName]
+ );
+
+ return result.rows[0] || null;
+};
+
+
+exports.addOrUpdateItem = async (itemName, quantity) => {
+ const result = await pool.query(
+ "SELECT id, bought FROM grocery_list WHERE item_name ILIKE $1",
+ [itemName]
+ );
+
+ if (result.rowCount > 0) {
+ await pool.query(
+ `UPDATE grocery_list
+ SET quantity = $1,
+ bought = FALSE
+ WHERE id = $2`,
+ [quantity, result.rows[0].id]
+ );
+ return result.rows[0].id;
+ } else {
+ const insert = await pool.query(
+ `INSERT INTO grocery_list
+ (item_name, quantity)
+ VALUES ($1, $2) RETURNING id`,
+ [itemName, quantity]
+ );
+ return insert.rows[0].id;
+ }
+};
+
+
+exports.setBought = async (id) => {
+ await pool.query("UPDATE grocery_list SET bought = TRUE WHERE id = $1", [id]);
+};
+
+
+exports.addHistoryRecord = async (itemId, quantity) => {
+ await pool.query(
+ `INSERT INTO grocery_history (list_item_id, quantity, added_on)
+ VALUES ($1, $2, NOW())`,
+ [itemId, quantity]
+ );
+};
+
+
+exports.getSuggestions = async (query) => {
+ const result = await pool.query(
+ `SELECT DISTINCT item_name
+ FROM grocery_list
+ WHERE item_name ILIKE $1
+ LIMIT 10`,
+ [`%${query}%`]
+ );
+ res = result.rows;
+ return result.rows;
+};
+
diff --git a/backend/models/user.model.js b/backend/models/user.model.js
index bb212fe..0340cc4 100644
--- a/backend/models/user.model.js
+++ b/backend/models/user.model.js
@@ -1,61 +1,61 @@
-const pool = require("../db/pool");
-
-exports.ROLES = {
- VIEWER: "viewer",
- EDITOR: "editor",
- ADMIN: "admin",
-}
-
-exports.findByUsername = async (username) => {
- query = `SELECT * FROM users WHERE username = ${username}`;
- const result = await pool.query("SELECT * FROM users WHERE username = $1", [username]);
- console.log(query);
- return result.rows[0];
-};
-
-exports.createUser = async (username, hashedPassword, name) => {
- const result = await pool.query(
- `INSERT INTO users (username, password, name, role)
- VALUES ($1, $2, $3, $4)`,
- [username, hashedPassword, name, this.ROLES.VIEWER]
- );
- return result.rows[0];
-};
-
-
-exports.getAllUsers = async () => {
- const result = await pool.query("SELECT id, username, name, role FROM users ORDER BY id ASC");
- return result.rows;
-};
-
-
-exports.updateUserRole = async (id, role) => {
- const result = await pool.query(
- `UPDATE users
- SET role = $1
- WHERE id = $2
- RETURNING id, username, name, role`,
- [role, id]
- );
- return result.rows[0];
-};
-
-
-exports.deleteUser = async (id) => {
- const result = await pool.query(
- `DELETE FROM users WHERE id = $1 RETURNING id`,
- [id]
- );
- return result.rowCount;
-};
-
-
-exports.checkIfUserExists = async (username) => {
- const result = await pool.query(
- "SELECT COUNT(*) FROM users WHERE username = $1",
- [username]
- );
- return result.rows[0].count > 0;
-}
-
-
+const pool = require("../db/pool");
+
+exports.ROLES = {
+ VIEWER: "viewer",
+ EDITOR: "editor",
+ ADMIN: "admin",
+}
+
+exports.findByUsername = async (username) => {
+ query = `SELECT * FROM users WHERE username = ${username}`;
+ const result = await pool.query("SELECT * FROM users WHERE username = $1", [username]);
+ console.log(query);
+ return result.rows[0];
+};
+
+exports.createUser = async (username, hashedPassword, name) => {
+ const result = await pool.query(
+ `INSERT INTO users (username, password, name, role)
+ VALUES ($1, $2, $3, $4)`,
+ [username, hashedPassword, name, this.ROLES.VIEWER]
+ );
+ return result.rows[0];
+};
+
+
+exports.getAllUsers = async () => {
+ const result = await pool.query("SELECT id, username, name, role FROM users ORDER BY id ASC");
+ return result.rows;
+};
+
+
+exports.updateUserRole = async (id, role) => {
+ const result = await pool.query(
+ `UPDATE users
+ SET role = $1
+ WHERE id = $2
+ RETURNING id, username, name, role`,
+ [role, id]
+ );
+ return result.rows[0];
+};
+
+
+exports.deleteUser = async (id) => {
+ const result = await pool.query(
+ `DELETE FROM users WHERE id = $1 RETURNING id`,
+ [id]
+ );
+ return result.rowCount;
+};
+
+
+exports.checkIfUserExists = async (username) => {
+ const result = await pool.query(
+ "SELECT COUNT(*) FROM users WHERE username = $1",
+ [username]
+ );
+ return result.rows[0].count > 0;
+}
+
+
diff --git a/backend/routes/admin.routes.js b/backend/routes/admin.routes.js
index 5a15e05..3dc9bd8 100644
--- a/backend/routes/admin.routes.js
+++ b/backend/routes/admin.routes.js
@@ -1,11 +1,11 @@
-const router = require("express").Router();
-const auth = require("../middleware/auth");
-const requireRole = require("../middleware/rbac");
-const usersController = require("../controllers/users.controller");
-const { ROLES } = require("../models/user.model");
-
-router.get("/users", auth, requireRole(ROLES.ADMIN), usersController.getAllUsers);
-router.put("/users", auth, requireRole(ROLES.ADMIN), usersController.updateUserRole);
-router.delete("/users", auth, requireRole(ROLES.ADMIN), usersController.deleteUser);
-
-module.exports = router;
+const router = require("express").Router();
+const auth = require("../middleware/auth");
+const requireRole = require("../middleware/rbac");
+const usersController = require("../controllers/users.controller");
+const { ROLES } = require("../models/user.model");
+
+router.get("/users", auth, requireRole(ROLES.ADMIN), usersController.getAllUsers);
+router.put("/users", auth, requireRole(ROLES.ADMIN), usersController.updateUserRole);
+router.delete("/users", auth, requireRole(ROLES.ADMIN), usersController.deleteUser);
+
+module.exports = router;
diff --git a/backend/routes/auth.routes.js b/backend/routes/auth.routes.js
index dba137e..75db9de 100644
--- a/backend/routes/auth.routes.js
+++ b/backend/routes/auth.routes.js
@@ -1,13 +1,13 @@
-const router = require("express").Router();
-const controller = require("../controllers/auth.controller");
-
-router.post("/register", controller.register);
-router.post("/login", controller.login);
-router.post("/", async (req, res) => {
- resText = `Grocery List API is running.\n` +
- `Roles available: ${Object.values(User.ROLES).join(', ')}`
-
- res.status(200).type("text/plain").send(resText);
-});
-
-module.exports = router;
+const router = require("express").Router();
+const controller = require("../controllers/auth.controller");
+
+router.post("/register", controller.register);
+router.post("/login", controller.login);
+router.post("/", async (req, res) => {
+ resText = `Grocery List API is running.\n` +
+ `Roles available: ${Object.values(User.ROLES).join(', ')}`
+
+ res.status(200).type("text/plain").send(resText);
+});
+
+module.exports = router;
diff --git a/backend/routes/list.routes.js b/backend/routes/list.routes.js
index e73b2b8..63e6026 100644
--- a/backend/routes/list.routes.js
+++ b/backend/routes/list.routes.js
@@ -1,19 +1,19 @@
-const router = require("express").Router();
-const controller = require("../controllers/lists.controller");
-const auth = require("../middleware/auth");
-const requireRole = require("../middleware/rbac");
-const { ROLES } = require("../models/user.model");
-const User = require("../models/user.model");
-
-
-
-router.get("/", auth, requireRole(...Object.values(ROLES)), controller.getList);
-router.get("/item-by-name", auth, requireRole(...Object.values(ROLES)), controller.getItemByName);
-router.get("/suggest", auth, requireRole(...Object.values(ROLES)), controller.getSuggestions);
-
-
-router.post("/add", auth, requireRole(ROLES.EDITOR, ROLES.ADMIN), controller.addItem);
-router.post("/mark-bought", auth, requireRole(ROLES.EDITOR, ROLES.ADMIN), controller.markBought);
-
-
-module.exports = router;
+const router = require("express").Router();
+const controller = require("../controllers/lists.controller");
+const auth = require("../middleware/auth");
+const requireRole = require("../middleware/rbac");
+const { ROLES } = require("../models/user.model");
+const User = require("../models/user.model");
+
+
+
+router.get("/", auth, requireRole(...Object.values(ROLES)), controller.getList);
+router.get("/item-by-name", auth, requireRole(...Object.values(ROLES)), controller.getItemByName);
+router.get("/suggest", auth, requireRole(...Object.values(ROLES)), controller.getSuggestions);
+
+
+router.post("/add", auth, requireRole(ROLES.EDITOR, ROLES.ADMIN), controller.addItem);
+router.post("/mark-bought", auth, requireRole(ROLES.EDITOR, ROLES.ADMIN), controller.markBought);
+
+
+module.exports = router;
diff --git a/backend/routes/users.routes.js b/backend/routes/users.routes.js
index e89edbf..c13c5be 100644
--- a/backend/routes/users.routes.js
+++ b/backend/routes/users.routes.js
@@ -1,10 +1,10 @@
-const router = require("express").Router();
-const auth = require("../middleware/auth");
-const requireRole = require("../middleware/rbac");
-const usersController = require("../controllers/users.controller");
-const { ROLES } = require("../models/user.model");
-
-router.get("/exists", usersController.checkIfUserExists);
-router.get("/test", usersController.test);
-
-module.exports = router;
+const router = require("express").Router();
+const auth = require("../middleware/auth");
+const requireRole = require("../middleware/rbac");
+const usersController = require("../controllers/users.controller");
+const { ROLES } = require("../models/user.model");
+
+router.get("/exists", usersController.checkIfUserExists);
+router.get("/test", usersController.test);
+
+module.exports = router;
diff --git a/docker-compose.yml b/docker-compose.yml
index de6750f..259cc37 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -1,29 +1,29 @@
-services:
- frontend:
- build:
- context: ./frontend
- dockerfile: Dockerfile.dev
- environment:
- - NODE_ENV=development
- volumes:
- - ./frontend:/app
- - /app/node_modules
- ports:
- - "3000:5173"
- depends_on:
- - backend
- restart: always
-
-
- backend:
- build:
- context: ./backend
- command: npm run dev
- volumes:
- - ./backend:/app
- - /app/node_modules
- ports:
- - "5000:5000"
- env_file:
- - ./backend/.env
- restart: always
+services:
+ frontend:
+ build:
+ context: ./frontend
+ dockerfile: Dockerfile.dev
+ environment:
+ - NODE_ENV=development
+ volumes:
+ - ./frontend:/app
+ - /app/node_modules
+ ports:
+ - "3000:5173"
+ depends_on:
+ - backend
+ restart: always
+
+
+ backend:
+ build:
+ context: ./backend
+ command: npm run dev
+ volumes:
+ - ./backend:/app
+ - /app/node_modules
+ ports:
+ - "5000:5000"
+ env_file:
+ - ./backend/.env
+ restart: always
diff --git a/frontend/src/App.jsx b/frontend/src/App.jsx
index d897821..f89c9c9 100644
--- a/frontend/src/App.jsx
+++ b/frontend/src/App.jsx
@@ -1,53 +1,53 @@
-import { BrowserRouter, Route, Routes } from "react-router-dom";
-import { ROLES } from "./constants/roles";
-import { AuthProvider } from "./context/AuthContext.jsx";
-
-import AdminPanel from "./pages/AdminPanel.jsx";
-import GroceryList from "./pages/GroceryList.jsx";
-import Login from "./pages/Login.jsx";
-import Register from "./pages/Register.jsx";
-
-import AppLayout from "./components/AppLayout.jsx";
-import PrivateRoute from "./utils/PrivateRoute.jsx";
-
-import RoleGuard from "./utils/RoleGuard.jsx";
-
-console.log("VITE_ALLOWED_HOSTS:", import.meta.env.VITE_ALLOWED_HOSTS);
-
-function App() {
- return (
-
Loading...
; - - return ( -Loading...
; + + return ( +{error}
} - - - -- Need an account? Register here -
-{error}
} + + + ++ Need an account? Register here +
+