• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

witseie-elen4010 / 2026-group-lab-002 / 25517131108

07 May 2026 07:22PM UTC coverage: 92.483% (+0.6%) from 91.921%
25517131108

push

github

web-flow
Merge pull request #71 from witseie-elen4010/feat/admin-access-control

Feat/admin access control

146 of 170 branches covered (85.88%)

Branch coverage included in aggregate %.

84 of 85 new or added lines in 4 files covered. (98.82%)

383 of 402 relevant lines covered (95.27%)

3.52 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

93.02
/src/controllers/admin-controller.js
1
const db = require('../../database/db');
4✔
2

3
const PAGE_SIZE = 20;
4✔
4

5
const getAllTables = () =>
4✔
6
  db.prepare(`SELECT name FROM sqlite_master WHERE type='table' ORDER BY name`).all().map(r => r.name);
25✔
7

8
const getColumns = (tableName) =>
4✔
9
  db.prepare(`PRAGMA table_info("${tableName}")`).all();
5✔
10

11
const showAdminDashboard = (req, res) => {
4✔
12
  const user = { id: req.session.userId, name: req.session.userName };
1✔
13
  const tables = getAllTables();
1✔
14
  res.render('admin-dashboard', {
1✔
15
    user, tables,
16
    activeTable: null, columns: [], rows: [], page: 1, totalPages: 1,
17
    error: null, success: null,
18
  });
19
};
20

21
const showTable = (req, res) => {
4✔
22
  const user = { id: req.session.userId, name: req.session.userName };
2✔
23
  const tables = getAllTables();
2✔
24
  const { tableName } = req.params;
2✔
25

26
  if (!tables.includes(tableName)) return res.status(404).send('Table not found');
2✔
27

28
  const page = Math.max(1, parseInt(req.query.page) || 1);
1✔
29
  const offset = (page - 1) * PAGE_SIZE;
1✔
30
  const totalRows = db.prepare(`SELECT COUNT(*) as count FROM "${tableName}"`).get().count;
1✔
31
  const totalPages = Math.max(1, Math.ceil(totalRows / PAGE_SIZE));
1✔
32
  const rows = db.prepare(`SELECT rowid, * FROM "${tableName}" LIMIT ? OFFSET ?`).all(PAGE_SIZE, offset);
1✔
33
  const columns = getColumns(tableName);
1✔
34

35
  res.render('admin-dashboard', {
1✔
36
    user, tables,
37
    activeTable: tableName, columns, rows, page, totalPages,
38
    error: req.query.error || null,
2✔
39
    success: req.query.success || null,
2✔
40
  });
41
};
42

43
const createRecord = (req, res) => {
4✔
44
  const tables = getAllTables();
2✔
45
  const { tableName } = req.params;
2✔
46
  if (!tables.includes(tableName)) return res.status(404).send('Table not found');
2!
47

48
  const columns = getColumns(tableName);
2✔
49
  const fields = columns.map(c => c.name);
4✔
50
  const values = fields.map(f => (req.body[f] !== '' && req.body[f] !== undefined) ? req.body[f] : null);
4!
51
  const placeholders = fields.map(() => '?').join(', ');
4✔
52
  const fieldList = fields.map(f => `"${f}"`).join(', ');
4✔
53

54
  try {
2✔
55
    db.prepare(`INSERT INTO "${tableName}" (${fieldList}) VALUES (${placeholders})`).run(...values);
2✔
56
    res.redirect(`/admin/table/${tableName}?success=Record+added`);
1✔
57
  } catch (err) {
58
    const totalRows = db.prepare(`SELECT COUNT(*) as count FROM "${tableName}"`).get().count;
1✔
59
    const totalPages = Math.max(1, Math.ceil(totalRows / PAGE_SIZE));
1✔
60
    const rows = db.prepare(`SELECT rowid, * FROM "${tableName}" LIMIT ?`).all(PAGE_SIZE);
1✔
61
    res.render('admin-dashboard', {
1✔
62
      user: { id: req.session.userId, name: req.session.userName },
63
      tables, activeTable: tableName, columns, rows, page: 1, totalPages,
64
      error: err.message, success: null,
65
    });
66
  }
67
};
68

69
const updateRecord = (req, res) => {
4✔
70
  const tables = getAllTables();
2✔
71
  const { tableName, rowId } = req.params;
2✔
72
  if (!tables.includes(tableName)) return res.status(404).send('Table not found');
2!
73

74
  const columns = getColumns(tableName);
2✔
75
  const updatable = columns.filter(c => c.pk === 0);
4✔
76
  if (updatable.length === 0)
2!
NEW
77
    return res.redirect(`/admin/table/${tableName}?error=This+table+has+no+editable+columns`);
×
78

79
  const setClauses = updatable.map(c => `"${c.name}" = ?`).join(', ');
2✔
80
  const values = [
2✔
81
    ...updatable.map(c => (req.body[c.name] !== '' && req.body[c.name] !== undefined) ? req.body[c.name] : null),
2✔
82
    rowId,
83
  ];
84

85
  try {
2✔
86
    db.prepare(`UPDATE "${tableName}" SET ${setClauses} WHERE rowid = ?`).run(...values);
2✔
87
    res.redirect(`/admin/table/${tableName}?success=Record+updated`);
1✔
88
  } catch (err) {
89
    res.redirect(`/admin/table/${tableName}?error=${encodeURIComponent(err.message)}`);
1✔
90
  }
91
};
92

93
const deleteRecord = (req, res) => {
4✔
94
  const tables = getAllTables();
2✔
95
  const { tableName, rowId } = req.params;
2✔
96
  if (!tables.includes(tableName)) return res.status(404).send('Table not found');
2!
97

98
  try {
2✔
99
    db.prepare(`DELETE FROM "${tableName}" WHERE rowid = ?`).run(rowId);
2✔
100
    res.redirect(`/admin/table/${tableName}?success=Record+deleted`);
1✔
101
  } catch (err) {
102
    res.redirect(`/admin/table/${tableName}?error=${encodeURIComponent(err.message)}`);
1✔
103
  }
104
};
105

106
module.exports = { showAdminDashboard, showTable, createRecord, updateRecord, deleteRecord };
4✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc