save
This commit is contained in:
136
server.js
136
server.js
@@ -10,6 +10,17 @@ const app = express();
|
||||
app.use(cors());
|
||||
app.use(express.json());
|
||||
|
||||
// Serve static files
|
||||
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)));
|
||||
|
||||
// Root route
|
||||
app.get('/', (req, res) => {
|
||||
res.sendFile(path.join(__dirname, 'pages', 'login.html'));
|
||||
});
|
||||
|
||||
// SQL Server Configuration
|
||||
const sqlConfig = {
|
||||
server: '172.20.235.176',
|
||||
@@ -17,14 +28,15 @@ const sqlConfig = {
|
||||
type: 'default',
|
||||
options: {
|
||||
userName: 'sa',
|
||||
password: 'robotics@2020'
|
||||
password: 'robotics@2022'
|
||||
}
|
||||
},
|
||||
options: {
|
||||
database: 'AccManager',
|
||||
trustServerCertificate: true,
|
||||
enableKeepAlive: true,
|
||||
connectTimeout: 30000
|
||||
connectTimeout: 30000,
|
||||
encrypt: false
|
||||
}
|
||||
};
|
||||
|
||||
@@ -40,8 +52,8 @@ async function initializeDatabase() {
|
||||
// Check and create database if not exists
|
||||
const masterConnection = new sql.ConnectionPool({
|
||||
server: '172.20.235.176',
|
||||
authentication: { type: 'default', options: { userName: 'sa', password: 'robotics@2020' } },
|
||||
options: { connectTimeout: 30000, database: 'master', trustServerCertificate: true }
|
||||
authentication: { type: 'default', options: { userName: 'sa', password: 'robotics@2022' } },
|
||||
options: { connectTimeout: 30000, database: 'master', trustServerCertificate: true, encrypt: false }
|
||||
});
|
||||
|
||||
await masterConnection.connect();
|
||||
@@ -91,6 +103,7 @@ async function createTables() {
|
||||
Status NVARCHAR(20) DEFAULT 'online',
|
||||
Icon NVARCHAR(50),
|
||||
Description NVARCHAR(500),
|
||||
Url NVARCHAR(255),
|
||||
CreatedDate DATETIME DEFAULT GETDATE(),
|
||||
UpdatedDate DATETIME DEFAULT GETDATE()
|
||||
)
|
||||
@@ -141,6 +154,16 @@ async function createTables() {
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure new columns exist on Applications for migrations
|
||||
try {
|
||||
await pool.request().query(`IF COL_LENGTH('dbo.Applications','Url') IS NULL ALTER TABLE Applications ADD Url NVARCHAR(255);`);
|
||||
await pool.request().query(`IF COL_LENGTH('dbo.Applications','Description') IS NULL ALTER TABLE Applications ADD Description NVARCHAR(500);`);
|
||||
// Backfill Url to empty string to avoid undefined in responses
|
||||
await pool.request().query(`UPDATE Applications SET Url = '' WHERE Url IS NULL;`);
|
||||
} catch (err) {
|
||||
console.error('Column addition error (Applications):', err.message);
|
||||
}
|
||||
|
||||
// Insert initial admin user
|
||||
try {
|
||||
await pool.request()
|
||||
@@ -162,12 +185,12 @@ async function createTables() {
|
||||
await pool.request()
|
||||
.query(`IF (SELECT COUNT(*) FROM Applications) = 0
|
||||
BEGIN
|
||||
INSERT INTO Applications (Name, Type, Status, Icon, Description)
|
||||
INSERT INTO Applications (Name, Type, Status, Icon, Description, Url)
|
||||
VALUES
|
||||
('AWS', 'Cloud', 'online', 'cloud', 'Amazon Web Services'),
|
||||
('GitHub', 'VCS', 'online', 'code', 'GitHub - Version Control'),
|
||||
('Google Workspace', 'Collaboration', 'online', 'mail', 'Google Workspace'),
|
||||
('Nginx Proxy', 'Infra', 'offline', 'dns', 'Nginx Web Server')
|
||||
('AWS', 'Cloud', 'online', 'cloud', 'Amazon Web Services', 'https://aws.amazon.com'),
|
||||
('GitHub', 'VCS', 'online', 'code', 'GitHub - Version Control', 'https://github.com'),
|
||||
('Google Workspace', 'Collaboration', 'online', 'mail', 'Google Workspace', 'https://workspace.google.com'),
|
||||
('Nginx Proxy', 'Infra', 'offline', 'dns', 'Nginx Web Server', 'https://nginx.org')
|
||||
END`);
|
||||
console.log('✓ Sample applications created');
|
||||
} catch (err) {
|
||||
@@ -275,7 +298,7 @@ app.post('/api/users', async (req, res) => {
|
||||
app.get('/api/applications', async (req, res) => {
|
||||
try {
|
||||
const result = await pool.request()
|
||||
.query('SELECT * FROM Applications ORDER BY Name');
|
||||
.query('SELECT AppId, Name, Type, Status, Icon, Description, Url, CreatedDate, UpdatedDate FROM Applications ORDER BY Name');
|
||||
res.json({ success: true, data: result.recordset });
|
||||
} catch (err) {
|
||||
res.status(500).json({ success: false, message: err.message });
|
||||
@@ -285,7 +308,7 @@ app.get('/api/applications', async (req, res) => {
|
||||
// Create application
|
||||
app.post('/api/applications', async (req, res) => {
|
||||
try {
|
||||
const { name, type, status, icon, description } = req.body;
|
||||
const { name, type, status, icon, description, url } = req.body;
|
||||
|
||||
const result = await pool.request()
|
||||
.input('name', sql.NVarChar, name)
|
||||
@@ -293,8 +316,9 @@ app.post('/api/applications', async (req, res) => {
|
||||
.input('status', sql.NVarChar, status)
|
||||
.input('icon', sql.NVarChar, icon)
|
||||
.input('description', sql.NVarChar, description)
|
||||
.query(`INSERT INTO Applications (Name, Type, Status, Icon, Description)
|
||||
VALUES (@name, @type, @status, @icon, @description);
|
||||
.input('url', sql.NVarChar, url)
|
||||
.query(`INSERT INTO Applications (Name, Type, Status, Icon, Description, Url)
|
||||
VALUES (@name, @type, @status, @icon, @description, @url);
|
||||
SELECT SCOPE_IDENTITY() as AppId`);
|
||||
|
||||
res.json({ success: true, message: 'Application created', appId: result.recordset[0].AppId });
|
||||
@@ -303,6 +327,48 @@ app.post('/api/applications', async (req, res) => {
|
||||
}
|
||||
});
|
||||
|
||||
// Update application
|
||||
app.put('/api/applications/:id', async (req, res) => {
|
||||
try {
|
||||
const { name, type, status, icon, description, url } = req.body;
|
||||
|
||||
await pool.request()
|
||||
.input('appId', sql.Int, req.params.id)
|
||||
.input('name', sql.NVarChar, name)
|
||||
.input('type', sql.NVarChar, type)
|
||||
.input('status', sql.NVarChar, status)
|
||||
.input('icon', sql.NVarChar, icon)
|
||||
.input('description', sql.NVarChar, description)
|
||||
.input('url', sql.NVarChar, url)
|
||||
.query(`UPDATE Applications
|
||||
SET Name = @name,
|
||||
Type = @type,
|
||||
Status = @status,
|
||||
Icon = @icon,
|
||||
Description = @description,
|
||||
Url = @url,
|
||||
UpdatedDate = GETDATE()
|
||||
WHERE AppId = @appId`);
|
||||
|
||||
res.json({ success: true, message: 'Application updated' });
|
||||
} catch (err) {
|
||||
res.status(500).json({ success: false, message: err.message });
|
||||
}
|
||||
});
|
||||
|
||||
// Delete application
|
||||
app.delete('/api/applications/:id', async (req, res) => {
|
||||
try {
|
||||
await pool.request()
|
||||
.input('appId', sql.Int, req.params.id)
|
||||
.query('DELETE FROM Applications WHERE AppId = @appId');
|
||||
|
||||
res.json({ success: true, message: 'Application deleted' });
|
||||
} catch (err) {
|
||||
res.status(500).json({ success: false, message: err.message });
|
||||
}
|
||||
});
|
||||
|
||||
// ==========================================
|
||||
// API ROUTES - Accounts
|
||||
// ==========================================
|
||||
@@ -346,6 +412,50 @@ app.post('/api/accounts', async (req, res) => {
|
||||
}
|
||||
});
|
||||
|
||||
// Update account
|
||||
app.put('/api/accounts/:id', async (req, res) => {
|
||||
try {
|
||||
const { userId, appId, accountUsername, accountPassword, email, accessLevel, notes } = req.body;
|
||||
|
||||
await pool.request()
|
||||
.input('accountId', sql.Int, req.params.id)
|
||||
.input('userId', sql.Int, userId)
|
||||
.input('appId', sql.Int, appId)
|
||||
.input('accountUsername', sql.NVarChar, accountUsername)
|
||||
.input('accountPassword', sql.NVarChar, accountPassword)
|
||||
.input('email', sql.NVarChar, email)
|
||||
.input('accessLevel', sql.NVarChar, accessLevel)
|
||||
.input('notes', sql.NVarChar, notes)
|
||||
.query(`UPDATE Accounts
|
||||
SET UserId = @userId,
|
||||
AppId = @appId,
|
||||
AccountUsername = @accountUsername,
|
||||
AccountPassword = @accountPassword,
|
||||
Email = @email,
|
||||
AccessLevel = @accessLevel,
|
||||
Notes = @notes,
|
||||
UpdatedDate = GETDATE()
|
||||
WHERE AccountId = @accountId`);
|
||||
|
||||
res.json({ success: true, message: 'Account updated' });
|
||||
} catch (err) {
|
||||
res.status(500).json({ success: false, message: err.message });
|
||||
}
|
||||
});
|
||||
|
||||
// Delete account
|
||||
app.delete('/api/accounts/:id', async (req, res) => {
|
||||
try {
|
||||
await pool.request()
|
||||
.input('accountId', sql.Int, req.params.id)
|
||||
.query('DELETE FROM Accounts WHERE AccountId = @accountId');
|
||||
|
||||
res.json({ success: true, message: 'Account deleted' });
|
||||
} catch (err) {
|
||||
res.status(500).json({ success: false, message: err.message });
|
||||
}
|
||||
});
|
||||
|
||||
// ==========================================
|
||||
// API ROUTES - Database Info
|
||||
// ==========================================
|
||||
|
||||
Reference in New Issue
Block a user