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
320 changes: 320 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,320 @@
# School Management System API Documentation

## Overview

This API provides functionality for managing schools, classrooms, and students with **JWT-based authentication** and **role-based access control (RBAC)**.

## Technologies Used

- **Node.js & Express.js** – Backend framework
- **MongoDB & Mongoose** – Database & ODM
- **Redis** – Caching
- **JWT** – Authentication
- **Jest & Supertest** – Testing

---

## **Authentication**

### **User Signup**

**Endpoint:** `POST /api/auth/signup`

**Request Body:**

```json
{
"name": "Admin",
"email": "[email protected]",
"password": "password",
"role": "superadmin"
}
```

**Response:**

```json
{
"message": "User registered successfully!"
}
```

---

### **User Login**

**Endpoint:** `POST /api/auth/login`

**Request Body:**

```json
{
"email": "[email protected]",
"password": "password"
}
```

**Response:**

```json
{
"token": "JWT_TOKEN"
}
```

---

## **Schools API**

### **Get All Schools**

**Endpoint:** `GET /api/schools`

**Headers:**

```json
{
"Authorization": "Bearer JWT_TOKEN"
}
```

**Response:**

```json
[
{
"_id": "12345",
"name": "Test School",
"address": "123 Street Lane"
}
]
```

---

### **Create a School (Superadmin Only)**

**Endpoint:** `POST /api/schools`

**Headers:**

```json
{
"Authorization": "Bearer JWT_TOKEN"
}
```

**Request Body:**

```json
{
"name": "New School",
"address": "456 Education Ave"
}
```

**Response:**

```json
{
"_id": "67890",
"name": "New School",
"address": "456 Education Ave"
}
```

---

## **Classrooms API**

### **Get All Classrooms**

**Endpoint:** `GET /api/classrooms`

**Headers:**

```json
{
"Authorization": "Bearer JWT_TOKEN"
}
```

**Response:**

```json
[
{
"_id": "abc123",
"school": "12345",
"name": "Class 1",
"capacity": 30
}
]
```

---

### **Create a Classroom**

**Endpoint:** `POST /api/classrooms`

**Headers:**

```json
{
"Authorization": "Bearer JWT_TOKEN"
}
```

**Request Body:**

```json
{
"school": "12345",
"name": "Class 2",
"capacity": 25
}
```

**Response:**

```json
{
"_id": "def456",
"school": "12345",
"name": "Class 2",
"capacity": 25
}
```

---

## **Students API**

### **Get All Students**

**Endpoint:** `GET /api/students`

**Headers:**

```json
{
"Authorization": "Bearer JWT_TOKEN"
}
```

**Response:**

```json
[
{
"_id": "stu789",
"classroom": "abc123",
"name": "John Doe",
"age": 12
}
]
```

---

### **Create a Student**

**Endpoint:** `POST /api/students`

**Headers:**

```json
{
"Authorization": "Bearer JWT_TOKEN"
}
```

**Request Body:**

```json
{
"classroom": "abc123",
"name": "Jane Doe",
"age": 11
}
```

**Response:**

```json
{
"_id": "stu456",
"classroom": "abc123",
"name": "Jane Doe",
"age": 11
}
```

---

## **Validation Rules**

- **School Name & Address:** Required, String
- **Classroom Name & Capacity:** Required, String & Number
- **Student Name & Age:** Required, String & Number

---

## **Testing**

### **Run Tests**

```sh
npm test
```

### **Sample Test Case**

```javascript
describe("School Management API", () => {
it("should return a list of schools", async () => {
const res = await request(app)
.get("/api/schools")
.set("Authorization", `Bearer ${authToken}`);
expect(res.statusCode).toBe(200);
expect(Array.isArray(res.body)).toBeTruthy();
}, 15000);
});
```

---

## **Environment Variables**

Create a `.env` file with the following variables:

```env
PORT=3000
MONGO_URI=mongodb://127.0.0.1:27017/school_db
JWT_SECRET=your_super_secret_key
REDIS_URL=redis://127.0.0.1:6379
```

---

## **Deployment Instructions**

1. **Install Dependencies**
```sh
npm install
```
2. **Start the Server**
```sh
npm start
```
3. **Run Tests**
```sh
npm test
```

---

## **Author**

Developed by **debo24 : https://github.com/debo24** 🚀
51 changes: 29 additions & 22 deletions app.js
Original file line number Diff line number Diff line change
@@ -1,30 +1,37 @@
const config = require('./config/index.config.js');
const Cortex = require('ion-cortex');
const ManagersLoader = require('./loaders/ManagersLoader.js');
const config = require('./config/index.config.js');
const Cortex = require('ion-cortex');
const ManagersLoader = require('./loaders/ManagersLoader.js');
const mongoose =require('mongoose');

const mongoDB = config.dotEnv.MONGO_URI? require('./connect/mongo')({
uri: config.dotEnv.MONGO_URI
}):null;
const mongoDB = mongoose.connect("mongodb://localhost:27017/",{
useNewUrlParser:true,
useCreateIndex:true,
useUnifiedTopology: true
}).then(()=>console.log('DB connected'))

const cache = require('./cache/cache.dbh')({
prefix: config.dotEnv.CACHE_PREFIX ,
prefix: config.dotEnv.CACHE_PREFIX,
url: config.dotEnv.CACHE_REDIS
});

const cortex = new Cortex({
prefix: config.dotEnv.CORTEX_PREFIX,
url: config.dotEnv.CORTEX_REDIS,
type: config.dotEnv.CORTEX_TYPE,
state: ()=>{
return {}
},
activeDelay: "50ms",
idlDelay: "200ms",
});



const managersLoader = new ManagersLoader({config, cache, cortex});
const managers = managersLoader.load();
let cortex = null;
if (config.dotEnv.CORTEX_PREFIX && cache && mongoDB) {
try {
cortex = new Cortex({
prefix: config.dotEnv.CORTEX_PREFIX,
cache,
database: mongoDB,
});
} catch (error) {
console.error("Failed to initialize Cortex:", error.message);
}
} else {
console.warn("⚠️ Warning: Cortex is not initialized due to missing parameters.");
}

managers.userServer.run();
module.exports = {
cortex,
mongoDB,
cache,
};
6 changes: 3 additions & 3 deletions config/index.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@ const CACHE_PREFIX = process.env.CACHE_PREFIX || `${SERVICE_

const MONGO_URI = process.env.MONGO_URI || `mongodb://localhost:27017/${SERVICE_NAME}`;
const config = require(`./envs/${ENV}.js`);
const LONG_TOKEN_SECRET = process.env.LONG_TOKEN_SECRET || null;
const SHORT_TOKEN_SECRET = process.env.SHORT_TOKEN_SECRET || null;
const NACL_SECRET = process.env.NACL_SECRET || null;
const LONG_TOKEN_SECRET = process.env.LONG_TOKEN_SECRET || 'HFDHKSFDSFNCSFIDFDIFERINS3SDSI';
const SHORT_TOKEN_SECRET = process.env.SHORT_TOKEN_SECRET || 'HFDHKSFDSFNCSFIDFDIFERINS3SDSI';
const NACL_SECRET = process.env.NACL_SECRET || 'HFDHKSFDSFNCSFIDFDIFERINS3SDSI';

if(!LONG_TOKEN_SECRET || !SHORT_TOKEN_SECRET || !NACL_SECRET) {
throw Error('missing .env variables check index.config');
Expand Down
Loading