mirror of
https://github.com/photoprism/photoprism.git
synced 2026-01-23 02:24:24 +00:00
Auth: Adjust JWT default scope and ACL, add tests #5230
Signed-off-by: Michael Mayer <michael@photoprism.app>
This commit is contained in:
parent
e1e673be7f
commit
6e43f14476
6 changed files with 66 additions and 2 deletions
|
|
@ -91,6 +91,39 @@ func TestAuthAnyJWT(t *testing.T) {
|
|||
assert.True(t, session.SessExpires > session.CreatedAt.Unix())
|
||||
assert.True(t, session.LastActive >= session.CreatedAt.Unix())
|
||||
})
|
||||
t.Run("ConfigScopePortalRole", func(t *testing.T) {
|
||||
fx := newPortalJWTFixture(t, "cluster-jwt-config")
|
||||
spec := fx.defaultClaimsSpec()
|
||||
spec.Scope = []string{"cluster", "config"}
|
||||
token := fx.issue(t, spec)
|
||||
|
||||
origScope := fx.nodeConf.Options().JWTScope
|
||||
fx.nodeConf.Options().JWTScope = "cluster config"
|
||||
get.SetConfig(fx.nodeConf)
|
||||
t.Cleanup(func() {
|
||||
fx.nodeConf.Options().JWTScope = origScope
|
||||
get.SetConfig(fx.nodeConf)
|
||||
})
|
||||
|
||||
gin.SetMode(gin.TestMode)
|
||||
w := httptest.NewRecorder()
|
||||
c, _ := gin.CreateTestContext(w)
|
||||
req, _ := http.NewRequest(http.MethodGet, "/api/v1/config", nil)
|
||||
req.Header.Set("Authorization", "Bearer "+token)
|
||||
req.Header.Set(header.UserAgent, "PhotoPrism Portal/1.0")
|
||||
req.RemoteAddr = "192.0.2.51:1234"
|
||||
c.Request = req
|
||||
|
||||
session := authAnyJWT(c, "192.0.2.51", token, acl.ResourceConfig, acl.Permissions{acl.ActionView})
|
||||
require.NotNil(t, session)
|
||||
assert.Equal(t, http.StatusOK, session.HttpStatus())
|
||||
assert.Equal(t, acl.RolePortal, session.GetClientRole())
|
||||
assert.True(t, session.Valid())
|
||||
|
||||
cfg := fx.nodeConf.ClientSession(session)
|
||||
require.NotNil(t, cfg)
|
||||
assert.Equal(t, string(config.ClientUser), cfg.Mode)
|
||||
})
|
||||
t.Run("ClusterCIDRAllowed", func(t *testing.T) {
|
||||
fx := newPortalJWTFixture(t, "cluster-jwt-cidr-allow")
|
||||
spec := fx.defaultClaimsSpec()
|
||||
|
|
|
|||
|
|
@ -2,12 +2,15 @@ package api
|
|||
|
||||
import (
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/tidwall/gjson"
|
||||
|
||||
"github.com/photoprism/photoprism/internal/auth/acl"
|
||||
"github.com/photoprism/photoprism/internal/config"
|
||||
"github.com/photoprism/photoprism/pkg/http/header"
|
||||
)
|
||||
|
||||
func TestGetClientConfig(t *testing.T) {
|
||||
|
|
@ -39,4 +42,29 @@ func TestGetClientConfig(t *testing.T) {
|
|||
assert.Equal(t, http.StatusUnauthorized, r.Code)
|
||||
conf.Options().DisableFrontend = false
|
||||
})
|
||||
t.Run("PortalJWT", func(t *testing.T) {
|
||||
fx := newPortalJWTFixture(t, "client-config-handler")
|
||||
|
||||
app, router, conf := NewApiTest()
|
||||
conf.SetAuthMode(config.AuthModePasswd)
|
||||
defer conf.SetAuthMode(config.AuthModePublic)
|
||||
|
||||
GetClientConfig(router)
|
||||
|
||||
spec := fx.defaultClaimsSpec()
|
||||
spec.Scope = []string{acl.ResourceCluster.String(), acl.ResourceConfig.String()}
|
||||
|
||||
token := fx.issue(t, spec)
|
||||
|
||||
req, _ := http.NewRequest(http.MethodGet, "/api/v1/config", nil)
|
||||
req.RemoteAddr = "10.10.0.5:1234"
|
||||
header.SetAuthorization(req, token)
|
||||
req.Header.Set(header.UserAgent, "PhotoPrism Portal/1.0")
|
||||
|
||||
w := httptest.NewRecorder()
|
||||
app.ServeHTTP(w, req)
|
||||
|
||||
assert.Equal(t, http.StatusOK, w.Code)
|
||||
assert.Equal(t, "user", gjson.Get(w.Body.String(), "mode").String())
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -58,6 +58,7 @@ var Rules = ACL{
|
|||
},
|
||||
ResourceConfig: Roles{
|
||||
RoleAdmin: GrantFullAccess,
|
||||
RolePortal: GrantFullAccess,
|
||||
RoleClient: GrantViewOwn,
|
||||
RoleDefault: GrantViewOwn,
|
||||
},
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ import (
|
|||
// DefaultPortalUrl specifies the default portal URL with variable cluster domain.
|
||||
var DefaultPortalUrl = "https://portal.${PHOTOPRISM_CLUSTER_DOMAIN}"
|
||||
var DefaultNodeRole = cluster.RoleInstance
|
||||
var DefaultJWTAllowedScopes = "cluster vision metrics"
|
||||
var DefaultJWTAllowedScopes = "config cluster vision metrics"
|
||||
|
||||
// ClusterDomain returns the cluster DOMAIN (lowercase DNS name; 1–63 chars).
|
||||
func (c *Config) ClusterDomain() string {
|
||||
|
|
|
|||
|
|
@ -181,7 +181,7 @@ func TestConfig_Cluster(t *testing.T) {
|
|||
c.options.JWTScope = "cluster vision"
|
||||
assert.Equal(t, list.ParseAttr("cluster vision"), c.JWTAllowedScopes())
|
||||
c.options.JWTScope = ""
|
||||
assert.Equal(t, list.ParseAttr("cluster vision metrics"), c.JWTAllowedScopes())
|
||||
assert.Equal(t, list.ParseAttr("config cluster vision metrics"), c.JWTAllowedScopes())
|
||||
})
|
||||
t.Run("Paths", func(t *testing.T) {
|
||||
c := NewConfig(CliTestContext())
|
||||
|
|
|
|||
|
|
@ -180,6 +180,8 @@ func NewTestOptionsForPath(dbName, dataPath string) *Options {
|
|||
DatabaseDriver: driver,
|
||||
DatabaseDSN: dsn,
|
||||
AdminPassword: "photoprism",
|
||||
ClusterCIDR: "",
|
||||
JWTScope: DefaultJWTAllowedScopes,
|
||||
OriginalsLimit: 66,
|
||||
ResolutionLimit: 33,
|
||||
VisionApi: true,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue