farheen-psql-app 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/.env ADDED
@@ -0,0 +1,8 @@
1
+ PORT=3000
2
+ DB_USER=postgres
3
+ DB_PASSWORD=farheen
4
+ DB_HOST=localhost
5
+ DB_PORT=5432
6
+ DB_NAME=farheen_db
7
+
8
+ JWT_SECRET_KEY=mysupersecretkey
package/package.json ADDED
@@ -0,0 +1,24 @@
1
+ {
2
+ "name": "farheen-psql-app",
3
+ "version": "1.0.0",
4
+ "main": "index.js",
5
+ "type": "module",
6
+ "scripts": {
7
+ "test": "echo \"Error: no test specified\" && exit 1",
8
+ "start": "node src/server.js",
9
+ "db:setup": "node script/setupdb.js"
10
+ },
11
+ "keywords": [],
12
+ "author": "",
13
+ "license": "ISC",
14
+ "description": "",
15
+ "dependencies": {
16
+ "bcryptjs": "^3.0.3",
17
+ "cors": "^2.8.6",
18
+ "dotenv": "^17.4.2",
19
+ "express": "^5.2.1",
20
+ "jsonwebtoken": "^9.0.3",
21
+ "node-pg-migrate": "^8.0.4",
22
+ "pg": "^8.21.0"
23
+ }
24
+ }
package/src/app.js ADDED
@@ -0,0 +1,14 @@
1
+ import express from "express";
2
+ const app = express();
3
+ import indexRoutes from "../src/routes/index.js";
4
+
5
+ app.use(cors());
6
+ app.use(express.json());
7
+
8
+ app.use("/api", indexRoutes);
9
+
10
+ app.use("/", () => {
11
+ console.log("Health check of the app");
12
+ })
13
+
14
+ export default app;
@@ -0,0 +1,15 @@
1
+ import pg from "pg";
2
+ import dotenv from "dotenv";
3
+
4
+ dotenv.config();
5
+ import { Pool } from "pg";
6
+
7
+ const pool = new Pool({
8
+ user: process.env.DB_USER,
9
+ host: process.env.DB_HOST,
10
+ database: process.env.DB_NAME,
11
+ password: process.env.DB_PASSWORD,
12
+ port: process.env.DB_PORT
13
+ })
14
+
15
+ export default pool;
@@ -0,0 +1,54 @@
1
+ import { createPermission, deletePermission, getAllPermissions } from "../services/permissionService.js";
2
+
3
+ export const createPermissionHandler = (req, res) => {
4
+
5
+ try {
6
+
7
+ const result = await createPermission(req.body);
8
+
9
+ return res.status(201).json({
10
+ success: true,
11
+ data: result
12
+ });
13
+
14
+ } catch (error) {
15
+ return res.status(500).json({
16
+ success: false,
17
+ message: error.message
18
+ });
19
+ }
20
+ }
21
+
22
+ export const getAllPermissionsHandler = (req, res) => {
23
+ try {
24
+ const result = await getAllPermissions();
25
+
26
+ return res.status(200).json({
27
+ success: true,
28
+ data: result
29
+ });
30
+
31
+ } catch (error) {
32
+ return res.status(500).json({
33
+ success: false,
34
+ message: error.message
35
+ });
36
+ }
37
+ }
38
+
39
+ export const deletePermissionHandler = (req, res) => {
40
+ try {
41
+ const result = await deletePermission(req.params.id);
42
+
43
+ return res.status(200).json({
44
+ success: true,
45
+ data: result
46
+ });
47
+
48
+ } catch (error) {
49
+ return res.status(500).json({
50
+ success: false,
51
+ message: error.message
52
+ });
53
+ }
54
+ }
@@ -0,0 +1,11 @@
1
+ import { createRoleService, getAllRolesService } from "../services/roleService.js";
2
+
3
+ export const createRoleHandler = (req, res) => {
4
+ const result = await createRoleService(req.body);
5
+ res.status(201).json(result);
6
+ }
7
+
8
+ export const getAllRoles = (req, res) => {
9
+ const result = await getAllRolesService();
10
+ res.status(200).json(result);
11
+ }
@@ -0,0 +1,76 @@
1
+ import * as userService from '../services/userService.js';
2
+
3
+ export const getAllUsers = async (req, res) => {
4
+ try {
5
+ const users = await userService.getAllUsers();
6
+ res.status(200).json(users);
7
+ } catch (error) {
8
+ console.error('Error fetching users:', error);
9
+ res.status(500).json({ error: 'Internal Server Error' });
10
+ }
11
+ };
12
+
13
+ export const getUserById = async (req, res) => {
14
+ try {
15
+ const { id } = req.params;
16
+ const user = await userService.getUserById(id);
17
+ if (!user) {
18
+ return res.status(404).json({ error: 'User not found' });
19
+ }
20
+ res.status(200).json(user);
21
+ } catch (error) {
22
+ console.error('Error fetching user:', error);
23
+ res.status(500).json({ error: 'Internal Server Error' });
24
+ }
25
+ };
26
+
27
+ export const createUser = async (req, res) => {
28
+ try {
29
+ const { name, email, age } = req.body;
30
+ if (!name || !email) {
31
+ return res.status(400).json({ error: 'Name and email are required' });
32
+ }
33
+ const newUser = await userService.createUser({ name, email, age });
34
+ res.status(201).json(newUser);
35
+ } catch (error) {
36
+ console.error('Error creating user:', error);
37
+ // Handle specific service errors
38
+ if (error.message === 'Age cannot be negative') {
39
+ return res.status(400).json({ error: error.message });
40
+ }
41
+ res.status(500).json({ error: 'Internal Server Error' });
42
+ }
43
+ };
44
+
45
+ export const updateUser = async (req, res) => {
46
+ try {
47
+ const { id } = req.params;
48
+ const { name, email, age } = req.body;
49
+
50
+ const updatedUser = await userService.updateUser(id, { name, email, age });
51
+ if (!updatedUser) {
52
+ return res.status(404).json({ error: 'User not found' });
53
+ }
54
+ res.status(200).json(updatedUser);
55
+ } catch (error) {
56
+ console.error('Error updating user:', error);
57
+ if (error.message === 'Age cannot be negative') {
58
+ return res.status(400).json({ error: error.message });
59
+ }
60
+ res.status(500).json({ error: 'Internal Server Error' });
61
+ }
62
+ };
63
+
64
+ export const deleteUser = async (req, res) => {
65
+ try {
66
+ const { id } = req.params;
67
+ const deletedUser = await userService.deleteUser(id);
68
+ if (!deletedUser) {
69
+ return res.status(404).json({ error: 'User not found' });
70
+ }
71
+ res.status(200).json({ message: 'User deleted successfully', user: deletedUser });
72
+ } catch (error) {
73
+ console.error('Error deleting user:', error);
74
+ res.status(500).json({ error: 'Internal Server Error' });
75
+ }
76
+ };
@@ -0,0 +1,12 @@
1
+ const permissionTable = `
2
+ CREATE TABLE IF NOT EXISTS permissions (
3
+ id SERIAL PRIMARY KEY,
4
+ module VARCHAR(100) NOT NULL,
5
+ action VARCHAR(100) NOT NULL,
6
+ description TEXT,
7
+ created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
8
+ UNIQUE(module, action)
9
+ );
10
+ `;
11
+
12
+ export default permissionTable;
@@ -0,0 +1,21 @@
1
+ const rolePermissionTable = `
2
+ CREATE TABLE IF NOT EXISTS role_permissions (
3
+ id SERIAL PRIMARY KEY,
4
+
5
+ role_id INTEGER NOT NULL,
6
+
7
+ permission_id INTEGER NOT NULL,
8
+
9
+ FOREIGN KEY(role_id)
10
+ REFERENCES roles(id)
11
+ ON DELETE CASCADE,
12
+
13
+ FOREIGN KEY(permission_id)
14
+ REFERENCES permissions(id)
15
+ ON DELETE CASCADE,
16
+
17
+ UNIQUE(role_id, permission_id)
18
+ );
19
+ `;
20
+
21
+ export default rolePermissionTable;
@@ -0,0 +1,12 @@
1
+ const roleTable = `
2
+ CREATE TABLE IF NOT EXISTS roles (
3
+ id SERIAL PRIMARY KEY,
4
+ role_name VARCHAR(100) UNIQUE NOT NULL,
5
+ description TEXT,
6
+ is_active BOOLEAN DEFAULT TRUE,
7
+ created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
8
+ updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
9
+ );
10
+ `;
11
+
12
+ export default roleTable;
@@ -0,0 +1,26 @@
1
+ const userTable = `
2
+ CREATE TABLE IF NOT EXISTS users (
3
+ id SERIAL PRIMARY KEY,
4
+
5
+ first_name VARCHAR(100) NOT NULL,
6
+
7
+ last_name VARCHAR(100),
8
+
9
+ email VARCHAR(255) UNIQUE NOT NULL,
10
+
11
+ password TEXT NOT NULL,
12
+
13
+ role_id INTEGER,
14
+
15
+ is_active BOOLEAN DEFAULT TRUE,
16
+
17
+ created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
18
+
19
+ updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
20
+
21
+ FOREIGN KEY(role_id)
22
+ REFERENCES roles(id)
23
+ );
24
+ `;
25
+
26
+ export default userTable;
@@ -0,0 +1,63 @@
1
+ import pg from "pg";
2
+ import dotenv from "dotenv";
3
+ import { Client } from "pg";
4
+ import roleTable from "./schemas/roleSchema";
5
+ import permissionTable from "./schemas/permissionSchema";
6
+ import rolePermissionTable from "./schemas/rolePermissionSchema";
7
+ import userTable from "./schemas/userSchema";
8
+ import pool from "../config/db.js";
9
+
10
+ dotenv.config();
11
+
12
+ const tables = [
13
+ roleTable,
14
+ permissionTable,
15
+ rolePermissionTable,
16
+ userTable
17
+ ];
18
+
19
+ export const setupdb = async () => {
20
+ const adminclient = new Client({
21
+ user: process.env.DB_USER,
22
+ host: process.env.DB_HOST,
23
+ database: 'postgres',
24
+ password: process.env.DB_PASSWORD,
25
+ port: process.env.DB_PORT
26
+ })
27
+
28
+ try {
29
+ await adminclient.connect();
30
+ console.log("Connected to admin database");
31
+
32
+ const dbName = process.env.DB_NAME;
33
+ const connectDbResult = await adminclient.query(
34
+ "SELECT 1 FROM pg_database WHERE datname = $1",
35
+ [dbName]
36
+ );
37
+
38
+ if (connectDbResult.rowCount === 0) {
39
+ console.log(`Databse '${dbName}' does not exit. Creating....`);
40
+ await adminclient.query(`CREATE DATABASE "${dbName}"`);
41
+ console.log(`Databse '${dbName}' created successfully`);
42
+ } else {
43
+ console.log(`Database '${dbName}' already exist.`);
44
+ }
45
+
46
+ try {
47
+ for (const table of tables) {
48
+ await pool.query(table);
49
+ }
50
+
51
+ console.log("✅ All tables created");
52
+
53
+ } catch (error) {
54
+ console.error("❌ Setup Error:", error);
55
+ }
56
+ } catch (error) {
57
+ console.error("Error creating/checking database", error);
58
+ } finally {
59
+ await adminclient.end();
60
+ }
61
+ }
62
+
63
+ // setupdb();
@@ -0,0 +1,5 @@
1
+ export const authorization = (module, action) => {
2
+ async (req, res, next) => {
3
+ const user = await U
4
+ }
5
+ }
@@ -0,0 +1,17 @@
1
+ import { verifyToken } from "../utils/jwt.js";
2
+
3
+ export const authentication = async (req, res, next) => {
4
+ try {
5
+ const token = req.headers.authorization.split(" ")[1];
6
+
7
+ if (!token) {
8
+ return res.status(403).json({ error: 'Unauthorized: No token provided' });
9
+ }
10
+
11
+ const decoded = verifyToken(token);
12
+ req.user = decoded;
13
+ next();
14
+ } catch (error) {
15
+ return res.status(401).json({ error: 'Unauthorized: Invalid token' });
16
+ }
17
+ }
@@ -0,0 +1,48 @@
1
+ export const createPermissionQuery = `
2
+ INSERT INTO permissions
3
+ (
4
+ permission_name,
5
+ description,
6
+ created_at
7
+ )
8
+ VALUES
9
+ (
10
+ $1,
11
+ $2,
12
+ NOW()
13
+ )
14
+ RETURNING *;
15
+ `;
16
+
17
+ export const getPermissionByIdQuery = `
18
+ SELECT *
19
+ FROM permissions
20
+ WHERE id = $1;
21
+ `;
22
+
23
+ export const getPermissionByNameQuery = `
24
+ SELECT *
25
+ FROM permissions
26
+ WHERE permission_name = $1;
27
+ `;
28
+
29
+ export const getAllPermissionsQuery = `
30
+ SELECT *
31
+ FROM permissions
32
+ ORDER BY id;
33
+ `;
34
+
35
+ export const updatePermissionQuery = `
36
+ UPDATE permissions
37
+ SET
38
+ permission_name = $1,
39
+ description = $2
40
+ WHERE id = $3
41
+ RETURNING *;
42
+ `;
43
+
44
+ export const deletePermissionQuery = `
45
+ DELETE FROM permissions
46
+ WHERE id = $1
47
+ RETURNING *;
48
+ `;
@@ -0,0 +1,48 @@
1
+ export const createRoleQuery = `
2
+ INSERT INTO roles
3
+ (
4
+ role_name,
5
+ description,
6
+ created_at
7
+ )
8
+ VALUES
9
+ (
10
+ $1,
11
+ $2,
12
+ NOW()
13
+ )
14
+ RETURNING *;
15
+ `;
16
+
17
+ export const getRoleByIdQuery = `
18
+ SELECT *
19
+ FROM roles
20
+ WHERE id = $1;
21
+ `;
22
+
23
+ export const getRoleByNameQuery = `
24
+ SELECT *
25
+ FROM roles
26
+ WHERE role_name = $1;
27
+ `;
28
+
29
+ export const getAllRolesQuery = `
30
+ SELECT *
31
+ FROM roles
32
+ ORDER BY id;
33
+ `;
34
+
35
+ export const updateRoleQuery = `
36
+ UPDATE roles
37
+ SET
38
+ role_name = $1,
39
+ description = $2
40
+ WHERE id = $3
41
+ RETURNING *;
42
+ `;
43
+
44
+ export const deleteRoleQuery = `
45
+ DELETE FROM roles
46
+ WHERE id = $1
47
+ RETURNING *;
48
+ `;
@@ -0,0 +1,29 @@
1
+ export const assignPermissionToRoleQuery = `
2
+ INSERT INTO role_permissions
3
+ (
4
+ role_id,
5
+ permission_id
6
+ )
7
+ VALUES
8
+ (
9
+ $1,
10
+ $2
11
+ )
12
+ RETURNING *;
13
+ `;
14
+
15
+ export const removePermissionFromRoleQuery = `
16
+ DELETE FROM role_permissions
17
+ WHERE role_id = $1
18
+ AND permission_id = $2;
19
+ `;
20
+
21
+ export const getRolePermissionsQuery = `
22
+ SELECT
23
+ p.id,
24
+ p.permission_name
25
+ FROM role_permissions rp
26
+ INNER JOIN permissions p
27
+ ON rp.permission_id = p.id
28
+ WHERE rp.role_id = $1;
29
+ `;
@@ -0,0 +1,72 @@
1
+ export const createUserQuery = `
2
+ INSERT INTO users
3
+ (
4
+ first_name,
5
+ last_name,
6
+ email,
7
+ password,
8
+ role_id,
9
+ is_active,
10
+ created_at,
11
+ updated_at
12
+ )
13
+ VALUES
14
+ (
15
+ $1,
16
+ $2,
17
+ $3,
18
+ $4,
19
+ $5,
20
+ $6,
21
+ NOW(),
22
+ NOW()
23
+ )
24
+ RETURNING *;
25
+ `;
26
+
27
+ export const getUserByIdQuery = `
28
+ SELECT
29
+ u.*,
30
+ r.role_name
31
+ FROM users u
32
+ LEFT JOIN roles r
33
+ ON u.role_id = r.id
34
+ WHERE u.id = $1;
35
+ `;
36
+
37
+ export const getUserByEmailQuery = `
38
+ SELECT *
39
+ FROM users
40
+ WHERE email = $1;
41
+ `;
42
+
43
+ export const getAllUsersQuery = `
44
+ SELECT
45
+ u.id,
46
+ u.first_name,
47
+ u.last_name,
48
+ u.email,
49
+ u.is_active,
50
+ r.role_name
51
+ FROM users u
52
+ LEFT JOIN roles r
53
+ ON u.role_id = r.id;
54
+ `;
55
+
56
+ export const updateUserQuery = `
57
+ UPDATE users
58
+ SET
59
+ first_name = $1,
60
+ last_name = $2,
61
+ email = $3,
62
+ role_id = $4,
63
+ updated_at = NOW()
64
+ WHERE id = $5
65
+ RETURNING *;
66
+ `;
67
+
68
+ export const deleteUserQuery = `
69
+ DELETE FROM users
70
+ WHERE id = $1
71
+ RETURNING *;
72
+ `;
@@ -0,0 +1,47 @@
1
+
2
+
3
+ import pool from "../config/db.js";
4
+ import { createPermissionQuery, deletePermissionQuery,
5
+ getAllPermissionsQuery, getPermissionByIdQuery } from "../models/permission.js";
6
+
7
+ export const createPermission = (data) => {
8
+
9
+ const {
10
+ module,
11
+ action,
12
+ description
13
+ } = data;
14
+
15
+ const result = await pool.query(createPermissionQuery, [module, action, description]);
16
+ return result.rows[0];
17
+ }
18
+
19
+ export const getAllPermissions = () => {
20
+
21
+ const result =
22
+ await pool.query(getAllPermissionsQuery);
23
+
24
+ return result.rows;
25
+ }
26
+
27
+ export const getPermissionById = (id) => {
28
+
29
+ const result =
30
+ await pool.query(
31
+ getPermissionByIdQuery,
32
+ [id]
33
+ );
34
+
35
+ return result.rows[0];
36
+ }
37
+
38
+ export const deletePermission = (id) => {
39
+
40
+ const result =
41
+ await pool.query(
42
+ deletePermissionQuery,
43
+ [id]
44
+ );
45
+
46
+ return result.rows[0];
47
+ }
@@ -0,0 +1,12 @@
1
+ import pool from "../config/db.js";
2
+ import { createRoleQuery, getAllRolesQuery } from "../models/role.js";
3
+
4
+ export const createRole = (data) => {
5
+ const result = await pool.query(createRoleQuery, [data.role_name, data.description]);
6
+ return result.rows[0];
7
+ }
8
+
9
+ export const getAllRoles = () => {
10
+ const result = await pool.query(getAllRolesQuery);
11
+ return result.rows;
12
+ }
@@ -0,0 +1,37 @@
1
+ import pool from "../config/db.js";
2
+
3
+ export const create = async (userData) => {
4
+ const { name, email, password, role } = userData;
5
+ const result = await pool.query(
6
+ `INSERT INTO users (name, email, password, role) VALUES ($1, $2, $3, $4) RETURNING *`,
7
+ [name, email, password, role]
8
+ )
9
+ return result.rows[0];
10
+ }
11
+
12
+ export const getAll = async () => {
13
+ const result = await pool.query(`SELECT * FROM user ORDER BY created_at DESC`);
14
+ return result.rows;
15
+ }
16
+
17
+ export const getById = async (id) => {
18
+ const result = await pool.query(`SELECT * FROM users WHERE id = $1`, [id]);
19
+ return result.rows[0];
20
+ }
21
+
22
+ export const getByEmail = async (email) => {
23
+ const result = await pool.query(`SELECT * FROM users WHERE email = $1`, [email]);
24
+ return result.rows[0];
25
+ }
26
+
27
+ export const update = async (id, userData) => {
28
+ const { name, email, role } = userData;
29
+ const result = await pool.query(`UPDATE users SET name = $1, email = $2, role = $3, updated_at = CURRENT_TIMESTAMPS WHERE id = $4 RETURNING *`,
30
+ [name, email, role, id]);
31
+ return result.rows[0];
32
+ }
33
+
34
+ export const remove = async (id) => {
35
+ const result = await pool.query(`DELETE FROM users WHERE id = $1 RETURNING *`, [id]);
36
+ return result.rows[0];
37
+ }
@@ -0,0 +1,4 @@
1
+ import express from "express";
2
+ const router = express.Router();
3
+
4
+ export default router;
@@ -0,0 +1,7 @@
1
+ import express from "express";
2
+ const router = express.Router();
3
+
4
+ router.post("/", );
5
+ router.get("/", );
6
+
7
+ export default router;
package/src/server.js ADDED
@@ -0,0 +1,27 @@
1
+ import express from "express";
2
+ import dotenv from "dotenv";
3
+ import pool from "./config/db.js";
4
+ import app from "./app";
5
+ import { setupdb } from "./database/setupdb.js";
6
+
7
+ const port = process.env.PORT;
8
+
9
+ dotenv.config();
10
+
11
+ const startServer = async () => {
12
+ try {
13
+ const client = await pool.connect();
14
+ console.log("Connected to PostgreSQL database successfully");
15
+
16
+ await setupdb();
17
+
18
+ app.listen(port, () => {
19
+ console.log(`Server is running on port '${port}'`);
20
+ })
21
+ } catch (error) {
22
+ console.error("Error connecting to the database", error);
23
+ process.exit(1);
24
+ }
25
+ }
26
+
27
+ startServer();
@@ -0,0 +1,21 @@
1
+ import permissionRepository
2
+ from "../repositories/permissionRepository.js";
3
+
4
+
5
+ export const createPermission = async (data) => {
6
+
7
+ return await permissionRepository
8
+ .createPermission(data);
9
+ }
10
+
11
+ export const getAllPermissions = async () => {
12
+
13
+ return await permissionRepository
14
+ .getAllPermissions();
15
+ }
16
+
17
+ export const deletePermission = async (id) => {
18
+
19
+ return await permissionRepository
20
+ .deletePermission(id);
21
+ }
@@ -0,0 +1,10 @@
1
+ import { getAllRolesQuery } from "../models/role";
2
+ import { createRole } from "../repositories/roleRepository.js";
3
+
4
+ export const createRoleService = (data) => {
5
+ return await createRole(data);
6
+ }
7
+
8
+ export const getAllRolesService = () => {
9
+ return await getAllRolesQuery();
10
+ }
@@ -0,0 +1,28 @@
1
+ import * as userRepository from '../repositories/userRepository.js';
2
+
3
+ export const getAllUsers = async () => {
4
+ return await userRepository.findAll();
5
+ };
6
+
7
+ export const getUserById = async (id) => {
8
+ return await userRepository.findById(id);
9
+ };
10
+
11
+ export const createUser = async (userData) => {
12
+ // Example of business logic in service
13
+ if (userData.age && userData.age < 0) {
14
+ throw new Error('Age cannot be negative');
15
+ }
16
+ return await userRepository.create(userData);
17
+ };
18
+
19
+ export const updateUser = async (id, userData) => {
20
+ if (userData.age && userData.age < 0) {
21
+ throw new Error('Age cannot be negative');
22
+ }
23
+ return await userRepository.update(id, userData);
24
+ };
25
+
26
+ export const deleteUser = async (id) => {
27
+ return await userRepository.remove(id);
28
+ };
@@ -0,0 +1,11 @@
1
+ import jwt from "jsonwebtoken";
2
+
3
+ export const accessToken = (user) => {
4
+ return jwt.sign({ id: user.id, email: user.email, role: user.role },
5
+ process.env.JWT_SECRET_key,
6
+ { expiresIn: '1d' });
7
+ }
8
+
9
+ export const verifyToken = (token) => {
10
+ return jwt.verify(token, process.env.JWT_SECRET_key);
11
+ }