dae7bd4cc6
implement GET /identity * GET /identity
212 lines
5.2 KiB
Go
212 lines
5.2 KiB
Go
package queryapi
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"net/http"
|
|
"strings"
|
|
|
|
"github.com/labstack/echo/v4"
|
|
"github.com/lestrrat-go/jwx/v2/jwt"
|
|
)
|
|
|
|
// Constants for route paths
|
|
const (
|
|
LOGIN_CALLBACK_PATH = "/login-callback"
|
|
)
|
|
|
|
// endpointsList keeps track of registered endpoints
|
|
// This list should be kept in sync with actual route registrations
|
|
var endpointsList = []string{
|
|
// Auth Service Endpoints
|
|
"/login",
|
|
LOGIN_CALLBACK_PATH,
|
|
"/logout",
|
|
"/home",
|
|
|
|
// Client Service Endpoints
|
|
"/client",
|
|
|
|
// Query API Endpoints
|
|
"/query",
|
|
|
|
// Document Service Endpoints
|
|
"/document",
|
|
|
|
// Export Service Endpoints
|
|
"/export",
|
|
|
|
// Identity Endpoint
|
|
"/identity",
|
|
|
|
// Swagger UI
|
|
"/swagger/index.html",
|
|
}
|
|
|
|
// homeHandler renders a simple HTML page with links to all endpoints
|
|
// and displays authentication status based on JWT token
|
|
func HomeHandler(c echo.Context) error {
|
|
var linksHTML string
|
|
baseURL := "http://localhost:8080"
|
|
|
|
// Create list items for each endpoint
|
|
for _, endpoint := range endpointsList {
|
|
// Skip endpoints with path parameters for direct linking
|
|
if strings.Contains(endpoint, ":") {
|
|
displayPath := strings.Replace(endpoint, ":id", "{id}", -1)
|
|
linksHTML += fmt.Sprintf("<li>%s (requires parameter)</li>\n", displayPath)
|
|
} else {
|
|
linksHTML += fmt.Sprintf("<li><a href=\"%s%s\">%s</a></li>\n", baseURL, endpoint, endpoint)
|
|
}
|
|
}
|
|
|
|
// Check if user is authenticated by looking for token in cookie
|
|
tokenCookie, err := c.Cookie("auth_token")
|
|
isAuthenticated := (err == nil && tokenCookie.Value != "")
|
|
|
|
// Variables for user info
|
|
var subject string
|
|
|
|
// If authenticated, try to decode the JWT token to get user info
|
|
if isAuthenticated {
|
|
// Use the same JWT parsing logic as the middleware to handle formatted tokens
|
|
tokenString := tokenCookie.Value
|
|
|
|
// Handle RFC-compliant unsecured JWTs that may have only 2 parts (header.payload.)
|
|
parts := strings.Split(tokenString, ".")
|
|
if len(parts) == 2 {
|
|
// Add empty signature part to make it parseable by the JWT library
|
|
tokenString = tokenString + "."
|
|
}
|
|
|
|
// Parse token without verification (just for display purposes)
|
|
token, err := jwt.Parse(
|
|
[]byte(tokenString),
|
|
jwt.WithVerify(false), // Skip signature verification
|
|
jwt.WithValidate(false), // Skip expiration and other validations
|
|
)
|
|
if err != nil {
|
|
subject = "JWT parsing failed: " + err.Error()
|
|
} else if token != nil {
|
|
claims, err := token.AsMap(context.Background())
|
|
if err != nil {
|
|
subject = "Claims extraction failed: " + err.Error()
|
|
} else {
|
|
if sub, ok := claims["sub"].(string); ok {
|
|
subject = sub
|
|
} else {
|
|
subject = "Subject claim not found or invalid type"
|
|
}
|
|
}
|
|
} else {
|
|
subject = "Token is nil"
|
|
}
|
|
}
|
|
|
|
// Create authentication status section
|
|
var authStatusHTML string
|
|
if isAuthenticated {
|
|
authStatusHTML = fmt.Sprintf(`
|
|
<div class="auth-status authenticated">
|
|
<h2>Authentication Status: Authenticated</h2>
|
|
<p><strong>Subject:</strong> %s</p>
|
|
<p><a href="/logout" class="logout-btn">Logout</a></p>
|
|
</div>
|
|
`, subject)
|
|
} else {
|
|
authStatusHTML = `
|
|
<div class="auth-status unauthenticated">
|
|
<h2>Authentication Status: Not Authenticated</h2>
|
|
<p>You are not currently logged in.</p>
|
|
<p><a href="/login" class="login-btn">Login</a></p>
|
|
</div>
|
|
`
|
|
}
|
|
|
|
// Create the complete HTML page
|
|
html := fmt.Sprintf(`
|
|
<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<title>Doczy Home</title>
|
|
<style>
|
|
body {
|
|
font-family: Arial, sans-serif;
|
|
line-height: 1.6;
|
|
margin: 20px;
|
|
max-width: 800px;
|
|
margin: 0 auto;
|
|
padding: 20px;
|
|
}
|
|
h1, h2 {
|
|
color: #333;
|
|
border-bottom: 1px solid #ddd;
|
|
padding-bottom: 10px;
|
|
}
|
|
ul {
|
|
margin-top: 20px;
|
|
}
|
|
li {
|
|
margin-bottom: 8px;
|
|
}
|
|
a {
|
|
color: #0066cc;
|
|
text-decoration: none;
|
|
}
|
|
a:hover {
|
|
text-decoration: underline;
|
|
}
|
|
.note {
|
|
background-color: #f8f9fa;
|
|
border-left: 4px solid #5bc0de;
|
|
padding: 10px 15px;
|
|
margin-top: 20px;
|
|
font-size: 0.9em;
|
|
}
|
|
.auth-status {
|
|
margin: 20px 0;
|
|
padding: 15px;
|
|
border-radius: 5px;
|
|
}
|
|
.authenticated {
|
|
background-color: #dff0d8;
|
|
border: 1px solid #d6e9c6;
|
|
}
|
|
.unauthenticated {
|
|
background-color: #f2dede;
|
|
border: 1px solid #ebccd1;
|
|
}
|
|
.login-btn, .logout-btn {
|
|
display: inline-block;
|
|
padding: 8px 16px;
|
|
background-color: #0066cc;
|
|
color: white;
|
|
border-radius: 4px;
|
|
text-decoration: none;
|
|
margin-top: 10px;
|
|
}
|
|
.logout-btn {
|
|
background-color: #d9534f;
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<h1>Doczy Home</h1>
|
|
|
|
%s
|
|
|
|
<h2>Available Endpoints</h2>
|
|
<ul>
|
|
%s
|
|
</ul>
|
|
|
|
<div class="note">
|
|
<p><strong>Note:</strong> This is a debugging page. Some endpoints require authentication or specific permissions.</p>
|
|
</div>
|
|
</body>
|
|
</html>
|
|
`, authStatusHTML, linksHTML)
|
|
|
|
return c.HTML(http.StatusOK, html)
|
|
}
|