diff --git a/.github/workflows/ai-review.yml b/.github/workflows/ai-review.yml index e8d8f81..6260b80 100644 --- a/.github/workflows/ai-review.yml +++ b/.github/workflows/ai-review.yml @@ -1,10 +1,10 @@ -name: AI Code Review +name: Dr. Concret.io Review on: pull_request: types: [opened, synchronize, reopened] jobs: - review: + diagnose: runs-on: ubuntu-latest permissions: contents: read @@ -16,3 +16,4 @@ jobs: - uses: concretios/ai-pr-reviewer@v1 with: gemini_api_key: ${{ secrets.GEMINI_API_KEY }} + submit_review_verdict: true diff --git a/app.js b/app.js index d4376c3..25bcc74 100644 --- a/app.js +++ b/app.js @@ -1,5 +1,6 @@ const express = require('express'); const tasksRouter = require('./routes/tasks'); +const usersRouter = require('./routes/users'); const app = express(); const PORT = process.env.PORT || 3000; @@ -11,6 +12,7 @@ app.get('/health', (req, res) => { }); app.use('/tasks', tasksRouter); +app.use('/users', usersRouter); app.listen(PORT, () => { console.log(`Server running on port ${PORT}`); diff --git a/routes/users.js b/routes/users.js new file mode 100644 index 0000000..b31cea6 --- /dev/null +++ b/routes/users.js @@ -0,0 +1,53 @@ +const express = require('express'); +const router = express.Router(); + +// In-memory user store +let users = []; + +// GET /users +router.get('/', (req, res) => { + res.json(users); // BUG: exposes passwords in response +}); + +// POST /users - register a new user +router.post('/', (req, res) => { + const { username, password, role } = req.body; + + // BUG: no validation — username/password can be undefined or empty + // BUG: password stored in plaintext + const user = { + id: users.length + 1, // BUG: id collision if users are deleted + username, + password, + role: role || 'user', + createdAt: new Date() + }; + + users.push(user); + res.status(201).json(user); +}); + +// POST /users/login +router.post('/login', (req, res) => { + const { username, password } = req.body; + + // BUG: == instead of === for comparison + const user = users.find(u => u.username == username && u.password == password); + if (!user) { + return res.status(401).json({ error: 'Invalid credentials' }); + } + + // BUG: no real token — returns user object including password + res.json({ token: 'hardcoded-token-abc123', user }); +}); + +// DELETE /users/:id — admin only, but no auth check +router.delete('/:id', (req, res) => { + // BUG: no authentication or authorization check + const index = users.findIndex(u => u.id === parseInt(req.params.id)); + if (index === -1) return res.status(404).json({ error: 'User not found' }); + users.splice(index, 1); + res.status(204).send(); +}); + +module.exports = router;