Files
photoprism/internal/commands/auth_jwt_keys.go
2025-09-26 02:38:49 +02:00

108 lines
2.4 KiB
Go

package commands
import (
"errors"
"fmt"
"strings"
"time"
"github.com/urfave/cli/v2"
"github.com/photoprism/photoprism/internal/config"
"github.com/photoprism/photoprism/internal/photoprism/get"
)
// AuthJWTKeysCommand groups JWT key management helpers.
var AuthJWTKeysCommand = &cli.Command{
Name: "keys",
Usage: "JWT signing key helpers",
Subcommands: []*cli.Command{
AuthJWTKeysListCommand,
},
}
// AuthJWTKeysListCommand lists JWT signing keys.
var AuthJWTKeysListCommand = &cli.Command{
Name: "ls",
Usage: "Lists JWT signing keys",
Aliases: []string{"list"},
ArgsUsage: "",
Flags: []cli.Flag{
JsonFlag(),
},
Action: authJWTKeysListAction,
}
// authJWTKeysListAction lists portal signing keys with metadata.
func authJWTKeysListAction(ctx *cli.Context) error {
return CallWithDependencies(ctx, func(conf *config.Config) error {
if err := requirePortal(conf); err != nil {
return err
}
manager := get.JWTManager()
if manager == nil {
return cli.Exit(errors.New("jwt manager not available"), 1)
}
keys := manager.AllKeys()
active, _ := manager.ActiveKey()
activeKid := ""
if active != nil {
activeKid = active.Kid
}
type keyInfo struct {
Kid string `json:"kid"`
CreatedAt string `json:"createdAt"`
NotAfter string `json:"notAfter,omitempty"`
Active bool `json:"active"`
}
rows := make([]keyInfo, 0, len(keys))
for _, k := range keys {
info := keyInfo{Kid: k.Kid, Active: k.Kid == activeKid}
if k.CreatedAt > 0 {
info.CreatedAt = time.Unix(k.CreatedAt, 0).UTC().Format(time.RFC3339)
}
if k.NotAfter > 0 {
info.NotAfter = time.Unix(k.NotAfter, 0).UTC().Format(time.RFC3339)
}
rows = append(rows, info)
}
if ctx.Bool("json") {
payload := map[string]any{
"keys": rows,
}
return printJSON(payload)
}
if len(rows) == 0 {
fmt.Println()
fmt.Println("No signing keys found.")
fmt.Println()
return nil
}
fmt.Println()
fmt.Println("JWT signing keys:")
for _, row := range rows {
status := ""
if row.Active {
status = " (active)"
}
parts := []string{fmt.Sprintf("KID: %s%s", row.Kid, status)}
if row.CreatedAt != "" {
parts = append(parts, fmt.Sprintf("created %s", row.CreatedAt))
}
if row.NotAfter != "" {
parts = append(parts, fmt.Sprintf("expires %s", row.NotAfter))
}
fmt.Printf("- %s\n", strings.Join(parts, ", "))
}
fmt.Println()
return nil
})
}