mirror of
https://github.com/Ernous/TorrServerJellyfin.git
synced 2025-12-19 13:36:09 +05:00
Refactor auth code
This commit is contained in:
@@ -241,12 +241,6 @@ const docTemplate = `{
|
||||
"name": "id",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "boolean",
|
||||
"description": "Not authenticated",
|
||||
"name": "not_auth",
|
||||
"in": "query"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
@@ -458,7 +452,7 @@ const docTemplate = `{
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Get m3u from last play",
|
||||
"description": "Get M3U from last played file",
|
||||
"name": "fromlast",
|
||||
"in": "query"
|
||||
},
|
||||
@@ -475,17 +469,10 @@ const docTemplate = `{
|
||||
"in": "query",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "File index in torrent",
|
||||
"name": "poster",
|
||||
"in": "query",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Set poster link of torrent",
|
||||
"name": "not_auth",
|
||||
"name": "poster",
|
||||
"in": "query",
|
||||
"required": true
|
||||
}
|
||||
|
||||
@@ -234,12 +234,6 @@
|
||||
"name": "id",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "boolean",
|
||||
"description": "Not authenticated",
|
||||
"name": "not_auth",
|
||||
"in": "query"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
@@ -451,7 +445,7 @@
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Get m3u from last play",
|
||||
"description": "Get M3U from last played file",
|
||||
"name": "fromlast",
|
||||
"in": "query"
|
||||
},
|
||||
@@ -468,17 +462,10 @@
|
||||
"in": "query",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "File index in torrent",
|
||||
"name": "poster",
|
||||
"in": "query",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Set poster link of torrent",
|
||||
"name": "not_auth",
|
||||
"name": "poster",
|
||||
"in": "query",
|
||||
"required": true
|
||||
}
|
||||
|
||||
@@ -452,10 +452,6 @@ paths:
|
||||
name: id
|
||||
required: true
|
||||
type: string
|
||||
- description: Not authenticated
|
||||
in: query
|
||||
name: not_auth
|
||||
type: boolean
|
||||
produces:
|
||||
- application/octet-stream
|
||||
responses:
|
||||
@@ -592,7 +588,7 @@ paths:
|
||||
in: query
|
||||
name: m3u
|
||||
type: string
|
||||
- description: Get m3u from last play
|
||||
- description: Get M3U from last played file
|
||||
in: query
|
||||
name: fromlast
|
||||
type: string
|
||||
@@ -605,14 +601,9 @@ paths:
|
||||
name: title
|
||||
required: true
|
||||
type: string
|
||||
- description: File index in torrent
|
||||
in: query
|
||||
name: poster
|
||||
required: true
|
||||
type: string
|
||||
- description: Set poster link of torrent
|
||||
in: query
|
||||
name: not_auth
|
||||
name: poster
|
||||
required: true
|
||||
type: string
|
||||
produces:
|
||||
|
||||
@@ -21,7 +21,6 @@ import (
|
||||
//
|
||||
// @Param hash path string true "Torrent hash"
|
||||
// @Param id path string true "File index in torrent"
|
||||
// @Param not_auth query bool false "Not authenticated"
|
||||
//
|
||||
// @Produce application/octet-stream
|
||||
// @Success 200 "Torrent data"
|
||||
@@ -29,7 +28,7 @@ import (
|
||||
func play(c *gin.Context) {
|
||||
hash := c.Param("hash")
|
||||
indexStr := c.Param("id")
|
||||
notAuth := c.GetBool("not_auth")
|
||||
notAuth := c.GetBool("auth_required") && c.GetString(gin.AuthUserKey) == ""
|
||||
|
||||
if hash == "" || indexStr == "" {
|
||||
c.AbortWithError(http.StatusNotFound, errors.New("link should not be empty"))
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"server/web/auth"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
@@ -8,15 +10,17 @@ type requestI struct {
|
||||
Action string `json:"action,omitempty"`
|
||||
}
|
||||
|
||||
func SetupRoute(route *gin.RouterGroup) {
|
||||
route.GET("/shutdown", shutdown)
|
||||
func SetupRoute(route gin.IRouter) {
|
||||
authorized := route.Group("/", auth.CheckAuth())
|
||||
|
||||
route.POST("/settings", settings)
|
||||
authorized.GET("/shutdown", shutdown)
|
||||
|
||||
route.POST("/torrents", torrents)
|
||||
route.POST("/torrent/upload", torrentUpload)
|
||||
authorized.POST("/settings", settings)
|
||||
|
||||
route.POST("/cache", cache)
|
||||
authorized.POST("/torrents", torrents)
|
||||
authorized.POST("/torrent/upload", torrentUpload)
|
||||
|
||||
authorized.POST("/cache", cache)
|
||||
|
||||
route.HEAD("/stream", stream)
|
||||
route.HEAD("/stream/*fname", stream)
|
||||
@@ -27,15 +31,15 @@ func SetupRoute(route *gin.RouterGroup) {
|
||||
route.HEAD("/play/:hash/:id", play)
|
||||
route.GET("/play/:hash/:id", play)
|
||||
|
||||
route.POST("/viewed", viewed)
|
||||
authorized.POST("/viewed", viewed)
|
||||
|
||||
route.GET("/playlistall/all.m3u", allPlayList)
|
||||
authorized.GET("/playlistall/all.m3u", allPlayList)
|
||||
route.GET("/playlist", playList)
|
||||
route.GET("/playlist/*fname", playList) // Is this endpoint still needed ? `fname` is never used in handler
|
||||
|
||||
route.GET("/download/:size", download)
|
||||
authorized.GET("/download/:size", download)
|
||||
|
||||
route.GET("/search/*query", rutorSearch)
|
||||
authorized.GET("/search/*query", rutorSearch)
|
||||
|
||||
route.GET("/ffp/:hash/:id", ffp)
|
||||
authorized.GET("/ffp/:hash/:id", ffp)
|
||||
}
|
||||
|
||||
@@ -45,7 +45,6 @@ import (
|
||||
// @Param play query string false "Start stream torrent"
|
||||
// @Param title query string true "Set title of torrent"
|
||||
// @Param poster query string true "Set poster link of torrent"
|
||||
// @Param not_auth query string true "Stream / playlist without authentication"
|
||||
//
|
||||
// @Produce application/octet-stream
|
||||
// @Success 200 "Data returned according to query"
|
||||
@@ -62,7 +61,7 @@ func stream(c *gin.Context) {
|
||||
title := c.Query("title")
|
||||
poster := c.Query("poster")
|
||||
data := ""
|
||||
notAuth := c.GetBool("not_auth")
|
||||
notAuth := c.GetBool("auth_required") && c.GetString(gin.AuthUserKey) == ""
|
||||
|
||||
if notAuth && (play || m3u) {
|
||||
streamNoAuth(c)
|
||||
|
||||
@@ -6,8 +6,6 @@ import (
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"strings"
|
||||
"unsafe"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
@@ -16,15 +14,15 @@ import (
|
||||
"server/settings"
|
||||
)
|
||||
|
||||
func SetupAuth(engine *gin.Engine) *gin.RouterGroup {
|
||||
func SetupAuth(engine *gin.Engine) {
|
||||
if !settings.HttpAuth {
|
||||
return nil
|
||||
return
|
||||
}
|
||||
accs := getAccounts()
|
||||
if accs == nil {
|
||||
return nil
|
||||
return
|
||||
}
|
||||
return engine.Group("/", BasicAuth(accs))
|
||||
engine.Use(BasicAuth(accs))
|
||||
}
|
||||
|
||||
func getAccounts() gin.Accounts {
|
||||
@@ -60,22 +58,28 @@ func (a authPairs) searchCredential(authValue string) (string, bool) {
|
||||
|
||||
func BasicAuth(accounts gin.Accounts) gin.HandlerFunc {
|
||||
pairs := processAccounts(accounts)
|
||||
return func(c *gin.Context) {
|
||||
return func(c *gin.Context) {
|
||||
c.Set("auth_required", true)
|
||||
|
||||
user, found := pairs.searchCredential(c.Request.Header.Get("Authorization"))
|
||||
if !found { // always accessible
|
||||
if strings.HasPrefix(c.FullPath(), "/stream") ||
|
||||
c.FullPath() == "/site.webmanifest" ||
|
||||
// https://github.com/YouROK/TorrServer/issues/172
|
||||
(strings.HasPrefix(c.FullPath(), "/play") && c.FullPath() != "/playlistall/all.m3u") ||
|
||||
(settings.SearchWA && strings.HasPrefix(c.FullPath(), "/search")) {
|
||||
c.Set("not_auth", true)
|
||||
return
|
||||
}
|
||||
c.Header("WWW-Authenticate", "Basic realm=Authorization Required")
|
||||
c.AbortWithStatus(http.StatusUnauthorized)
|
||||
if found {
|
||||
c.Set(gin.AuthUserKey, user)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func CheckAuth() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
if !settings.HttpAuth {
|
||||
return
|
||||
}
|
||||
c.Set(gin.AuthUserKey, user)
|
||||
|
||||
if _, ok := c.Get(gin.AuthUserKey); ok {
|
||||
return
|
||||
}
|
||||
|
||||
c.Header("WWW-Authenticate", "Basic realm=Authorization Required")
|
||||
c.AbortWithStatus(http.StatusUnauthorized)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,8 +101,5 @@ func authorizationHeader(user, password string) string {
|
||||
}
|
||||
|
||||
func StringToBytes(s string) (b []byte) {
|
||||
sh := *(*reflect.StringHeader)(unsafe.Pointer(&s))
|
||||
bh := (*reflect.SliceHeader)(unsafe.Pointer(&b))
|
||||
bh.Data, bh.Len, bh.Cap = sh.Data, sh.Len, sh.Len
|
||||
return b
|
||||
return unsafe.Slice(unsafe.StringData(s), len(s))
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"sync"
|
||||
|
||||
"server/version"
|
||||
"server/web/auth"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
@@ -30,10 +31,12 @@ func asset(c *gin.Context, t string, d []byte) {
|
||||
c.Data(200, t+"; charset=UTF-8", d)
|
||||
}
|
||||
|
||||
func SetupRoute(r *gin.RouterGroup) {
|
||||
r.GET("/msx/:pth", msxPTH)
|
||||
r.GET("/msx/imdb", msxIMDB)
|
||||
r.GET("/msx/imdb/:id", msxIMDBID)
|
||||
func SetupRoute(r gin.IRouter) {
|
||||
authorized := r.Group("/", auth.CheckAuth())
|
||||
|
||||
authorized.GET("/msx/:pth", msxPTH)
|
||||
authorized.GET("/msx/imdb", msxIMDB)
|
||||
authorized.GET("/msx/imdb/:id", msxIMDBID)
|
||||
}
|
||||
|
||||
// msxPTH godoc
|
||||
|
||||
@@ -6,13 +6,16 @@ import (
|
||||
|
||||
"server/settings"
|
||||
"server/torr"
|
||||
"server/web/auth"
|
||||
"server/web/pages/template"
|
||||
)
|
||||
|
||||
func SetupRoute(route *gin.RouterGroup) {
|
||||
template.RouteWebPages(route)
|
||||
route.GET("/stat", statPage)
|
||||
route.GET("/magnets", getTorrents)
|
||||
func SetupRoute(route gin.IRouter) {
|
||||
authorized := route.Group("/", auth.CheckAuth())
|
||||
|
||||
template.RouteWebPages(authorized)
|
||||
authorized.GET("/stat", statPage)
|
||||
authorized.GET("/magnets", getTorrents)
|
||||
}
|
||||
|
||||
// stat godoc
|
||||
|
||||
@@ -3,10 +3,11 @@ package template
|
||||
import (
|
||||
"crypto/md5"
|
||||
"fmt"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func RouteWebPages(route *gin.RouterGroup) {
|
||||
func RouteWebPages(route gin.IRouter) {
|
||||
route.GET("/", func(c *gin.Context) {
|
||||
etag := fmt.Sprintf("%x", md5.Sum(Indexhtml))
|
||||
c.Header("Cache-Control", "public, max-age=31536000")
|
||||
|
||||
@@ -71,19 +71,14 @@ func Start() {
|
||||
|
||||
route := gin.New()
|
||||
route.Use(log.WebLogger(), blocker.Blocker(), gin.Recovery(), cors.New(corsCfg), location.Default())
|
||||
auth.SetupAuth(route)
|
||||
|
||||
route.GET("/echo", echo)
|
||||
|
||||
routeAuth := auth.SetupAuth(route)
|
||||
if routeAuth != nil {
|
||||
api.SetupRoute(routeAuth)
|
||||
msx.SetupRoute(routeAuth)
|
||||
pages.SetupRoute(routeAuth)
|
||||
} else {
|
||||
api.SetupRoute(&route.RouterGroup)
|
||||
msx.SetupRoute(&route.RouterGroup)
|
||||
pages.SetupRoute(&route.RouterGroup)
|
||||
}
|
||||
api.SetupRoute(route)
|
||||
msx.SetupRoute(route)
|
||||
pages.SetupRoute(route)
|
||||
|
||||
if settings.BTsets.EnableDLNA {
|
||||
dlna.Start()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user