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

cameri / nostream / 29747125451

20 Jul 2026 01:38PM UTC coverage: 69.209% (+0.8%) from 68.364%
29747125451

Pull #690

github

web-flow
Merge 0447dcd43 into 0bfa0b59b
Pull Request #690: feat(admin): add authenticated settings API endpoints

2228 of 3584 branches covered (62.17%)

Branch coverage included in aggregate %.

91 of 94 new or added lines in 11 files covered. (96.81%)

2 existing lines in 1 file now uncovered.

5104 of 7010 relevant lines covered (72.81%)

25.15 hits per line

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

91.67
/src/controllers/admin/patch-settings-controller.ts
1
import { Request, Response } from 'express'
2

3
import { Settings } from '../../@types/settings'
4
import { IController } from '../../@types/controllers'
5
import { adminSettingsPatchBodySchema } from '../../schemas/admin-settings-schema'
2✔
6
import {
2✔
7
  getByPath,
8
  loadMergedSettings,
9
  loadUserSettings,
10
  saveSettings,
11
  setByPath,
12
  validatePathAgainstDefaults,
13
  validateSettings,
14
} from '../../utils/settings-config'
15
import {
2✔
16
  isWriteProtectedSettingsPath,
17
  redactSettingsValue,
18
} from '../../utils/settings-redaction'
19
import { validateSchema } from '../../utils/validation'
2✔
20

21
export class PatchAdminSettingsController implements IController {
2✔
22
  public async handleRequest(request: Request, response: Response): Promise<void> {
23
    const validation = validateSchema(adminSettingsPatchBodySchema)(request.body)
4✔
24
    if (validation.error) {
4✔
25
      response.status(400).setHeader('content-type', 'application/json').send({ error: 'Invalid request' })
1✔
26
      return
1✔
27
    }
28

29
    const { path, value } = validation.value
3✔
30

31
    if (isWriteProtectedSettingsPath(path)) {
3✔
32
      response
1✔
33
        .status(400)
34
        .setHeader('content-type', 'application/json')
35
        .send({
36
          error: 'Validation failed',
37
          issues: [{ path, message: 'Path is write-protected' }],
38
        })
39
      return
1✔
40
    }
41

42
    const pathIssues = validatePathAgainstDefaults(path)
2✔
43
    if (pathIssues.length > 0) {
2✔
44
      response
1✔
45
        .status(400)
46
        .setHeader('content-type', 'application/json')
47
        .send({ error: 'Validation failed', issues: pathIssues })
48
      return
1✔
49
    }
50

51
    const userSettings = loadUserSettings() as unknown as Record<string, unknown>
1✔
52
    const nextUserSettings = setByPath(userSettings, path, value)
1✔
53

54
    const merged = loadMergedSettings() as unknown as Record<string, unknown>
1✔
55
    const mergedNext = setByPath(merged, path, getByPath(nextUserSettings, path))
1✔
56
    const validationIssues = validateSettings(mergedNext as unknown as Settings)
1✔
57

58
    if (validationIssues.length > 0) {
1!
NEW
59
      response
×
60
        .status(400)
61
        .setHeader('content-type', 'application/json')
62
        .send({ error: 'Validation failed', issues: validationIssues })
NEW
63
      return
×
64
    }
65

66
    saveSettings(nextUserSettings as unknown as Settings)
1✔
67

68
    const updatedValue = redactSettingsValue(path, getByPath(nextUserSettings, path))
1✔
69

70
    response.status(200).setHeader('content-type', 'application/json').send({
1✔
71
      ok: true,
72
      path,
73
      value: updatedValue,
74
    })
75
  }
76
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc