Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions create-a-container/public/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -368,3 +368,39 @@ main {
.navbar {
border-bottom: 2px solid #1a252f;
}

/* Alert/Message boxes */
.alert {
margin-bottom: 1rem;
padding: 0.75rem;
border: 1px solid transparent;
border-radius: 4px;
}

.alert-success {
color: #155724;
background-color: #d4edda;
border-color: #c3e6cb;
}

.alert-error {
color: #721c24;
background-color: #f8d7da;
border-color: #f5c6cb;
}

.alert-info {
color: #004085;
background-color: #cce5ff;
border-color: #b8daff;
}

.alert-info strong {
display: block;
margin-bottom: 0.5rem;
}

.alert-info p {
margin: 0.5rem 0 0 0;
font-size: 0.9em;
}
16 changes: 8 additions & 8 deletions create-a-container/routers/apikeys.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ router.use(requireAuth);
router.get('/', async (req, res) => {
const user = await User.findOne({ where: { uid: req.session.user } });
if (!user) {
req.flash('error', 'User not found');
await req.flash('error', 'User not found');
return res.redirect('/login');
}

Expand Down Expand Up @@ -46,7 +46,7 @@ router.get('/new', (req, res) => {
router.post('/', async (req, res) => {
const user = await User.findOne({ where: { uid: req.session.user } });
if (!user) {
req.flash('error', 'User not found');
await req.flash('error', 'User not found');
return res.redirect('/login');
}

Expand Down Expand Up @@ -79,7 +79,7 @@ router.post('/', async (req, res) => {
});
}

req.flash('success', 'API key created successfully. This is the only time it will be shown!');
await req.flash('success', 'API key created successfully. This is the only time it will be shown!');
return res.render('apikeys/created', {
plainKey: apiKeyData.plainKey,
apiKey,
Expand All @@ -91,7 +91,7 @@ router.post('/', async (req, res) => {
router.get('/:id', async (req, res) => {
const user = await User.findOne({ where: { uid: req.session.user } });
if (!user) {
req.flash('error', 'User not found');
await req.flash('error', 'User not found');
return res.redirect('/login');
}

Expand All @@ -113,7 +113,7 @@ router.get('/:id', async (req, res) => {
return res.status(404).json({ error: 'API key not found' });
}

req.flash('error', 'API key not found');
await req.flash('error', 'API key not found');
return res.redirect('/apikeys');
}

Expand All @@ -135,7 +135,7 @@ router.get('/:id', async (req, res) => {
router.delete('/:id', async (req, res) => {
const user = await User.findOne({ where: { uid: req.session.user } });
if (!user) {
req.flash('error', 'User not found');
await req.flash('error', 'User not found');
return res.redirect('/login');
}

Expand All @@ -156,7 +156,7 @@ router.delete('/:id', async (req, res) => {
return res.status(404).json({ error: 'API key not found' });
}

req.flash('error', 'API key not found');
await req.flash('error', 'API key not found');
return res.redirect('/apikeys');
}

Expand All @@ -170,7 +170,7 @@ router.delete('/:id', async (req, res) => {
return res.status(204).send();
}

req.flash('success', 'API key deleted successfully');
await req.flash('success', 'API key deleted successfully');
return res.redirect('/apikeys');
});

Expand Down
40 changes: 20 additions & 20 deletions create-a-container/routers/containers.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ router.get('/new', requireAuth, async (req, res) => {
const siteId = parseInt(req.params.siteId, 10);
const site = await Site.findByPk(siteId);
if (!site) {
req.flash('error', 'Site not found');
await req.flash('error', 'Site not found');
return res.redirect('/sites');
}

Expand Down Expand Up @@ -121,7 +121,7 @@ router.get('/', requireAuth, async (req, res) => {

const site = await Site.findByPk(siteId);
if (!site) {
req.flash('error', 'Site not found');
await req.flash('error', 'Site not found');
return res.redirect('/sites');
}

Expand Down Expand Up @@ -186,7 +186,7 @@ router.get('/:id/edit', requireAuth, async (req, res) => {

const site = await Site.findByPk(siteId);
if (!site) {
req.flash('error', 'Site not found');
await req.flash('error', 'Site not found');
return res.redirect('/sites');
}

Expand Down Expand Up @@ -228,7 +228,7 @@ router.get('/:id/edit', requireAuth, async (req, res) => {
});

if (!container) {
req.flash('error', 'Container not found');
await req.flash('error', 'Container not found');
return res.redirect(`/sites/${siteId}/containers`);
}

Expand All @@ -255,7 +255,7 @@ router.post('/', async (req, res) => {
// Validate site exists
const site = await Site.findByPk(siteId);
if (!site) {
req.flash('error', 'Site not found');
await req.flash('error', 'Site not found');
return res.redirect('/sites');
}

Expand Down Expand Up @@ -422,7 +422,7 @@ router.post('/', async (req, res) => {
// Commit the transaction
await t.commit();

req.flash('success', `Container "${hostname}" is being created. Check back shortly for status updates.`);
await req.flash('success', `Container "${hostname}" is being created. Check back shortly for status updates.`);
return res.redirect(`/jobs/${job.id}`);
} catch (err) {
// Rollback the transaction
Expand All @@ -444,7 +444,7 @@ router.post('/', async (req, res) => {
errorMessage += err.message;
}

req.flash('error', errorMessage);
await req.flash('error', errorMessage);
return res.redirect(`/sites/${siteId}/containers/new`);
}
});
Expand All @@ -456,7 +456,7 @@ router.put('/:id', requireAuth, async (req, res) => {

const site = await Site.findByPk(siteId);
if (!site) {
req.flash('error', 'Site not found');
await req.flash('error', 'Site not found');
return res.redirect('/sites');
}

Expand All @@ -477,7 +477,7 @@ router.put('/:id', requireAuth, async (req, res) => {
});

if (!container) {
req.flash('error', 'Container not found');
await req.flash('error', 'Container not found');
return res.redirect(`/sites/${siteId}/containers`);
}

Expand Down Expand Up @@ -624,15 +624,15 @@ router.put('/:id', requireAuth, async (req, res) => {
});

if (restartJob) {
req.flash('success', 'Container configuration updated. Restarting container...');
await req.flash('success', 'Container configuration updated. Restarting container...');
return res.redirect(`/jobs/${restartJob.id}`);
} else {
req.flash('success', 'Container services updated successfully');
await req.flash('success', 'Container services updated successfully');
}
return res.redirect(`/sites/${siteId}/containers`);
} catch (err) {
console.error('Error updating container:', err);
req.flash('error', 'Failed to update container: ' + err.message);
await req.flash('error', 'Failed to update container: ' + err.message);
return res.redirect(`/sites/${siteId}/containers/${containerId}/edit`);
}
});
Expand All @@ -645,7 +645,7 @@ router.delete('/:id', requireAuth, async (req, res) => {
// Validate site exists
const site = await Site.findByPk(siteId);
if (!site) {
req.flash('error', 'Site not found');
await req.flash('error', 'Site not found');
return res.redirect('/sites');
}

Expand All @@ -663,24 +663,24 @@ router.delete('/:id', requireAuth, async (req, res) => {
});

if (!container) {
req.flash('error', 'Container not found');
await req.flash('error', 'Container not found');
return res.redirect(`/sites/${siteId}/containers`);
}

// Verify the container's node belongs to this site
if (!container.node || container.node.siteId !== siteId) {
req.flash('error', 'Container does not belong to this site');
await req.flash('error', 'Container does not belong to this site');
return res.redirect(`/sites/${siteId}/containers`);
}

const node = container.node;
if (!node.apiUrl) {
req.flash('error', 'Node API URL not configured');
await req.flash('error', 'Node API URL not configured');
return res.redirect(`/sites/${siteId}/containers`);
}

if (!node.tokenId || !node.secret) {
req.flash('error', 'Node API token not configured');
await req.flash('error', 'Node API token not configured');
return res.redirect(`/sites/${siteId}/containers`);
}

Expand All @@ -696,7 +696,7 @@ router.delete('/:id', requireAuth, async (req, res) => {

if (proxmoxHostname && proxmoxHostname !== container.hostname) {
console.error(`Hostname mismatch: DB has "${container.hostname}", Proxmox has "${proxmoxHostname}" for VMID ${container.containerId}`);
req.flash('error', `Safety check failed: Proxmox container hostname "${proxmoxHostname}" does not match database hostname "${container.hostname}". Manual intervention required.`);
await req.flash('error', `Safety check failed: Proxmox container hostname "${proxmoxHostname}" does not match database hostname "${container.hostname}". Manual intervention required.`);
return res.redirect(`/sites/${siteId}/containers`);
}

Expand All @@ -721,11 +721,11 @@ router.delete('/:id', requireAuth, async (req, res) => {
await container.destroy();
} catch (error) {
console.error(error);
req.flash('error', `Failed to delete container: ${error.message}`);
await req.flash('error', `Failed to delete container: ${error.message}`);
return res.redirect(`/sites/${siteId}/containers`);
}

req.flash('success', `Container ${container.hostname} deleted successfully`);
await req.flash('success', `Container ${container.hostname} deleted successfully`);
return res.redirect(`/sites/${siteId}/containers`);
});

Expand Down
Loading
Loading