this repo has no description
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat: add logger and identity gen

Signed-off-by: A. Ottr <alex@otter.foo>

A. Ottr c52e50dc 36fa2f58

+145 -5
+46 -5
cmd/nox/main.go
··· 3 3 import ( 4 4 "context" 5 5 "fmt" 6 - "log" 7 6 "os" 8 7 9 8 "github.com/aottr/nox/internal/config" 10 9 "github.com/aottr/nox/internal/constants" 10 + "github.com/aottr/nox/internal/crypto" 11 + "github.com/aottr/nox/internal/logging" 11 12 "github.com/aottr/nox/internal/processor" 12 13 "github.com/urfave/cli/v3" 13 14 ) 14 15 15 16 func main() { 17 + 18 + logging.Init() 19 + logging.SetLevel("info") 20 + log := logging.Get() 16 21 17 22 var configPath string 18 23 var statePath string ··· 95 100 Action: func(ctx context.Context, cmd *cli.Command) error { 96 101 fmt.Println("encrypting file", inputPath) 97 102 fmt.Println("writing to", outputPath) 98 - fmt.Println(cmd.StringSlice("recipient")) 103 + recipients, err := crypto.StringsToRecipients(cmd.StringSlice("recipient")) 104 + if err != nil { 105 + return err 106 + } 107 + out, err := crypto.EncryptFile(inputPath, recipients) 108 + if err != nil { 109 + return err 110 + } 111 + fmt.Println(string(out)) 112 + // priv, pub, err := crypto.GenerateAndWriteX25519Identity("test.key") 113 + // if err != nil { 114 + // return err 115 + // } 116 + // fmt.Println(priv) 117 + // fmt.Println(pub) 118 + 119 + return nil 120 + }, 121 + }, 122 + { 123 + Name: "generate", 124 + Flags: []cli.Flag{ 125 + &cli.StringFlag{ 126 + Name: "output", 127 + Usage: "path to output file", 128 + Aliases: []string{"o"}, 129 + Value: constants.StandardOutput, 130 + Destination: &outputPath, 131 + }, 132 + }, 133 + Action: func(ctx context.Context, cmd *cli.Command) error { 134 + priv, pub, err := crypto.GenerateIdentity(cmd.String("output")) 135 + if err != nil { 136 + return err 137 + } 138 + fmt.Println(priv) 139 + fmt.Println(pub) 99 140 return nil 100 141 }, 101 142 }, ··· 135 176 Verbose: verbose, 136 177 }) 137 178 if err != nil { 138 - log.Fatalf("failed to build runtime context: %v", err) 179 + log.Error("failed to build runtime context", "error", err.Error()) 139 180 } 140 181 if cmd.String("app") != "" { 141 182 return processor.SyncApp(rtx) ··· 154 195 IdentityPaths: identityPaths, 155 196 }) 156 197 if err != nil { 157 - log.Fatalf("failed to build runtime context: %v", err) 198 + log.Error("failed to build runtime context", "error", err.Error()) 158 199 } 159 200 return processor.ValidateConfig(rtx.Config) 160 201 }, ··· 163 204 } 164 205 165 206 if err := cmd.Run(context.Background(), os.Args); err != nil { 166 - log.Fatal(err) 207 + log.Error("failed to run command", "error", err.Error()) 167 208 } 168 209 }
+25
internal/crypto/identity.go
··· 4 4 "bytes" 5 5 "fmt" 6 6 "os" 7 + "path/filepath" 7 8 8 9 "filippo.io/age" 9 10 ) ··· 36 37 37 38 return allIdentities, nil 38 39 } 40 + 41 + func GenerateIdentity(path string) (priv string, pub string, err error) { 42 + id, err := age.GenerateX25519Identity() 43 + if err != nil { 44 + return "", "", fmt.Errorf("generate identity: %w", err) 45 + } 46 + 47 + priv = id.String() // "AGE-SECRET-KEY-1..." 48 + pub = id.Recipient().String() // "age1..." 49 + 50 + // ensure directory exists and apply permissions 51 + if err := os.MkdirAll(filepath.Dir(path), 0o700); err != nil { 52 + return "", "", fmt.Errorf("mkdir %s: %w", filepath.Dir(path), err) 53 + } 54 + if err := os.WriteFile(path, []byte(priv+"\n"), 0o600); err != nil { 55 + return "", "", fmt.Errorf("write identity: %w", err) 56 + } 57 + 58 + // write public key 59 + if err := os.WriteFile(path+".pub", []byte(pub+"\n"), 0o644); err != nil { 60 + return "", "", fmt.Errorf("write identity: %w", err) 61 + } 62 + return priv, pub, nil 63 + }
+27
internal/crypto/recipient.go
··· 1 + package crypto 2 + 3 + import ( 4 + "bytes" 5 + "fmt" 6 + "strings" 7 + 8 + "filippo.io/age" 9 + ) 10 + 11 + func StringsToRecipients(strs []string) ([]age.Recipient, error) { 12 + var b bytes.Buffer 13 + for _, s := range strs { 14 + s = strings.TrimSpace(s) 15 + if s == "" { 16 + continue 17 + } 18 + // age.ParseRecipients accepts multiple lines... 19 + b.WriteString(s) 20 + b.WriteByte('\n') 21 + } 22 + recips, err := age.ParseRecipients(&b) 23 + if err != nil { 24 + return nil, fmt.Errorf("parse recipients: %w", err) 25 + } 26 + return recips, nil 27 + }
+47
internal/logging/logger.go
··· 1 + package logging 2 + 3 + import ( 4 + "log/slog" 5 + "os" 6 + "strings" 7 + "sync" 8 + ) 9 + 10 + type Logger = *slog.Logger 11 + 12 + var ( 13 + once sync.Once 14 + logger *slog.Logger 15 + logLevel = &slog.LevelVar{} 16 + ) 17 + 18 + func Get() Logger { 19 + Init() 20 + return logger 21 + } 22 + 23 + func Init() { 24 + once.Do(func() { 25 + logLevel.Set(slog.LevelInfo) 26 + 27 + h := slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{ 28 + Level: logLevel, 29 + }) 30 + logger = slog.New(h) 31 + }) 32 + } 33 + 34 + func SetLevel(s string) { 35 + switch strings.ToLower(s) { 36 + case "debug": 37 + logLevel.Set(slog.LevelDebug) 38 + case "info": 39 + logLevel.Set(slog.LevelInfo) 40 + case "warn", "warning": 41 + logLevel.Set(slog.LevelWarn) 42 + case "error": 43 + logLevel.Set(slog.LevelError) 44 + default: 45 + logLevel.Set(slog.LevelInfo) 46 + } 47 + }