193 lines
6.3 KiB
TypeScript
193 lines
6.3 KiB
TypeScript
|
|
import { Challenge, Team, Solve, CTFState, BlogPost } from '../types';
|
|
|
|
const API_BASE = '/api';
|
|
|
|
class ApiService {
|
|
private getHeaders() {
|
|
const session = localStorage.getItem('hip6_session');
|
|
const headers: HeadersInit = { 'Content-Type': 'application/json' };
|
|
if (session) {
|
|
const { token } = JSON.parse(session);
|
|
if (token) headers['Authorization'] = `Bearer ${token}`;
|
|
}
|
|
return headers;
|
|
}
|
|
|
|
async getState(): Promise<CTFState> {
|
|
const res = await fetch(`${API_BASE}/state`);
|
|
if (!res.ok) throw new Error(`HTTP Error ${res.status}`);
|
|
return res.json();
|
|
}
|
|
|
|
async login(name: string, pass: string): Promise<{ team: Team, token: string }> {
|
|
const res = await fetch(`${API_BASE}/auth/login`, {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({ name, password: pass }),
|
|
});
|
|
if (!res.ok) {
|
|
const err = await res.json();
|
|
throw new Error(err.message || 'Invalid credentials');
|
|
}
|
|
return res.json();
|
|
}
|
|
|
|
async register(name: string, pass: string): Promise<{ team: Team, token: string }> {
|
|
const res = await fetch(`${API_BASE}/auth/register`, {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({ name, password: pass }),
|
|
});
|
|
if (!res.ok) {
|
|
const err = await res.json();
|
|
throw new Error(err.message || 'Registration failed');
|
|
}
|
|
return res.json();
|
|
}
|
|
|
|
async toggleCtf(): Promise<void> {
|
|
const res = await fetch(`${API_BASE}/admin/toggle-ctf`, {
|
|
method: 'POST',
|
|
headers: this.getHeaders(),
|
|
});
|
|
if (!res.ok) throw new Error('Failed to toggle CTF');
|
|
}
|
|
|
|
async resetScores(): Promise<void> {
|
|
const res = await fetch(`${API_BASE}/admin/reset-scores`, {
|
|
method: 'POST',
|
|
headers: this.getHeaders(),
|
|
});
|
|
if (!res.ok) throw new Error('Failed to reset scores');
|
|
}
|
|
|
|
async backupDatabase(): Promise<any> {
|
|
const res = await fetch(`${API_BASE}/admin/db/export`, {
|
|
method: 'GET',
|
|
headers: this.getHeaders(),
|
|
});
|
|
if (!res.ok) throw new Error('Backup failed');
|
|
return res.json();
|
|
}
|
|
|
|
async restoreDatabase(file: File): Promise<void> {
|
|
const formData = new FormData();
|
|
formData.append('restoreFile', file);
|
|
const session = localStorage.getItem('hip6_session');
|
|
const headers: HeadersInit = session ? { 'Authorization': `Bearer ${JSON.parse(session).token}` } : {};
|
|
const res = await fetch(`${API_BASE}/admin/db/restore`, { method: 'POST', headers, body: formData });
|
|
if (!res.ok) throw new Error('Restore failed');
|
|
}
|
|
|
|
async exportChallenges(): Promise<{ challenges: any[] }> {
|
|
const res = await fetch(`${API_BASE}/admin/challenges/export`, {
|
|
method: 'GET',
|
|
headers: this.getHeaders(),
|
|
});
|
|
if (!res.ok) throw new Error('Export failed');
|
|
return res.json();
|
|
}
|
|
|
|
async importChallenges(file: File): Promise<void> {
|
|
const formData = new FormData();
|
|
formData.append('importFile', file);
|
|
const session = localStorage.getItem('hip6_session');
|
|
const headers: HeadersInit = session ? { 'Authorization': `Bearer ${JSON.parse(session).token}` } : {};
|
|
const res = await fetch(`${API_BASE}/admin/challenges/import`, { method: 'POST', headers, body: formData });
|
|
if (!res.ok) throw new Error('Import failed');
|
|
}
|
|
|
|
async deleteAllChallenges(): Promise<void> {
|
|
const res = await fetch(`${API_BASE}/admin/challenges/all`, {
|
|
method: 'DELETE',
|
|
headers: this.getHeaders(),
|
|
});
|
|
if (!res.ok) throw new Error('Failed to delete all challenges');
|
|
}
|
|
|
|
async updateConfig(formData: FormData): Promise<void> {
|
|
const session = localStorage.getItem('hip6_session');
|
|
const headers: HeadersInit = session ? { 'Authorization': `Bearer ${JSON.parse(session).token}` } : {};
|
|
const res = await fetch(`${API_BASE}/admin/config`, { method: 'PUT', headers, body: formData });
|
|
if (!res.ok) throw new Error('Failed to update config');
|
|
}
|
|
|
|
async updateTeam(id: string, data: any): Promise<void> {
|
|
const res = await fetch(`${API_BASE}/admin/teams/${id}`, {
|
|
method: 'PUT',
|
|
headers: this.getHeaders(),
|
|
body: JSON.stringify(data),
|
|
});
|
|
if (!res.ok) throw new Error('Failed to update team');
|
|
}
|
|
|
|
async updateProfile(data: any): Promise<void> {
|
|
const res = await fetch(`${API_BASE}/profile`, {
|
|
method: 'PUT',
|
|
headers: this.getHeaders(),
|
|
body: JSON.stringify(data),
|
|
});
|
|
if (!res.ok) throw new Error('Failed to update profile');
|
|
}
|
|
|
|
async deleteTeam(id: string): Promise<void> {
|
|
const res = await fetch(`${API_BASE}/admin/teams/${id}`, {
|
|
method: 'DELETE',
|
|
headers: this.getHeaders(),
|
|
});
|
|
if (!res.ok) throw new Error('Failed to delete team');
|
|
}
|
|
|
|
async submitFlag(challengeId: string, flag: string): Promise<{ success: boolean }> {
|
|
const res = await fetch(`${API_BASE}/challenges/submit`, {
|
|
method: 'POST',
|
|
headers: this.getHeaders(),
|
|
body: JSON.stringify({ challengeId, flag }),
|
|
});
|
|
return res.json();
|
|
}
|
|
|
|
async upsertChallenge(formData: FormData, id?: string): Promise<any> {
|
|
const method = id ? 'PUT' : 'POST';
|
|
const url = id ? `${API_BASE}/admin/challenges/${id}` : `${API_BASE}/admin/challenges`;
|
|
const session = localStorage.getItem('hip6_session');
|
|
const headers: HeadersInit = session ? { 'Authorization': `Bearer ${JSON.parse(session).token}` } : {};
|
|
const res = await fetch(url, { method, headers, body: formData });
|
|
return res.json();
|
|
}
|
|
|
|
async deleteChallenge(id: string): Promise<void> {
|
|
const res = await fetch(`${API_BASE}/admin/challenges/${id}`, {
|
|
method: 'DELETE',
|
|
headers: this.getHeaders(),
|
|
});
|
|
if (!res.ok) throw new Error('Failed to delete challenge');
|
|
}
|
|
|
|
async createBlogPost(data: any): Promise<void> {
|
|
const res = await fetch(`${API_BASE}/admin/blogs`, {
|
|
method: 'POST',
|
|
headers: this.getHeaders(),
|
|
body: JSON.stringify(data),
|
|
});
|
|
}
|
|
|
|
async updateBlogPost(id: string, data: any): Promise<void> {
|
|
const res = await fetch(`${API_BASE}/admin/blogs/${id}`, {
|
|
method: 'PUT',
|
|
headers: this.getHeaders(),
|
|
body: JSON.stringify(data),
|
|
});
|
|
}
|
|
|
|
async deleteBlogPost(id: string): Promise<void> {
|
|
const res = await fetch(`${API_BASE}/admin/blogs/${id}`, {
|
|
method: 'DELETE',
|
|
headers: this.getHeaders(),
|
|
});
|
|
}
|
|
}
|
|
|
|
export const api = new ApiService();
|