From c0694cbc56f87030f3747db084b9297e1a9e245f Mon Sep 17 00:00:00 2001 From: cangui Date: Tue, 15 Jul 2025 17:25:58 +0200 Subject: [PATCH] add apiV2 for flutter --- internal/login/login.go | 60 ++++++++++++++++++++++++++++++++++++++++- internal/route/main.go | 39 +++++++++++++++------------ 2 files changed, 81 insertions(+), 18 deletions(-) diff --git a/internal/login/login.go b/internal/login/login.go index dd837be..2f9a827 100644 --- a/internal/login/login.go +++ b/internal/login/login.go @@ -66,4 +66,62 @@ func LoginHandler(db *gorm.DB) http.HandlerFunc { return - }} \ No newline at end of file + }} + + func LoginHandlerApi(db *gorm.DB) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "application/json") + + // 1. Lire les données JSON envoyées par Flutter + var input struct { + Email string `json:"email"` + Password string `json:"password"` + } + if err := json.NewDecoder(r.Body).Decode(&input); err != nil { + http.Error(w, `{"error":"Invalid JSON format"}`, http.StatusBadRequest) + return + } + + // 2. Rechercher l'utilisateur en base + var user models.User + if err := db.Where("email = ?", input.Email).First(&user).Error; err != nil { + w.WriteHeader(http.StatusUnauthorized) + json.NewEncoder(w).Encode(map[string]string{ + "error": "Invalid email or password", + }) + return + } + + // 3. Comparer le mot de passe + if err := bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(input.Password)); err != nil { + w.WriteHeader(http.StatusUnauthorized) + json.NewEncoder(w).Encode(map[string]string{ + "error": "Invalid email or password", + }) + return + } + + // 4. Créer un token JWT + tokenString, err := jwt.CreateToken(user.Username) // à adapter selon ta fonction + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + json.NewEncoder(w).Encode(map[string]string{ + "error": "Failed to generate token", + }) + return + } + + // 5. Répondre en JSON pour Flutter + w.WriteHeader(http.StatusOK) + json.NewEncoder(w).Encode(map[string]interface{}{ + "message": "Login successful", + "token": tokenString, + "user": map[string]interface{}{ + "id": user.ID, + "username": user.Username, + "email": user.Email, + // ajoute d'autres infos utiles ici si nécessaire + }, + }) + } +} diff --git a/internal/route/main.go b/internal/route/main.go index feda3ab..dd1f473 100644 --- a/internal/route/main.go +++ b/internal/route/main.go @@ -70,6 +70,8 @@ func RoutesPublic(r *mux.Router, bd *gorm.DB) { // Page de login r.HandleFunc("/login", renders.Login) r.HandleFunc("/api/login", login.LoginHandler(bd)).Methods("POST") + r.HandleFunc("/apiV2/login", login.LoginHandlerApi(bd)).Methods("POST") + r.HandleFunc("/api/scan/{id}", library.ScanFolder(bd)).Methods("GET") r.HandleFunc("/api/download/stream", renders.HandleJobsStream(bd)) @@ -232,28 +234,31 @@ func RoutesProtected(r *mux.Router, bd *gorm.DB) { r.HandleFunc("/hls/{partID:[0-9]+}/{file}", renders.HLSStream(bd)).Methods("GET") r.HandleFunc("/hls/{partID:[0-9]+}/", renders.HLSStream(bd)).Methods("GET") //API Scan folder - // —————— JSON API routes —————— - r.HandleFunc("/api/dashboard", renders.DashboardJSON(bd)).Methods("GET") - r.HandleFunc("/api/menu-library", renders.MenuLibraryJSON(bd)).Methods("GET") - r.HandleFunc("/api/settings", renders.SettingsJSON()).Methods("GET") - r.HandleFunc("/api/library", renders.LibraryJSON()).Methods("GET") - r.HandleFunc("/api/godownloader/download", renders.GoDownloadJSON()).Methods("GET") - r.HandleFunc("/api/godownloader/linkcollectors", renders.GoDownloadLinkCollectorsJSON()).Methods("GET") - r.HandleFunc("/api/godownloader/settings/delete", renders.GoDownloadSettingDeleteJSON(bd)).Methods("POST") - r.HandleFunc("/api/godownloader/settings/toggle", renders.GoDownloadSettingToggleActiveJSON(bd)).Methods("POST") - r.HandleFunc("/api/godownloader/settings", renders.GoDownloadSettingJSON(bd)).Methods("GET", "POST") - r.HandleFunc("/api/godownloader/settings/table", renders.GoDownloadPartialTableJSON(bd)).Methods("GET") - r.HandleFunc("/api/godownloader2", renders.GoDownload2JSON(bd)).Methods("GET") - r.HandleFunc("/api/add-job", renders.HandleAddJobJSON(bd)).Methods("POST") - r.HandleFunc("/api/jobs/list", renders.HandleListJobsPartialJSON(bd)).Methods("GET") - r.HandleFunc("/api/add-jobs-multiple", renders.HandleAddJobsMultipleJSON(bd)).Methods("POST") + // —————— JSON API routes apiV2 —————— + r.HandleFunc("/apiV2/dashboard", renders.DashboardJSON(bd)).Methods("GET") + r.HandleFunc("/apiV2/menu-library", renders.MenuLibraryJSON(bd)).Methods("GET") + r.HandleFunc("/apiV2/settings", renders.SettingsJSON()).Methods("GET") + r.HandleFunc("/apiV2/library", renders.LibraryJSON()).Methods("GET") - r.HandleFunc("/api/stream", renders.StreamHandlerJSON()).Methods("GET") + r.HandleFunc("/apiV2/godownloader/download", renders.GoDownloadJSON()).Methods("GET") + r.HandleFunc("/apiV2/godownloader/linkcollectors", renders.GoDownloadLinkCollectorsJSON()).Methods("GET") + r.HandleFunc("/apiV2/godownloader/settings/delete", renders.GoDownloadSettingDeleteJSON(bd)).Methods("POST") + r.HandleFunc("/apiV2/godownloader/settings/toggle", renders.GoDownloadSettingToggleActiveJSON(bd)).Methods("POST") + r.HandleFunc("/apiV2/godownloader/settings", renders.GoDownloadSettingJSON(bd)).Methods("GET", "POST") + r.HandleFunc("/apiV2/godownloader/settings/table", renders.GoDownloadPartialTableJSON(bd)).Methods("GET") - r.HandleFunc("/api/pathmedia/{id}", renders.PathMediaJSON(bd)).Methods("GET") + r.HandleFunc("/apiV2/godownloader2", renders.GoDownload2JSON(bd)).Methods("GET") + + r.HandleFunc("/apiV2/add-job", renders.HandleAddJobJSON(bd)).Methods("POST") + r.HandleFunc("/apiV2/jobs/list", renders.HandleListJobsPartialJSON(bd)).Methods("GET") + r.HandleFunc("/apiV2/add-jobs-multiple", renders.HandleAddJobsMultipleJSON(bd)).Methods("POST") + + r.HandleFunc("/apiV2/stream", renders.StreamHandlerJSON()).Methods("GET") + + r.HandleFunc("/apiV2/pathmedia/{id}", renders.PathMediaJSON(bd)).Methods("GET") //r.HandleFunc("/api/media/detail/{partID}", renders.MediaDetailJSON(bd)).Methods("GET") }