fix: prevent nil-panic on server and improve OAuth callback handling
Load config eagerly during server startup so sortByUrgency never hits a nil config. Add nil-guard in BuildUrgencyCoefficients as belt-and-suspenders defense. Fix OAuth callback to support both GET and POST, and resolve issuer URLs properly with path.Dir. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -39,7 +39,22 @@ func GetLoginURL(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
// OAuthCallback handles the OAuth callback
|
||||
func OAuthCallback(w http.ResponseWriter, r *http.Request) {
|
||||
code := r.URL.Query().Get("code")
|
||||
var code string
|
||||
|
||||
// Support both GET (direct OAuth redirect) and POST (frontend exchange)
|
||||
if r.Method == http.MethodPost {
|
||||
var req struct {
|
||||
Code string `json:"code"`
|
||||
}
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
errorResponse(w, http.StatusBadRequest, "invalid request body")
|
||||
return
|
||||
}
|
||||
code = req.Code
|
||||
} else {
|
||||
code = r.URL.Query().Get("code")
|
||||
}
|
||||
|
||||
if code == "" {
|
||||
errorResponse(w, http.StatusBadRequest, "missing code parameter")
|
||||
return
|
||||
|
||||
@@ -41,6 +41,7 @@ func (s *Server) setupRoutes() {
|
||||
|
||||
// OAuth endpoints (no auth required)
|
||||
r.Get("/auth/login", handlers.GetLoginURL)
|
||||
r.Get("/auth/callback", handlers.OAuthCallback)
|
||||
r.Post("/auth/callback", handlers.OAuthCallback)
|
||||
r.Post("/auth/refresh", handlers.RefreshToken)
|
||||
r.Post("/auth/logout", handlers.Logout)
|
||||
|
||||
@@ -6,10 +6,23 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"path"
|
||||
|
||||
"golang.org/x/oauth2"
|
||||
)
|
||||
|
||||
// issuerBase resolves ".." to get the base OAuth path from the issuer URL.
|
||||
// e.g. "https://auth.example.com/application/o/app/" -> "https://auth.example.com/application/o/"
|
||||
func issuerBase(issuer string) string {
|
||||
u, err := url.Parse(issuer)
|
||||
if err != nil {
|
||||
return issuer
|
||||
}
|
||||
u.Path = path.Dir(path.Clean(u.Path)) + "/"
|
||||
return u.String()
|
||||
}
|
||||
|
||||
type OAuthClient struct {
|
||||
config *oauth2.Config
|
||||
cfg *Config
|
||||
@@ -22,8 +35,8 @@ func NewOAuthClient(cfg *Config) *OAuthClient {
|
||||
ClientSecret: cfg.OAuthClientSecret,
|
||||
RedirectURL: cfg.OAuthRedirectURI,
|
||||
Endpoint: oauth2.Endpoint{
|
||||
AuthURL: cfg.OAuthIssuer + "../authorize/",
|
||||
TokenURL: cfg.OAuthIssuer + "../token/",
|
||||
AuthURL: issuerBase(cfg.OAuthIssuer) + "authorize/",
|
||||
TokenURL: issuerBase(cfg.OAuthIssuer) + "token/",
|
||||
},
|
||||
Scopes: []string{"openid", "profile", "email"},
|
||||
},
|
||||
@@ -47,7 +60,7 @@ type UserInfo struct {
|
||||
}
|
||||
|
||||
func (c *OAuthClient) GetUserInfo(ctx context.Context, accessToken string) (*UserInfo, error) {
|
||||
req, err := http.NewRequestWithContext(ctx, "GET", c.cfg.OAuthIssuer+"../userinfo/", nil)
|
||||
req, err := http.NewRequestWithContext(ctx, "GET", issuerBase(c.cfg.OAuthIssuer)+"userinfo/", nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -170,8 +170,12 @@ func (t *Task) urgencyProject(coeff float64) float64 {
|
||||
return 0.0
|
||||
}
|
||||
|
||||
// BuildUrgencyCoefficients creates UrgencyCoefficients from config
|
||||
// BuildUrgencyCoefficients creates UrgencyCoefficients from config.
|
||||
// If cfg is nil, uses DefaultConfig() to prevent nil-pointer panics.
|
||||
func BuildUrgencyCoefficients(cfg *Config) *UrgencyCoefficients {
|
||||
if cfg == nil {
|
||||
cfg = DefaultConfig()
|
||||
}
|
||||
return &UrgencyCoefficients{
|
||||
Due: cfg.UrgencyDue,
|
||||
PriorityH: cfg.UrgencyPriorityH,
|
||||
|
||||
Reference in New Issue
Block a user