CLI: Add photoprism connect command
Signed-off-by: Michael Mayer <michael@photoprism.app>
This commit is contained in:
parent
653f381f81
commit
84d1e7de1d
9 changed files with 88 additions and 30 deletions
|
@ -36,7 +36,7 @@ var version = "development"
|
|||
var log = event.Log
|
||||
|
||||
const appName = "PhotoPrism"
|
||||
const appAbout = "PhotoPrism® CE"
|
||||
const appAbout = "PhotoPrism®"
|
||||
const appEdition = "ce"
|
||||
const appDescription = "PhotoPrism® is an AI-Powered Photos App for the Decentralized Web." +
|
||||
" It makes use of the latest technologies to tag and find pictures automatically without getting in your way." +
|
||||
|
|
|
@ -65,6 +65,7 @@ var PhotoPrism = []cli.Command{
|
|||
ShowCommand,
|
||||
VersionCommand,
|
||||
ShowConfigCommand,
|
||||
ConnectCommand,
|
||||
}
|
||||
|
||||
// childAlreadyRunning tests if a .pid file at filePath is a running process.
|
||||
|
|
36
internal/commands/connect.go
Normal file
36
internal/commands/connect.go
Normal file
|
@ -0,0 +1,36 @@
|
|||
package commands
|
||||
|
||||
import (
|
||||
"github.com/urfave/cli"
|
||||
|
||||
"github.com/photoprism/photoprism/internal/config"
|
||||
)
|
||||
|
||||
// ConnectCommand configures the command name, flags, and action.
|
||||
var ConnectCommand = cli.Command{
|
||||
Name: "connect",
|
||||
Usage: "Connects your membership account",
|
||||
ArgsUsage: "[activation code]",
|
||||
Action: connectAction,
|
||||
}
|
||||
|
||||
// connectAction connects your membership account.
|
||||
func connectAction(ctx *cli.Context) error {
|
||||
return CallWithDependencies(ctx, func(conf *config.Config) error {
|
||||
token := ctx.Args().First()
|
||||
|
||||
// Fail if no code was provided.
|
||||
if token == "" {
|
||||
return cli.ShowSubcommandHelp(ctx)
|
||||
}
|
||||
|
||||
// Connect to hub.
|
||||
if err := conf.ResyncHub(token); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Infof("successfully connected your account")
|
||||
|
||||
return nil
|
||||
})
|
||||
}
|
|
@ -73,7 +73,7 @@ type ClientConfig struct {
|
|||
Countries entity.Countries `json:"countries"`
|
||||
People entity.People `json:"people"`
|
||||
Thumbs ThumbSizes `json:"thumbs"`
|
||||
License string `json:"license"`
|
||||
Membership string `json:"membership"`
|
||||
Customer string `json:"customer"`
|
||||
MapKey string `json:"mapKey"`
|
||||
DownloadToken string `json:"downloadToken,omitempty"`
|
||||
|
@ -289,7 +289,7 @@ func (c *Config) ClientPublic() ClientConfig {
|
|||
Lenses: entity.Lenses{},
|
||||
Countries: entity.Countries{},
|
||||
People: entity.People{},
|
||||
License: c.Hub().Status,
|
||||
Membership: c.Hub().Membership(),
|
||||
Customer: "",
|
||||
MapKey: "",
|
||||
Thumbs: Thumbs,
|
||||
|
@ -378,7 +378,7 @@ func (c *Config) ClientShare() ClientConfig {
|
|||
People: entity.People{},
|
||||
Colors: colors.All.List(),
|
||||
Thumbs: Thumbs,
|
||||
License: c.Hub().Status,
|
||||
Membership: c.Hub().Membership(),
|
||||
Customer: c.Hub().Customer(),
|
||||
MapKey: c.Hub().MapKey(),
|
||||
DownloadToken: c.DownloadToken(),
|
||||
|
@ -471,7 +471,7 @@ func (c *Config) ClientUser(withSettings bool) ClientConfig {
|
|||
People: entity.People{},
|
||||
Colors: colors.All.List(),
|
||||
Thumbs: Thumbs,
|
||||
License: c.Hub().Status,
|
||||
Membership: c.Hub().Membership(),
|
||||
Customer: c.Hub().Customer(),
|
||||
MapKey: c.Hub().MapKey(),
|
||||
DownloadToken: c.DownloadToken(),
|
||||
|
|
|
@ -350,9 +350,7 @@ func (c *Config) Name() string {
|
|||
// About returns the app about string.
|
||||
func (c *Config) About() string {
|
||||
if c.options.About == "" {
|
||||
return "PhotoPrism® Dev"
|
||||
} else if strings.HasSuffix(c.options.About, "CE") && c.Sponsor() {
|
||||
return strings.Replace(c.options.About, "CE", "Plus", 1)
|
||||
return "PhotoPrism®"
|
||||
}
|
||||
|
||||
return c.options.About
|
||||
|
@ -563,7 +561,7 @@ func (c *Config) Sponsor() bool {
|
|||
if Sponsor || c.options.Sponsor {
|
||||
return true
|
||||
} else if c.hub != nil {
|
||||
Sponsor = c.Hub().Plus()
|
||||
Sponsor = c.Hub().Sponsor()
|
||||
}
|
||||
|
||||
return Sponsor
|
||||
|
@ -757,13 +755,25 @@ func (c *Config) ResolutionLimit() int {
|
|||
return result
|
||||
}
|
||||
|
||||
// UpdateHub renews backend api credentials for maps and places without a token.
|
||||
// UpdateHub renews backend api credentials with an optional activation code.
|
||||
func (c *Config) UpdateHub() {
|
||||
_ = c.ResyncHub("")
|
||||
if c.hub == nil {
|
||||
return
|
||||
}
|
||||
|
||||
if token := os.Getenv(EnvVar("CONNECT")); token != "" && !c.Hub().Sponsor() {
|
||||
_ = c.ResyncHub(token)
|
||||
} else {
|
||||
_ = c.ResyncHub("")
|
||||
}
|
||||
}
|
||||
|
||||
// ResyncHub renews backend api credentials for maps and places with an optional token.
|
||||
func (c *Config) ResyncHub(token string) error {
|
||||
if c.hub == nil {
|
||||
return fmt.Errorf("hub is not initialized")
|
||||
}
|
||||
|
||||
if err := c.hub.ReSync(token); err != nil {
|
||||
log.Debugf("config: %s, see https://docs.photoprism.app/getting-started/troubleshooting/firewall/", err)
|
||||
if token != "" {
|
||||
|
|
|
@ -73,7 +73,7 @@ func TestConfig_About(t *testing.T) {
|
|||
c := NewConfig(CliTestContext())
|
||||
|
||||
name := c.About()
|
||||
assert.Equal(t, "PhotoPrism® Dev", name)
|
||||
assert.Equal(t, "PhotoPrism®", name)
|
||||
}
|
||||
|
||||
func TestConfig_Edition(t *testing.T) {
|
||||
|
|
|
@ -24,10 +24,12 @@ import (
|
|||
"github.com/photoprism/photoprism/pkg/fs"
|
||||
)
|
||||
|
||||
type Status string
|
||||
|
||||
const (
|
||||
StatusUnknown = ""
|
||||
StatusNew = "unregistered"
|
||||
StatusCommunity = "ce"
|
||||
StatusUnknown Status = ""
|
||||
StatusNew Status = "unregistered"
|
||||
StatusCommunity Status = "ce"
|
||||
)
|
||||
|
||||
// Config represents backend api credentials for maps & geodata.
|
||||
|
@ -39,7 +41,7 @@ type Config struct {
|
|||
Session string `json:"session" yaml:"Session"`
|
||||
session *Session `json:"-" yaml:"-"`
|
||||
sessionMu sync.Mutex `json:"-" yaml:"-"`
|
||||
Status string `json:"status" yaml:"Status"`
|
||||
Status Status `json:"status" yaml:"Status"`
|
||||
Serial string `json:"serial" yaml:"Serial"`
|
||||
Env string `json:"-" yaml:"-"`
|
||||
UserAgent string `json:"-" yaml:"-"`
|
||||
|
@ -71,6 +73,15 @@ func (c *Config) MapKey() string {
|
|||
}
|
||||
}
|
||||
|
||||
// Membership returns the membership level as string.
|
||||
func (c *Config) Membership() string {
|
||||
if !c.Sponsor() {
|
||||
return string(StatusCommunity)
|
||||
}
|
||||
|
||||
return string(c.Status)
|
||||
}
|
||||
|
||||
// Customer returns the customer name.
|
||||
func (c *Config) Customer() string {
|
||||
if sess, err := c.DecodeSession(true); err != nil {
|
||||
|
@ -86,8 +97,8 @@ func (c *Config) Propagate() {
|
|||
places.Secret = c.Secret
|
||||
}
|
||||
|
||||
// Plus reports if you have a community membership.
|
||||
func (c *Config) Plus() bool {
|
||||
// Sponsor reports if you support the project.
|
||||
func (c *Config) Sponsor() bool {
|
||||
switch c.Status {
|
||||
case StatusUnknown, StatusNew, StatusCommunity:
|
||||
return false
|
||||
|
|
|
@ -13,18 +13,18 @@ func TestConfig_MapKey(t *testing.T) {
|
|||
})
|
||||
}
|
||||
|
||||
func TestConfig_Plus(t *testing.T) {
|
||||
func TestConfig_Sponsor(t *testing.T) {
|
||||
t.Run("Status", func(t *testing.T) {
|
||||
c := NewConfig("0.0.0", "testdata/new.yml", "zr58wrg19i8jfjam", "test", "PhotoPrism/Test", "test")
|
||||
c.Key = "0e159b773c6fb779c3bf6c8ba6e322abf559dbaf"
|
||||
c.Secret = "23f0024975bd65ade06edcc8191f7fcc"
|
||||
assert.False(t, c.Plus())
|
||||
c.Status = "plus"
|
||||
assert.False(t, c.Plus())
|
||||
assert.False(t, c.Sponsor())
|
||||
c.Status = "sponsor"
|
||||
assert.False(t, c.Sponsor())
|
||||
c.Session = "bde6d0cf514e5456591de5ae09d981056eb88dccf71ba268974bf2cc7b028545e7641c1dfbaa716e4d13f8b0e0d1863e64c16e1f0ac551fc85e1171a87cbda6608cbe330de9e0d5f5b0e14ff61f2ff08fee369"
|
||||
assert.True(t, c.Plus())
|
||||
assert.True(t, c.Sponsor())
|
||||
c.Status = ""
|
||||
assert.False(t, c.Plus())
|
||||
assert.False(t, c.Sponsor())
|
||||
c.Session = ""
|
||||
})
|
||||
}
|
||||
|
|
|
@ -133,7 +133,7 @@ func TestConfig_DecodeSession(t *testing.T) {
|
|||
assert.Equal(t, "8dd8b115d052f91ac74b1c2475e305009366c487", c.Key)
|
||||
assert.Equal(t, "ddf4ce46afbf6c16a6bd8555ab1e4efb", c.Secret)
|
||||
assert.Equal(t, "7607796238c26b2d95007957b05c72d63f504346576bc2aa064a6dc54344de47d2ab38422bd1d061c067a16ef517e6054d8b7f5336c120431935518277fed45e49472aaf740cac1bc33ab2e362c767007a59e953e9973709", c.Session)
|
||||
assert.Equal(t, "unregistered", c.Status)
|
||||
assert.Equal(t, Status("unregistered"), c.Status)
|
||||
assert.Equal(t, "0.0.0", c.Version)
|
||||
})
|
||||
}
|
||||
|
@ -149,7 +149,7 @@ func TestConfig_Load(t *testing.T) {
|
|||
assert.Equal(t, "b32e9ccdc90eb7c0f6f1b9fbc82b8a2b0e993304", c.Key)
|
||||
assert.Equal(t, "5991ea36a9611e9e00a8360c10b91567", c.Secret)
|
||||
assert.Equal(t, "3ef5685c6391a568731c8fc94ccad82d92dea60476c8b672990047c822248f45366fc0e8e812ad15e0b5ae1eb20e866235c56b", c.Session)
|
||||
assert.Equal(t, "unregistered", c.Status)
|
||||
assert.Equal(t, Status("unregistered"), c.Status)
|
||||
assert.Equal(t, "0.0.0", c.Version)
|
||||
})
|
||||
t.Run("hub2.yml", func(t *testing.T) {
|
||||
|
@ -162,7 +162,7 @@ func TestConfig_Load(t *testing.T) {
|
|||
assert.Equal(t, "ab66cb5cfb3658dbea0a1433df048d900934ac68", c.Key)
|
||||
assert.Equal(t, "6b0f8440fe307d3120b3a4366350094b", c.Secret)
|
||||
assert.Equal(t, "c0ca88fc3094b70a1947b5b10f980a420cd6b1542a20f6f26ecc6a16f340473b9fb16b80be1078e86d886b3a8d46bf8184d147", c.Session)
|
||||
assert.Equal(t, "unregistered", c.Status)
|
||||
assert.Equal(t, Status("unregistered"), c.Status)
|
||||
assert.Equal(t, "200925-f8e2b580-Darwin-i386-DEBUG", c.Version)
|
||||
})
|
||||
t.Run("not existing filename", func(t *testing.T) {
|
||||
|
@ -191,7 +191,7 @@ func TestConfig_Save(t *testing.T) {
|
|||
assert.Equal(t, "b32e9ccdc90eb7c0f6f1b9fbc82b8a2b0e993304", c.Key)
|
||||
assert.Equal(t, "5991ea36a9611e9e00a8360c10b91567", c.Secret)
|
||||
assert.Equal(t, "3ef5685c6391a568731c8fc94ccad82d92dea60476c8b672990047c822248f45366fc0e8e812ad15e0b5ae1eb20e866235c56b", c.Session)
|
||||
assert.Equal(t, "unregistered", c.Status)
|
||||
assert.Equal(t, Status("unregistered"), c.Status)
|
||||
assert.Equal(t, "0.0.0", c.Version)
|
||||
|
||||
c.FileName = "testdata/hub-save.yml"
|
||||
|
@ -205,7 +205,7 @@ func TestConfig_Save(t *testing.T) {
|
|||
assert.Equal(t, "b32e9ccdc90eb7c0f6f1b9fbc82b8a2b0e993304", c.Key)
|
||||
assert.Equal(t, "5991ea36a9611e9e00a8360c10b91567", c.Secret)
|
||||
assert.Equal(t, "3ef5685c6391a568731c8fc94ccad82d92dea60476c8b672990047c822248f45366fc0e8e812ad15e0b5ae1eb20e866235c56b", c.Session)
|
||||
assert.Equal(t, "unregistered", c.Status)
|
||||
assert.Equal(t, Status("unregistered"), c.Status)
|
||||
assert.Equal(t, "0.0.0", c.Version)
|
||||
|
||||
assert.FileExists(t, "testdata/hub-save.yml")
|
||||
|
@ -217,7 +217,7 @@ func TestConfig_Save(t *testing.T) {
|
|||
assert.Equal(t, "b32e9ccdc90eb7c0f6f1b9fbc82b8a2b0e993304", c.Key)
|
||||
assert.Equal(t, "5991ea36a9611e9e00a8360c10b91567", c.Secret)
|
||||
assert.Equal(t, "3ef5685c6391a568731c8fc94ccad82d92dea60476c8b672990047c822248f45366fc0e8e812ad15e0b5ae1eb20e866235c56b", c.Session)
|
||||
assert.Equal(t, "unregistered", c.Status)
|
||||
assert.Equal(t, Status("unregistered"), c.Status)
|
||||
assert.Equal(t, "0.0.0", c.Version)
|
||||
})
|
||||
t.Run("not existing filename", func(t *testing.T) {
|
||||
|
|
Loading…
Reference in a new issue