feat(tkuser): 알림 수신자 탭에 ntfy 구독 관리 추가
- notificationRecipientModel에 ntfy CRUD 메서드 추가 (같은 DB 직접 쿼리) - ntfy 라우트 3개 추가 (GET/POST/DELETE, /:type 위에 배치) - 알림 수신자 탭 상단에 ntfy 구독 관리 카드 렌더링 - ntfy 추가 모달에 앱 설정 안내 문구 포함 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -83,6 +83,52 @@ const notificationRecipientController = {
|
||||
}
|
||||
},
|
||||
|
||||
// === ntfy 구독 관리 ===
|
||||
|
||||
// ntfy 구독자 목록
|
||||
getNtfySubscribers: async (req, res) => {
|
||||
try {
|
||||
const subscribers = await notificationRecipientModel.getNtfySubscribers();
|
||||
res.json({ success: true, data: subscribers });
|
||||
} catch (error) {
|
||||
console.error('ntfy 구독자 조회 오류:', error);
|
||||
res.status(500).json({ success: false, error: 'ntfy 구독자 조회 실패' });
|
||||
}
|
||||
},
|
||||
|
||||
// ntfy 구독 등록 (관리자)
|
||||
addNtfySubscription: async (req, res) => {
|
||||
try {
|
||||
const { userId } = req.params;
|
||||
if (!userId) {
|
||||
return res.status(400).json({ success: false, error: '사용자 ID가 필요합니다.' });
|
||||
}
|
||||
if (!await checkNrPermission(req.user)) {
|
||||
return res.status(403).json({ success: false, error: '알림 수신자 관리 권한이 없습니다.' });
|
||||
}
|
||||
await notificationRecipientModel.addNtfySubscription(Number(userId));
|
||||
res.json({ success: true, message: 'ntfy 구독이 등록되었습니다.' });
|
||||
} catch (error) {
|
||||
console.error('ntfy 구독 등록 오류:', error);
|
||||
res.status(500).json({ success: false, error: 'ntfy 구독 등록 실패' });
|
||||
}
|
||||
},
|
||||
|
||||
// ntfy 구독 해제 (관리자)
|
||||
removeNtfySubscription: async (req, res) => {
|
||||
try {
|
||||
const { userId } = req.params;
|
||||
if (!await checkNrPermission(req.user)) {
|
||||
return res.status(403).json({ success: false, error: '알림 수신자 관리 권한이 없습니다.' });
|
||||
}
|
||||
await notificationRecipientModel.removeNtfySubscription(Number(userId));
|
||||
res.json({ success: true, message: 'ntfy 구독이 해제되었습니다.' });
|
||||
} catch (error) {
|
||||
console.error('ntfy 구독 해제 오류:', error);
|
||||
res.status(500).json({ success: false, error: 'ntfy 구독 해제 실패' });
|
||||
}
|
||||
},
|
||||
|
||||
// 유형별 수신자 일괄 설정
|
||||
setRecipients: async (req, res) => {
|
||||
try {
|
||||
|
||||
@@ -138,6 +138,29 @@ const notificationRecipientModel = {
|
||||
return !!row;
|
||||
},
|
||||
|
||||
// === ntfy 구독 관리 ===
|
||||
|
||||
async getNtfySubscribers() {
|
||||
const db = getPool();
|
||||
const [rows] = await db.query(`
|
||||
SELECT ns.user_id, ns.created_at, u.username, u.name as user_name
|
||||
FROM ntfy_subscriptions ns
|
||||
JOIN sso_users u ON u.user_id = ns.user_id
|
||||
ORDER BY u.name
|
||||
`);
|
||||
return rows;
|
||||
},
|
||||
|
||||
async addNtfySubscription(userId) {
|
||||
const db = getPool();
|
||||
await db.query('INSERT IGNORE INTO ntfy_subscriptions (user_id) VALUES (?)', [userId]);
|
||||
},
|
||||
|
||||
async removeNtfySubscription(userId) {
|
||||
const db = getPool();
|
||||
await db.query('DELETE FROM ntfy_subscriptions WHERE user_id = ?', [userId]);
|
||||
},
|
||||
|
||||
// 유형별 수신자 일괄 설정
|
||||
async setRecipients(notificationType, userIds, createdBy = null) {
|
||||
const db = getPool();
|
||||
|
||||
@@ -13,6 +13,11 @@ router.get('/types', controller.getTypes);
|
||||
// 전체 수신자 목록 (유형별 그룹화)
|
||||
router.get('/', controller.getAll);
|
||||
|
||||
// ntfy 구독 관리 (/:type보다 위에 배치해야 "ntfy"를 type으로 잡지 않음)
|
||||
router.get('/ntfy', controller.getNtfySubscribers);
|
||||
router.post('/ntfy/:userId', controller.addNtfySubscription);
|
||||
router.delete('/ntfy/:userId', controller.removeNtfySubscription);
|
||||
|
||||
// 유형별 수신자 조회
|
||||
router.get('/:type', controller.getByType);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user