UC done v1.0
This commit is contained in:
Generated
+8
@@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ProjectModuleManager">
|
||||||
|
<modules>
|
||||||
|
<module fileurl="file://$PROJECT_DIR$/.idea/proiect-licenta.iml" filepath="$PROJECT_DIR$/.idea/proiect-licenta.iml" />
|
||||||
|
</modules>
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
Generated
+12
@@ -0,0 +1,12 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<module type="WEB_MODULE" version="4">
|
||||||
|
<component name="NewModuleRootManager">
|
||||||
|
<content url="file://$MODULE_DIR$">
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/.tmp" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/temp" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/tmp" />
|
||||||
|
</content>
|
||||||
|
<orderEntry type="inheritedJdk" />
|
||||||
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
|
</component>
|
||||||
|
</module>
|
||||||
Generated
+6
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="VcsDirectoryMappings">
|
||||||
|
<mapping directory="" vcs="Git" />
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
Generated
+52
@@ -0,0 +1,52 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ChangeListManager">
|
||||||
|
<list default="true" id="2152dea8-6b25-43ba-8914-cdb9ea320ee7" name="Changes" comment="">
|
||||||
|
<change beforePath="$PROJECT_DIR$/NodejsConsoleApp1.sln" beforeDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/NodejsConsoleApp1/NodejsConsoleApp1.njsproj" beforeDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/NodejsConsoleApp1/README.md" beforeDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/NodejsConsoleApp1/app.js" beforeDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/NodejsConsoleApp1/package.json" beforeDir="false" />
|
||||||
|
</list>
|
||||||
|
<option name="SHOW_DIALOG" value="false" />
|
||||||
|
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
||||||
|
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
|
||||||
|
<option name="LAST_RESOLUTION" value="IGNORE" />
|
||||||
|
</component>
|
||||||
|
<component name="Git.Settings">
|
||||||
|
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
|
||||||
|
</component>
|
||||||
|
<component name="MarkdownSettingsMigration">
|
||||||
|
<option name="stateVersion" value="1" />
|
||||||
|
</component>
|
||||||
|
<component name="ProjectColorInfo"><![CDATA[{
|
||||||
|
"customColor": "",
|
||||||
|
"associatedIndex": 7
|
||||||
|
}]]></component>
|
||||||
|
<component name="ProjectId" id="2eEtibIvxHojohW7av6S4GEmw3j" />
|
||||||
|
<component name="ProjectViewState">
|
||||||
|
<option name="hideEmptyMiddlePackages" value="true" />
|
||||||
|
<option name="showLibraryContents" value="true" />
|
||||||
|
</component>
|
||||||
|
<component name="PropertiesComponent"><![CDATA[{
|
||||||
|
"keyToString": {
|
||||||
|
"RunOnceActivity.OpenProjectViewOnStart": "true",
|
||||||
|
"RunOnceActivity.ShowReadmeOnStart": "true",
|
||||||
|
"last_opened_file_path": "C:/Users/Andrei Cerbu/Documents/FACULTATE/proiect-licenta/UC",
|
||||||
|
"nodejs_package_manager_path": "npm",
|
||||||
|
"vue.rearranger.settings.migration": "true"
|
||||||
|
}
|
||||||
|
}]]></component>
|
||||||
|
<component name="SpellCheckerSettings" RuntimeDictionaries="0" Folders="0" CustomDictionaries="0" DefaultDictionary="application-level" UseSingleDictionary="true" transferred="true" />
|
||||||
|
<component name="TaskManager">
|
||||||
|
<task active="true" id="Default" summary="Default task">
|
||||||
|
<changelist id="2152dea8-6b25-43ba-8914-cdb9ea320ee7" name="Changes" comment="" />
|
||||||
|
<created>1711481695345</created>
|
||||||
|
<option name="number" value="Default" />
|
||||||
|
<option name="presentableId" value="Default" />
|
||||||
|
<updated>1711481695345</updated>
|
||||||
|
<workItem from="1711481698534" duration="22000" />
|
||||||
|
</task>
|
||||||
|
<servers />
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
|
|
||||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
|
||||||
# Visual Studio Version 17
|
|
||||||
VisualStudioVersion = 17.9.34622.214
|
|
||||||
MinimumVisualStudioVersion = 10.0.40219.1
|
|
||||||
Project("{9092AA53-FB77-4645-B42D-1CCCA6BD08BD}") = "NodejsConsoleApp1", "NodejsConsoleApp1\NodejsConsoleApp1.njsproj", "{903FFD42-2EFB-4EBC-868D-ACD6A28F1435}"
|
|
||||||
EndProject
|
|
||||||
Global
|
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
|
||||||
Debug|Any CPU = Debug|Any CPU
|
|
||||||
Release|Any CPU = Release|Any CPU
|
|
||||||
EndGlobalSection
|
|
||||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
|
||||||
{903FFD42-2EFB-4EBC-868D-ACD6A28F1435}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{903FFD42-2EFB-4EBC-868D-ACD6A28F1435}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{903FFD42-2EFB-4EBC-868D-ACD6A28F1435}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{903FFD42-2EFB-4EBC-868D-ACD6A28F1435}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
EndGlobalSection
|
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
|
||||||
HideSolutionNode = FALSE
|
|
||||||
EndGlobalSection
|
|
||||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
|
||||||
SolutionGuid = {CE066DFD-4EDF-4BE5-8C93-6638F0A8D00B}
|
|
||||||
EndGlobalSection
|
|
||||||
EndGlobal
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
|
|
||||||
<PropertyGroup>
|
|
||||||
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion>
|
|
||||||
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
|
|
||||||
<Name>NodejsConsoleApp1</Name>
|
|
||||||
<RootNamespace>NodejsConsoleApp1</RootNamespace>
|
|
||||||
</PropertyGroup>
|
|
||||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
|
||||||
<PropertyGroup>
|
|
||||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
|
||||||
<SchemaVersion>2.0</SchemaVersion>
|
|
||||||
<ProjectGuid>903ffd42-2efb-4ebc-868d-acd6a28f1435</ProjectGuid>
|
|
||||||
<ProjectHome>.</ProjectHome>
|
|
||||||
<StartupFile>app.js</StartupFile>
|
|
||||||
<StartWebBrowser>False</StartWebBrowser>
|
|
||||||
<SearchPath>
|
|
||||||
</SearchPath>
|
|
||||||
<WorkingDirectory>.</WorkingDirectory>
|
|
||||||
<OutputPath>.</OutputPath>
|
|
||||||
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
|
||||||
<ProjectTypeGuids>{3AF33F2E-1136-4D97-BBB7-1795711AC8B8};{9092AA53-FB77-4645-B42D-1CCCA6BD08BD}</ProjectTypeGuids>
|
|
||||||
<StartWebBrowser>false</StartWebBrowser>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
|
|
||||||
<DebugSymbols>true</DebugSymbols>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
|
|
||||||
<DebugSymbols>true</DebugSymbols>
|
|
||||||
</PropertyGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<Content Include="app.js" />
|
|
||||||
<Content Include="package.json" />
|
|
||||||
<Content Include="README.md" />
|
|
||||||
</ItemGroup>
|
|
||||||
<Import Project="$(VSToolsPath)\Node.js Tools\Microsoft.NodejsToolsV2.targets" />
|
|
||||||
</Project>
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
# NodejsConsoleApp1
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
console.log('Hello world');
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "nodejs-console-app1",
|
|
||||||
"version": "0.0.0",
|
|
||||||
"description": "NodejsConsoleApp1",
|
|
||||||
"main": "app.js",
|
|
||||||
"author": {
|
|
||||||
"name": ""
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"eslint": "^8.21.0"
|
|
||||||
},
|
|
||||||
"eslintConfig": {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Generated
+5
@@ -0,0 +1,5 @@
|
|||||||
|
# Default ignored files
|
||||||
|
/shelf/
|
||||||
|
/workspace.xml
|
||||||
|
# Editor-based HTTP Client requests
|
||||||
|
/httpRequests/
|
||||||
Generated
+1
@@ -0,0 +1 @@
|
|||||||
|
package.json
|
||||||
Generated
+12
@@ -0,0 +1,12 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<module type="WEB_MODULE" version="4">
|
||||||
|
<component name="NewModuleRootManager">
|
||||||
|
<content url="file://$MODULE_DIR$">
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/.tmp" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/temp" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/tmp" />
|
||||||
|
</content>
|
||||||
|
<orderEntry type="inheritedJdk" />
|
||||||
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
|
</component>
|
||||||
|
</module>
|
||||||
Generated
+12
@@ -0,0 +1,12 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<module type="WEB_MODULE" version="4">
|
||||||
|
<component name="NewModuleRootManager">
|
||||||
|
<content url="file://$MODULE_DIR$">
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/.tmp" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/temp" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/tmp" />
|
||||||
|
</content>
|
||||||
|
<orderEntry type="inheritedJdk" />
|
||||||
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
|
</component>
|
||||||
|
</module>
|
||||||
Generated
+6
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="JavaScriptLibraryMappings">
|
||||||
|
<includedPredefinedLibrary name="Node.js Core" />
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
Generated
+6
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="JavaScriptSettings">
|
||||||
|
<option name="languageLevel" value="FLOW" />
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
Generated
+8
@@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ProjectModuleManager">
|
||||||
|
<modules>
|
||||||
|
<module fileurl="file://$PROJECT_DIR$/.idea/backend.iml" filepath="$PROJECT_DIR$/.idea/backend.iml" />
|
||||||
|
</modules>
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
Generated
+11
@@ -0,0 +1,11 @@
|
|||||||
|
<component name="ProjectRunConfigurationManager">
|
||||||
|
<configuration default="false" name="bin\www" type="NodeJSConfigurationType" path-to-js-file="bin/www" working-dir="$PROJECT_DIR$">
|
||||||
|
<envs>
|
||||||
|
<env name="DEBUG" value="backend:*" />
|
||||||
|
</envs>
|
||||||
|
<EXTENSION ID="com.jetbrains.nodejs.run.NodeStartBrowserRunConfigurationExtension">
|
||||||
|
<browser url="http://localhost:3000/" />
|
||||||
|
</EXTENSION>
|
||||||
|
<method v="2" />
|
||||||
|
</configuration>
|
||||||
|
</component>
|
||||||
Generated
+8
@@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="VcsDirectoryMappings">
|
||||||
|
<mapping directory="$PROJECT_DIR$/../.." vcs="Git" />
|
||||||
|
<mapping directory="$PROJECT_DIR$/.." vcs="Git" />
|
||||||
|
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
Generated
+1804
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,29 @@
|
|||||||
|
{
|
||||||
|
"name": "uc",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "",
|
||||||
|
"main": "app.js",
|
||||||
|
"scripts": {
|
||||||
|
"start": "node ./src/app.js",
|
||||||
|
"dev": "nodemon ./src/app.js"
|
||||||
|
},
|
||||||
|
"keywords": [],
|
||||||
|
"author": "Cerbu Andrei- Mihnea",
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"axios": "^1.6.8",
|
||||||
|
"body-parser": "^1.20.2",
|
||||||
|
"cheerio": "^1.0.0-rc.12",
|
||||||
|
"cors": "^2.8.5",
|
||||||
|
"cron": "^3.1.6",
|
||||||
|
"crypto-js": "^4.2.0",
|
||||||
|
"express": "^4.19.1",
|
||||||
|
"joi": "^17.12.2",
|
||||||
|
"json": "^11.0.0",
|
||||||
|
"uuid": "^9.0.1"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"concurrently": "^8.2.2",
|
||||||
|
"nodemon": "^3.1.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
const express = require('express');
|
||||||
|
const {json} = require("body-parser");
|
||||||
|
const cors = require('cors');
|
||||||
|
|
||||||
|
const app = express();
|
||||||
|
const port = process.env.PORT || 5000;
|
||||||
|
|
||||||
|
app.use(cors());
|
||||||
|
app.use(json());
|
||||||
|
|
||||||
|
app.locals.apiKey = 'uc_api'
|
||||||
|
|
||||||
|
const checkJson = require('./middlewares/checkJson');
|
||||||
|
const apiKeyValidation = require('./middlewares/apiKeyValidation');
|
||||||
|
const setAdminValues = require('./middlewares/setAdminValues');
|
||||||
|
|
||||||
|
app.use(apiKeyValidation)
|
||||||
|
app.use(checkJson)
|
||||||
|
app.use(setAdminValues);
|
||||||
|
|
||||||
|
const usersRouter = require('./routes/users');
|
||||||
|
const departmentsRouter = require('./routes/departments');
|
||||||
|
const adminRouter = require('./routes/admin');
|
||||||
|
|
||||||
|
app.use('/users', usersRouter);
|
||||||
|
app.use('/departments', departmentsRouter);
|
||||||
|
app.use('/admin', adminRouter);
|
||||||
|
|
||||||
|
app.listen(port, () => {
|
||||||
|
console.log(`Server running on http://localhost:${port}`);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Graceful shutdown function
|
||||||
|
function gracefulShutdown() {
|
||||||
|
console.log('\nGracefully shutting down from SIGINT (Ctrl-C)');
|
||||||
|
|
||||||
|
process.exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
process.on('SIGTERM', gracefulShutdown);
|
||||||
|
process.on('SIGINT', gracefulShutdown);
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"id": "5ad08e32-9d5a-4054-b96f-ba361c02f30a",
|
||||||
|
"dir_config": "{dir_1: {}}",
|
||||||
|
"total_space": 0.1
|
||||||
|
}
|
||||||
|
]
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"adminKey": "590dceb42261808e4a804607b38eb119a09c93d84554bac0d23d705d5c6e8ca5",
|
||||||
|
"ceoID": "5ad08e32-9d5a-4054-b96f-ba361c02f30a"
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"id": "6cd67946-6fe7-46df-9740-25eea7b95f69",
|
||||||
|
"name": "Programatori",
|
||||||
|
"key": "a2bb3329528704715e29c27fd778892d177bcacfd73e38bde818aef560f4d549"
|
||||||
|
}
|
||||||
|
]
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"1": "6cd67946-6fe7-46df-9740-25eea7b95f69"
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"id": "5ad08e32-9d5a-4054-b96f-ba361c02f30a",
|
||||||
|
"name": "Andrei Cerbu",
|
||||||
|
"email": "a@c.com",
|
||||||
|
"password": "4dd45a4455b1db1fd9c204a6d7c26f30"
|
||||||
|
}
|
||||||
|
]
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
class DepartmentAlreadyExistsError extends Error {
|
||||||
|
constructor(message = 'This department is already in system') {
|
||||||
|
super(message);
|
||||||
|
this.name = 'DepartmentAlreadyExistsError';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = DepartmentAlreadyExistsError
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
class DepartmentNotExistingError extends Error {
|
||||||
|
constructor(message = 'Department not found') {
|
||||||
|
super(message);
|
||||||
|
this.name = 'DepartmentNotExistingError';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = DepartmentNotExistingError;
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
class ImproperDirStructureError extends Error {
|
||||||
|
constructor(message = 'the provided structure is not a valid JSON') {
|
||||||
|
super(message);
|
||||||
|
this.name = 'ImproperDirStructureError';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = ImproperDirStructureError
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
class InvalidDepartmentJsonError extends Error {
|
||||||
|
constructor(message = 'Invalid JSON format for security levels') {
|
||||||
|
super(message);
|
||||||
|
this.name = 'InvalidDepartmentJsonError';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports=InvalidDepartmentJsonError;
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
class InvalidKeyErrorException extends Error {
|
||||||
|
constructor(message = 'Invalid key for this operation') {
|
||||||
|
super(message);
|
||||||
|
this.name = 'InvalidKeyErrorException';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports=InvalidKeyErrorException;
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
class UserAlreadyExistsException extends Error {
|
||||||
|
constructor(message = 'User already exists in system') {
|
||||||
|
super(message);
|
||||||
|
this.name = 'UserAlreadyExistsException';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = UserAlreadyExistsException
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
class UserNotExistingError extends Error {
|
||||||
|
constructor(message = 'User not found in the system!') {
|
||||||
|
super(message);
|
||||||
|
this.name = 'UserNotExistingError';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = UserNotExistingError
|
||||||
@@ -0,0 +1,75 @@
|
|||||||
|
const httpStatus = {
|
||||||
|
// Informational
|
||||||
|
CONTINUE: 100,
|
||||||
|
SWITCHING_PROTOCOLS: 101,
|
||||||
|
PROCESSING: 102,
|
||||||
|
|
||||||
|
// Success
|
||||||
|
OK: 200,
|
||||||
|
CREATED: 201,
|
||||||
|
ACCEPTED: 202,
|
||||||
|
NO_CONTENT: 204,
|
||||||
|
|
||||||
|
// Redirection
|
||||||
|
MOVED_PERMANENTLY: 301,
|
||||||
|
FOUND: 302,
|
||||||
|
SEE_OTHER: 303,
|
||||||
|
NOT_MODIFIED: 304,
|
||||||
|
TEMPORARY_REDIRECT: 307,
|
||||||
|
|
||||||
|
// Client Error
|
||||||
|
BAD_REQUEST: 400,
|
||||||
|
UNAUTHORIZED: 401,
|
||||||
|
FORBIDDEN: 403,
|
||||||
|
NOT_FOUND: 404,
|
||||||
|
METHOD_NOT_ALLOWED: 405,
|
||||||
|
CONFLICT: 409,
|
||||||
|
GONE: 410,
|
||||||
|
UNSUPPORTED_MEDIA_TYPE: 415,
|
||||||
|
|
||||||
|
// Server Error
|
||||||
|
INTERNAL_SERVER_ERROR: 500,
|
||||||
|
NOT_IMPLEMENTED: 501,
|
||||||
|
SERVICE_UNAVAILABLE: 503
|
||||||
|
};
|
||||||
|
|
||||||
|
const httpStatusMessages = {
|
||||||
|
// Informational
|
||||||
|
[httpStatus.CONTINUE]: "Continue",
|
||||||
|
[httpStatus.SWITCHING_PROTOCOLS]: "Switching Protocols",
|
||||||
|
[httpStatus.PROCESSING]: "Processing",
|
||||||
|
|
||||||
|
// Success
|
||||||
|
[httpStatus.OK]: "OK",
|
||||||
|
[httpStatus.CREATED]: "Created",
|
||||||
|
[httpStatus.ACCEPTED]: "Accepted",
|
||||||
|
[httpStatus.NO_CONTENT]: "No Content",
|
||||||
|
|
||||||
|
// Redirection
|
||||||
|
[httpStatus.MOVED_PERMANENTLY]: "Moved Permanently",
|
||||||
|
[httpStatus.FOUND]: "Found",
|
||||||
|
[httpStatus.SEE_OTHER]: "See Other",
|
||||||
|
[httpStatus.NOT_MODIFIED]: "Not Modified",
|
||||||
|
[httpStatus.TEMPORARY_REDIRECT]: "Temporary Redirect",
|
||||||
|
|
||||||
|
// Client Error
|
||||||
|
[httpStatus.BAD_REQUEST]: "Bad Request",
|
||||||
|
[httpStatus.UNAUTHORIZED]: "Unauthorized",
|
||||||
|
[httpStatus.FORBIDDEN]: "Forbidden",
|
||||||
|
[httpStatus.NOT_FOUND]: "Not Found",
|
||||||
|
[httpStatus.METHOD_NOT_ALLOWED]: "Method Not Allowed",
|
||||||
|
[httpStatus.CONFLICT]: "Conflict",
|
||||||
|
[httpStatus.GONE]: "Gone",
|
||||||
|
[httpStatus.UNSUPPORTED_MEDIA_TYPE]: "Unsupported Media Type",
|
||||||
|
|
||||||
|
// Server Error
|
||||||
|
[httpStatus.INTERNAL_SERVER_ERROR]: "Internal Server Error",
|
||||||
|
[httpStatus.NOT_IMPLEMENTED]: "Not Implemented",
|
||||||
|
[httpStatus.SERVICE_UNAVAILABLE]: "Service Unavailable"
|
||||||
|
};
|
||||||
|
|
||||||
|
const httpHeaders = {
|
||||||
|
JSON: { 'name': 'Content-Type', 'value': 'application/json' }
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = {httpStatus, httpStatusMessages, httpHeaders};
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
const {httpHeaders} = require("./httpResponses");
|
||||||
|
|
||||||
|
const headers = {
|
||||||
|
[httpHeaders.JSON.name]: httpHeaders.JSON.value
|
||||||
|
}
|
||||||
|
|
||||||
|
function sendResponse(res, statusCode, message, data = null, headers_parsed = {}) {
|
||||||
|
Object.entries(headers).forEach(([key, value]) => {
|
||||||
|
res.setHeader(key, value);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Set headers if provided
|
||||||
|
Object.entries(headers_parsed).forEach(([key, value]) => {
|
||||||
|
res.setHeader(key, value);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Send the response with status code, message, and optional data
|
||||||
|
res.status(statusCode).json({ message, data });
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = { sendResponse };
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
const { sendResponse } = require('../helpers/responseHelper');
|
||||||
|
const {httpStatus, httpStatusMessages} = require('../helpers/httpResponses')
|
||||||
|
function apiKeyValidation(req, res, next) {
|
||||||
|
const apiKey = req.headers['x-api-key'];
|
||||||
|
|
||||||
|
if (apiKey !== req.app.locals.apiKey) {
|
||||||
|
return sendResponse(res, httpStatus.UNAUTHORIZED, httpStatusMessages[httpStatus.UNAUTHORIZED]);
|
||||||
|
}
|
||||||
|
next();
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = apiKeyValidation;
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
const { sendResponse } = require('../helpers/responseHelper');
|
||||||
|
const {httpStatus, httpStatusMessages} = require("../helpers/httpResponses");
|
||||||
|
|
||||||
|
function checkJson(req, res, next) {
|
||||||
|
if(req.method === 'GET'){
|
||||||
|
next()
|
||||||
|
}
|
||||||
|
|
||||||
|
if (['POST', 'PUT', 'PATCH'].includes(req.method) && req.headers['content-type'] !== 'application/json') {
|
||||||
|
return sendResponse(res, httpStatus.BAD_REQUEST, httpStatusMessages[httpStatus.BAD_REQUEST]);
|
||||||
|
}
|
||||||
|
|
||||||
|
next();
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = checkJson;
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
const path = require("path");
|
||||||
|
const fs = require("fs");
|
||||||
|
|
||||||
|
function SetAdminValuesMiddleware(req, res, next){
|
||||||
|
if(!req.path.startsWith('/admin')){
|
||||||
|
next();
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
try{
|
||||||
|
const configFilePath = path.join(__dirname, '..', 'db', 'config.json');
|
||||||
|
const config = JSON.parse(fs.readFileSync(configFilePath));
|
||||||
|
|
||||||
|
res.locals.adminKey = config.adminKey === undefined ? " " : config.adminKey;
|
||||||
|
res.locals.ceoID = config.ceoID === undefined ? " " : config.ceoID;
|
||||||
|
|
||||||
|
next();
|
||||||
|
|
||||||
|
fs.writeFileSync(configFilePath, JSON.stringify(
|
||||||
|
{
|
||||||
|
adminKey: res.locals.adminKey,
|
||||||
|
ceoID: res.locals.ceoID
|
||||||
|
}, null, 2));
|
||||||
|
return res;
|
||||||
|
} catch(error){
|
||||||
|
console.log(error.message);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = SetAdminValuesMiddleware;
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
const Joi = require('joi');
|
||||||
|
|
||||||
|
const ceoRegisterModel = Joi.object({
|
||||||
|
name: Joi.string().required(),
|
||||||
|
email: Joi.string().email().required()
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = ceoRegisterModel;
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
const Joi = require('joi');
|
||||||
|
|
||||||
|
const departmentRegisterModel = Joi.object({
|
||||||
|
name: Joi.string().required()
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = departmentRegisterModel
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
const Joi = require('joi');
|
||||||
|
|
||||||
|
const dirStructureModel = Joi.object({
|
||||||
|
id: Joi.string().guid().required(),
|
||||||
|
dir_config: Joi.string().required(),
|
||||||
|
total_space: Joi.number().positive().required()
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = dirStructureModel
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
const usersRegisterModelSchema = require('./usersRegisterModel');
|
||||||
|
const usersLoginModelSchema = require('./usersLoginModel');
|
||||||
|
const dirStructureModelSchema = require('./dirStructureModel');
|
||||||
|
const departmentRegisterModelSchema = require('./departmentRegisterModel');
|
||||||
|
const ceoRegisterModelSchema = require('./ceoRegisterModel')
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
schemas: {
|
||||||
|
dirStructureModelSchema,
|
||||||
|
usersRegisterModelSchema,
|
||||||
|
usersLoginModelSchema,
|
||||||
|
departmentRegisterModelSchema,
|
||||||
|
ceoRegisterModelSchema
|
||||||
|
},
|
||||||
|
};
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
const Joi = require('joi');
|
||||||
|
|
||||||
|
const usersLoginModel = Joi.object({
|
||||||
|
email: Joi.string().email().required(),
|
||||||
|
password: Joi.string().min(8).max(20).required()
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = usersLoginModel;
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
const Joi = require('joi');
|
||||||
|
|
||||||
|
const usersRegisterModel = Joi.object({
|
||||||
|
name: Joi.string().required(),
|
||||||
|
email: Joi.string().email().required(),
|
||||||
|
password: Joi.string().min(8).max(20).required()
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = usersRegisterModel;
|
||||||
@@ -0,0 +1,152 @@
|
|||||||
|
const express = require('express');
|
||||||
|
const fs = require('fs');
|
||||||
|
const crypto = require('crypto');
|
||||||
|
const {v4: uuidv4} = require("uuid");
|
||||||
|
const path = require("path");
|
||||||
|
|
||||||
|
const { sendResponse } = require('../helpers/responseHelper');
|
||||||
|
const {httpStatus, httpStatusMessages} = require('../helpers/httpResponses')
|
||||||
|
const {schemas} = require("../models/schemaMapper");
|
||||||
|
const InvalidKeyErrorException = require("../exceptions/invalidKeyErrorException");
|
||||||
|
const UserNotExistingError = require("../exceptions/userNotExistingError");
|
||||||
|
|
||||||
|
const router = express.Router();
|
||||||
|
|
||||||
|
router.get('/reset_key', (req, res) => {
|
||||||
|
|
||||||
|
const adminKey= crypto.randomBytes(32).toString('hex');
|
||||||
|
res.locals.adminKey = adminKey;
|
||||||
|
sendResponse(res, httpStatus.OK, httpStatusMessages[httpStatus.OK], adminKey);
|
||||||
|
});
|
||||||
|
|
||||||
|
router.get('/reset', (req, res) => {
|
||||||
|
try {
|
||||||
|
const requestAdminKey = req.headers['admin-key'];
|
||||||
|
|
||||||
|
if (requestAdminKey !== res.locals.adminKey) {
|
||||||
|
throw new InvalidKeyErrorException();
|
||||||
|
}
|
||||||
|
|
||||||
|
fs.writeFileSync(path.join(__dirname, '..', 'db', 'users.json'), '[]');
|
||||||
|
fs.writeFileSync(path.join(__dirname, '..', 'db', 'departments.json'), '[]');
|
||||||
|
fs.writeFileSync(path.join(__dirname, '..', 'db', 'security_levels.json'), '{}');
|
||||||
|
fs.writeFileSync(path.join(__dirname, '..', 'db', 'backup_schemas.json'), '{}');
|
||||||
|
fs.writeFileSync(path.join(__dirname, '..', 'db', 'config.json'), JSON.stringify({
|
||||||
|
adminKey: ' ',
|
||||||
|
ceoID: ' '
|
||||||
|
}, null, 2));
|
||||||
|
|
||||||
|
const adminPassword = crypto.randomBytes(16).toString('hex'); // Generating random password
|
||||||
|
const ceoID = uuidv4();
|
||||||
|
res.locals.ceoID = ceoID;
|
||||||
|
const adminAccount = {
|
||||||
|
id: ceoID,
|
||||||
|
name: 'CEO',
|
||||||
|
email: 'ceo@yourfirm.com',
|
||||||
|
password: adminPassword
|
||||||
|
};
|
||||||
|
|
||||||
|
const usersData = [adminAccount];
|
||||||
|
fs.writeFileSync(path.join(__dirname, '..', 'db', 'users.json'),
|
||||||
|
JSON.stringify(usersData, null, 2));
|
||||||
|
|
||||||
|
sendResponse(res, httpStatus.CREATED, httpStatusMessages[httpStatus.CREATED]);
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error.message);
|
||||||
|
if(error instanceof InvalidKeyErrorException){
|
||||||
|
return sendResponse(res, httpStatus.UNAUTHORIZED, error.message);
|
||||||
|
}
|
||||||
|
|
||||||
|
sendResponse(res, httpStatus.INTERNAL_SERVER_ERROR, httpStatusMessages[httpStatus.INTERNAL_SERVER_ERROR]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const validateRegisterCeoBody = (req, res, next) => {
|
||||||
|
const { error, value } = schemas.ceoRegisterModelSchema.validate(req.body);
|
||||||
|
if (error) {
|
||||||
|
return sendResponse(res, httpStatus.BAD_REQUEST, error.details[0].message);
|
||||||
|
}
|
||||||
|
req.jsonModel = value;
|
||||||
|
next();
|
||||||
|
}
|
||||||
|
|
||||||
|
router.put('/change_admin_credentials', validateRegisterCeoBody, (req, res) => {
|
||||||
|
try {
|
||||||
|
const requestAdminKey = req.headers['admin-key'];
|
||||||
|
if (requestAdminKey !== res.locals.adminKey) {
|
||||||
|
throw new InvalidKeyErrorException();
|
||||||
|
}
|
||||||
|
|
||||||
|
const usersFilePath = path.join(__dirname, '..', 'db', 'users.json');
|
||||||
|
const usersData = JSON.parse(fs.readFileSync(usersFilePath, 'utf8'));
|
||||||
|
|
||||||
|
const adminIndex = usersData.findIndex(user => user.id === res.locals.ceoID);
|
||||||
|
if (adminIndex === -1) {
|
||||||
|
throw new UserNotExistingError();
|
||||||
|
}
|
||||||
|
|
||||||
|
const { name, email } = req.body; // Using req.body instead of req.jsonModel
|
||||||
|
const newPassword = crypto.randomBytes(16).toString('hex'); // Generate new random password
|
||||||
|
|
||||||
|
// Update the user data
|
||||||
|
usersData[adminIndex] = {
|
||||||
|
id: res.locals.ceoID,
|
||||||
|
name: name,
|
||||||
|
email: email,
|
||||||
|
password: newPassword
|
||||||
|
};
|
||||||
|
|
||||||
|
// Write the updated user data back to the file
|
||||||
|
fs.writeFileSync(usersFilePath, JSON.stringify(usersData, null, 2));
|
||||||
|
|
||||||
|
sendResponse(res, httpStatus.OK, httpStatusMessages[httpStatus.OK]);
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error.message);
|
||||||
|
if (error instanceof InvalidKeyErrorException) {
|
||||||
|
return sendResponse(res, httpStatus.UNAUTHORIZED, error.message);
|
||||||
|
}
|
||||||
|
if (error instanceof UserNotExistingError) {
|
||||||
|
return sendResponse(res, httpStatus.NOT_FOUND, error.message);
|
||||||
|
}
|
||||||
|
|
||||||
|
sendResponse(res, httpStatus.INTERNAL_SERVER_ERROR, httpStatusMessages[httpStatus.INTERNAL_SERVER_ERROR])
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
router.post('/validate_admin_password', (req, res) => {
|
||||||
|
try {
|
||||||
|
const requestAdminKey = req.headers['admin-key'];
|
||||||
|
if (requestAdminKey !== res.locals.adminKey) {
|
||||||
|
throw new InvalidKeyErrorException();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(req.body.password === undefined){
|
||||||
|
return sendResponse(res, httpStatus.BAD_REQUEST, httpStatusMessages[httpStatus.BAD_REQUEST]);
|
||||||
|
}
|
||||||
|
const password = req.body.password;
|
||||||
|
|
||||||
|
const usersFilePath = path.join(__dirname, '..', 'db', 'users.json');
|
||||||
|
const usersData = fs.readFileSync(usersFilePath, 'utf8');
|
||||||
|
const usersJson = JSON.parse(usersData);
|
||||||
|
|
||||||
|
const user = usersJson.find(user => user.id === res.locals.ceoID);
|
||||||
|
if(user.password !== password){
|
||||||
|
return sendResponse(res, httpStatus.UNAUTHORIZED, httpStatusMessages[httpStatus.UNAUTHORIZED]);
|
||||||
|
}
|
||||||
|
|
||||||
|
sendResponse(res, httpStatus.OK, httpStatusMessages[httpStatus.OK]);
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error.message);
|
||||||
|
if(error instanceof InvalidKeyErrorException){
|
||||||
|
return sendResponse(res, httpStatus.UNAUTHORIZED, error.message);
|
||||||
|
}
|
||||||
|
|
||||||
|
sendResponse(res, httpStatus.INTERNAL_SERVER_ERROR, httpStatusMessages[httpStatus.INTERNAL_SERVER_ERROR]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
router.use((req, res) => {
|
||||||
|
return sendResponse(res, httpStatus.NOT_FOUND, "Path not found");
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = router;
|
||||||
@@ -0,0 +1,224 @@
|
|||||||
|
const express = require('express');
|
||||||
|
const fs = require('fs');
|
||||||
|
const path = require('path');
|
||||||
|
const { v4: uuidv4 } = require('uuid');
|
||||||
|
const crypto = require('crypto');
|
||||||
|
|
||||||
|
const { sendResponse } = require('../helpers/responseHelper');
|
||||||
|
const {httpStatus, httpStatusMessages} = require('../helpers/httpResponses')
|
||||||
|
const {schemas} = require("../models/schemaMapper");
|
||||||
|
|
||||||
|
const DepartmentAlreadyExistsError = require("../exceptions/departmentAlreadyExistsError");
|
||||||
|
const InvalidDepartmentJsonError = require("../exceptions/invalidDepartmentJsonError");
|
||||||
|
const DepartmentNotExistingError = require("../exceptions/departmentNotExistingError");
|
||||||
|
|
||||||
|
const router = express.Router();
|
||||||
|
|
||||||
|
router.get('/', (req, res) => {
|
||||||
|
try {
|
||||||
|
const departmentsFilePath = path.join(__dirname, '..', 'db', 'departments.json');
|
||||||
|
const departmentsData = fs.readFileSync(departmentsFilePath, 'utf8');
|
||||||
|
const departments = JSON.parse(departmentsData);
|
||||||
|
|
||||||
|
|
||||||
|
return sendResponse(res, httpStatus.OK, httpStatusMessages[httpStatus.OK], departments);
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`Error: ${error.message}`);
|
||||||
|
return sendResponse(res, httpStatus.INTERNAL_SERVER_ERROR, httpStatusMessages[httpStatus.INTERNAL_SERVER_ERROR]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
function generateAESKey() {
|
||||||
|
return crypto.randomBytes(32).toString('hex');
|
||||||
|
}
|
||||||
|
|
||||||
|
router.post('/', validateRegisterBody, createDepartment, addSecurityLevel, (req, res) => {
|
||||||
|
return res;
|
||||||
|
});
|
||||||
|
|
||||||
|
function validateRegisterBody(req, res, next) {
|
||||||
|
const { error, value } = schemas.departmentRegisterModelSchema.validate(req.body);
|
||||||
|
if (error) {
|
||||||
|
return sendResponse(res, httpStatus.BAD_REQUEST, error.details[0].message);
|
||||||
|
}
|
||||||
|
req.jsonModel = value;
|
||||||
|
next();
|
||||||
|
}
|
||||||
|
|
||||||
|
function createDepartment(req, res, next) {
|
||||||
|
try {
|
||||||
|
const { name } = req.jsonModel;
|
||||||
|
|
||||||
|
const departmentsFilePath = path.join(__dirname, '..', 'db', 'departments.json');
|
||||||
|
const departmentsData = fs.readFileSync(departmentsFilePath, 'utf8');
|
||||||
|
const departments = JSON.parse(departmentsData);
|
||||||
|
|
||||||
|
const existingDepartment = departments.find(department => department.name === name);
|
||||||
|
if (existingDepartment) {
|
||||||
|
throw new DepartmentAlreadyExistsError();
|
||||||
|
}
|
||||||
|
|
||||||
|
const departmentId = uuidv4();
|
||||||
|
const aesKey = generateAESKey();
|
||||||
|
const newDepartment = {
|
||||||
|
id: departmentId,
|
||||||
|
name: name,
|
||||||
|
key: aesKey
|
||||||
|
};
|
||||||
|
|
||||||
|
departments.push(newDepartment);
|
||||||
|
fs.writeFileSync(departmentsFilePath, JSON.stringify(departments, null, 2));
|
||||||
|
|
||||||
|
req.departmentId = departmentId;
|
||||||
|
next();
|
||||||
|
|
||||||
|
return res;
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`Error: ${error.message}`);
|
||||||
|
if (error instanceof DepartmentAlreadyExistsError) {
|
||||||
|
return sendResponse(res, httpStatus.CONFLICT, error.message);
|
||||||
|
}
|
||||||
|
return sendResponse(res, httpStatus.INTERNAL_SERVER_ERROR, httpStatusMessages[httpStatus.INTERNAL_SERVER_ERROR]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function addSecurityLevel(req, res) {
|
||||||
|
try {
|
||||||
|
const { departmentId } = req;
|
||||||
|
|
||||||
|
const securityLevelsFilePath = path.join(__dirname, '..', 'db', 'security_levels.json');
|
||||||
|
const securityLevelsData = fs.readFileSync(securityLevelsFilePath, 'utf8');
|
||||||
|
const securityLevels = JSON.parse(securityLevelsData);
|
||||||
|
|
||||||
|
const nextIndex = Object.keys(securityLevels).length + 1;
|
||||||
|
securityLevels[nextIndex] = departmentId;
|
||||||
|
|
||||||
|
fs.writeFileSync(securityLevelsFilePath, JSON.stringify(securityLevels, null, 2));
|
||||||
|
|
||||||
|
return sendResponse(res, httpStatus.CREATED, httpStatusMessages[httpStatus.CREATED]);
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`Error: ${error.message}`);
|
||||||
|
return sendResponse(res, httpStatus.INTERNAL_SERVER_ERROR, httpStatusMessages[httpStatus.INTERNAL_SERVER_ERROR]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
router.put('/', validateDepartmentsJson, validateSecurityLevels, updateSecurityLevels);
|
||||||
|
|
||||||
|
function validateDepartmentsJson(req, res, next) {
|
||||||
|
try {
|
||||||
|
for (const key in req.body) {
|
||||||
|
if (!Number.isInteger(parseInt(key)) || typeof req.body[key] !== 'string') {
|
||||||
|
throw new InvalidDepartmentJsonError();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
next();
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`Error: ${error.message}`);
|
||||||
|
return sendResponse(res, httpStatus.BAD_REQUEST, error.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function validateSecurityLevels(req, res, next) {
|
||||||
|
try {
|
||||||
|
const securityLevelsFilePath = path.join(__dirname, '..', 'db', 'security_levels.json');
|
||||||
|
const securityLevelsData = fs.readFileSync(securityLevelsFilePath, 'utf8');
|
||||||
|
const securityLevels = JSON.parse(securityLevelsData);
|
||||||
|
|
||||||
|
if (Object.keys(req.body).length !== Object.keys(securityLevels).length) {
|
||||||
|
throw new InvalidDepartmentJsonError('Number of keys does not match the database');
|
||||||
|
}
|
||||||
|
|
||||||
|
const encounteredValues = new Set();
|
||||||
|
const securityLevelValues = Object.values(securityLevels);
|
||||||
|
|
||||||
|
for (const key in req.body) {
|
||||||
|
const requestBodyValue = req.body[key];
|
||||||
|
if (!securityLevels.hasOwnProperty(key)) {
|
||||||
|
throw new InvalidDepartmentJsonError('Invalid key found in request body');
|
||||||
|
}
|
||||||
|
const securityLevelValue = securityLevels[key];
|
||||||
|
|
||||||
|
if (!securityLevelValues.includes(securityLevelValue)) {
|
||||||
|
throw new InvalidDepartmentJsonError('Values do not match the database');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (encounteredValues.has(requestBodyValue)) {
|
||||||
|
throw new InvalidDepartmentJsonError('Duplicate values found in request body');
|
||||||
|
}
|
||||||
|
|
||||||
|
encounteredValues.add(requestBodyValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
next();
|
||||||
|
return res;
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`Error: ${error.message}`);
|
||||||
|
return sendResponse(res, httpStatus.BAD_REQUEST, error.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateSecurityLevels(req, res) {
|
||||||
|
try {
|
||||||
|
const securityLevelsFilePath = path.join(__dirname, '..', 'db', 'security_levels.json');
|
||||||
|
fs.writeFileSync(securityLevelsFilePath, JSON.stringify(req.body, null, 2));
|
||||||
|
|
||||||
|
return sendResponse(res, httpStatus.OK, httpStatusMessages[httpStatus.OK]);
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`Error: ${error.message}`);
|
||||||
|
return sendResponse(res, httpStatus.INTERNAL_SERVER_ERROR, httpStatusMessages[httpStatus.INTERNAL_SERVER_ERROR]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
router.delete('/:id', async (req, res) => {
|
||||||
|
const id = req.params.id;
|
||||||
|
|
||||||
|
try {
|
||||||
|
deleteDepartment(id, res);
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`Error: ${error.message}`);
|
||||||
|
|
||||||
|
if (error instanceof DepartmentNotExistingError) {
|
||||||
|
return sendResponse(res, httpStatus.NOT_FOUND, error.message);
|
||||||
|
}
|
||||||
|
|
||||||
|
return sendResponse(res, httpStatus.INTERNAL_SERVER_ERROR, httpStatusMessages[httpStatus.INTERNAL_SERVER_ERROR]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
function deleteDepartment(id, res) {
|
||||||
|
const departmentsFilePath = path.join(__dirname, '..', 'db', 'departments.json');
|
||||||
|
const departmentsData = fs.readFileSync(departmentsFilePath, 'utf8');
|
||||||
|
const departmentsJson = JSON.parse(departmentsData);
|
||||||
|
|
||||||
|
const index = departmentsJson.findIndex(department => department.id === id);
|
||||||
|
if (index === -1) {
|
||||||
|
throw new DepartmentNotExistingError();
|
||||||
|
}
|
||||||
|
|
||||||
|
departmentsJson.splice(index, 1);
|
||||||
|
fs.writeFileSync(departmentsFilePath, JSON.stringify(departmentsJson, null, 2));
|
||||||
|
|
||||||
|
const securityLevelsFilePath = path.join(__dirname, '..', 'db', 'security_levels.json');
|
||||||
|
const securityLevelsData = fs.readFileSync(securityLevelsFilePath, 'utf8');
|
||||||
|
const securityLevelsJson = JSON.parse(securityLevelsData);
|
||||||
|
|
||||||
|
const securityIndex = securityLevelsJson.findIndex(level => level.id === id);
|
||||||
|
if (securityIndex !== -1) {
|
||||||
|
securityLevelsJson.splice(securityIndex, 1);
|
||||||
|
fs.writeFileSync(securityLevelsFilePath, JSON.stringify(securityLevelsJson, null, 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
return sendResponse(res, httpStatus.OK, httpStatusMessages[httpStatus.OK]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
router.use((req, res) => {
|
||||||
|
return sendResponse(res, httpStatus.NOT_FOUND, "Path not found");
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = router;
|
||||||
@@ -0,0 +1,199 @@
|
|||||||
|
const express = require('express');
|
||||||
|
const fs = require('fs');
|
||||||
|
const path = require('path');
|
||||||
|
const { v4: uuidv4 } = require('uuid');
|
||||||
|
const crypto = require('crypto');
|
||||||
|
|
||||||
|
const { sendResponse } = require('../helpers/responseHelper');
|
||||||
|
const {httpStatus, httpStatusMessages} = require('../helpers/httpResponses')
|
||||||
|
const {schemas} = require("../models/schemaMapper");
|
||||||
|
|
||||||
|
const UserAlreadyExistsException =require('../exceptions/userAlreadyExistsError');
|
||||||
|
const UserNotExistingError = require("../exceptions/userNotExistingError");
|
||||||
|
const ImproperDirStructureError = require("../exceptions/improperDirStructureError");
|
||||||
|
|
||||||
|
const router = express.Router();
|
||||||
|
|
||||||
|
|
||||||
|
router.get('/', async(req, res) => {
|
||||||
|
try {
|
||||||
|
const usersFilePath = path.join(__dirname, '..', 'db', 'users.json');
|
||||||
|
const usersData = fs.readFileSync(usersFilePath, 'utf8');
|
||||||
|
const usersJson = JSON.parse(usersData);
|
||||||
|
|
||||||
|
return sendResponse(res, httpStatus.OK, httpStatusMessages[httpStatus.OK], usersJson)
|
||||||
|
} catch (error) {
|
||||||
|
return sendResponse(res, httpStatus.INTERNAL_SERVER_ERROR, httpStatusMessages[httpStatus.INTERNAL_SERVER_ERROR])
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const validateRegisterBody = (req, res, next) => {
|
||||||
|
const { error, value } = schemas.usersRegisterModelSchema.validate(req.body);
|
||||||
|
if (error) {
|
||||||
|
return sendResponse(res, httpStatus.BAD_REQUEST, error.details[0].message);
|
||||||
|
}
|
||||||
|
req.jsonModel = value;
|
||||||
|
next();
|
||||||
|
}
|
||||||
|
|
||||||
|
router.post('/register', validateRegisterBody, async (req, res) => {
|
||||||
|
try {
|
||||||
|
const usersFilePath = path.join(__dirname, '..', 'db', 'users.json');
|
||||||
|
const usersData = fs.readFileSync(usersFilePath, 'utf8');
|
||||||
|
const usersJson = JSON.parse(usersData);
|
||||||
|
|
||||||
|
const { name, email, password } = req.jsonModel;
|
||||||
|
|
||||||
|
const existingUser = usersJson.find(user => user.email === email);
|
||||||
|
if (existingUser) {
|
||||||
|
throw new UserAlreadyExistsException();
|
||||||
|
}
|
||||||
|
|
||||||
|
const userId = uuidv4();
|
||||||
|
const hashedPassword = crypto.createHash('sha256').update(password).digest('hex');
|
||||||
|
|
||||||
|
const newUser = {
|
||||||
|
id: userId,
|
||||||
|
name: name,
|
||||||
|
email: email,
|
||||||
|
password: hashedPassword
|
||||||
|
};
|
||||||
|
|
||||||
|
usersJson.push(newUser);
|
||||||
|
fs.writeFileSync(usersFilePath, JSON.stringify(usersJson, null, 2));
|
||||||
|
|
||||||
|
return sendResponse(res, httpStatus.CREATED, httpStatusMessages[httpStatus.CREATED]);
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`Error: ${error.message}`);
|
||||||
|
|
||||||
|
if (error instanceof UserAlreadyExistsException) {
|
||||||
|
return sendResponse(res, httpStatus.CONFLICT, error.message);
|
||||||
|
}
|
||||||
|
|
||||||
|
return sendResponse(res, httpStatus.INTERNAL_SERVER_ERROR, httpStatusMessages[httpStatus.INTERNAL_SERVER_ERROR]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
const validateLoginBody = (req, res, next) => {
|
||||||
|
const { error, value } = schemas.usersLoginModelSchema.validate(req.body);
|
||||||
|
if (error) {
|
||||||
|
return sendResponse(res, httpStatus.BAD_REQUEST, error.details[0].message);
|
||||||
|
}
|
||||||
|
req.jsonModel = value;
|
||||||
|
next();
|
||||||
|
}
|
||||||
|
|
||||||
|
router.post('/login', validateLoginBody, async (req, res) => {
|
||||||
|
try {
|
||||||
|
const usersFilePath = path.join(__dirname, '..', 'db', 'users.json');
|
||||||
|
const usersData = fs.readFileSync(usersFilePath, 'utf8');
|
||||||
|
const usersJson = JSON.parse(usersData);
|
||||||
|
|
||||||
|
const { email, password } = req.jsonModel;
|
||||||
|
const hashedPassword = crypto.createHash('sha256').update(password).digest('hex');
|
||||||
|
const user = usersJson.find(user => user.email === email && user.password === hashedPassword);
|
||||||
|
|
||||||
|
if (!user) {
|
||||||
|
throw new UserNotExistingError('Invalid email or password');
|
||||||
|
}
|
||||||
|
|
||||||
|
return sendResponse(res, httpStatus.OK, 'Login successful');
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`Error: ${error.message}`);
|
||||||
|
|
||||||
|
if (error instanceof UserNotExistingError) {
|
||||||
|
return sendResponse(res, httpStatus.UNAUTHORIZED, error.message);
|
||||||
|
}
|
||||||
|
|
||||||
|
return sendResponse(res, httpStatus.INTERNAL_SERVER_ERROR, httpStatusMessages[httpStatus.INTERNAL_SERVER_ERROR]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
const validateDirStructureBody = (req, res, next) => {
|
||||||
|
const { error, value } = schemas.dirStructureModelSchema.validate(req.body);
|
||||||
|
if (error) {
|
||||||
|
return sendResponse(res, httpStatus.BAD_REQUEST, error.details[0].message);
|
||||||
|
}
|
||||||
|
req.jsonModel = value;
|
||||||
|
next();
|
||||||
|
};
|
||||||
|
|
||||||
|
router.put('/dir_structure', validateDirStructureBody, (req, res) => {
|
||||||
|
try {
|
||||||
|
const { id, dir_config, total_space } = req.jsonModel;
|
||||||
|
|
||||||
|
const backupFilePath = path.join(__dirname, '..', 'db', 'backup_schemas.json');
|
||||||
|
let backupArray = [];
|
||||||
|
if (fs.existsSync(backupFilePath)) {
|
||||||
|
const backupData = fs.readFileSync(backupFilePath, 'utf8');
|
||||||
|
try {
|
||||||
|
backupArray = JSON.parse(backupData);
|
||||||
|
} catch (jsonParseError) {
|
||||||
|
throw new ImproperDirStructureError();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const existingIndex = backupArray.findIndex(item => item.id === id);
|
||||||
|
if (existingIndex !== -1) {
|
||||||
|
backupArray[existingIndex] = {
|
||||||
|
id: id,
|
||||||
|
dir_config: dir_config,
|
||||||
|
total_space: total_space
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
backupArray.push({
|
||||||
|
id: id,
|
||||||
|
dir_config: dir_config,
|
||||||
|
total_space: total_space
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
fs.writeFileSync(backupFilePath, JSON.stringify(backupArray, null, 2));
|
||||||
|
|
||||||
|
return sendResponse(res, httpStatus.OK, httpStatusMessages[httpStatus.OK]);
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`Error: ${error.message}`);
|
||||||
|
if (error instanceof ImproperDirStructureError) {
|
||||||
|
return sendResponse(res, httpStatus.BAD_REQUEST, error.message);
|
||||||
|
}
|
||||||
|
return sendResponse(res, httpStatus.INTERNAL_SERVER_ERROR, httpStatusMessages[httpStatus.INTERNAL_SERVER_ERROR]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
router.delete('/:id', async (req, res) => {
|
||||||
|
const id = req.params.id;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const usersFilePath = path.join(__dirname, '..', 'db', 'users.json');
|
||||||
|
const usersData = fs.readFileSync(usersFilePath, 'utf8');
|
||||||
|
const usersJson = JSON.parse(usersData);
|
||||||
|
|
||||||
|
const index = usersJson.findIndex(user => user.id === id);
|
||||||
|
if (index === -1) {
|
||||||
|
throw new UserNotExistingError();
|
||||||
|
}
|
||||||
|
|
||||||
|
usersJson.splice(index, 1);
|
||||||
|
fs.writeFileSync(usersFilePath, JSON.stringify(usersJson, null, 2));
|
||||||
|
|
||||||
|
return sendResponse(res, httpStatus.OK, httpStatusMessages[httpStatus.OK]);
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`Error: ${error.message}`);
|
||||||
|
|
||||||
|
if (error instanceof UserNotExistingError) {
|
||||||
|
return sendResponse(res, httpStatus.NOT_FOUND, error.message);
|
||||||
|
}
|
||||||
|
|
||||||
|
return sendResponse(res, httpStatus.INTERNAL_SERVER_ERROR, httpStatusMessages[httpStatus.INTERNAL_SERVER_ERROR]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
router.use((req, res) => {
|
||||||
|
return sendResponse(res, httpStatus.NOT_FOUND, "Path not found");
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = router;
|
||||||
Generated
+5
@@ -0,0 +1,5 @@
|
|||||||
|
# Default ignored files
|
||||||
|
/shelf/
|
||||||
|
/workspace.xml
|
||||||
|
# Editor-based HTTP Client requests
|
||||||
|
/httpRequests/
|
||||||
Generated
+6
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="JavaScriptLibraryMappings">
|
||||||
|
<includedPredefinedLibrary name="Node.js Core" />
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
Generated
+8
@@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ProjectModuleManager">
|
||||||
|
<modules>
|
||||||
|
<module fileurl="file://$PROJECT_DIR$/.idea/proiect-licenta.iml" filepath="$PROJECT_DIR$/.idea/proiect-licenta.iml" />
|
||||||
|
</modules>
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
Generated
+12
@@ -0,0 +1,12 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<module type="WEB_MODULE" version="4">
|
||||||
|
<component name="NewModuleRootManager">
|
||||||
|
<content url="file://$MODULE_DIR$">
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/.tmp" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/temp" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/tmp" />
|
||||||
|
</content>
|
||||||
|
<orderEntry type="inheritedJdk" />
|
||||||
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
|
</component>
|
||||||
|
</module>
|
||||||
Generated
+6
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="VcsDirectoryMappings">
|
||||||
|
<mapping directory="" vcs="Git" />
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
Generated
+1966
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,23 @@
|
|||||||
|
{
|
||||||
|
"name": "proiect-licenta",
|
||||||
|
"productName": "Aplicatie",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "Aplicatie P2P pentru stocarea resurselor digitale",
|
||||||
|
"main": "src/main/main.js",
|
||||||
|
"scripts": {
|
||||||
|
"start": "electron ./src/main/main.js",
|
||||||
|
"dev": "electronmon ./src/main/main.js"
|
||||||
|
},
|
||||||
|
"author": "Cerbu Andrei - Mihnea",
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"bootstrap": "^5.3.3",
|
||||||
|
"electron": "^29.1.5",
|
||||||
|
"express": "^4.19.2",
|
||||||
|
"nodemon": "^3.1.0",
|
||||||
|
"toastify-js": "^1.12.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"electronmon": "^2.0.2"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
const {app, BrowserWindow, screen, Menu} = require("electron");
|
||||||
|
const path = require("path")
|
||||||
|
|
||||||
|
const isMac = process.platform === 'darwin';
|
||||||
|
|
||||||
|
const createMainWindow = ((title, width, height) => {
|
||||||
|
const mainWindows = new BrowserWindow({
|
||||||
|
title: title,
|
||||||
|
width: width,
|
||||||
|
height: height
|
||||||
|
});
|
||||||
|
|
||||||
|
mainWindows.loadFile(path.join(__dirname, '..', 'renderer', 'index.html'))
|
||||||
|
.then(r => console.log('Main window works!'));
|
||||||
|
})
|
||||||
|
|
||||||
|
app.whenReady().then(() => {
|
||||||
|
const title = "Application"
|
||||||
|
const mainScreen = screen.getPrimaryDisplay();
|
||||||
|
const {width: width, height: height} = mainScreen.size;
|
||||||
|
createMainWindow(title, width / 1.5, height / 1.5)
|
||||||
|
|
||||||
|
app.on('activate', () => {
|
||||||
|
if(BrowserWindow.getAllWindows().length === 0){
|
||||||
|
createMainWindow(title, width, height);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
app.on('window-all-closed', () =>{
|
||||||
|
if(!isMac){
|
||||||
|
app.quit();
|
||||||
|
}
|
||||||
|
})
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content = "IE=edge">
|
||||||
|
<meta name="viewport" content="width=device width, initial-scale=1.0">
|
||||||
|
<title>App</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>Hello World!</h1>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
Reference in New Issue
Block a user