Easily track and manage your CCTV cameras.
The CCTV management app
is a simple management CCTV app, designed for organizations, groups, or companies to manage their CCTV cameras and provide daily reporting on the installed CCTV. Users with specific roles can register the CCTV they oversee in the system and create reports based on the events captured by the CCTV cameras daily.
- CCTV management app contents
Application Stacks:
- Makefile
- Express
- Node JS
- Mongo DB
- Mongoose ODM
- Docker
- Docker Compose
To run this app, follow this steps:
-
Make sure you have Makefile, Docker and Docker Compose installed and configured on your system.
-
Clone this repository:
git clone https://github.com/vinutama/kecilin-cctv-tht.git
-
Navigate to the project directory:
cd kecilin-cctv-tht
-
Create .env file called
app.env
and fill the following:DB_NAME=You desired database name DB_HOST=Database hosting on docker container DB_USER=Database root user name DB_PASSWORD=Database root user password DB_PORT=Database Port BCRYPT_SALT=Your desired bcrypt salt JWT_SECRET=Your JWR secret ADMIN_USER=Default created admin username ADMIN_PASS=Default created admin password (must contains lower case, upper case, number and special character)
-
Create .env file called
db.env
and fill the following:MONGO_INITDB_ROOT_USERNAME=Default DB Admin user MongoDB MONGO_INITDB_ROOT_PASSWORD=Default DB Admin password MongoDB MONGO_INITDB_DATABASE=Initialize database name that want to be created INIT_DB_USER=Must same with DB_USER defined on `app.env` INIT_DB_PASSWORD=Must same with DB_PASSWORD defined on `app.env`
-
Open your terminal and run:
make fresh-start
if you want to make sure to see the logs from the server run:
make logs-web
Wait server's container connected to MongoDB container
-
You are good to go! open the http://localhost:3000.
- Authentication and Authorization
- User management (CRUD)
- CCTV management (CRUD), pagination, filtering
- Report management (CRUD), pagination, filtering
- Detailed validations
-
📖 API Contents
-
User Section API
-
CCTV Section API
-
Report Section API
-
By default, this app created one user superadmin.
The credetianls is based on value in your app.env
ADMIN_USER
ADMIN_PASS
superadmin
admin
maintainer
requestBody = {
username: String,
/*
validation:
- required
*/
password: String,
/*
validation:
- required
- minimum length 6
- must contains uppercase, lettercase, digit and special characters
*/
};
response = {
message: "", // success message
data: {
accessToken: "",
id: "",
username: "",
role: "",
},
};
// Need Authenticate and Only admin can add new User
requestHeaders = {Authorization: <superAdminToken>}
requestBody = {
name: String,
/*
validation:
- required
*/
username: String,
/*
validation:
- required
- unique
*/
password: String,
/*
validation:
- required
- minimum length 6
- must contains uppercase, lettercase, digit and special characters
*/
role: String,
/*
validation:
- cannot create user more than 1 role "superadmin"
- optional by default: "maintainer"
- if provided, validate ENUM ("superadmin", "admin", "maintainer")
*/
};
response = {
message: "", // success message
data: {
accessToken: "",
id: "",
username: "",
role: "",
},
};
// Need Authenticate and only superadmin can get list users
requestHeaders = {Authorization: <superAdminToken>}
response = {
message: "", // success message
data: [
{
id: "",
name: "",
username: "",
password: "",
role: "",
createdAt: "",
updatedAt: "",
},
...
]
};
// Need Authenticate and Only admin can add new User
requestHeaders = {Authorization: <superAdminToken>}
requestBody = {
name: String,
/*
validation:
- optional
*/
username: String,
/*
validation:
- optional
- unique
*/
password: String,
/*
validation:
- optional
- minimum length 6
- must contains uppercase, lettercase, digit and special characters
*/
role: String,
/*
validation:
- optional
- cannot create user more than 1 role "superadmin"
- optional by default: "maintainer"
- if provided, validate ENUM ("superadmin", "admin", "maintainer")
*/
};
response = {
message: "", // success message
data: {
accessToken: "",
id: "",
username: "",
role: "",
},
};
// Need Authenticate and Only admin can add new User
requestHeaders = {Authorization: <superAdminToken>}
response = {
message: "", // success message
data: {
accessToken: "",
id: "",
username: "",
role: "",
},
};
// Need Authenticate and Only superadmin || admin role can register new CCTV
requestHeaders = {Authorization: <superAdminToken> || <adminToken>}
requestBody = {
model: String,
/*
validation:
- required
*/
area: String,
/*
validation:
- required
*/
ipAddress: String,
/*
validation:
- required
- unique
- must IPv4 format
*/
status: String,
/*
validation:
- optional by default: "inactive"
- if provided, validate ENUM ("active", "inactive")
*/
notes: String,
/*
validation:
- optional
*/
};
response = {
message: "", // success message
data: {
id: "",
model: "",
area: "",
ipAddress: "",
status: "",
notes: ""
createdAt: "",
updatedAt: "",
},
};
// Need Authenticate and All user role can get and search CCTVs
requestHeaders = {Authorization: <allToken>}
// all request query OPTIONAL
requestQuery = {
model: String,
/*
Filter based on model name (case-insensitive)
*/
area: String,
/*
Filter based on area (case-insensitive)
*/
ipAddress: String,
/*
Filter based on IP address (case-insensitive)
*/
status: String,
/*
Filter based on status (case-sensitive)
'active', 'inactive'
*/
sort: String,
/*
Will set data sorted by createdAt
'asc', 'desc
By default is 'desc'
*/
limit: Number,
/*
Will set limit returned row per page
By default: 5
*/
offset: Number,
/*
Will move to the page X
By default: 1
*/
};
response = {
message: "", // success message
data: [
{
id: "",
model: "",
area: "",
ipAddress: "",
status: "",
notes: ""
createdAt: "",
updatedAt: "",
},
...
]
};
// Need Authenticate and All user role can get and search CCTVs
requestHeaders = {Authorization: <allToken>}
response = {
message: "", // success message
data: {
id: "",
model: "",
area: "",
ipAddress: "",
status: "",
notes: ""
createdAt: "",
updatedAt: "",
},
};
// Need Authenticate and Only superadmin || admin role can edit CCTV data
requestHeaders = {Authorization: <superAdminToken> || <adminToken>}
// All request body is OPTIONAL
requestBody = {
model: String,
/*
validation:
- required
*/
area: String,
/*
validation:
- required
- unique
*/
ipAddress: String,
/*
validation:
- required
- unique
- must IPv4 format
*/
status: String,
/*
validation:
- optional by default: "inactive"
- if provided, validate ENUM ("active", "inactive")
*/
notes: String,
/*
validation:
- optional
*/
};
response = {
message: "", // success message
data: {
id: "",
model: "",
area: "",
ipAddress: "",
status: "",
notes: ""
createdAt: "",
updatedAt: "",
},
};
- Validation rules:
- Can only delete when CCTV's status is
inactive
- Can only delete when CCTV's status is
// Need Authenticate and Only superadmin || admin role can delete CCTV data
requestHeaders = {Authorization: <superAdminToken> || <adminToken>}
response = {
message: "", // success message
data: {
id: "",
model: "",
area: "",
ipAddress: "",
status: "",
notes: ""
createdAt: "",
updatedAt: "",
},
};
// Need Authenticate and superadmin || admin || maintainer role can register new Report
requestHeaders = {Authorization: <superAdminToken> || <adminToken> || <maintainerToken>}
requestBody = {
description: String,
/*
validation:
- optional
*/
status: String,
/*
validation:
- need to validated with this ENUM:
('investigate', 'suspicious, 'criminal_detected', 'clear')
- by default: "investigate"
*/
};
response = {
message: "", // success message
data: {
id: "",
description: "",
status: "",
owner: "",
createdAt: "",
updatedAt: "",
},
};
- user role
superadmin
oradmin
it will get all user reports - user role
maintainer
it will get only owned reports
requestHeaders = {Authorization: <allToken>}
// all request query OPTIONAL
requestQuery = {
userId: String,
/*
Filter based on owner
*/
status: String,
/*
Filter based on status
('investigate', 'suspicious, 'criminal_detected', 'clear')
*/
date: String,
/*
Filter based on exact date with format (DDDD-MM-YY)
ex: ?date=2024-05-11
*/
sort: String,
/*
Will set data sorted by createdAt
'asc', 'desc
By default is 'desc'
*/
limit: Number,
/*
Will set limit returned row per page
By default: 5
*/
offset: Number,
/*
Will move to the page X
By default: 1
*/
};
response = {
message: "", // success message
data: [
{
id: "",
description: "",
status: "",
owner: "",
createdAt: "",
updatedAt: "",
},
...
]
};
requestHeaders = {Authorization: <superAdminToken> || <adminToken> || <maintainerToken>}
response = {
message: "", // success message
data: {
id: "",
description: "",
status: "",
owner: "",
createdAt: "",
updatedAt: "",
},
};
// Need authenticate and only report owner can edit
requestHeaders = {Authorization: <reportOwnerToken>}
requestBody = {
description: String,
/*
validation:
- optional
*/
status: String,
/*
validation:
- need to validated with this ENUM:
('investigate', 'suspicious, 'criminal_detected', 'clear')
- by default: "investigate"
*/
};
response = {
message: "", // success message
data: {
id: "",
description: "",
status: "",
owner: "",
createdAt: "",
updatedAt: "",
},
};
// Need authenticate and only report owner can delete
requestHeaders = {Authorization: <reportOwnerToken>}
response = {
message: "", // success message
data: {
id: "",
description: "",
status: "",
owner: "",
createdAt: "",
updatedAt: "",
},
};