441 lines
18 KiB
TypeScript
441 lines
18 KiB
TypeScript
import axios from 'axios'
|
|
import * as SecureStore from 'expo-secure-store'
|
|
import { API_BASE } from '../constants/Config'
|
|
|
|
const client = axios.create({
|
|
baseURL: API_BASE,
|
|
timeout: 15000,
|
|
// 자체서명 인증서 허용 (개발/테스트)
|
|
})
|
|
|
|
client.interceptors.request.use(async (cfg) => {
|
|
const token = await SecureStore.getItemAsync('grd_token')
|
|
if (token) cfg.headers.Authorization = `Bearer ${token}`
|
|
return cfg
|
|
})
|
|
|
|
client.interceptors.response.use(
|
|
(r) => r,
|
|
async (err) => {
|
|
if (err.response?.status === 401) {
|
|
await SecureStore.deleteItemAsync('grd_token')
|
|
await SecureStore.deleteItemAsync('grd_user')
|
|
}
|
|
return Promise.reject(err)
|
|
}
|
|
)
|
|
|
|
/* ── 인증 ── */
|
|
export const login = (username: string, password: string) =>
|
|
client.post('/api/auth/login', { username, password })
|
|
|
|
export const getMe = () =>
|
|
client.get('/api/auth/me')
|
|
|
|
/* ── 인증·보안 (#33 #34 #37 #38) ── */
|
|
/* 등록 디바이스 관리 */
|
|
export const getDevices = () =>
|
|
client.get('/api/auth/devices')
|
|
export const deleteDevice = (id: string | number) =>
|
|
client.delete(`/api/auth/devices/${id}`)
|
|
|
|
/* 보안 이벤트 로그 */
|
|
export const getSecurityEvents = () =>
|
|
client.get('/api/auth/events')
|
|
|
|
/* Zero Trust 네트워크 상태 */
|
|
export const getNetworkStatus = () =>
|
|
client.get('/api/auth/network-status')
|
|
|
|
/* 멀티기관 전환 */
|
|
export const getInstitutions = () =>
|
|
client.get('/api/institutions/')
|
|
export const switchTenant = (tenantId: string | number) =>
|
|
client.post('/api/auth/switch-tenant', { tenant_id: tenantId })
|
|
|
|
/* ── 대시보드 ── */
|
|
export const getDashboard = () =>
|
|
client.get('/api/dashboard')
|
|
|
|
/* ── SR ── */
|
|
export const getSRList = (page = 0, size = 20) =>
|
|
client.get(`/api/tasks?page=${page}&size=${size}`)
|
|
|
|
export const getSRDetail = (id: number) =>
|
|
client.get(`/api/tasks/${id}`)
|
|
|
|
export const createSR = (data: { title: string; description: string; priority: string; sr_type: string }) =>
|
|
client.post('/api/tasks', data)
|
|
|
|
export const updateSRStatus = (id: number, status: string) =>
|
|
client.patch(`/api/tasks/${id}/status`, { status })
|
|
|
|
/* SR 부분 수정 (스와이프 상태 전환 등) */
|
|
export const patchSR = (id: number, data: Record<string, unknown>) =>
|
|
client.patch(`/api/tasks/${id}`, data)
|
|
|
|
/* 빠른 SR 등록 (FormData 또는 JSON) */
|
|
export const createSRRaw = (data: Record<string, unknown>) =>
|
|
client.post('/api/tasks', data)
|
|
|
|
/* 일괄 상태 변경 */
|
|
export const batchUpdateSR = (ids: number[], status: string) =>
|
|
client.patch('/api/tasks/batch', { ids, status })
|
|
|
|
/* 에스컬레이션 */
|
|
export const escalateSR = (id: number, reason?: string) =>
|
|
client.post(`/api/tasks/${id}/escalate`, { reason: reason ?? '' })
|
|
|
|
/* 구독 / 팔로우 토글 */
|
|
export const subscribeSR = (id: number, subscribe: boolean) =>
|
|
client.post(`/api/tasks/${id}/subscribe`, { subscribe })
|
|
|
|
/* 만족도 평가 */
|
|
export const rateSR = (id: number, score: number, comment?: string) =>
|
|
client.post(`/api/tasks/${id}/rating`, { score, comment: comment ?? '' })
|
|
|
|
/* 코멘트 작성 (내부/외부) */
|
|
export const addSRComment = (id: number, content: string, isInternal: boolean) =>
|
|
client.post(`/api/tasks/${id}/comments`, { content, is_internal: isInternal })
|
|
|
|
export const getSRComments = (id: number) =>
|
|
client.get(`/api/tasks/${id}/comments`)
|
|
|
|
/* 인시던트 타임라인 */
|
|
export const getSRTimeline = (id: number) =>
|
|
client.get(`/api/tasks/${id}/timeline`)
|
|
|
|
/* 관련 SR */
|
|
export const getRelatedSR = (id: number) =>
|
|
client.get(`/api/tasks`, { params: { related_to: id } })
|
|
|
|
/* 중복 SR 감지 */
|
|
export const findSimilarSR = (title: string, limit = 3) =>
|
|
client.get(`/api/tasks`, { params: { title_similar: title, status: 'open', limit } })
|
|
|
|
/* SR 템플릿 */
|
|
export const getSRTemplates = () =>
|
|
client.get('/api/tasks/templates')
|
|
|
|
/* 미처리 SR 카운트 (뱃지용) */
|
|
export const getOpenSRCount = () =>
|
|
client.get('/api/tasks', { params: { status: 'open', assigned_to: 'me', size: 1 } })
|
|
|
|
/* ── AI 챗봇 ── */
|
|
export const sendAIMessage = (message: string) =>
|
|
client.post('/api/chatbot/message', { message })
|
|
|
|
/* ── 라이선스 ── */
|
|
export const getLicenseStatus = () =>
|
|
client.get('/api/license/status')
|
|
|
|
/* ── 알림 ── */
|
|
export const getNotifications = () =>
|
|
client.get('/api/notifications?size=30')
|
|
|
|
export const markNotificationRead = (id: number) =>
|
|
client.patch(`/api/notifications/${id}/read`)
|
|
|
|
/* ── DR 자동화 ── */
|
|
export const getDRDashboard = () => client.get('/api/dr/dashboard')
|
|
export const getDRRtoRpo = () => client.get('/api/dr/rto-rpo')
|
|
export const getDRScenarios = () => client.get('/api/dr/scenarios')
|
|
export const runDRTest = (scenarioId: number) =>
|
|
client.post('/api/dr/test', { scenario_id: scenarioId, test_type: 'RECOVERY' })
|
|
|
|
/* ── 네트워크 장비 ── */
|
|
export const getNetworkDevices = (instId?: number) =>
|
|
client.get('/api/network/devices', { params: instId ? { inst_id: instId } : {} })
|
|
export const getNetworkTopology = () => client.get('/api/network/topology')
|
|
export const backupNetworkDevice = (id: number) =>
|
|
client.post(`/api/network/devices/${id}/backup`)
|
|
export const getNetworkDiff = (id: number) =>
|
|
client.get(`/api/network/devices/${id}/diff`)
|
|
|
|
/* ── CSAP 점검 ── */
|
|
export const getCSAPDashboard = () => client.get('/api/compliance/csap/dashboard')
|
|
export const getCSAPItems = () => client.get('/api/compliance/csap/items')
|
|
export const getCSAPResults = () => client.get('/api/compliance/csap/results')
|
|
|
|
/* ── 모니터링·알림 (#39~#50) ── */
|
|
|
|
/* #39 서버 상태 대시보드 — 이름/상태/리소스 수치만 (IP·계정·PW 노출 금지) */
|
|
export const getServerStatus = () => client.get('/api/servers/status')
|
|
|
|
/* #42 서버 부하 히트맵 (status 재활용 가능, 별도 엔드포인트 우선 시도) */
|
|
export const getServerHeatmap = () => client.get('/api/servers/status')
|
|
|
|
/* #47 서버 메트릭 시계열 (range: 1h/6h/24h) */
|
|
export const getServerMetrics = (id: string | number, range = '1h') =>
|
|
client.get(`/api/servers/${id}/metrics`, { params: { range } })
|
|
|
|
/* #43 SLA 위반 예측 */
|
|
export const getSLAPrediction = () => client.get('/api/sla/prediction')
|
|
|
|
/* #44 서비스 상태 */
|
|
export const getServiceStatus = () => client.get('/api/service-status')
|
|
|
|
/* #45 알림 규칙 노코드 편집기 */
|
|
export const getAlertRules = () => client.get('/api/alert-rules/')
|
|
export const createAlertRule = (data: Record<string, unknown>) =>
|
|
client.post('/api/alert-rules/', data)
|
|
export const updateAlertRule = (id: string | number, data: Record<string, unknown>) =>
|
|
client.put(`/api/alert-rules/${id}`, data)
|
|
export const deleteAlertRule = (id: string | number) =>
|
|
client.delete(`/api/alert-rules/${id}`)
|
|
export const toggleAlertRule = (id: string | number) =>
|
|
client.patch(`/api/alert-rules/${id}/toggle`)
|
|
|
|
/* #46 온콜 스케줄 */
|
|
export const getOncallSchedule = () => client.get('/api/oncall/schedule')
|
|
|
|
/* #48 임계값 초과 이력 */
|
|
export const getThresholdHistory = (page = 0, size = 30) =>
|
|
client.get('/api/threshold-history', { params: { page, size } })
|
|
|
|
/* #49 커스텀 대시보드 위젯 */
|
|
export const getCustomDashboard = () => client.get('/api/custom-dashboard')
|
|
export const saveCustomDashboard = (widgets: unknown[]) =>
|
|
client.put('/api/custom-dashboard', { widgets })
|
|
|
|
/* #50 글로벌 통합 검색 */
|
|
export const globalSearch = (q: string, types = 'sr,server,kb,institution') =>
|
|
client.get('/api/search/', { params: { q, types } })
|
|
|
|
/* ──────────────────────────────────────────────
|
|
* 승인·워크플로우 (#63~#70)
|
|
* ────────────────────────────────────────────── */
|
|
|
|
/* #63 승인 요청 목록 (기본: 대기 상태) */
|
|
export const getApprovals = (status = 'pending') =>
|
|
client.get('/api/approvals/', { params: { status } })
|
|
|
|
/* #64 승인 / 반려 */
|
|
export const approveRequest = (id: string | number, comment = '') =>
|
|
client.post(`/api/approvals/${id}/approve`, { comment })
|
|
export const rejectRequest = (id: string | number, reason: string) =>
|
|
client.post(`/api/approvals/${id}/reject`, { reason })
|
|
|
|
/* #64 언두 — 3초 내 실행취소 */
|
|
export const cancelApproval = (id: string | number) =>
|
|
client.patch(`/api/approvals/${id}/cancel`)
|
|
|
|
/* #65 다단계 승인 진행 단계 */
|
|
export const getApprovalStages = (id: string | number) =>
|
|
client.get(`/api/approvals/${id}/stages`)
|
|
|
|
/* #67 대리결재 설정 */
|
|
export const getDelegation = () =>
|
|
client.get('/api/approvals/delegate')
|
|
export const setDelegation = (data: {
|
|
delegate_to: string | number
|
|
start_date: string
|
|
end_date: string
|
|
reason: string
|
|
}) => client.post('/api/approvals/delegate', data)
|
|
export const cancelDelegation = (id: string | number) =>
|
|
client.delete(`/api/approvals/delegate/${id}`)
|
|
|
|
/* #67 사용자 검색 (대리인 지정용) */
|
|
export const searchUsers = (q: string) =>
|
|
client.get('/api/auth/users', { params: { q } })
|
|
|
|
/* #68 변경 관리 캘린더 */
|
|
export const getChangeCalendar = (month: string) =>
|
|
client.get('/api/changes/calendar', { params: { month } })
|
|
|
|
/* #69 자동화 규칙 조회 (워크플로우 엔진) */
|
|
export const getAutomationRules = () =>
|
|
client.get('/api/automation-rules/')
|
|
|
|
/* #70 SLA 예외 승인 */
|
|
export const getSLAExceptionPending = () =>
|
|
client.get('/api/tasks', { params: { sla_exception_pending: true } })
|
|
export const requestSLAException = (
|
|
id: string | number,
|
|
data: { reason: string; new_deadline: string }
|
|
) => client.post(`/api/tasks/${id}/sla-exception`, data)
|
|
|
|
/* ──────────────────────────────────────────────
|
|
* 지식베이스·문서 (#71~#77)
|
|
* ────────────────────────────────────────────── */
|
|
export const getKBList = (q = '', category = '', page = 0, size = 20) =>
|
|
client.get('/api/kb/', { params: { q, category, page, size } })
|
|
export const getKBDetail = (id: string | number) =>
|
|
client.get(`/api/kb/${id}`)
|
|
export const getKBBookmarks = () =>
|
|
client.get('/api/kb/bookmarks')
|
|
export const toggleKBBookmark = (id: string | number) =>
|
|
client.post(`/api/kb/${id}/bookmark`)
|
|
|
|
export const ocrScanDocument = (formData: FormData) =>
|
|
client.post('/api/ocr/parse', formData, { headers: { 'Content-Type': 'multipart/form-data' } })
|
|
|
|
export const getMeetingMinutes = (page = 0) =>
|
|
client.get('/api/meetings/', { params: { page, size: 20 } })
|
|
export const getMeetingMinuteDetail = (id: string | number) =>
|
|
client.get(`/api/meetings/${id}`)
|
|
|
|
export const getReleaseNotes = () =>
|
|
client.get('/api/system/release-notes')
|
|
|
|
/* ──────────────────────────────────────────────
|
|
* 준수·거버넌스 (#78~#84)
|
|
* ────────────────────────────────────────────── */
|
|
export const getCSAPScore = () =>
|
|
client.get('/api/compliance/csap/dashboard')
|
|
export const getCSAPNonCompliant = () =>
|
|
client.get('/api/compliance/csap/items', { params: { status: 'fail' } })
|
|
export const createCSAPSR = (itemId: string | number) =>
|
|
client.post('/api/tasks', { title: `CSAP 미준수 즉시 조치: 항목 ${itemId}`, description: `CSAP 점검 항목 ${itemId} 미준수 즉시 조치`, priority: 'HIGH', sr_type: 'CHANGE', csap_item_id: itemId })
|
|
|
|
export const getAuditLogs = (page = 0, size = 30) =>
|
|
client.get('/api/audit/', { params: { page, size } })
|
|
|
|
export const getLicenseExpired = () =>
|
|
client.get('/api/license/status')
|
|
|
|
export const getPatchStatus = () =>
|
|
client.get('/api/patches/status')
|
|
export const getPIITypes = () =>
|
|
client.get('/api/patches/pii-types')
|
|
export const applyPatch = (cveId: string) =>
|
|
client.post(`/api/patches/${cveId}/apply`)
|
|
|
|
export const getAISOCEvents = (page = 0) =>
|
|
client.get('/api/ai-soc/events', { params: { page, size: 20 } })
|
|
|
|
/* ──────────────────────────────────────────────
|
|
* 통계·보고 (#93~#97)
|
|
* ────────────────────────────────────────────── */
|
|
export const getMyStats = () =>
|
|
client.get('/api/stats/my')
|
|
export const getInstitutionStats = () =>
|
|
client.get('/api/stats/institutions')
|
|
export const getDeployHistory = () =>
|
|
client.get('/api/stats/deploy-history')
|
|
export const getKPIDashboard = () =>
|
|
client.get('/api/stats/kpi')
|
|
export const getReportData = () =>
|
|
client.get('/api/stats/export-pdf')
|
|
|
|
/* ──────────────────────────────────────────────
|
|
* 협업·연동 (#98~#100)
|
|
* ────────────────────────────────────────────── */
|
|
export const getSRChat = (srId: number, page = 0) =>
|
|
client.get(`/api/sr-chat/${srId}/messages`, { params: { page, size: 50 } })
|
|
export const sendSRChat = (srId: number, content: string, msgType = 'text') =>
|
|
client.post(`/api/sr-chat/${srId}/messages`, { content, msg_type: msgType })
|
|
|
|
export const getAPKQRCode = () =>
|
|
client.get('/api/cicd/status')
|
|
export const getBuilds = () =>
|
|
client.get('/api/cicd/builds')
|
|
export const triggerBuild = (project: string) =>
|
|
client.post('/api/cicd/builds/trigger', { project })
|
|
|
|
/* ──────────────────────────────────────────────
|
|
* 2세대 확장 API (#101~#200)
|
|
* ────────────────────────────────────────────── */
|
|
|
|
/* AIOps / 예측 */
|
|
export const getFailurePredictions = () =>
|
|
client.get('/api/predictive/failure')
|
|
export const getCapacityPredictions = (days: 30 | 60 | 90) =>
|
|
client.get('/api/capacity/predictions', { params: { days } })
|
|
|
|
/* GreenOps */
|
|
export const getGreenopsEnergy = () => client.get('/api/greenops/energy')
|
|
export const getGreenopsCarbon = () => client.get('/api/greenops/carbon')
|
|
|
|
/* 비용 최적화 */
|
|
export const getCostRecommendations = () =>
|
|
client.get('/api/cost-optimizer/recommendations')
|
|
export const getSavingsDashboard = () =>
|
|
client.get('/api/mobile2/savings-dashboard')
|
|
|
|
/* 서비스 의존성 */
|
|
export const getServiceDependencyMap = () =>
|
|
client.get('/api/knowledge-graph/service-map')
|
|
|
|
/* 정책 위반 */
|
|
export const getPolicyViolations = () =>
|
|
client.get('/api/policy/violations')
|
|
|
|
/* 전자서명 */
|
|
export const getPendingDocs = () =>
|
|
client.get('/api/approvals/pending-docs')
|
|
export const signDocument = (id: string | number, pinHash: string) =>
|
|
client.post(`/api/approvals/${id}/sign`, { pin_hash: pinHash })
|
|
|
|
/* 하드웨어 보증 */
|
|
export const getHWWarranty = () => client.get('/api/cmdb/warranty')
|
|
|
|
/* NFC / 자산 */
|
|
export const getAssetById = (id: string | number) =>
|
|
client.get(`/api/cmdb/assets/${id}`)
|
|
export const nfcCheckin = (serverId: string | number) =>
|
|
client.post('/api/servers/field-checkin', { server_id: serverId, source: 'nfc', method: 'nfc_tag' })
|
|
|
|
/* CVE / 위협 */
|
|
export const getCVEList = () => client.get('/api/patches/cve')
|
|
export const getThreatFeed = () => client.get('/api/ai-soc/threats')
|
|
export const searchIOC = (q: string) =>
|
|
client.get('/api/ai-soc/ioc/search', { params: { q } })
|
|
export const getSecurityScore = () => client.get('/api/ai-soc/security-score')
|
|
|
|
/* AI 이력 / 브리핑 */
|
|
export const getChatbotHistory = (page = 0) =>
|
|
client.get('/api/mobile2/chatbot-history', { params: { page, size: 20 } })
|
|
export const getAIBriefing = () =>
|
|
client.get('/api/ai-insights/briefing')
|
|
export const getOllamaStatus = () =>
|
|
client.get('/api/ai-insights/ollama-status')
|
|
export const pullOllamaModel = (model: string) =>
|
|
client.post('/api/ai-insights/ollama-pull', { model })
|
|
|
|
/* 캘린더 / 유지보수 */
|
|
export const getWorkCalendar = (year: number, month: number) =>
|
|
client.get('/api/mobile2/work-calendar', { params: { year, month } })
|
|
export const getMaintenanceWindows = () =>
|
|
client.get('/api/cmdb/maintenance')
|
|
export const cancelMaintenanceWindow = (id: string | number) =>
|
|
client.delete(`/api/cmdb/maintenance/${id}`)
|
|
|
|
/* VM */
|
|
export const getVMs = () => client.get('/api/cloud/vms')
|
|
export const vmAction = (id: string | number, action: 'start' | 'stop' | 'reboot') =>
|
|
client.post(`/api/cloud/vms/${id}/${action}`)
|
|
|
|
/* SSL / EOL */
|
|
export const getSSLCerts = () => client.get('/api/cmdb/ssl-certs')
|
|
export const getEOLSoftware = () => client.get('/api/cmdb/eol-software')
|
|
|
|
/* 리더보드 / 히트맵 */
|
|
export const getTeamLeaderboard = () =>
|
|
client.get('/api/mobile2/team-leaderboard')
|
|
export const getSRHourlyPattern = () =>
|
|
client.get('/api/mobile2/hourly-pattern')
|
|
|
|
/* 나라장터 / 시민 */
|
|
export const getG2BContracts = () =>
|
|
client.get('/api/public-sector/g2b-contracts')
|
|
export const getCitizenRequests = () =>
|
|
client.get('/api/citizen/requests')
|
|
|
|
/* Ollama 브리핑 보조 */
|
|
export const getHourlyPattern = () =>
|
|
client.get('/api/mobile2/hourly-pattern')
|
|
export const getIncidentPatterns = () =>
|
|
client.get('/api/mobile2/incident-patterns')
|
|
export const getHandoverChecklist = () =>
|
|
client.get('/api/mobile2/handover-checklist')
|
|
export const getTeamPresence = () =>
|
|
client.get('/api/mobile2/team-presence')
|
|
export const getAppVersion = () =>
|
|
client.get('/api/mobile2/app-version')
|
|
export const getAnnouncements = () =>
|
|
client.get('/api/mobile2/announcements')
|
|
|
|
export default client
|