From 900a569c512cbc297dc19f98b17fe8c1196c93bb Mon Sep 17 00:00:00 2001 From: DungTT Date: Tue, 31 Mar 2026 13:48:10 +0700 Subject: [PATCH] fomat --- DATABASE_SETUP.md | 291 ------------- RUN_COMMANDS.md | 220 ---------- SETUP_GUIDE.md | 294 ------------- server.js => backend/server.js | 9 +- codedialog.html | 270 ------------ database/run-setup.ps1 | 63 --- database/setup_output.log | 1 - install-nodejs.ps1 | 35 -- package.json | 6 +- index.html => public/index.html | 0 {js => public/js}/app.js | 196 +++++++-- modals.html => public/modals.html | 12 + {pages => public/pages}/accounts.html | 6 +- {pages => public/pages}/applications.html | 6 +- {pages => public/pages}/index.html | 3 + {pages => public/pages}/login.html | 8 +- requirements.txt | 4 - server_python.py | 480 ---------------------- setup_full_log.txt | Bin 288 -> 0 bytes setup_output.log | 53 --- 20 files changed, 204 insertions(+), 1753 deletions(-) delete mode 100644 DATABASE_SETUP.md delete mode 100644 RUN_COMMANDS.md delete mode 100644 SETUP_GUIDE.md rename server.js => backend/server.js (98%) delete mode 100644 codedialog.html delete mode 100644 database/run-setup.ps1 delete mode 100644 database/setup_output.log delete mode 100644 install-nodejs.ps1 rename index.html => public/index.html (100%) rename {js => public/js}/app.js (84%) rename modals.html => public/modals.html (92%) rename {pages => public/pages}/accounts.html (98%) rename {pages => public/pages}/applications.html (97%) rename {pages => public/pages}/index.html (97%) rename {pages => public/pages}/login.html (98%) delete mode 100644 requirements.txt delete mode 100644 server_python.py delete mode 100644 setup_full_log.txt delete mode 100644 setup_output.log diff --git a/DATABASE_SETUP.md b/DATABASE_SETUP.md deleted file mode 100644 index 1eb927a..0000000 --- a/DATABASE_SETUP.md +++ /dev/null @@ -1,291 +0,0 @@ -# AccManager Backend Setup Guide - -## 📋 Database Information - -**Server:** 172.20.235.176 -**Database:** AccManager -**User:** sa -**Password:** robotics@2020 - -## 📊 Database Structure - -### Tables Created - -#### 1. **Users** - Quản lý người dùng -- `UserId` (INT) - Primary Key -- `Username` (NVARCHAR) - Unique -- `Password` (NVARCHAR) -- `Email` (NVARCHAR) -- `FullName` (NVARCHAR) -- `Role` (NVARCHAR) - admin, user, viewer -- `Status` (NVARCHAR) - Active/Inactive -- `CreatedDate` (DATETIME) -- `LastLogin` (DATETIME) -- `IsActive` (BIT) - -#### 2. **Applications** - Danh sách ứng dụng -- `AppId` (INT) - Primary Key -- `Name` (NVARCHAR) -- `Type` (NVARCHAR) - Cloud, VCS, Collaboration, Infra -- `Status` (NVARCHAR) - online/offline -- `Icon` (NVARCHAR) -- `Description` (NVARCHAR) -- `CreatedDate` (DATETIME) -- `UpdatedDate` (DATETIME) - -#### 3. **Accounts** - Tài khoản ứng dụng -- `AccountId` (INT) - Primary Key -- `UserId` (INT) - Foreign Key -- `AppId` (INT) - Foreign Key -- `AccountUsername` (NVARCHAR) -- `AccountPassword` (NVARCHAR) -- `Email` (NVARCHAR) -- `AccessLevel` (NVARCHAR) -- `Status` (NVARCHAR) -- `Notes` (NVARCHAR) -- `CreatedDate` (DATETIME) -- `UpdatedDate` (DATETIME) - -#### 4. **AuditLog** - Nhật ký hoạt động -- `LogId` (INT) - Primary Key -- `UserId` (INT) - Foreign Key -- `Action` (NVARCHAR) - INSERT, UPDATE, DELETE -- `TableName` (NVARCHAR) -- `RecordId` (INT) -- `OldValue` (NVARCHAR) -- `NewValue` (NVARCHAR) -- `Timestamp` (DATETIME) - -## 🔐 Default Admin Account - -**Username:** admin -**Password:** admin -**Role:** admin -**Status:** Active - -## 🚀 Installation & Setup - -### 1. Install Node.js Dependencies - -```bash -npm install -``` - -### 2. Run Backend Server - -```bash -npm start -``` - -Server sẽ chạy tại: **http://localhost:3000** - -### 3. Kiểm tra Database Connection - -```bash -curl http://localhost:3000/api/health -``` - -Response: -```json -{ - "status": "OK", - "database": "Connected" -} -``` - -## 📡 API Endpoints - -### Authentication - -#### Login -```bash -POST /api/auth/login -Content-Type: application/json - -{ - "username": "admin", - "password": "admin" -} -``` - -### Users - -#### Get All Users -```bash -GET /api/users -``` - -#### Get User Details -```bash -GET /api/users/:id -``` - -#### Create New User -```bash -POST /api/users -Content-Type: application/json - -{ - "username": "newuser", - "password": "password123", - "email": "user@example.com", - "fullname": "Full Name", - "role": "user" -} -``` - -### Applications - -#### Get All Applications -```bash -GET /api/applications -``` - -#### Create Application -```bash -POST /api/applications -Content-Type: application/json - -{ - "name": "New App", - "type": "Cloud", - "status": "online", - "icon": "cloud", - "description": "Application description" -} -``` - -### Accounts - -#### Get User Accounts -```bash -GET /api/accounts/user/:userId -``` - -#### Create Account -```bash -POST /api/accounts -Content-Type: application/json - -{ - "userId": 1, - "appId": 1, - "accountUsername": "account_user", - "accountPassword": "account_pass", - "email": "account@example.com", - "accessLevel": "Admin", - "notes": "Account notes" -} -``` - -### Database Info - -#### Get Database Statistics -```bash -GET /api/database/info -``` - -Response: -```json -{ - "success": true, - "database": "AccManager", - "server": "172.20.235.176", - "tables": [ - { - "TableName": "Accounts", - "ColumnCount": 11 - }, - { - "TableName": "Applications", - "ColumnCount": 7 - }, - { - "TableName": "AuditLog", - "ColumnCount": 8 - }, - { - "TableName": "Users", - "ColumnCount": 10 - } - ], - "statistics": { - "users": 1, - "applications": 4, - "accounts": 0 - } -} -``` - -## 🔧 Frontend Integration - -Update frontend API calls to use the backend server: - -```javascript -// Change from localStorage to API calls -const API_URL = 'http://localhost:3000/api'; - -// Example: Login -async function login(username, password) { - const response = await fetch(`${API_URL}/auth/login`, { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ username, password }) - }); - return response.json(); -} - -// Example: Get user accounts -async function getAccounts(userId) { - const response = await fetch(`${API_URL}/accounts/user/${userId}`); - return response.json(); -} -``` - -## 📝 Initial Data Created - -### Users -- **admin** (admin role) - -### Applications -- AWS (Cloud) - online -- GitHub (VCS) - online -- Google Workspace (Collaboration) - online -- Nginx Proxy (Infra) - offline - -## 🐛 Troubleshooting - -### Connection Error -``` -Database connection failed: Error -``` -**Solution:** -- Kiểm tra SQL Server đang chạy -- Kiểm tra network connectivity đến 172.20.235.176 -- Kiểm tra username/password đúng -- Kiểm tra SQL Server Authentication được enable - -### Port Already in Use -``` -listen EADDRINUSE: address already in use :::3000 -``` -**Solution:** -```bash -# Change port in .env -PORT=3001 -``` - -### MSSQL Module Not Found -```bash -npm install mssql -``` - -## 📚 References - -- [ExpressJS Documentation](https://expressjs.com/) -- [MSSQL Package](https://github.com/tediousjs/node-mssql) -- [SQL Server Documentation](https://docs.microsoft.com/en-us/sql/) - ---- - -**Status:** ✓ Database created, ✓ Tables created, ✓ Admin user created, ✓ Backend ready diff --git a/RUN_COMMANDS.md b/RUN_COMMANDS.md deleted file mode 100644 index 560ceeb..0000000 --- a/RUN_COMMANDS.md +++ /dev/null @@ -1,220 +0,0 @@ -# 🚀 Hướng Dẫn Chạy AccManager - Dành cho Người Dùng Mới - -## 📋 Bước 1: Kiểm Tra Node.js - -Mở **PowerShell** và chạy: - -```powershell -node --version -npm --version -``` - -**Kết quả mong đợi:** -``` -v18.16.0 (hoặc version cao hơn) -9.6.7 (hoặc version khác) -``` - -Nếu thấy version → **OK, tiếp tục bước 2** - ---- - -## 📋 Bước 2: Vào Thư Mục Dự Án - -Copy-paste lệnh này vào PowerShell: - -```powershell -cd d:\RoboticsSource\AccManager -``` - ---- - -## 📋 Bước 3: Cài Đặt Dependencies - -Copy-paste lệnh này vào PowerShell: - -```powershell -npm install -``` - -**Chờ cho tới khi thấy:** -``` -added XXX packages in XXs -``` - -(Sẽ mất 1-3 phút tùy tốc độ mạng) - ---- - -## 📋 Bước 4: Chạy Backend Server - -Copy-paste lệnh này vào PowerShell: - -```powershell -npm start -``` - -**Khi thành công, bạn sẽ thấy:** -``` -======================================== -AccManager Backend Server -======================================== -✓ Server running on http://localhost:3000 -✓ Database: AccManager -✓ Default admin: admin / admin - -API Endpoints: - POST /api/auth/login - GET /api/database/info - GET /api/users - GET /api/applications - GET /api/accounts/user/:userId -======================================== -``` - -**👉 ĐỪNG ĐÓNG TERMINAL NÀY - Server đang chạy!** - ---- - -## 🌐 Bước 5: Mở Ứng Dụng - -**Mở trình duyệt** (Chrome, Firefox, Edge...) copy-paste URL này: - -``` -http://localhost:3000/pages/login.html -``` - ---- - -## 🔐 Bước 6: Đăng Nhập - -**Nhập thông tin:** -- Username: `admin` -- Password: `admin` - -Nhấp **Login** - ---- - -## ✅ Nếu Thành Công - -Bạn sẽ thấy: -- ✓ Trang Dashboard -- ✓ Quản lý Accounts -- ✓ Quản lý Applications -- ✓ Thông tin Database - ---- - -## ❌ Nếu Có Lỗi - -### Lỗi 1: "npm: The term 'npm' is not recognized" -**Giải pháp:** -- Đóng PowerShell hiện tại -- Mở PowerShell **mới** -- Chạy lại `npm --version` - -### Lỗi 2: "Cannot find module 'express'" -**Giải pháp:** -```powershell -npm install -npm start -``` - -### Lỗi 3: "Port 3000 already in use" -**Giải pháp:** Có chương trình khác dùng port 3000 -```powershell -# Dừng server cũ (Ctrl+C) -# Rồi chạy lại: npm start -``` - -### Lỗi 4: "Cannot connect to database" -**Giải pháp:** Kiểm tra SQL Server -- Đảm bảo SQL Server đang chạy -- IP: 172.20.235.176 có reach được không - -```powershell -ping 172.20.235.176 -``` - ---- - -## 💡 Full Workflow - Copy Toàn Bộ Lệnh - -Nếu bạn muốn copy toàn bộ một lần: - -```powershell -# Kiểm tra Node.js -node --version - -# Vào thư mục -cd d:\RoboticsSource\AccManager - -# Cài packages -npm install - -# Chạy server -npm start -``` - ---- - -## 🎯 Các Lệnh Hữu Ích Khác - -### Dừng Server -Nhấp **Ctrl + C** trong PowerShell - -### Chạy Server Ở Chế Độ Development (auto-restart) -```powershell -npm run dev -``` - -### Kiểm Tra API Health -Mở browser khác nhập: -``` -http://localhost:3000/api/health -``` - -### Xem Tất Cả Users -``` -http://localhost:3000/api/users -``` - -### Xem Tất Cả Applications -``` -http://localhost:3000/api/applications -``` - -### Database Info -``` -http://localhost:3000/api/database/info -``` - ---- - -## 📊 Sơ Đồ Port - -| URL | Port | Mục đích | -|-----|------|---------| -| http://localhost:3000/pages/login.html | 3000 | Frontend | -| http://localhost:3000/api/health | 3000 | Backend API | -| 172.20.235.176 | 1433 | SQL Server | - ---- - -## 🎯 Tóm Tắt - 4 Bước Chính - -1. **Mở PowerShell** -2. **Chạy:** - ```powershell - cd d:\RoboticsSource\AccManager - npm install - npm start - ``` -3. **Chờ thấy "Server running on http://localhost:3000"** -4. **Mở browser vào: http://localhost:3000/pages/login.html** -5. **Đăng nhập: admin / admin** - ---- - -**Chúc bạn thành công! 🚀** diff --git a/SETUP_GUIDE.md b/SETUP_GUIDE.md deleted file mode 100644 index 5471692..0000000 --- a/SETUP_GUIDE.md +++ /dev/null @@ -1,294 +0,0 @@ -# 🚀 AccManager Backend - Complete Setup Guide - -## ⚠️ Pre-requisites - -### 1. Install Node.js & npm - -**Download từ:** https://nodejs.org/ -**Khuyến khích:** LTS version (v18 hoặc mới hơn) - -#### Kiểm tra installation: -```bash -node --version -npm --version -``` - -Expected output: -``` -v18.* (or newer) -9.* (or newer) -``` - -### 2. Verify SQL Server Connection - -Trước khi chạy backend, kiểm tra SQL Server: - -```bash -ping 172.20.235.176 -``` - -Nếu không ping được, kiểm tra: -- SQL Server đang chạy -- Firewall cho phép port 1433 -- Network connectivity - ---- - -## 📥 Setup Steps - -### Step 1: Install Node Packages - -```bash -cd d:\RoboticsSource\AccManager -npm install -``` - -Wait cho tới khi mô tả xuất hiện `added X packages` - -### Step 2: Run Backend Server - -```bash -npm start -``` - -**Expected Output:** -``` -======================================== -AccManager Backend Server -======================================== -✓ Server running on http://localhost:3000 -✓ Database: AccManager -✓ Default admin: admin / admin - -API Endpoints: - POST /api/auth/login - GET /api/database/info - GET /api/users - GET /api/applications - GET /api/accounts/user/:userId -======================================== -``` - -### Step 3: Test Connection - -Mở terminal mới, chạy: - -```bash -curl http://localhost:3000/api/health -``` - -**Response:** -```json -{ - "status": "OK", - "database": "Connected" -} -``` - -### Step 4: Test Database Info - -```bash -curl http://localhost:3000/api/database/info -``` - ---- - -## 📝 Database Structure - -### Database Name: `AccManager` - -#### Tables: -1. **Users** (1 admin account) - - Username: admin - - Password: admin - - Role: admin - -2. **Applications** (4 sample apps) - - AWS - - GitHub - - Google Workspace - - Nginx Proxy - -3. **Accounts** (empty, ready to use) - -4. **AuditLog** (empty, for logging) - ---- - -## 🧪 Test API Endpoints - -### Test 1: Login -```bash -curl -X POST http://localhost:3000/api/auth/login \ - -H "Content-Type: application/json" \ - -d "{\"username\":\"admin\",\"password\":\"admin\"}" -``` - -### Test 2: Get Users -```bash -curl http://localhost:3000/api/users -``` - -### Test 3: Get Applications -```bash -curl http://localhost:3000/api/applications -``` - -### Test 4: View Database Info -```bash -curl http://localhost:3000/api/database/info -``` - ---- - -## 🔌 Frontend Integration - -Update your frontend to connect to the backend: - -### Option 1: Update app.js - -```javascript -const API_URL = 'http://localhost:3000/api'; - -// Update login function -async function login(username, password) { - const response = await fetch(`${API_URL}/auth/login`, { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ username, password }) - }); - const data = await response.json(); - - if (data.success) { - localStorage.setItem('currentUser', JSON.stringify(data.user)); - window.location.href = './pages/accounts.html'; - } else { - alert('Login failed: ' + data.message); - } -} - -// Update get accounts function -async function getAccounts(userId) { - const response = await fetch(`${API_URL}/accounts/user/${userId}`); - const data = await response.json(); - return data.data || []; -} -``` - ---- - -## 📦 Project Structure - -``` -d:\RoboticsSource\AccManager\ -├── server.js # Backend server (Node.js) -├── package.json # Dependencies -├── .env # Configuration -├── DATABASE_SETUP.md # This file -├── database/ -│ └── setup.sql # SQL setup script -├── index.html # Frontend entry -├── pages/ -│ ├── login.html -│ ├── accounts.html -│ ├── applications.html -│ └── index.html -└── js/ - └── app.js # Frontend logic -``` - ---- - -## 🔒 Security Notes - -⚠️ **For Development Only:** -- Admin password is hardcoded as "admin" -- SQL credentials in code (not recommended for production) -- CORS enabled for all origins - -### For Production: -1. Use environment variables -2. Hash passwords with bcrypt -3. Implement JWT authentication -4. Use firewalls and VPNs -5. Enable SSL/TLS - ---- - -## 🐛 Troubleshooting - -### Error: "Cannot find module 'express'" -```bash -npm install -``` - -### Error: "Connection failed" -Check: -- SQL Server running -- IP address correct: 172.20.235.176 -- Port 1433 accessible -- Username/password correct - -### Error: "Port 3000 already in use" -```bash -# Change port in .env -PORT=3001 - -# Then restart server -npm start -``` - -### Error: "CORS error in browser" -This is normal during development. The backend already has CORS enabled. - ---- - -## 📊 Database Credentials - -``` -Server: 172.20.235.176 -Database: AccManager -User: sa -Password: robotics@2020 -``` - ---- - -## ✅ Verification Checklist - -- [ ] Node.js installed -- [ ] npm packages installed (`npm install`) -- [ ] Backend server running (`npm start`) -- [ ] Can access http://localhost:3000/api/health -- [ ] Can login with admin/admin -- [ ] Database shows tables and statistics -- [ ] Frontend connects to backend - ---- - -## 📚 Additional Commands - -### Install Development Tools -```bash -npm install -D nodemon -npm run dev # Auto-restart on code changes -``` - -### Check npm packages -```bash -npm list -``` - -### Update packages -```bash -npm update -``` - -### Clear npm cache -```bash -npm cache clean --force -``` - ---- - -**For Support:** Check server logs for error messages diff --git a/server.js b/backend/server.js similarity index 98% rename from server.js rename to backend/server.js index ee257e1..a503383 100644 --- a/server.js +++ b/backend/server.js @@ -10,15 +10,14 @@ const app = express(); app.use(cors()); app.use(express.json()); -// Serve static files +// Serve static files from /public const path = require('path'); -app.use(express.static(path.join(__dirname, 'pages'))); -app.use(express.static(path.join(__dirname, 'js'))); -app.use(express.static(path.join(__dirname))); +const publicDir = path.join(__dirname, '..', 'public'); +app.use(express.static(publicDir)); // Root route app.get('/', (req, res) => { - res.sendFile(path.join(__dirname, 'pages', 'login.html')); + res.sendFile(path.join(publicDir, 'pages', 'login.html')); }); // SQL Server Configuration diff --git a/codedialog.html b/codedialog.html deleted file mode 100644 index 3bcddcf..0000000 --- a/codedialog.html +++ /dev/null @@ -1,270 +0,0 @@ - - - - - - - - Sentinel Accounts - Account Details - - - - - - - - - - -
- -
-
Sentinel Accounts
-
- notifications - help_outline -
-
-
- - - -
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- -
- -
- -
-
- Resource - Details -

