Compare commits

...

3 Commits

Author SHA1 Message Date
yusing
5e15fd4bbe fix(fileserver): correct middleware handler to avoid self recursion 2025-08-19 22:26:38 +08:00
yusing
a5022e31a2 fix(auth,oidc): added GET method /auth/callback endpoint to fix OIDC 404 and update documentation accordingly 2025-08-19 22:26:30 +08:00
yusing
a057f0e956 fix(homepage): incorrect url
- fixed url being overridden
- fixed sub-subdomain being stripped
- fixed empty url for routes with FQDN aliases
2025-08-19 21:01:04 +08:00
8 changed files with 239 additions and 11 deletions

View File

@@ -52,6 +52,7 @@ func NewHandler() *gin.Engine {
{
v1Auth.HEAD("/check", authApi.Check)
v1Auth.POST("/login", authApi.Login)
v1Auth.GET("/callback", authApi.Callback)
v1Auth.POST("/callback", authApi.Callback)
v1Auth.POST("/logout", authApi.Logout)
}

View File

@@ -8,7 +8,7 @@ import (
// @x-id "callback"
// @Base /api/v1
// @Summary Post Auth Callback
// @Summary Auth Callback
// @Description Handles the callback from the provider after successful authentication
// @Tags auth
// @Produce plain
@@ -18,6 +18,7 @@ import (
// @Failure 400 {string} string "OIDC: invalid request (missing state cookie or oauth state)"
// @Failure 400 {string} string "Userpass: invalid request / credentials"
// @Failure 500 {string} string "Internal server error"
// @Router /auth/callback [get]
// @Router /auth/callback [post]
func Callback(c *gin.Context) {
auth.GetDefaultAuth().PostAuthCallbackHandler(c.Writer, c.Request)

View File

@@ -176,6 +176,54 @@ const docTemplate = `{
}
},
"/auth/callback": {
"get": {
"description": "Handles the callback from the provider after successful authentication",
"produces": [
"text/plain"
],
"tags": [
"auth"
],
"summary": "Auth Callback",
"parameters": [
{
"description": "Userpass only",
"name": "body",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/auth.UserPassAuthCallbackRequest"
}
}
],
"responses": {
"200": {
"description": "Userpass: OK",
"schema": {
"type": "string"
}
},
"302": {
"description": "OIDC: Redirects to home page",
"schema": {
"type": "string"
}
},
"400": {
"description": "Userpass: invalid request / credentials",
"schema": {
"type": "string"
}
},
"500": {
"description": "Internal server error",
"schema": {
"type": "string"
}
}
},
"x-id": "callback"
},
"post": {
"description": "Handles the callback from the provider after successful authentication",
"produces": [
@@ -184,7 +232,7 @@ const docTemplate = `{
"tags": [
"auth"
],
"summary": "Post Auth Callback",
"summary": "Auth Callback",
"parameters": [
{
"description": "Userpass only",
@@ -1675,6 +1723,9 @@ const docTemplate = `{
"addr": {
"type": "string"
},
"is_nerdctl": {
"type": "boolean"
},
"name": {
"type": "string"
},
@@ -2337,6 +2388,18 @@ const docTemplate = `{
"type"
],
"properties": {
"container_runtime": {
"enum": [
"docker",
"podman",
"nerdctl"
],
"allOf": [
{
"$ref": "#/definitions/agent.ContainerRuntime"
}
]
},
"host": {
"type": "string"
},
@@ -2862,6 +2925,9 @@ const docTemplate = `{
"client": {
"$ref": "#/definitions/PEMPairResponse"
},
"container_runtime": {
"$ref": "#/definitions/agent.ContainerRuntime"
},
"host": {
"type": "string"
}
@@ -2942,6 +3008,19 @@ const docTemplate = `{
}
}
},
"agent.ContainerRuntime": {
"type": "string",
"enum": [
"docker",
"podman",
"nerdctl"
],
"x-enum-varnames": [
"ContainerRuntimeDocker",
"ContainerRuntimePodman",
"ContainerRuntimeNerdctl"
]
},
"auth.UserPassAuthCallbackRequest": {
"type": "object",
"properties": {

View File

@@ -172,6 +172,55 @@
}
},
"/auth/callback": {
"get": {
"description": "Handles the callback from the provider after successful authentication",
"produces": [
"text/plain"
],
"tags": [
"auth"
],
"summary": "Auth Callback",
"parameters": [
{
"description": "Userpass only",
"name": "body",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/auth.UserPassAuthCallbackRequest"
}
}
],
"responses": {
"200": {
"description": "Userpass: OK",
"schema": {
"type": "string"
}
},
"302": {
"description": "OIDC: Redirects to home page",
"schema": {
"type": "string"
}
},
"400": {
"description": "Userpass: invalid request / credentials",
"schema": {
"type": "string"
}
},
"500": {
"description": "Internal server error",
"schema": {
"type": "string"
}
}
},
"x-id": "callback",
"operationId": "callback"
},
"post": {
"description": "Handles the callback from the provider after successful authentication",
"produces": [
@@ -180,7 +229,7 @@
"tags": [
"auth"
],
"summary": "Post Auth Callback",
"summary": "Auth Callback",
"parameters": [
{
"description": "Userpass only",
@@ -1704,6 +1753,11 @@
"x-nullable": false,
"x-omitempty": false
},
"is_nerdctl": {
"type": "boolean",
"x-nullable": false,
"x-omitempty": false
},
"name": {
"type": "string",
"x-nullable": false,
@@ -2644,6 +2698,20 @@
"type"
],
"properties": {
"container_runtime": {
"enum": [
"docker",
"podman",
"nerdctl"
],
"allOf": [
{
"$ref": "#/definitions/agent.ContainerRuntime"
}
],
"x-nullable": false,
"x-omitempty": false
},
"host": {
"type": "string",
"x-nullable": false,
@@ -3387,6 +3455,11 @@
"x-nullable": false,
"x-omitempty": false
},
"container_runtime": {
"$ref": "#/definitions/agent.ContainerRuntime",
"x-nullable": false,
"x-omitempty": false
},
"host": {
"type": "string",
"x-nullable": false,
@@ -3499,6 +3572,21 @@
"x-nullable": false,
"x-omitempty": false
},
"agent.ContainerRuntime": {
"type": "string",
"enum": [
"docker",
"podman",
"nerdctl"
],
"x-enum-varnames": [
"ContainerRuntimeDocker",
"ContainerRuntimePodman",
"ContainerRuntimeNerdctl"
],
"x-nullable": false,
"x-omitempty": false
},
"auth.UserPassAuthCallbackRequest": {
"type": "object",
"properties": {

View File

@@ -4,6 +4,8 @@ definitions:
properties:
addr:
type: string
is_nerdctl:
type: boolean
name:
type: string
version:
@@ -452,6 +454,13 @@ definitions:
- MetricsPeriod1mo
NewAgentRequest:
properties:
container_runtime:
allOf:
- $ref: '#/definitions/agent.ContainerRuntime'
enum:
- docker
- podman
- nerdctl
host:
type: string
name:
@@ -810,6 +819,8 @@ definitions:
$ref: '#/definitions/PEMPairResponse'
client:
$ref: '#/definitions/PEMPairResponse'
container_runtime:
$ref: '#/definitions/agent.ContainerRuntime'
host:
type: string
type: object
@@ -861,6 +872,16 @@ definitions:
status_codes:
$ref: '#/definitions/LogFilter-StatusCodeRange'
type: object
agent.ContainerRuntime:
enum:
- docker
- podman
- nerdctl
type: string
x-enum-varnames:
- ContainerRuntimeDocker
- ContainerRuntimePodman
- ContainerRuntimeNerdctl
auth.UserPassAuthCallbackRequest:
properties:
password:
@@ -1368,6 +1389,38 @@ paths:
- agent
x-id: verify
/auth/callback:
get:
description: Handles the callback from the provider after successful authentication
parameters:
- description: Userpass only
in: body
name: body
required: true
schema:
$ref: '#/definitions/auth.UserPassAuthCallbackRequest'
produces:
- text/plain
responses:
"200":
description: 'Userpass: OK'
schema:
type: string
"302":
description: 'OIDC: Redirects to home page'
schema:
type: string
"400":
description: 'Userpass: invalid request / credentials'
schema:
type: string
"500":
description: Internal server error
schema:
type: string
summary: Auth Callback
tags:
- auth
x-id: callback
post:
description: Handles the callback from the provider after successful authentication
parameters:
@@ -1396,7 +1449,7 @@ paths:
description: Internal server error
schema:
type: string
summary: Post Auth Callback
summary: Auth Callback
tags:
- auth
x-id: callback

View File

@@ -45,6 +45,7 @@ func (c *OverrideConfig) GetOverride(alias string, item *ItemConfig) *ItemConfig
c.mu.RLock()
defer c.mu.RUnlock()
if itemOverride, hasOverride := c.ItemOverrides[alias]; hasOverride {
itemOverride.URL = item.URL // NOTE: we don't want to override the URL
item = itemOverride
}
if show, ok := c.ItemVisibility[alias]; ok {

View File

@@ -71,8 +71,9 @@ func (s *FileServer) Start(parent task.Parent) gperr.Error {
}
if s.middleware != nil {
next := s.handler
s.handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
s.middleware.ServeHTTP(s.handler.ServeHTTP, w, r)
s.middleware.ServeHTTP(next.ServeHTTP, w, r)
})
}

View File

@@ -104,11 +104,15 @@ func HomepageItems(proto, hostname, categoryFilter, providerFilter string) homep
hp := make(homepage.Homepage)
if strings.Count(hostname, ".") > 1 {
_, hostname, _ = strings.Cut(hostname, ".") // remove the subdomain
}
for _, r := range HTTP.Iter {
if providerFilter != "" && r.ProviderName() != providerFilter {
continue
}
item := r.HomepageItem()
item := *r.HomepageItem()
if categoryFilter != "" && item.Category != categoryFilter {
continue
}
@@ -121,11 +125,11 @@ func HomepageItems(proto, hostname, categoryFilter, providerFilter string) homep
// append hostname if provided and only if alias is not FQDN
if hostname != "" && item.URL == "" {
if !strings.Contains(item.Alias, ".") {
if strings.Count(hostname, ".") > 1 {
_, hostname, _ = strings.Cut(hostname, ".") // remove the subdomain
}
isFQDNAlias := strings.Contains(item.Alias, ".")
if !isFQDNAlias {
item.URL = fmt.Sprintf("%s://%s.%s", proto, item.Alias, hostname)
} else {
item.URL = fmt.Sprintf("%s://%s", proto, item.Alias)
}
}
@@ -134,7 +138,7 @@ func HomepageItems(proto, hostname, categoryFilter, providerFilter string) homep
item.URL = fmt.Sprintf("%s://%s", proto, item.URL)
}
hp.Add(item)
hp.Add(&item)
}
return hp
}