| 78 | } |
| 79 | |
| 80 | export function createAdminSettingsRouter(): Router { |
| 81 | const router = Router(); |
| 82 | |
| 83 | // GET /api/admin/settings - Get all system settings |
| 84 | router.get('/', requireAuth, requireAdmin, async (_req: Request, res: Response) => { |
| 85 | try { |
| 86 | const settings = await getAllSettings(); |
| 87 | const billingChannel = await getBillingChannel(); |
| 88 | const escalationChannel = await getEscalationChannel(); |
| 89 | const adminChannel = await getAdminChannel(); |
| 90 | const prospectChannel = await getProspectChannel(); |
| 91 | const prospectTriageEnabled = await getProspectTriageEnabled(); |
| 92 | const errorChannel = await getErrorChannel(); |
| 93 | |
| 94 | const editorialChannel = await getEditorialChannel(); |
| 95 | const announcementChannel = await getAnnouncementChannel(); |
| 96 | |
| 97 | res.json({ |
| 98 | settings, |
| 99 | billing_channel: billingChannel, |
| 100 | escalation_channel: escalationChannel, |
| 101 | admin_channel: adminChannel, |
| 102 | prospect_channel: prospectChannel, |
| 103 | prospect_triage_enabled: prospectTriageEnabled, |
| 104 | error_channel: errorChannel, |
| 105 | editorial_channel: editorialChannel, |
| 106 | announcement_channel: announcementChannel, |
| 107 | }); |
| 108 | } catch (error) { |
| 109 | logger.error({ err: error }, 'Failed to get system settings'); |
| 110 | res.status(500).json({ |
| 111 | error: 'Failed to get system settings', |
| 112 | }); |
| 113 | } |
| 114 | }); |
| 115 | |
| 116 | // GET /api/admin/settings/slack-channels - List available Slack channels for picker |
| 117 | router.get('/slack-channels', requireAuth, requireAdmin, async (req: Request, res: Response) => { |
| 118 | try { |
| 119 | if (!isSlackConfigured()) { |
| 120 | res.status(400).json({ |
| 121 | error: 'Slack not configured', |
| 122 | message: 'ADDIE_BOT_TOKEN is not set', |
| 123 | }); |
| 124 | return; |
| 125 | } |
| 126 | |
| 127 | // `visibility=public` returns public channels for pickers that target |
| 128 | // broad-visibility destinations (e.g. the public announcement channel). |
| 129 | // Any other value, or no value, keeps the default: private channels |
| 130 | // only, because the other channel settings carry sensitive content. |
| 131 | const visibility = typeof req.query.visibility === 'string' ? req.query.visibility : null; |
| 132 | const types = visibility === 'public' ? 'public_channel' : 'private_channel'; |
| 133 | const channels = await getSlackChannels({ |
| 134 | types, |
| 135 | exclude_archived: true, |
| 136 | }); |
| 137 | |