Account Details

-
- -
- -
- -
-
- cloud -
-
-
Cloud - Infrastructure
-
AWS Production
-
-
- Active -
-
- -
- -
- -
- alternate_email - admin.aws_prod - -
-
- -
- -
- lock - ••••••••••••••• - -
-
-
- -
- -
- Alex Rivera Profile -
-
Account Owner -
-
Alex Rivera
-
-
- -
-
Date Created
-
- calendar_today - Oct 24, 2023 -
-
-
-
- -
- - -
-
-
- - - \ No newline at end of file diff --git a/database/run-setup.ps1 b/database/run-setup.ps1 deleted file mode 100644 index 868f8e5..0000000 --- a/database/run-setup.ps1 +++ /dev/null @@ -1,63 +0,0 @@ -# PowerShell Script to Execute SQL Server Setup -# Database: AccManager -# Server: 172.20.235.176 - -# SQL Server Connection Info -$ServerName = "172.20.235.176" -$Username = "sa" -$Password = "robotics@2022" -$SqlScriptPath = Join-Path $PSScriptRoot "setup.sql" - -Write-Host "========================================" -ForegroundColor Cyan -Write-Host "AccManager Database Setup" -ForegroundColor Cyan -Write-Host "========================================" -ForegroundColor Cyan -Write-Host "" - -# Check if sqlcmd is available -if (-not (Get-Command sqlcmd -ErrorAction SilentlyContinue)) { - Write-Host "ERROR: sqlcmd is not available on this system." -ForegroundColor Red - Write-Host "Please install SQL Server Command Line Tools (sqlcmd)" -ForegroundColor Yellow - Write-Host "Download from: https://docs.microsoft.com/en-us/sql/tools/sqlcmd-utility" -ForegroundColor Yellow - exit -} - -# Check if SQL script file exists -if (-not (Test-Path $SqlScriptPath)) { - Write-Host "ERROR: SQL script file not found: $SqlScriptPath" -ForegroundColor Red - exit -} - -Write-Host "Server: $ServerName" -ForegroundColor Green -Write-Host "User: $Username" -ForegroundColor Green -Write-Host "Script: $SqlScriptPath" -ForegroundColor Green -Write-Host "" - -# Execute SQL Script -Write-Host "Executing SQL script..." -ForegroundColor Yellow -Write-Host "" - -try { - sqlcmd -S $ServerName -U $Username -P $Password -i $SqlScriptPath -o "setup_output.log" - - Write-Host "" - Write-Host "========================================" -ForegroundColor Green - Write-Host "SETUP COMPLETED SUCCESSFULLY!" -ForegroundColor Green - Write-Host "========================================" -ForegroundColor Green - Write-Host "" - Write-Host "Output saved to: setup_output.log" -ForegroundColor Cyan - Write-Host "" - - # Display output - Write-Host "Setup Output:" -ForegroundColor Cyan - Get-Content "setup_output.log" -} -catch { - Write-Host "ERROR executing SQL script:" -ForegroundColor Red - Write-Host $_.Exception.Message -ForegroundColor Red - exit -} - -Write-Host "" -Write-Host "========================================" -ForegroundColor Green -Write-Host "Database is ready to use!" -ForegroundColor Green -Write-Host "========================================" -ForegroundColor Green diff --git a/database/setup_output.log b/database/setup_output.log deleted file mode 100644 index e0be56a..0000000 --- a/database/setup_output.log +++ /dev/null @@ -1 +0,0 @@ -Sqlcmd: Error: Microsoft ODBC Driver 17 for SQL Server : Login failed for user 'sa'.. diff --git a/install-nodejs.ps1 b/install-nodejs.ps1 deleted file mode 100644 index c4490e5..0000000 --- a/install-nodejs.ps1 +++ /dev/null @@ -1,35 +0,0 @@ -# Install Node.js automatically (Run as Administrator) - -Write-Host "Installing Node.js LTS..." -ForegroundColor Green - -# Check if winget is available -if (Get-Command winget -ErrorAction SilentlyContinue) { - Write-Host "Found winget, installing Node.js..." -ForegroundColor Cyan - winget install OpenJS.NodeJS -} -else { - Write-Host "winget not found. Downloading Node.js installer..." -ForegroundColor Yellow - - # Download Node.js LTS - $NodeURL = "https://nodejs.org/dist/v18.16.0/node-v18.16.0-x64.msi" - $InstallerPath = "$env:TEMP\nodejs-installer.msi" - - Write-Host "Downloading from: $NodeURL" - Invoke-WebRequest -Uri $NodeURL -OutFile $InstallerPath -UseBasicParsing - - Write-Host "Running installer..." -ForegroundColor Cyan - Start-Process -FilePath "msiexec.exe" -ArgumentList "/i $InstallerPath /quiet /norestart" -Wait - - Remove-Item $InstallerPath -} - -Write-Host "Installation complete! Refreshing environment..." -ForegroundColor Green - -# Refresh PATH -$env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path","User") - -Write-Host "Checking installation..." -ForegroundColor Cyan -node --version -npm --version - -Write-Host "Ready to run npm install!" -ForegroundColor Green diff --git a/package.json b/package.json index fe36208..3ac53ea 100644 --- a/package.json +++ b/package.json @@ -2,10 +2,10 @@ "name": "accmanager-backend", "version": "1.0.0", "description": "Backend server for AccManager application", - "main": "server.js", + "main": "backend/server.js", "scripts": { - "start": "node server.js", - "dev": "nodemon server.js" + "start": "node backend/server.js", + "dev": "nodemon backend/server.js" }, "keywords": ["accmanager", "backend", "express", "mssql"], "author": "", diff --git a/index.html b/public/index.html similarity index 100% rename from index.html rename to public/index.html diff --git a/js/app.js b/public/js/app.js similarity index 84% rename from js/app.js rename to public/js/app.js index 82a913f..10d138b 100644 --- a/js/app.js +++ b/public/js/app.js @@ -15,7 +15,49 @@ class AccountManager { this.applications = []; this.apiBase = '/api'; this.currentPage = 'dashboard'; + this.accountSearchTerm = ''; + this.applicationSearchTerm = ''; + this.accountServiceFilter = ''; + this.configureNotifications(); this.initPromise = this.init(); + this.pendingAccountAppId = undefined; + } + + configureNotifications() { + if (window.Notiflix?.Notify) { + Notiflix.Notify.init({ + position: 'right-top', + timeout: 2500, + clickToClose: true, + pauseOnHover: true, + distance: '12px', + fontSize: '14px' + }); + } + } + + notifySuccess(message) { + if (window.Notiflix?.Notify) { + Notiflix.Notify.success(message); + } else { + alert(message); + } + } + + notifyFailure(message) { + if (window.Notiflix?.Notify) { + Notiflix.Notify.failure(message); + } else { + alert(message); + } + } + + notifyWarning(message) { + if (window.Notiflix?.Notify) { + Notiflix.Notify.warning(message); + } else { + alert(message); + } } getUserId() { @@ -112,6 +154,7 @@ class AccountManager { // Account table row clicks this.setupAccountRowListeners(); + this.setupFilters(); } setupFormListeners() { @@ -144,6 +187,27 @@ class AccountManager { if (roleEl) roleEl.textContent = this.currentUser?.role || this.currentUser?.Role || 'Administrator'; } + getFilteredAccounts() { + const svcFilter = this.accountServiceFilter || ''; + const search = (this.accountSearchTerm || '').toLowerCase(); + return this.accounts.filter(acc => { + const matchesService = !svcFilter || String(acc.AppId) === String(svcFilter); + if (!matchesService) return false; + if (!search) return true; + const hay = [acc.AccountUsername, acc.Email, acc.AppName, acc.AppType].map(v => (v || '').toLowerCase()); + return hay.some(val => val.includes(search)); + }); + } + + getFilteredApplications() { + const search = (this.applicationSearchTerm || '').toLowerCase(); + if (!search) return this.applications; + return this.applications.filter(app => { + const hay = [app.Name, app.Type, app.Description, app.Url, app.Icon].map(v => (v || '').toLowerCase()); + return hay.some(val => val.includes(search)); + }); + } + handleLogout() { if (confirm('Are you sure you want to logout?')) { this.saveToStorage('currentUser', null); @@ -234,6 +298,7 @@ class AccountManager { } getAccountsContent() { + const filteredAccounts = this.getFilteredAccounts(); return `
@@ -257,12 +322,15 @@ class AccountManager { ${this.applications.map(app => ``).join('')}
-
+
+ Search + +
- ${this.accounts.length > 0 ? ` + ${filteredAccounts.length > 0 ? `
@@ -274,7 +342,7 @@ class AccountManager { - ${this.accounts.map(acc => ` + ${filteredAccounts.map(acc => ` @@ -315,6 +383,7 @@ class AccountManager { } getApplicationsContent() { + const filteredApps = this.getFilteredApplications(); return `
@@ -362,6 +431,10 @@ class AccountManager {
+
+ Search + +
@@ -375,7 +448,7 @@ class AccountManager { - ${this.applications.map(app => ` + ${filteredApps.map(app => `
@@ -457,16 +530,16 @@ class AccountManager { .then(res => res.json()) .then(data => { if (data.success) { - alert('Account deleted successfully'); + this.notifySuccess('Account deleted successfully'); this.closeModals(); - location.href = './accounts.html'; + this.refreshAccountsUI(); } else { - alert(data.message || 'Delete account failed'); + this.notifyFailure(data.message || 'Delete account failed'); } }) .catch(err => { console.error(err); - alert('Delete account failed'); + this.notifyFailure('Delete account failed'); }); } }); @@ -489,6 +562,7 @@ class AccountManager { if (ownerInput) ownerInput.value = this.currentUser?.Username || this.currentUser?.username || ''; if (serviceSelect) serviceSelect.value = account?.AppId || ''; } + this.pendingAccountAppId = account?.AppId; this.editingAccountId = account?.AccountId; this.closeModals(); this.openAccountModal(); @@ -510,6 +584,7 @@ class AccountManager { if (ownerInput) ownerInput.value = this.currentUser?.Username || this.currentUser?.username || ''; if (serviceSelect) serviceSelect.value = account?.AppId || ''; } + this.pendingAccountAppId = account?.AppId; this.editingAccountId = account?.AccountId; this.closeModals(); this.openAccountModal(); @@ -543,6 +618,11 @@ class AccountManager { this.currentViewAppId = appId; document.getElementById('viewAppName').textContent = app?.Name || '-'; document.getElementById('viewAppType').textContent = app?.Type || '-'; + const iconVal = app?.Icon || app?.icon || 'apps'; + const iconSymbolEl = document.getElementById('viewAppIconSymbol'); + const iconNameEl = document.getElementById('viewAppIconName'); + if (iconSymbolEl) iconSymbolEl.textContent = iconVal; + if (iconNameEl) iconNameEl.textContent = iconVal; document.getElementById('viewAppDescription').textContent = app?.Description || '-'; const urlEl = document.getElementById('viewAppUrl'); const urlVal = app?.Url || app?.url; @@ -578,16 +658,16 @@ class AccountManager { .then(res => res.json()) .then(data => { if (data.success) { - alert('Application deleted successfully'); + this.notifySuccess('Application deleted successfully'); this.closeModals(); - location.href = './applications.html'; + this.refreshApplicationsUI(); } else { - alert(data.message || 'Delete application failed'); + this.notifyFailure(data.message || 'Delete application failed'); } }) .catch(err => { console.error(err); - alert('Delete application failed'); + this.notifyFailure('Delete application failed'); }); } }); @@ -602,6 +682,7 @@ class AccountManager { document.getElementById('appType').value = app?.Type || ''; document.getElementById('appStatus').value = app?.Status || 'online'; document.getElementById('appDescription').value = app?.Description || ''; + document.getElementById('appIcon').value = app?.Icon || app?.icon || ''; document.getElementById('appUrl').value = app?.Url || app?.url || ''; this.editingAppId = app?.AppId; this.closeModals(); @@ -618,6 +699,7 @@ class AccountManager { document.getElementById('appType').value = app?.Type || ''; document.getElementById('appStatus').value = app?.Status || 'online'; document.getElementById('appDescription').value = app?.Description || ''; + document.getElementById('appIcon').value = app?.Icon || app?.icon || ''; document.getElementById('appUrl').value = app?.Url || ''; this.editingAppId = app?.AppId; this.closeModals(); @@ -631,6 +713,7 @@ class AccountManager { document.querySelectorAll('#addAccountBtn').forEach(btn => { btn.addEventListener('click', () => { this.editingAccountId = undefined; + this.pendingAccountAppId = undefined; this.openAccountModal(); }); }); @@ -644,7 +727,36 @@ class AccountManager { }); } - handleAccountSubmit(e) { + setupFilters() { + const serviceFilter = document.getElementById('serviceFilter'); + if (serviceFilter) { + serviceFilter.value = this.accountServiceFilter || ''; + serviceFilter.addEventListener('change', (e) => { + this.accountServiceFilter = e.target.value; + this.refreshAccountsUI(); + }); + } + + const accountSearch = document.getElementById('accountSearch'); + if (accountSearch) { + accountSearch.value = this.accountSearchTerm; + accountSearch.addEventListener('input', (e) => { + this.accountSearchTerm = e.target.value.toLowerCase(); + this.refreshAccountsUI(); + }); + } + + const appSearch = document.getElementById('appSearch'); + if (appSearch) { + appSearch.value = this.applicationSearchTerm; + appSearch.addEventListener('input', (e) => { + this.applicationSearchTerm = e.target.value.toLowerCase(); + this.refreshApplicationsUI(); + }); + } + } + + async handleAccountSubmit(e) { e.preventDefault(); const accountForm = document.getElementById('accountForm'); const userId = this.getUserId(); @@ -653,23 +765,23 @@ class AccountManager { const accountPassword = (accountForm?.querySelector('#accountPassword')?.value || '').trim(); const accountEmail = ((accountForm?.querySelector('#accountOwner')?.value || '').trim()) || this.currentUser?.Username || this.currentUser?.username || ''; if (!accountForm) { - alert('Account form not found.'); + this.notifyFailure('Account form not found.'); return; } if (!userId) { - alert('User is not authenticated. Please login again.'); + this.notifyFailure('User is not authenticated. Please login again.'); return; } if (!appId) { - alert('Please select a service.'); + this.notifyWarning('Please select a service.'); return; } if (!accountUsername) { - alert('Please enter a username.'); + this.notifyWarning('Please enter a username.'); return; } if (!accountPassword) { - alert('Please enter a password.'); + this.notifyWarning('Please enter a password.'); return; } const payload = { @@ -693,25 +805,37 @@ class AccountManager { }).then(res => res.json()).then(data => { if (data.success) { this.editingAccountId = undefined; - alert(isEdit ? 'Account updated successfully' : 'Account created successfully'); + this.pendingAccountAppId = undefined; + this.notifySuccess(isEdit ? 'Account updated successfully' : 'Account created successfully'); this.closeModals(); - location.href = './accounts.html'; + this.refreshAccountsUI(); } else { - alert(data.message || 'Save account failed'); + this.notifyFailure(data.message || 'Save account failed'); } }).catch(err => { console.error(err); - alert('Save account failed'); + this.notifyFailure('Save account failed'); }); } - handleAppSubmit(e) { + async refreshAccountsUI() { + await this.fetchAccounts(); + const mainContent = document.getElementById('mainContent'); + if (mainContent) { + mainContent.innerHTML = this.getAccountsContent(); + this.setupAccountRowListeners(); + this.setupAddButtonListeners(); + this.setupFilters(); + } + } + + async handleAppSubmit(e) { e.preventDefault(); const payload = { name: document.getElementById('appName').value, type: document.getElementById('appType').value, status: document.getElementById('appStatus').value, - icon: 'cloud', + icon: (document.getElementById('appIcon')?.value || 'apps').trim() || 'apps', description: document.getElementById('appDescription')?.value || '', url: (document.getElementById('appUrl')?.value || '').trim() }; @@ -727,24 +851,38 @@ class AccountManager { }).then(res => res.json()).then(data => { if (data.success) { this.editingAppId = undefined; - alert(isEdit ? 'Application updated successfully' : 'Application created successfully'); + this.notifySuccess(isEdit ? 'Application updated successfully' : 'Application created successfully'); this.closeModals(); - location.href = './applications.html'; + this.refreshApplicationsUI(); } else { - alert(data.message || 'Save application failed'); + this.notifyFailure(data.message || 'Save application failed'); } }).catch(err => { console.error(err); - alert('Save application failed'); + this.notifyFailure('Save application failed'); }); } + async refreshApplicationsUI() { + await this.fetchApplications(); + const mainContent = document.getElementById('mainContent'); + if (mainContent) { + mainContent.innerHTML = this.getApplicationsContent(); + this.setupAccountRowListeners(); + this.setupAddButtonListeners(); + this.setupFilters(); + } + } + openAccountModal() { // Refresh service options so newly added applications appear const serviceSelect = document.getElementById('accountService'); if (serviceSelect) { serviceSelect.innerHTML = `` + this.applications.map(app => ``).join(''); + if (this.editingAccountId !== undefined && this.pendingAccountAppId) { + serviceSelect.value = this.pendingAccountAppId; + } } if (this.editingAccountId === undefined) { @@ -768,8 +906,10 @@ class AccountManager { document.getElementById('appName').value = ''; document.getElementById('appType').value = ''; document.getElementById('appStatus').value = 'online'; + const iconInput = document.getElementById('appIcon'); const desc = document.getElementById('appDescription'); const url = document.getElementById('appUrl'); + if (iconInput) iconInput.value = ''; if (desc) desc.value = ''; if (url) url.value = ''; } diff --git a/modals.html b/public/modals.html similarity index 92% rename from modals.html rename to public/modals.html index 5359426..74fe02c 100644 --- a/modals.html +++ b/public/modals.html @@ -108,6 +108,11 @@
+
+ + +

Nhập tên icon từ https://fonts.google.com/icons (ví dụ: cloud, apps, security).

+
@@ -149,6 +154,13 @@
-
+
+ +
+ apps + apps +
+
-
diff --git a/pages/accounts.html b/public/pages/accounts.html similarity index 98% rename from pages/accounts.html rename to public/pages/accounts.html index 40284df..bf67bc5 100644 --- a/pages/accounts.html +++ b/public/pages/accounts.html @@ -3,12 +3,15 @@ - VaultSentinel - Accounts Management + Robot Manager Account - Accounts Management + + + + +