Files
hipctf/services/api.ts
m0rph3us1987 1c756af238 initial commit
2026-01-07 13:27:11 +01:00

180 lines
5.4 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> {
try {
const res = await fetch(`${API_BASE}/state`);
if (!res.ok) throw new Error(`HTTP Error ${res.status}`);
return res.json();
} catch (err) {
console.error('API Error (getState):', err);
throw err;
}
}
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('Unauthorized or failed to toggle CTF');
}
async updateConfig(formData: FormData): Promise<void> {
const session = localStorage.getItem('hip6_session');
const headers: HeadersInit = {};
if (session) {
const { token } = JSON.parse(session);
headers['Authorization'] = `Bearer ${token}`;
}
const res = await fetch(`${API_BASE}/admin/config`, {
method: 'PUT',
headers,
body: formData,
});
if (!res.ok) throw new Error('Failed to update configuration');
}
async updateTeam(id: string, data: { name: string, isDisabled: boolean, isAdmin: boolean, password?: string }): Promise<void> {
const res = await fetch(`${API_BASE}/admin/teams/${id}`, {
method: 'PUT',
headers: this.getHeaders(),
body: JSON.stringify(data),
});
if (!res.ok) {
const err = await res.json();
throw new Error(err.message || 'Failed to update team');
}
}
async updateProfile(data: { password?: string }): Promise<void> {
const res = await fetch(`${API_BASE}/profile`, {
method: 'PUT',
headers: this.getHeaders(),
body: JSON.stringify(data),
});
if (!res.ok) {
const err = await res.json();
throw new Error(err.message || '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 }),
});
if (!res.ok) throw new Error('Submission failed');
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 = {};
if (session) {
const { token } = JSON.parse(session);
headers['Authorization'] = `Bearer ${token}`;
}
const res = await fetch(url, {
method,
headers,
body: formData,
});
if (!res.ok) {
const err = await res.json().catch(() => ({ message: 'Save failed' }));
throw new Error(err.message || 'Failed to save challenge');
}
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: { title: string, content: string }): Promise<void> {
const res = await fetch(`${API_BASE}/admin/blogs`, {
method: 'POST',
headers: this.getHeaders(),
body: JSON.stringify(data),
});
if (!res.ok) throw new Error('Failed to create blog post');
}
async updateBlogPost(id: string, data: { title: string, content: string }): Promise<void> {
const res = await fetch(`${API_BASE}/admin/blogs/${id}`, {
method: 'PUT',
headers: this.getHeaders(),
body: JSON.stringify(data),
});
if (!res.ok) throw new Error('Failed to update blog post');
}
async deleteBlogPost(id: string): Promise<void> {
const res = await fetch(`${API_BASE}/admin/blogs/${id}`, {
method: 'DELETE',
headers: this.getHeaders(),
});
if (!res.ok) throw new Error('Failed to delete blog post');
}
}
export const api = new ApiService();