From f783a983922220c72a1c80e3e60cbaacabbe1ab5 Mon Sep 17 00:00:00 2001 From: DanielS Date: Wed, 15 Jul 2026 00:58:13 +0200 Subject: [PATCH] docs: add lic server api spec and index in second brain --- .brain/index.md | 1 + .brain/licserver-api.md | 114 ++++++++++++++++++++++++++++++++++++++++ shop/scratch_test.js | 64 ++++++++++++++++++++++ 3 files changed, 179 insertions(+) create mode 100644 .brain/licserver-api.md create mode 100644 shop/scratch_test.js diff --git a/.brain/index.md b/.brain/index.md index 172a6ec..ba1c8d5 100644 --- a/.brain/index.md +++ b/.brain/index.md @@ -2,3 +2,4 @@ - [Supabase Schema](file:///c:/source/webshop/.brain/supabase-schema.md) - [ADR Log](file:///c:/source/webshop/.brain/adr-log.md) +- [LicServer API Spezifikation](file:///c:/source/webshop/.brain/licserver-api.md) diff --git a/.brain/licserver-api.md b/.brain/licserver-api.md new file mode 100644 index 0000000..f912d79 --- /dev/null +++ b/.brain/licserver-api.md @@ -0,0 +1,114 @@ +# LicServer API Spezifikation (v1) + +Dokumentation der REST-Schnittstellen des CASPOS Lizenzservers (`http://192.168.178.174:9981`). + +## 1. Endpunkte + +### Activation (Aktivierung) + +#### `POST /v1/activate` +Aktiviert eine neue Lizenz. + +**Request Body (`application/json`):** +```json +{ + "productId": "string", + "productVersion": "string", + "activationCode": "string", + "hardwareBindingType": "string", + "hardwareBindingId": "string" +} +``` + +**Response `200 OK` (`application/json`):** +```json +{ + "licenseData": { + "id": "string", + "serialNumber": "string", + "productId": "string", + "filename": "string", + "content": "string" // Base64 Byte-Inhalt + }, + "apiKey": "string", + "secret": "string" +} +``` + +**Response Headers:** +- `ETag` (string): Der ETag-Wert der Lizenz. + +--- + +#### `POST /v1/activate-existing` +Aktiviert eine bereits vorhandene Lizenz erneut. + +**Request Body (`application/json`):** +```json +{ + "productId": "string", + "productVersion": "string", + "serialNumber": "string", + "proofOfPossessionHash": "string", + "salt": "string", + "hardwareBindingType": "string", + "hardwareBindingId": "string" +} +``` + +**Response `200 OK` (`application/json`):** +*Gleiche Struktur wie bei `/v1/activate`.* + +--- + +### Licenses (Lizenzen) + +#### `GET /v1/licenses/{id}` +Holt die Lizenz-Details zu einer bestimmten Lizenz-ID. + +**Request Parameters:** +- `id` (path, string, required): Die UUID der Lizenz. +- `If-None-Match` (header, string, optional): ETag zur Cache-Validierung. + +**Response `200 OK` (`application/json`):** +```json +{ + "id": "string", + "serialNumber": "string", + "productId": "string", + "filename": "string", + "content": "string" // Base64 Byte-Inhalt +} +``` + +**Response `304 Not Modified`:** +Falls die Lizenz nicht verändert wurde. + +**Response `404 Not Found` / `403 Forbidden`:** +Standard Fehlerobjekt `ProblemDetails`. + +--- + +## 2. Typen & Schemas + +### `LicenseData` +```json +{ + "id": "string", + "serialNumber": "string", + "productId": "string", + "filename": "string", + "content": "string" // Base64 Byte-Inhalt +} +``` + +### `ProblemDetails` +```json +{ + "type": "string", + "title": "string", + "status": 0, + "detail": "string", + "instance": "string" +} +``` diff --git a/shop/scratch_test.js b/shop/scratch_test.js new file mode 100644 index 0000000..1afa90b --- /dev/null +++ b/shop/scratch_test.js @@ -0,0 +1,64 @@ +const { createClient } = require('@supabase/supabase-js'); +const fs = require('fs'); +const path = require('path'); + +// Read .env.local +const envPath = path.join(__dirname, '.env.local'); +const envContent = fs.readFileSync(envPath, 'utf8'); +const env = {}; +envContent.split('\n').forEach(line => { + const parts = line.split('='); + if (parts.length >= 2) { + env[parts[0].trim()] = parts.slice(1).join('=').trim(); + } +}); + +const supabaseUrl = env['NEXT_PUBLIC_SUPABASE_URL']; +const supabaseKey = env['SUPABASE_SERVICE_ROLE_KEY']; + +async function main() { + const supabase = createClient(supabaseUrl, supabaseKey); + const { data: licRow, error } = await supabase + .from('settings') + .select('licserver_base_url, licserver_api_key') + .eq('id', 'licserver') + .single(); + + if (error || !licRow) { + console.error("Failed to load licserver config:", error); + return; + } + + const base = 'http://192.168.178.174:9981'; // Target API port 9981 + const apiKey = licRow.licserver_api_key; + + console.log("Using API Base:", base); + console.log("API Key found:", apiKey ? "Yes (length " + apiKey.length + ")" : "No"); + + // Try some standard endpoints + const endpoints = [ + '/api-v1/licenses', + '/api-v1/partners', + '/api-v1/companies', + ]; + + for (const ep of endpoints) { + const url = base + ep; + console.log(`\nFetching: ${url}`); + try { + const res = await fetch(url, { + headers: { + 'X-Api-Key': apiKey || '', + 'Accept': 'application/json' + } + }); + console.log(`Status: ${res.status} ${res.statusText}`); + const text = await res.text(); + console.log(`Response (first 500 chars):`, text.substring(0, 500)); + } catch (e) { + console.error(`Error fetching ${url}:`, e.message); + } + } +} + +main();