mirror of
https://github.com/R0m1k3/Loki.git
synced 2026-10-20 13:38:11 +02:00
Rebaptise AJEAN en Loki (fork, lignée conservée)
- module github.com/R0m1k3/Loki, cmd/loki, internal/loki (package loki) - LOKI_HOME, LOKI_MODEL_DIRS, LOKI_SERVICE, LOKI_DL_CONNS ; /etc/loki ; units loki-engine / loki-ui ; binaire et aide CLI - updateRepo pointe sur R0m1k3/Loki (l'auto-update ne tirera plus les binaires AJEAN amont) Conservé à l'identique : le domaine ajean.link (service de tunnel amont), les littéraux de migration 0.7.x (migrate_07.go), RELEASE_NOTES.md et LICENSE (historique et licence de l'amont). go build/vet/test : verts.
This commit is contained in:
157 files changed
+928
-928
No files matched your search
@@ -0,0 +1,100 @@
|
||||
package loki
|
||||
|
||||
// web_link_api.go — API locale pilotant l'accès distant (ajean.link) depuis l'UI
|
||||
// web de Loki, pour éviter le terminal. Le panneau « Accès distant » ouvre une
|
||||
// popup app.ajean.link/connect.html qui gère compte + paiement puis renvoie une
|
||||
// clé de liaison (jl_…) ; l'UI la POSTe ici, et Loki fait le `loki link` tout
|
||||
// seul (écrit le token + (re)démarre le service).
|
||||
//
|
||||
// Ces routes ne sont accessibles qu'en LOCAL : à travers le tunnel du relais,
|
||||
// newLinkHandler refuse tout /api/* non chiffré (boîte noire). La configuration
|
||||
// de l'accès distant se fait donc depuis la machine elle-même, ce qui est correct.
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// remoteServerURL est l'URL du portail distant pointant droit sur cette machine.
|
||||
func remoteServerURL() string {
|
||||
return "https://app.ajean.link/server.html?m=" + machineID()
|
||||
}
|
||||
|
||||
// handleLinkStatus (GET /api/link/status) : état de l'accès distant pour l'UI.
|
||||
func handleLinkStatus(w http.ResponseWriter, r *http.Request) {
|
||||
tok := readLinkToken()
|
||||
sendJSON(w, http.StatusOK, map[string]any{
|
||||
"linked": tok != "",
|
||||
"active": uiServiceActive(),
|
||||
"machineURL": remoteServerURL(),
|
||||
"fingerprint": e2eFingerprint(),
|
||||
})
|
||||
}
|
||||
|
||||
// handleLinkConnect (POST /api/link/connect {token}) : enregistre la clé de
|
||||
// liaison remise par la popup connect.html et (re)démarre le service de lien.
|
||||
func handleLinkConnect(w http.ResponseWriter, r *http.Request) {
|
||||
var req struct{ Token string }
|
||||
_ = json.NewDecoder(r.Body).Decode(&req)
|
||||
tok := strings.TrimSpace(req.Token)
|
||||
if !strings.HasPrefix(tok, "jl_") {
|
||||
sendJSON(w, http.StatusBadRequest, map[string]any{"error": "clé de liaison invalide"})
|
||||
return
|
||||
}
|
||||
if err := saveLinkToken(tok); err != nil {
|
||||
sendJSON(w, http.StatusInternalServerError, map[string]any{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
// Redémarre le service d'interface pour qu'il relise la clé et ouvre le
|
||||
// tunnel. Sur une machine sans systemd (dev/Windows), la clé est quand même
|
||||
// enregistrée : on renvoie l'info en signalant que le service n'a pas démarré.
|
||||
svcErr := ""
|
||||
if err := uiServiceCtl("restart"); err != nil {
|
||||
svcErr = err.Error()
|
||||
}
|
||||
sendJSON(w, http.StatusOK, map[string]any{
|
||||
"ok": true,
|
||||
"linked": true,
|
||||
"active": uiServiceActive(),
|
||||
"machineURL": remoteServerURL(),
|
||||
"serviceErr": svcErr,
|
||||
})
|
||||
}
|
||||
|
||||
// handleLinkStart (POST /api/link/start) : (re)démarre le worker de lien sans
|
||||
// repasser par la popup de connexion — le token est déjà enregistré. Utile quand
|
||||
// le tunnel est tombé, ou sur un poste sans systemd où personne ne le relance.
|
||||
func handleLinkStart(w http.ResponseWriter, r *http.Request) {
|
||||
if readLinkToken() == "" {
|
||||
sendJSON(w, http.StatusBadRequest, map[string]any{"error": "aucune clé de liaison enregistrée"})
|
||||
return
|
||||
}
|
||||
if err := uiServiceCtl("restart"); err != nil {
|
||||
sendJSON(w, http.StatusInternalServerError, map[string]any{"error": err.Error(), "active": uiServiceActive()})
|
||||
return
|
||||
}
|
||||
sendJSON(w, http.StatusOK, map[string]any{"ok": true, "active": uiServiceActive()})
|
||||
}
|
||||
|
||||
// handleLinkDisconnect (POST /api/link/disconnect) : arrête le service et oublie
|
||||
// la clé (équivalent `loki link stop` + `loki link logout`).
|
||||
func handleLinkDisconnect(w http.ResponseWriter, r *http.Request) {
|
||||
_ = uiServiceCtl("stop")
|
||||
_ = removeLinkToken()
|
||||
sendJSON(w, http.StatusOK, map[string]any{"ok": true, "linked": false, "active": false})
|
||||
}
|
||||
|
||||
// handleLinkPairCode (POST /api/link/paircode) : génère un code d'appairage frais
|
||||
// (usage unique, TTL 10 min) + l'empreinte E2E, à saisir UNE fois dans le portail
|
||||
// distant lors de la première connexion (confirmation de la boîte noire). Évite le
|
||||
// détour par `loki link code` en terminal.
|
||||
func handleLinkPairCode(w http.ResponseWriter, r *http.Request) {
|
||||
code, err := newPairCode()
|
||||
if err != nil {
|
||||
sendJSON(w, http.StatusInternalServerError, map[string]any{"error": fmt.Sprintf("génération du code (droits ?): %v", err)})
|
||||
return
|
||||
}
|
||||
sendJSON(w, http.StatusOK, map[string]any{"code": code, "fingerprint": e2eFingerprint()})
|
||||
}
|
||||
Reference in new issue
Block a user