mirror of
https://github.com/photoprism/photoprism.git
synced 2025-12-12 00:34:13 +01:00
CI: Apply Go linter recommendations to "internal/commands" package #5330
Signed-off-by: Michael Mayer <michael@photoprism.app>
This commit is contained in:
@@ -23,7 +23,7 @@ func TestAuthAddCommand(t *testing.T) {
|
|||||||
output, err := RunWithTestContext(AuthAddCommand, []string{"add", "--scope=test", "--expires=5000", "--name=xyz"})
|
output, err := RunWithTestContext(AuthAddCommand, []string{"add", "--scope=test", "--expires=5000", "--name=xyz"})
|
||||||
|
|
||||||
// Check command output for plausibility.
|
// Check command output for plausibility.
|
||||||
//t.Logf(output)
|
// t.Logf(output)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.NotContains(t, output, "App Password")
|
assert.NotContains(t, output, "App Password")
|
||||||
assert.Contains(t, output, "Access Token")
|
assert.Contains(t, output, "Access Token")
|
||||||
@@ -34,7 +34,7 @@ func TestAuthAddCommand(t *testing.T) {
|
|||||||
output, err := RunWithTestContext(AuthAddCommand, []string{"add", "--scope=test", "--expires=5000", "xxxxx"})
|
output, err := RunWithTestContext(AuthAddCommand, []string{"add", "--scope=test", "--expires=5000", "xxxxx"})
|
||||||
|
|
||||||
// Check command output for plausibility.
|
// Check command output for plausibility.
|
||||||
//t.Logf(output)
|
// t.Logf(output)
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
assert.Empty(t, output)
|
assert.Empty(t, output)
|
||||||
|
|
||||||
@@ -44,7 +44,7 @@ func TestAuthAddCommand(t *testing.T) {
|
|||||||
output, err := RunWithTestContext(AuthAddCommand, []string{"add", "--scope=test", "--expires=5000", "alice"})
|
output, err := RunWithTestContext(AuthAddCommand, []string{"add", "--scope=test", "--expires=5000", "alice"})
|
||||||
|
|
||||||
// Check command output for plausibility.
|
// Check command output for plausibility.
|
||||||
//t.Logf(output)
|
// t.Logf(output)
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
assert.Empty(t, output)
|
assert.Empty(t, output)
|
||||||
})
|
})
|
||||||
@@ -53,7 +53,7 @@ func TestAuthAddCommand(t *testing.T) {
|
|||||||
output, err := RunWithTestContext(AuthAddCommand, []string{"add", "--name=test", "--expires=5000", "alice"})
|
output, err := RunWithTestContext(AuthAddCommand, []string{"add", "--name=test", "--expires=5000", "alice"})
|
||||||
|
|
||||||
// Check command output for plausibility.
|
// Check command output for plausibility.
|
||||||
//t.Logf(output)
|
// t.Logf(output)
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
assert.Empty(t, output)
|
assert.Empty(t, output)
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -128,7 +128,7 @@ func authJWTInspectAction(ctx *cli.Context) error {
|
|||||||
// readTokenInput loads the token from CLI args, file, or STDIN.
|
// readTokenInput loads the token from CLI args, file, or STDIN.
|
||||||
func readTokenInput(ctx *cli.Context) (string, error) {
|
func readTokenInput(ctx *cli.Context) (string, error) {
|
||||||
if file := strings.TrimSpace(ctx.String("file")); file != "" {
|
if file := strings.TrimSpace(ctx.String("file")); file != "" {
|
||||||
data, err := os.ReadFile(file)
|
data, err := os.ReadFile(file) //nolint:gosec // user-supplied path is intended
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", cli.Exit(err, 1)
|
return "", cli.Exit(err, 1)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ func TestAuthListCommand(t *testing.T) {
|
|||||||
output, err := RunWithTestContext(AuthListCommand, []string{"ls", "--csv", "alice"})
|
output, err := RunWithTestContext(AuthListCommand, []string{"ls", "--csv", "alice"})
|
||||||
|
|
||||||
// Check command output for plausibility.
|
// Check command output for plausibility.
|
||||||
//t.Logf(output)
|
// t.Logf(output)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Contains(t, output, "Session ID;")
|
assert.Contains(t, output, "Session ID;")
|
||||||
assert.Contains(t, output, "alice;")
|
assert.Contains(t, output, "alice;")
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import (
|
|||||||
"github.com/photoprism/photoprism/internal/entity"
|
"github.com/photoprism/photoprism/internal/entity"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// AuthResetDescription explains the effect of the auth reset command.
|
||||||
const AuthResetDescription = "This command recreates the auth_sessions database table so that it is compatible with the current version. As a result, all users and clients must re-authenticate. Note that any client access tokens and app passwords that users may have created are also deleted and must be recreated."
|
const AuthResetDescription = "This command recreates the auth_sessions database table so that it is compatible with the current version. As a result, all users and clients must re-authenticate. Note that any client access tokens and app passwords that users may have created are also deleted and must be recreated."
|
||||||
|
|
||||||
// AuthResetCommand configures the command name, flags, and action.
|
// AuthResetCommand configures the command name, flags, and action.
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ func TestAuthResetCommand(t *testing.T) {
|
|||||||
output, err := RunWithTestContext(AuthResetCommand, []string{"reset"})
|
output, err := RunWithTestContext(AuthResetCommand, []string{"reset"})
|
||||||
|
|
||||||
// Check command output for plausibility.
|
// Check command output for plausibility.
|
||||||
//t.Logf(output)
|
// t.Logf(output)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Empty(t, output)
|
assert.Empty(t, output)
|
||||||
|
|
||||||
|
|||||||
@@ -23,10 +23,11 @@ const (
|
|||||||
ClientRegenerateSecret = "set a new randomly generated client secret"
|
ClientRegenerateSecret = "set a new randomly generated client secret"
|
||||||
ClientEnable = "enable client authentication if disabled"
|
ClientEnable = "enable client authentication if disabled"
|
||||||
ClientDisable = "disable client authentication"
|
ClientDisable = "disable client authentication"
|
||||||
ClientSecretInfo = "\nPLEASE WRITE DOWN THE %s CLIENT SECRET, AS YOU WILL NOT BE ABLE TO SEE IT AGAIN:"
|
ClientSecretInfo = "\nPLEASE WRITE DOWN THE %s CLIENT SECRET, AS YOU WILL NOT BE ABLE TO SEE IT AGAIN:" //nolint:gosec // informational message only
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
// ClientRoleUsage describes allowed client roles for CLI help.
|
||||||
ClientRoleUsage = fmt.Sprintf("client authorization `ROLE`, e.g. %s", acl.ClientRoles.CliUsageString())
|
ClientRoleUsage = fmt.Sprintf("client authorization `ROLE`, e.g. %s", acl.ClientRoles.CliUsageString())
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -35,9 +35,7 @@ func clientsModAction(ctx *cli.Context) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Find client record.
|
// Find client record.
|
||||||
var client *entity.Client
|
client := entity.FindClientByUID(frm.ID())
|
||||||
|
|
||||||
client = entity.FindClientByUID(frm.ID())
|
|
||||||
|
|
||||||
if client == nil {
|
if client == nil {
|
||||||
return fmt.Errorf("client %s not found", clean.Log(frm.ID()))
|
return fmt.Errorf("client %s not found", clean.Log(frm.ID()))
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ func TestClientsModCommand(t *testing.T) {
|
|||||||
output0, err := RunWithTestContext(ClientsShowCommand, []string{"show", "cs7pvt5h8rw9aaqj"})
|
output0, err := RunWithTestContext(ClientsShowCommand, []string{"show", "cs7pvt5h8rw9aaqj"})
|
||||||
|
|
||||||
// Check command output for plausibility.
|
// Check command output for plausibility.
|
||||||
//t.Logf(output0)
|
// t.Logf(output0)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Contains(t, output0, "AuthEnabled │ true")
|
assert.Contains(t, output0, "AuthEnabled │ true")
|
||||||
assert.Contains(t, output0, "oauth2")
|
assert.Contains(t, output0, "oauth2")
|
||||||
@@ -28,7 +28,7 @@ func TestClientsModCommand(t *testing.T) {
|
|||||||
output, err := RunWithTestContext(ClientsModCommand, []string{"mod", "--disable", "cs7pvt5h8rw9aaqj"})
|
output, err := RunWithTestContext(ClientsModCommand, []string{"mod", "--disable", "cs7pvt5h8rw9aaqj"})
|
||||||
|
|
||||||
// Check command output for plausibility.
|
// Check command output for plausibility.
|
||||||
//t.Logf(output)
|
// t.Logf(output)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Empty(t, output)
|
assert.Empty(t, output)
|
||||||
|
|
||||||
@@ -36,7 +36,7 @@ func TestClientsModCommand(t *testing.T) {
|
|||||||
output1, err := RunWithTestContext(ClientsShowCommand, []string{"show", "cs7pvt5h8rw9aaqj"})
|
output1, err := RunWithTestContext(ClientsShowCommand, []string{"show", "cs7pvt5h8rw9aaqj"})
|
||||||
|
|
||||||
// Check command output for plausibility.
|
// Check command output for plausibility.
|
||||||
//t.Logf(output1)
|
// t.Logf(output1)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Contains(t, output1, "AuthEnabled │ false")
|
assert.Contains(t, output1, "AuthEnabled │ false")
|
||||||
|
|
||||||
@@ -51,7 +51,7 @@ func TestClientsModCommand(t *testing.T) {
|
|||||||
output3, err := RunWithTestContext(ClientsShowCommand, []string{"show", "cs7pvt5h8rw9aaqj"})
|
output3, err := RunWithTestContext(ClientsShowCommand, []string{"show", "cs7pvt5h8rw9aaqj"})
|
||||||
|
|
||||||
// Check command output for plausibility.
|
// Check command output for plausibility.
|
||||||
//t.Logf(output3)
|
// t.Logf(output3)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Contains(t, output3, "│ AuthEnabled │ true ")
|
assert.Contains(t, output3, "│ AuthEnabled │ true ")
|
||||||
})
|
})
|
||||||
@@ -60,7 +60,7 @@ func TestClientsModCommand(t *testing.T) {
|
|||||||
output, err := RunWithTestContext(ClientsModCommand, []string{"mod", "--regenerate", "cs7pvt5h8rw9aaqj"})
|
output, err := RunWithTestContext(ClientsModCommand, []string{"mod", "--regenerate", "cs7pvt5h8rw9aaqj"})
|
||||||
|
|
||||||
// Check command output for plausibility.
|
// Check command output for plausibility.
|
||||||
//t.Logf(output)
|
// t.Logf(output)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Contains(t, output, "Client Secret")
|
assert.Contains(t, output, "Client Secret")
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -40,9 +40,7 @@ func clientsRemoveAction(ctx *cli.Context) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Find client record.
|
// Find client record.
|
||||||
var m *entity.Client
|
m := entity.FindClientByUID(id)
|
||||||
|
|
||||||
m = entity.FindClientByUID(id)
|
|
||||||
|
|
||||||
if m == nil {
|
if m == nil {
|
||||||
return fmt.Errorf("client %s not found", clean.Log(id))
|
return fmt.Errorf("client %s not found", clean.Log(id))
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ func TestCientsRemoveCommand(t *testing.T) {
|
|||||||
// Run command with test context.
|
// Run command with test context.
|
||||||
output0, err := RunWithTestContext(ClientsShowCommand, []string{"show", "cs7pvt5h8rw9aaqj"})
|
output0, err := RunWithTestContext(ClientsShowCommand, []string{"show", "cs7pvt5h8rw9aaqj"})
|
||||||
|
|
||||||
//t.Logf(output0)
|
// t.Logf(output0)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.NotContains(t, output0, "not found")
|
assert.NotContains(t, output0, "not found")
|
||||||
assert.Contains(t, output0, "client")
|
assert.Contains(t, output0, "client")
|
||||||
@@ -20,14 +20,14 @@ func TestCientsRemoveCommand(t *testing.T) {
|
|||||||
output, err := RunWithTestContext(ClientsRemoveCommand, []string{"rm", "cs7pvt5h8rw9aaqj"})
|
output, err := RunWithTestContext(ClientsRemoveCommand, []string{"rm", "cs7pvt5h8rw9aaqj"})
|
||||||
|
|
||||||
// Check command output for plausibility.
|
// Check command output for plausibility.
|
||||||
//t.Logf(output)
|
// t.Logf(output)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Empty(t, output)
|
assert.Empty(t, output)
|
||||||
|
|
||||||
// Run command with test context.
|
// Run command with test context.
|
||||||
output2, err := RunWithTestContext(ClientsShowCommand, []string{"show", "cs7pvt5h8rw9aaqj"})
|
output2, err := RunWithTestContext(ClientsShowCommand, []string{"show", "cs7pvt5h8rw9aaqj"})
|
||||||
|
|
||||||
//t.Logf(output2)
|
// t.Logf(output2)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.NotContains(t, output2, "not found")
|
assert.NotContains(t, output2, "not found")
|
||||||
assert.Contains(t, output2, "client")
|
assert.Contains(t, output2, "client")
|
||||||
@@ -36,7 +36,7 @@ func TestCientsRemoveCommand(t *testing.T) {
|
|||||||
// Run command with test context.
|
// Run command with test context.
|
||||||
output0, err := RunWithTestContext(ClientsShowCommand, []string{"show", "cs7pvt5h8rw9aaqj"})
|
output0, err := RunWithTestContext(ClientsShowCommand, []string{"show", "cs7pvt5h8rw9aaqj"})
|
||||||
|
|
||||||
//t.Logf(output0)
|
// t.Logf(output0)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.NotContains(t, output0, "not found")
|
assert.NotContains(t, output0, "not found")
|
||||||
assert.Contains(t, output0, "client")
|
assert.Contains(t, output0, "client")
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ func TestClientsResetCommand(t *testing.T) {
|
|||||||
output, err := RunWithTestContext(ClientsResetCommand, []string{"reset"})
|
output, err := RunWithTestContext(ClientsResetCommand, []string{"reset"})
|
||||||
|
|
||||||
// Check command output for plausibility.
|
// Check command output for plausibility.
|
||||||
//t.Logf(output)
|
// t.Logf(output)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Empty(t, output)
|
assert.Empty(t, output)
|
||||||
|
|
||||||
|
|||||||
@@ -31,9 +31,7 @@ func clientsShowAction(ctx *cli.Context) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Find client record.
|
// Find client record.
|
||||||
var m *entity.Client
|
m := entity.FindClientByUID(id)
|
||||||
|
|
||||||
m = entity.FindClientByUID(id)
|
|
||||||
|
|
||||||
if m == nil {
|
if m == nil {
|
||||||
return fmt.Errorf("client %s not found", clean.Log(id))
|
return fmt.Errorf("client %s not found", clean.Log(id))
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ func TestClientsShowCommand(t *testing.T) {
|
|||||||
output, err := RunWithTestContext(ClientsShowCommand, []string{"show", "cs5gfen1bgxz7s9i"})
|
output, err := RunWithTestContext(ClientsShowCommand, []string{"show", "cs5gfen1bgxz7s9i"})
|
||||||
|
|
||||||
// Check command output for plausibility.
|
// Check command output for plausibility.
|
||||||
//t.Logf(output)
|
// t.Logf(output)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Contains(t, output, "Alice")
|
assert.Contains(t, output, "Alice")
|
||||||
assert.Contains(t, output, "oauth2")
|
assert.Contains(t, output, "oauth2")
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ func clusterNodesListAction(ctx *cli.Context) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Pagination identical to API defaults.
|
// Pagination identical to API defaults.
|
||||||
count := int(ctx.Uint("count"))
|
count := int(ctx.Uint("count")) //nolint:gosec // CLI flag bounded by validation
|
||||||
if count <= 0 || count > 1000 {
|
if count <= 0 || count > 1000 {
|
||||||
count = 100
|
count = 100
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -216,11 +216,12 @@ func clusterNodesRotateAction(ctx *cli.Context) error {
|
|||||||
|
|
||||||
if (resp.Secrets != nil && resp.Secrets.ClientSecret != "") || resp.Database.Password != "" {
|
if (resp.Secrets != nil && resp.Secrets.ClientSecret != "") || resp.Database.Password != "" {
|
||||||
fmt.Println("PLEASE WRITE DOWN THE FOLLOWING CREDENTIALS; THEY WILL NOT BE SHOWN AGAIN:")
|
fmt.Println("PLEASE WRITE DOWN THE FOLLOWING CREDENTIALS; THEY WILL NOT BE SHOWN AGAIN:")
|
||||||
if resp.Secrets != nil && resp.Secrets.ClientSecret != "" && resp.Database.Password != "" {
|
switch {
|
||||||
|
case resp.Secrets != nil && resp.Secrets.ClientSecret != "" && resp.Database.Password != "":
|
||||||
fmt.Printf("\n%s\n", report.Credentials("Node Client Secret", resp.Secrets.ClientSecret, "DB Password", resp.Database.Password))
|
fmt.Printf("\n%s\n", report.Credentials("Node Client Secret", resp.Secrets.ClientSecret, "DB Password", resp.Database.Password))
|
||||||
} else if resp.Secrets != nil && resp.Secrets.ClientSecret != "" {
|
case resp.Secrets != nil && resp.Secrets.ClientSecret != "":
|
||||||
fmt.Printf("\n%s\n", report.Credentials("Node Client Secret", resp.Secrets.ClientSecret, "", ""))
|
fmt.Printf("\n%s\n", report.Credentials("Node Client Secret", resp.Secrets.ClientSecret, "", ""))
|
||||||
} else if resp.Database.Password != "" {
|
case resp.Database.Password != "":
|
||||||
fmt.Printf("\n%s\n", report.Credentials("DB User", resp.Database.User, "DB Password", resp.Database.Password))
|
fmt.Printf("\n%s\n", report.Credentials("DB User", resp.Database.User, "DB Password", resp.Database.Password))
|
||||||
}
|
}
|
||||||
if resp.Database.DSN != "" {
|
if resp.Database.DSN != "" {
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ var (
|
|||||||
var ClusterRegisterCommand = &cli.Command{
|
var ClusterRegisterCommand = &cli.Command{
|
||||||
Name: "register",
|
Name: "register",
|
||||||
Usage: "Registers a node or updates its credentials within a cluster",
|
Usage: "Registers a node or updates its credentials within a cluster",
|
||||||
Flags: append(append([]cli.Flag{
|
Flags: append([]cli.Flag{
|
||||||
regDryRun,
|
regDryRun,
|
||||||
regNameFlag,
|
regNameFlag,
|
||||||
regRoleFlag,
|
regRoleFlag,
|
||||||
@@ -68,7 +68,7 @@ var ClusterRegisterCommand = &cli.Command{
|
|||||||
regRotateSec,
|
regRotateSec,
|
||||||
regWriteConf,
|
regWriteConf,
|
||||||
regForceFlag,
|
regForceFlag,
|
||||||
}, report.CliFlags...)),
|
}, report.CliFlags...),
|
||||||
Action: clusterRegisterAction,
|
Action: clusterRegisterAction,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -320,22 +320,18 @@ func unzipSafe(zipPath, dest string) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
defer rc.Close()
|
||||||
|
|
||||||
// Create/truncate target
|
// Create/truncate target
|
||||||
out, err := os.OpenFile(target, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, f.Mode())
|
out, err := os.OpenFile(target, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, f.Mode()) //nolint:gosec // paths derived from zip entries validated earlier
|
||||||
if err != nil {
|
if err != nil {
|
||||||
rc.Close()
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
defer out.Close()
|
||||||
|
|
||||||
if _, err := io.Copy(out, rc); err != nil {
|
if _, err := io.Copy(out, rc); err != nil { //nolint:gosec // zip entries size is bounded by upstream
|
||||||
out.Close()
|
|
||||||
rc.Close()
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
out.Close()
|
|
||||||
rc.Close()
|
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ import (
|
|||||||
"github.com/photoprism/photoprism/pkg/fs"
|
"github.com/photoprism/photoprism/pkg/fs"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// NONINTERACTIVE is the CLI environment flag to disable prompts.
|
||||||
const NONINTERACTIVE = "noninteractive"
|
const NONINTERACTIVE = "noninteractive"
|
||||||
|
|
||||||
var log = event.Log
|
var log = event.Log
|
||||||
|
|||||||
@@ -160,9 +160,10 @@ func downloadAction(ctx *cli.Context) error {
|
|||||||
|
|
||||||
impersonate := strings.ToLower(strings.TrimSpace(ctx.String("impersonate")))
|
impersonate := strings.ToLower(strings.TrimSpace(ctx.String("impersonate")))
|
||||||
|
|
||||||
if impersonate == "" {
|
switch impersonate {
|
||||||
|
case "":
|
||||||
impersonate = "firefox"
|
impersonate = "firefox"
|
||||||
} else if impersonate == "none" {
|
case "none":
|
||||||
impersonate = ""
|
impersonate = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -282,14 +283,14 @@ func downloadAction(ctx *cli.Context) error {
|
|||||||
}
|
}
|
||||||
func() {
|
func() {
|
||||||
defer downloadResult.Close()
|
defer downloadResult.Close()
|
||||||
f, ferr := os.Create(downloadFilePath)
|
f, ferr := os.Create(downloadFilePath) //nolint:gosec // download target path chosen by user
|
||||||
if ferr != nil {
|
if ferr != nil {
|
||||||
log.Errorf("create file failed: %v", ferr)
|
log.Errorf("create file failed: %v", ferr)
|
||||||
failures++
|
failures++
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
defer f.Close()
|
||||||
if _, cerr := io.Copy(f, downloadResult); cerr != nil {
|
if _, cerr := io.Copy(f, downloadResult); cerr != nil {
|
||||||
_ = f.Close()
|
|
||||||
log.Errorf("write file failed: %v", cerr)
|
log.Errorf("write file failed: %v", cerr)
|
||||||
failures++
|
failures++
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ func createArgsLoggingYtDlp(t *testing.T) string {
|
|||||||
b.WriteString(" if \"%%~A\"==\"--version\" ( echo 2025.09.23 & goto :eof )\r\n")
|
b.WriteString(" if \"%%~A\"==\"--version\" ( echo 2025.09.23 & goto :eof )\r\n")
|
||||||
b.WriteString(" if \"%%~A\"==\"--dump-single-json\" ( echo {\"id\":\"abc\",\"title\":\"Test\",\"url\":\"http://example.com\",\"_type\":\"video\"} & goto :eof )\r\n")
|
b.WriteString(" if \"%%~A\"==\"--dump-single-json\" ( echo {\"id\":\"abc\",\"title\":\"Test\",\"url\":\"http://example.com\",\"_type\":\"video\"} & goto :eof )\r\n")
|
||||||
b.WriteString(")\r\n")
|
b.WriteString(")\r\n")
|
||||||
if err := os.WriteFile(path, []byte(b.String()), 0o755); err != nil {
|
if err := os.WriteFile(path, []byte(b.String()), 0o600); err != nil {
|
||||||
t.Fatalf("failed to write fake yt-dlp: %v", err)
|
t.Fatalf("failed to write fake yt-dlp: %v", err)
|
||||||
}
|
}
|
||||||
return path
|
return path
|
||||||
@@ -44,7 +44,7 @@ func createArgsLoggingYtDlp(t *testing.T) string {
|
|||||||
b.WriteString("echo '[download]' 1>&2\n")
|
b.WriteString("echo '[download]' 1>&2\n")
|
||||||
b.WriteString("echo 'DATA'\n")
|
b.WriteString("echo 'DATA'\n")
|
||||||
|
|
||||||
if err := os.WriteFile(path, []byte(b.String()), 0o755); err != nil {
|
if err := os.WriteFile(path, []byte(b.String()), 0o600); err != nil {
|
||||||
t.Fatalf("failed to write fake yt-dlp: %v", err)
|
t.Fatalf("failed to write fake yt-dlp: %v", err)
|
||||||
}
|
}
|
||||||
return path
|
return path
|
||||||
@@ -98,7 +98,7 @@ func TestRunDownload_FileMethod_OmitsFormatSort(t *testing.T) {
|
|||||||
// Give the logging script a moment to flush in slower environments.
|
// Give the logging script a moment to flush in slower environments.
|
||||||
time.Sleep(20 * time.Millisecond)
|
time.Sleep(20 * time.Millisecond)
|
||||||
|
|
||||||
data, err := os.ReadFile(argsLog)
|
data, err := os.ReadFile(argsLog) //nolint:gosec // test temp file
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("reading args log failed: %v", err)
|
t.Fatalf("reading args log failed: %v", err)
|
||||||
}
|
}
|
||||||
@@ -157,7 +157,7 @@ func TestRunDownload_FileMethod_WithFormatSort(t *testing.T) {
|
|||||||
|
|
||||||
time.Sleep(20 * time.Millisecond)
|
time.Sleep(20 * time.Millisecond)
|
||||||
|
|
||||||
data, err := os.ReadFile(argsLog)
|
data, err := os.ReadFile(argsLog) //nolint:gosec // test temp file
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("reading args log failed: %v", err)
|
t.Fatalf("reading args log failed: %v", err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -184,7 +184,7 @@ func runDownload(conf *config.Config, opts DownloadOpts, inputURLs []string) err
|
|||||||
}
|
}
|
||||||
func() {
|
func() {
|
||||||
defer downloadResult.Close()
|
defer downloadResult.Close()
|
||||||
f, ferr := os.Create(downloadFilePath)
|
f, ferr := os.Create(downloadFilePath) //nolint:gosec // download target path chosen by user
|
||||||
if ferr != nil {
|
if ferr != nil {
|
||||||
log.Errorf("create file failed: %v", ferr)
|
log.Errorf("create file failed: %v", ferr)
|
||||||
failures++
|
failures++
|
||||||
|
|||||||
@@ -74,7 +74,11 @@ func findAction(ctx *cli.Context) error {
|
|||||||
rows := make([][]string, 0, len(results))
|
rows := make([][]string, 0, len(results))
|
||||||
|
|
||||||
for _, found := range results {
|
for _, found := range results {
|
||||||
v := []string{found.FileName, found.FileMime, humanize.Bytes(uint64(found.FileSize)), found.FileHash}
|
size := found.FileSize
|
||||||
|
if size < 0 {
|
||||||
|
size = 0
|
||||||
|
}
|
||||||
|
v := []string{found.FileName, found.FileMime, humanize.Bytes(uint64(size)), found.FileHash} //nolint:gosec // size non-negative after check
|
||||||
rows = append(rows, v)
|
rows = append(rows, v)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ func TestFindCommand(t *testing.T) {
|
|||||||
output, err := RunWithTestContext(FindCommand, []string{"find", "--csv"})
|
output, err := RunWithTestContext(FindCommand, []string{"find", "--csv"})
|
||||||
|
|
||||||
// Check command output for plausibility.
|
// Check command output for plausibility.
|
||||||
//t.Logf(output)
|
// t.Logf(output)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Contains(t, output, "File Name;Mime Type;")
|
assert.Contains(t, output, "File Name;Mime Type;")
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import (
|
|||||||
"github.com/photoprism/photoprism/pkg/txt/report"
|
"github.com/photoprism/photoprism/pkg/txt/report"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// MigrationsStatusCommand lists migration status.
|
||||||
var MigrationsStatusCommand = &cli.Command{
|
var MigrationsStatusCommand = &cli.Command{
|
||||||
Name: "ls",
|
Name: "ls",
|
||||||
Aliases: []string{"status", "show"},
|
Aliases: []string{"status", "show"},
|
||||||
@@ -25,6 +26,7 @@ var MigrationsStatusCommand = &cli.Command{
|
|||||||
Action: migrationsStatusAction,
|
Action: migrationsStatusAction,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MigrationsRunCommand runs pending migrations.
|
||||||
var MigrationsRunCommand = &cli.Command{
|
var MigrationsRunCommand = &cli.Command{
|
||||||
Name: "run",
|
Name: "run",
|
||||||
Aliases: []string{"execute", "migrate"},
|
Aliases: []string{"execute", "migrate"},
|
||||||
@@ -110,15 +112,16 @@ func migrationsStatusAction(ctx *cli.Context) error {
|
|||||||
finished = "-"
|
finished = "-"
|
||||||
}
|
}
|
||||||
|
|
||||||
if m.Error != "" {
|
switch {
|
||||||
|
case m.Error != "":
|
||||||
info = m.Error
|
info = m.Error
|
||||||
} else if m.Finished() {
|
case m.Finished():
|
||||||
info = "OK"
|
info = "OK"
|
||||||
} else if m.StartedAt.IsZero() {
|
case m.StartedAt.IsZero():
|
||||||
info = "-"
|
info = "-"
|
||||||
} else if m.Repeat(false) {
|
case m.Repeat(false):
|
||||||
info = "Repeat"
|
info = "Repeat"
|
||||||
} else {
|
default:
|
||||||
info = "Running?"
|
info = "Running?"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -131,12 +131,12 @@ func termEcho(on bool) {
|
|||||||
Sys: nil}
|
Sys: nil}
|
||||||
var ws syscall.WaitStatus
|
var ws syscall.WaitStatus
|
||||||
cmd := "echo"
|
cmd := "echo"
|
||||||
if on == false {
|
if !on {
|
||||||
cmd = "-echo"
|
cmd = "-echo"
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enable/disable echoing.
|
// Enable/disable echoing.
|
||||||
pid, err := syscall.ForkExec(
|
pid, err := syscall.ForkExec( //nolint:gosec // uses fixed binary and arguments
|
||||||
"/bin/stty",
|
"/bin/stty",
|
||||||
[]string{"stty", cmd},
|
[]string{"stty", cmd},
|
||||||
&attrs)
|
&attrs)
|
||||||
|
|||||||
@@ -65,9 +65,10 @@ func showConfigAction(ctx *cli.Context) error {
|
|||||||
rows, cols := rep.Report(conf)
|
rows, cols := rep.Report(conf)
|
||||||
opt := report.Options{Format: format, NoWrap: rep.NoWrap}
|
opt := report.Options{Format: format, NoWrap: rep.NoWrap}
|
||||||
result, _ := report.Render(rows, cols, opt)
|
result, _ := report.Render(rows, cols, opt)
|
||||||
if opt.Format == report.Markdown {
|
switch opt.Format {
|
||||||
|
case report.Markdown:
|
||||||
fmt.Printf("### %s\n\n", rep.Title)
|
fmt.Printf("### %s\n\n", rep.Title)
|
||||||
} else if opt.Format == report.Default {
|
case report.Default:
|
||||||
fmt.Printf("%s\n\n", strings.ToUpper(rep.Title))
|
fmt.Printf("%s\n\n", strings.ToUpper(rep.Title))
|
||||||
}
|
}
|
||||||
fmt.Println(result)
|
fmt.Println(result)
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import (
|
|||||||
var ShowScopesCommand = &cli.Command{
|
var ShowScopesCommand = &cli.Command{
|
||||||
Name: "scopes",
|
Name: "scopes",
|
||||||
Usage: "Displays supported authorization scopes",
|
Usage: "Displays supported authorization scopes",
|
||||||
Flags: append(report.CliFlags),
|
Flags: report.CliFlags,
|
||||||
Action: showScopesAction,
|
Action: showScopesAction,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import (
|
|||||||
var ShowSourcesCommand = &cli.Command{
|
var ShowSourcesCommand = &cli.Command{
|
||||||
Name: "sources",
|
Name: "sources",
|
||||||
Usage: "Displays supported metadata sources and their priorities",
|
Usage: "Displays supported metadata sources and their priorities",
|
||||||
Flags: append(report.CliFlags),
|
Flags: report.CliFlags,
|
||||||
Action: showSourcesAction,
|
Action: showSourcesAction,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ func statusAction(ctx *cli.Context) error {
|
|||||||
if resp, reqErr := client.Do(req); reqErr != nil {
|
if resp, reqErr := client.Do(req); reqErr != nil {
|
||||||
return fmt.Errorf("cannot connect to %s:%d", conf.HttpHost(), conf.HttpPort())
|
return fmt.Errorf("cannot connect to %s:%d", conf.HttpHost(), conf.HttpPort())
|
||||||
} else if resp.StatusCode != 200 {
|
} else if resp.StatusCode != 200 {
|
||||||
return fmt.Errorf("server running at %s:%d, bad status %d\n", conf.HttpHost(), conf.HttpPort(), resp.StatusCode)
|
return fmt.Errorf("server running at %s:%d, bad status %d", conf.HttpHost(), conf.HttpPort(), resp.StatusCode)
|
||||||
} else if body, readErr := io.ReadAll(resp.Body); readErr != nil {
|
} else if body, readErr := io.ReadAll(resp.Body); readErr != nil {
|
||||||
return readErr
|
return readErr
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
// UserRoleUsage describes allowed user roles for CLI help.
|
||||||
UserRoleUsage = fmt.Sprintf("user account `ROLE`, e.g. %s", acl.UserRoles.CliUsageString())
|
UserRoleUsage = fmt.Sprintf("user account `ROLE`, e.g. %s", acl.UserRoles.CliUsageString())
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -134,10 +134,6 @@ func usersAddAction(ctx *cli.Context) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := entity.AddUser(frm); err != nil {
|
return entity.AddUser(frm)
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ func TestUsersLegacyCommand(t *testing.T) {
|
|||||||
output, err := RunWithTestContext(UsersLegacyCommand, []string{""})
|
output, err := RunWithTestContext(UsersLegacyCommand, []string{""})
|
||||||
|
|
||||||
// Check command output for plausibility.
|
// Check command output for plausibility.
|
||||||
//t.Logf(output)
|
// t.Logf(output)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Contains(t, output, "│ ID │ UID │ Name │ User │ Email │ Admin │ Created At │")
|
assert.Contains(t, output, "│ ID │ UID │ Name │ User │ Email │ Admin │ Created At │")
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import (
|
|||||||
"github.com/photoprism/photoprism/internal/entity"
|
"github.com/photoprism/photoprism/internal/entity"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// UsersResetDescription explains the effect of the users reset command.
|
||||||
const UsersResetDescription = "This command recreates the session and user management database tables so that they are compatible with the current version. Should you experience login problems, for example after an upgrade from an earlier version or a development preview, we recommend that you first try the \"photoprism auth reset --yes\" command to see if it solves the issue. Note that any client access tokens and app passwords that users may have created are also deleted and must be recreated."
|
const UsersResetDescription = "This command recreates the session and user management database tables so that they are compatible with the current version. Should you experience login problems, for example after an upgrade from an earlier version or a development preview, we recommend that you first try the \"photoprism auth reset --yes\" command to see if it solves the issue. Note that any client access tokens and app passwords that users may have created are also deleted and must be recreated."
|
||||||
|
|
||||||
// UsersResetCommand configures the command name, flags, and action.
|
// UsersResetCommand configures the command name, flags, and action.
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ func TestUsersResetCommand(t *testing.T) {
|
|||||||
output, err := RunWithTestContext(UsersResetCommand, []string{"reset"})
|
output, err := RunWithTestContext(UsersResetCommand, []string{"reset"})
|
||||||
|
|
||||||
// Check command output for plausibility.
|
// Check command output for plausibility.
|
||||||
//t.Logf(output)
|
// t.Logf(output)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Empty(t, output)
|
assert.Empty(t, output)
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ func TestUsersShowCommand(t *testing.T) {
|
|||||||
output, err := RunWithTestContext(UsersShowCommand, []string{"show", "alice"})
|
output, err := RunWithTestContext(UsersShowCommand, []string{"show", "alice"})
|
||||||
|
|
||||||
// Check command output for plausibility.
|
// Check command output for plausibility.
|
||||||
//t.Logf(output)
|
// t.Logf(output)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Contains(t, output, "Alice")
|
assert.Contains(t, output, "Alice")
|
||||||
assert.Contains(t, output, "admin")
|
assert.Contains(t, output, "admin")
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ func TestUsersCommand(t *testing.T) {
|
|||||||
// Run command with test context.
|
// Run command with test context.
|
||||||
output2, err := RunWithTestContext(UsersShowCommand, []string{"show", "john.admin"})
|
output2, err := RunWithTestContext(UsersShowCommand, []string{"show", "john.admin"})
|
||||||
|
|
||||||
//t.Logf(output2)
|
// t.Logf(output2)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Contains(t, output2, "John")
|
assert.Contains(t, output2, "John")
|
||||||
assert.Contains(t, output2, "admin")
|
assert.Contains(t, output2, "admin")
|
||||||
@@ -38,7 +38,7 @@ func TestUsersCommand(t *testing.T) {
|
|||||||
// Run command with test context.
|
// Run command with test context.
|
||||||
output4, err := RunWithTestContext(UsersShowCommand, []string{"show", "john.admin"})
|
output4, err := RunWithTestContext(UsersShowCommand, []string{"show", "john.admin"})
|
||||||
|
|
||||||
//t.Logf(output4)
|
// t.Logf(output4)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Contains(t, output4, "Johnny")
|
assert.Contains(t, output4, "Johnny")
|
||||||
assert.Contains(t, output4, "admin")
|
assert.Contains(t, output4, "admin")
|
||||||
@@ -57,7 +57,7 @@ func TestUsersCommand(t *testing.T) {
|
|||||||
// Run command with test context.
|
// Run command with test context.
|
||||||
output6, err := RunWithTestContext(UsersShowCommand, []string{"show", "john.admin"})
|
output6, err := RunWithTestContext(UsersShowCommand, []string{"show", "john.admin"})
|
||||||
|
|
||||||
//t.Logf(output6)
|
// t.Logf(output6)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Contains(t, output6, "Johnny")
|
assert.Contains(t, output6, "Johnny")
|
||||||
assert.Contains(t, output6, "admin")
|
assert.Contains(t, output6, "admin")
|
||||||
|
|||||||
@@ -23,6 +23,6 @@ var VisionCommands = &cli.Command{
|
|||||||
var VisionSourcesCommand = &cli.Command{
|
var VisionSourcesCommand = &cli.Command{
|
||||||
Name: "sources",
|
Name: "sources",
|
||||||
Usage: "Displays supported metadata sources and their priorities",
|
Usage: "Displays supported metadata sources and their priorities",
|
||||||
Flags: append(report.CliFlags),
|
Flags: report.CliFlags,
|
||||||
Action: showSourcesAction,
|
Action: showSourcesAction,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ import (
|
|||||||
var VisionListCommand = &cli.Command{
|
var VisionListCommand = &cli.Command{
|
||||||
Name: "ls",
|
Name: "ls",
|
||||||
Usage: "Lists the configured computer vision models",
|
Usage: "Lists the configured computer vision models",
|
||||||
Flags: append(report.CliFlags),
|
Flags: report.CliFlags,
|
||||||
Action: visionListAction,
|
Action: visionListAction,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user