mirror of
https://github.com/photoprism/photoprism.git
synced 2025-12-12 08:44:04 +01:00
Config: Move Portal flag to ClientConfig struct
Signed-off-by: Michael Mayer <michael@photoprism.app>
This commit is contained in:
@@ -820,7 +820,7 @@ export default class Config {
|
||||
|
||||
// isPortal returns true if this is a cluster portal server.
|
||||
isPortal() {
|
||||
return this.feature("portal");
|
||||
return this.values && this.values.portal;
|
||||
}
|
||||
|
||||
// isPro returns true if this is team version.
|
||||
|
||||
@@ -192,8 +192,8 @@ export const ItemsPerPage = () => [
|
||||
{ text: "100", title: "100", value: 100 },
|
||||
];
|
||||
|
||||
export const StartPages = (features) => {
|
||||
if (features.portal) {
|
||||
export const StartPages = (features, isPortal) => {
|
||||
if (isPortal) {
|
||||
return [{ value: "default", text: $gettext("Default"), visible: true }];
|
||||
}
|
||||
return [
|
||||
|
||||
@@ -64,7 +64,7 @@
|
||||
<v-select
|
||||
v-model="settings.ui.startPage"
|
||||
:disabled="busy"
|
||||
:items="options.StartPages(settings.features)"
|
||||
:items="options.StartPages(settings.features, isPortal)"
|
||||
tabindex="2"
|
||||
item-title="text"
|
||||
item-value="value"
|
||||
@@ -437,7 +437,7 @@ export default {
|
||||
isDemo: this.$config.isDemo(),
|
||||
isAdmin: this.$session.isAdmin(),
|
||||
isSuperAdmin: this.$session.isSuperAdmin(),
|
||||
isPublic: this.$config.get("public"),
|
||||
isPublic: this.$config.isPublic(),
|
||||
isPortal: this.$config.isPortal(),
|
||||
config: this.$config.values,
|
||||
settings: new Settings(this.$config.getSettings()),
|
||||
|
||||
@@ -86,7 +86,7 @@ func shouldAttemptJWT(c *gin.Context, token string) bool {
|
||||
// shouldAllowJWT reports whether the current node configuration permits JWT
|
||||
// authentication for the request originating from clientIP.
|
||||
func shouldAllowJWT(conf *config.Config, clientIP string) bool {
|
||||
if conf == nil || conf.IsPortal() {
|
||||
if conf == nil || conf.Portal() {
|
||||
return false
|
||||
}
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ func ClusterMetrics(router *gin.RouterGroup) {
|
||||
}
|
||||
|
||||
conf := get.Config()
|
||||
if !conf.IsPortal() {
|
||||
if !conf.Portal() {
|
||||
AbortFeatureDisabled(c)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ func ClusterListNodes(router *gin.RouterGroup) {
|
||||
|
||||
conf := get.Config()
|
||||
|
||||
if !conf.IsPortal() {
|
||||
if !conf.Portal() {
|
||||
AbortFeatureDisabled(c)
|
||||
return
|
||||
}
|
||||
@@ -134,7 +134,7 @@ func ClusterGetNode(router *gin.RouterGroup) {
|
||||
|
||||
conf := get.Config()
|
||||
|
||||
if !conf.IsPortal() {
|
||||
if !conf.Portal() {
|
||||
AbortFeatureDisabled(c)
|
||||
return
|
||||
}
|
||||
@@ -194,7 +194,7 @@ func ClusterUpdateNode(router *gin.RouterGroup) {
|
||||
|
||||
conf := get.Config()
|
||||
|
||||
if !conf.IsPortal() {
|
||||
if !conf.Portal() {
|
||||
AbortFeatureDisabled(c)
|
||||
return
|
||||
}
|
||||
@@ -274,7 +274,7 @@ func ClusterDeleteNode(router *gin.RouterGroup) {
|
||||
|
||||
conf := get.Config()
|
||||
|
||||
if !conf.IsPortal() {
|
||||
if !conf.Portal() {
|
||||
AbortFeatureDisabled(c)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ func ClusterNodesRegister(router *gin.RouterGroup) {
|
||||
conf := get.Config()
|
||||
|
||||
// Must be a portal.
|
||||
if !conf.IsPortal() {
|
||||
if !conf.Portal() {
|
||||
AbortFeatureDisabled(c)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ func ClusterSummary(router *gin.RouterGroup) {
|
||||
|
||||
conf := get.Config()
|
||||
|
||||
if !conf.IsPortal() {
|
||||
if !conf.Portal() {
|
||||
AbortFeatureDisabled(c)
|
||||
return
|
||||
}
|
||||
@@ -73,7 +73,7 @@ func ClusterHealth(router *gin.RouterGroup) {
|
||||
c.Header(header.AccessControlAllowOrigin, header.Any)
|
||||
|
||||
// Return error if not a portal node.
|
||||
if !conf.IsPortal() {
|
||||
if !conf.Portal() {
|
||||
AbortFeatureDisabled(c)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -59,7 +59,7 @@ func ClusterGetTheme(router *gin.RouterGroup) {
|
||||
*/
|
||||
|
||||
// Abort if this is not a portal server.
|
||||
if !conf.IsPortal() {
|
||||
if !conf.Portal() {
|
||||
AbortFeatureDisabled(c)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ func TestAuthJWTCommands(t *testing.T) {
|
||||
get.SetConfig(conf)
|
||||
conf.RegisterDb()
|
||||
|
||||
require.True(t, conf.IsPortal())
|
||||
require.True(t, conf.Portal())
|
||||
|
||||
manager := get.JWTManager()
|
||||
require.NotNil(t, manager)
|
||||
|
||||
@@ -27,7 +27,7 @@ var ClusterHealthCommand = &cli.Command{
|
||||
|
||||
func clusterHealthAction(ctx *cli.Context) error {
|
||||
return CallWithDependencies(ctx, func(conf *config.Config) error {
|
||||
if !conf.IsPortal() {
|
||||
if !conf.Portal() {
|
||||
return fmt.Errorf("cluster health is only available on a Portal node")
|
||||
}
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ var ClusterNodesListCommand = &cli.Command{
|
||||
|
||||
func clusterNodesListAction(ctx *cli.Context) error {
|
||||
return CallWithDependencies(ctx, func(conf *config.Config) error {
|
||||
if !conf.IsPortal() {
|
||||
if !conf.Portal() {
|
||||
return cli.Exit(fmt.Errorf("node listing is only available on a Portal node"), 2)
|
||||
}
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ var ClusterNodesModCommand = &cli.Command{
|
||||
|
||||
func clusterNodesModAction(ctx *cli.Context) error {
|
||||
return CallWithDependencies(ctx, func(conf *config.Config) error {
|
||||
if !conf.IsPortal() {
|
||||
if !conf.Portal() {
|
||||
return cli.Exit(fmt.Errorf("node update is only available on a Portal node"), 2)
|
||||
}
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ var ClusterNodesRemoveCommand = &cli.Command{
|
||||
|
||||
func clusterNodesRemoveAction(ctx *cli.Context) error {
|
||||
return CallWithDependencies(ctx, func(conf *config.Config) error {
|
||||
if !conf.IsPortal() {
|
||||
if !conf.Portal() {
|
||||
return cli.Exit(fmt.Errorf("node delete is only available on a Portal node"), 2)
|
||||
}
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@ func clusterNodesRotateAction(ctx *cli.Context) error {
|
||||
|
||||
// Determine node name. On portal, resolve id->name via registry; otherwise treat key as name.
|
||||
name := clean.DNSLabel(key)
|
||||
if conf.IsPortal() {
|
||||
if conf.Portal() {
|
||||
if r, err := reg.NewClientRegistryWithConfig(conf); err == nil {
|
||||
if n, err := r.FindByNodeUUID(key); err == nil && n != nil {
|
||||
name = n.Name
|
||||
|
||||
@@ -24,7 +24,7 @@ var ClusterNodesShowCommand = &cli.Command{
|
||||
|
||||
func clusterNodesShowAction(ctx *cli.Context) error {
|
||||
return CallWithDependencies(ctx, func(conf *config.Config) error {
|
||||
if !conf.IsPortal() {
|
||||
if !conf.Portal() {
|
||||
return cli.Exit(fmt.Errorf("node show is only available on a Portal node"), 2)
|
||||
}
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ var ClusterSummaryCommand = &cli.Command{
|
||||
|
||||
func clusterSummaryAction(ctx *cli.Context) error {
|
||||
return CallWithDependencies(ctx, func(conf *config.Config) error {
|
||||
if !conf.IsPortal() {
|
||||
if !conf.Portal() {
|
||||
return fmt.Errorf("cluster summary is only available on a Portal node")
|
||||
}
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ var allowedJWTScope = func() map[string]struct{} {
|
||||
|
||||
// requirePortal returns a CLI error when the active configuration is not a portal node.
|
||||
func requirePortal(conf *config.Config) error {
|
||||
if conf == nil || !conf.IsPortal() {
|
||||
if conf == nil || !conf.Portal() {
|
||||
return cli.Exit(errors.New("command requires a Portal node"), 2)
|
||||
}
|
||||
return nil
|
||||
|
||||
@@ -62,6 +62,7 @@ type ClientConfig struct {
|
||||
Trace bool `json:"trace"`
|
||||
Test bool `json:"test"`
|
||||
Demo bool `json:"demo"`
|
||||
Portal bool `json:"portal"`
|
||||
Sponsor bool `json:"sponsor"`
|
||||
ReadOnly bool `json:"readonly"`
|
||||
UploadNSFW bool `json:"uploadNSFW"`
|
||||
@@ -312,6 +313,7 @@ func (c *Config) ClientPublic() *ClientConfig {
|
||||
Trace: c.Trace(),
|
||||
Test: c.Test(),
|
||||
Demo: c.Demo(),
|
||||
Portal: c.Portal(),
|
||||
Sponsor: c.Sponsor(),
|
||||
ReadOnly: c.ReadOnly(),
|
||||
Public: c.Public(),
|
||||
@@ -407,6 +409,7 @@ func (c *Config) ClientShare() *ClientConfig {
|
||||
Trace: c.Trace(),
|
||||
Test: c.Test(),
|
||||
Demo: c.Demo(),
|
||||
Portal: c.Portal(),
|
||||
Sponsor: c.Sponsor(),
|
||||
ReadOnly: c.ReadOnly(),
|
||||
UploadNSFW: c.UploadNSFW(),
|
||||
@@ -510,6 +513,7 @@ func (c *Config) ClientUser(withSettings bool) *ClientConfig {
|
||||
Trace: c.Trace(),
|
||||
Test: c.Test(),
|
||||
Demo: c.Demo(),
|
||||
Portal: c.Portal(),
|
||||
Sponsor: c.Sponsor(),
|
||||
ReadOnly: c.ReadOnly(),
|
||||
UploadNSFW: c.UploadNSFW(),
|
||||
|
||||
@@ -53,6 +53,7 @@ func TestConfig_ClientConfig(t *testing.T) {
|
||||
assert.Equal(t, true, cfg.Debug)
|
||||
assert.Equal(t, AuthModePublic, cfg.AuthMode)
|
||||
assert.Equal(t, false, cfg.Demo)
|
||||
assert.Equal(t, false, cfg.Portal)
|
||||
assert.Equal(t, true, cfg.Sponsor)
|
||||
assert.Equal(t, false, cfg.ReadOnly)
|
||||
|
||||
|
||||
@@ -84,8 +84,8 @@ func (c *Config) PortalUrl() string {
|
||||
return c.options.PortalUrl
|
||||
}
|
||||
|
||||
// IsPortal returns true if the configured node type is "portal".
|
||||
func (c *Config) IsPortal() bool {
|
||||
// Portal returns true if the configured node type is "portal".
|
||||
func (c *Config) Portal() bool {
|
||||
return c.NodeRole() == cluster.RolePortal
|
||||
}
|
||||
|
||||
@@ -123,7 +123,7 @@ func (c *Config) JoinToken() string {
|
||||
}
|
||||
}
|
||||
|
||||
if !c.IsPortal() {
|
||||
if !c.Portal() {
|
||||
return ""
|
||||
}
|
||||
|
||||
@@ -182,7 +182,7 @@ func (c *Config) NodeName() string {
|
||||
}
|
||||
|
||||
// Default: portal nodes → "portal".
|
||||
if c.IsPortal() {
|
||||
if c.Portal() {
|
||||
return "portal"
|
||||
}
|
||||
|
||||
|
||||
@@ -94,11 +94,11 @@ func TestConfig_Cluster(t *testing.T) {
|
||||
c := NewConfig(CliTestContext())
|
||||
|
||||
// Defaults
|
||||
assert.False(t, c.IsPortal())
|
||||
assert.False(t, c.Portal())
|
||||
|
||||
// Toggle values
|
||||
c.Options().NodeRole = string(cluster.RolePortal)
|
||||
assert.True(t, c.IsPortal())
|
||||
assert.True(t, c.Portal())
|
||||
c.Options().NodeRole = ""
|
||||
})
|
||||
t.Run("JWKSUrlSetter", func(t *testing.T) {
|
||||
|
||||
@@ -21,7 +21,6 @@ type FeatureSettings struct {
|
||||
People bool `json:"people" yaml:"People"`
|
||||
Places bool `json:"places" yaml:"Places"`
|
||||
Private bool `json:"private" yaml:"Private"`
|
||||
Portal bool `json:"portal" yaml:"-"`
|
||||
Ratings bool `json:"ratings" yaml:"Ratings"`
|
||||
Reactions bool `json:"reactions" yaml:"Reactions"`
|
||||
Review bool `json:"review" yaml:"Review"`
|
||||
|
||||
@@ -97,7 +97,6 @@ func NewSettings(theme, language, timeZone string) *Settings {
|
||||
Services: true,
|
||||
Account: true,
|
||||
Delete: true,
|
||||
Portal: false,
|
||||
},
|
||||
Import: ImportSettings{
|
||||
Path: RootPath,
|
||||
|
||||
@@ -36,8 +36,6 @@ func (c *Config) initSettings() {
|
||||
log.Debugf("settings: saved to %s ", settingsFile)
|
||||
}
|
||||
|
||||
c.settings.Features.Portal = c.IsPortal()
|
||||
|
||||
i18n.SetDir(c.LocalesPath())
|
||||
|
||||
c.settings.Propagate()
|
||||
|
||||
@@ -22,7 +22,7 @@ var (
|
||||
func initJWTManager() {
|
||||
if conf == nil {
|
||||
return
|
||||
} else if !conf.IsPortal() {
|
||||
} else if !conf.Portal() {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -121,7 +121,7 @@ func IssuePortalJWT(spec jwt.ClaimsSpec) (string, error) {
|
||||
func IssuePortalJWTForNode(nodeUUID string, scopes []string, ttl time.Duration) (string, error) {
|
||||
if conf == nil {
|
||||
return "", errors.New("jwt: missing config")
|
||||
} else if !conf.IsPortal() {
|
||||
} else if !conf.Portal() {
|
||||
return "", errors.New("jwt: not supported on nodes")
|
||||
}
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ func registerWellknownRoutes(router *gin.Engine, conf *config.Config) {
|
||||
|
||||
// Registers the "/.well-known/jwks.json" endpoint for cluster JWT verification.
|
||||
router.GET(conf.BaseUri("/.well-known/jwks.json"), func(c *gin.Context) {
|
||||
if !conf.IsPortal() {
|
||||
if !conf.Portal() {
|
||||
c.JSON(http.StatusNotFound, gin.H{"error": "not found"})
|
||||
return
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ func InitConfig(c *config.Config) error {
|
||||
|
||||
role := c.NodeRole()
|
||||
// Skip on portal nodes and unknown node types.
|
||||
if c.IsPortal() || (role != cluster.RoleInstance && role != cluster.RoleService) {
|
||||
if c.Portal() || (role != cluster.RoleInstance && role != cluster.RoleService) {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ import "time"
|
||||
|
||||
// BootstrapAutoJoinEnabled indicates whether cluster bootstrap logic is enabled
|
||||
// for nodes by default. Portal nodes ignore this value; gating is decided by
|
||||
// runtime checks (e.g., conf.IsPortal() and conf.NodeRole()).
|
||||
// runtime checks (e.g., conf.Portal() and conf.NodeRole()).
|
||||
var BootstrapAutoJoinEnabled = true
|
||||
|
||||
// BootstrapAutoThemeEnabled indicates whether bootstrap should attempt to
|
||||
|
||||
Reference in New Issue
Block a user