package auth import ( "database/sql" "net/http" "git.beisel.it/florian/hostname-service/db" "git.beisel.it/florian/hostname-service/models" "golang.org/x/crypto/bcrypt" "github.com/gin-gonic/gin" ) // LoginHandler godoc // @Summary User login // @Description Authenticate user and return JWT token // @Tags Authentication // @Accept json // @Produce json // @Param loginCredentials body models.LoginCredentials true "Login Credentials" // @Success 200 {object} map[string]string "Successfully authenticated, JWT token returned" // @Failure 400 {object} map[string]string "Invalid request body" // @Failure 401 {object} map[string]string "Invalid login credentials" // @Failure 500 {object} map[string]string "Internal server error" // @Router /login [post] func LoginHandler(c *gin.Context) { var creds models.LoginCredentials // Bind JSON to creds if err := c.BindJSON(&creds); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request body"}) return } // Fetch user from the database var storedCreds models.User err := db.DB.QueryRow("SELECT username, password FROM users WHERE username = ?", creds.Username).Scan(&storedCreds.Username, &storedCreds.Password) if err != nil { if err == sql.ErrNoRows { // User not found c.JSON(http.StatusUnauthorized, gin.H{"error": "Invalid login credentials"}) return } // Other errors c.JSON(http.StatusInternalServerError, gin.H{"error": "Internal server error"}) return } // Compare provided password with stored hashed password if err := bcrypt.CompareHashAndPassword([]byte(storedCreds.Password), []byte(creds.Password)); err != nil { // Password does not match c.JSON(http.StatusUnauthorized, gin.H{"error": "Invalid login credentials"}) return } // If password matches, generate a JWT token token, err := GenerateToken(storedCreds.Username) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to generate token"}) return } // Send the token in the response c.JSON(http.StatusOK, gin.H{"token": token}) }