annotate cmd/sievemgr/internal/config/config.go @ 5:4dff4c3f0fbb

Introduce configuration file where account information is specified Introduce a configuration file where account information must be specified instead of passing it with each invocation on the command line. Each account has a name by which it can be selected and one may be specified as the default account. This is intended to improve usability for productive usage. Enforce strict permissions since passwords may be specified for non-interactive usage. Remove command-line flags for passing account information.
author Guido Berhoerster <guido+sievemgr@berhoerster.name>
date Tue, 03 Nov 2020 23:44:45 +0100
parents
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
5
4dff4c3f0fbb Introduce configuration file where account information is specified
Guido Berhoerster <guido+sievemgr@berhoerster.name>
parents:
diff changeset
1 // Copyright (C) 2020 Guido Berhoerster <guido+sievemgr@berhoerster.name>
4dff4c3f0fbb Introduce configuration file where account information is specified
Guido Berhoerster <guido+sievemgr@berhoerster.name>
parents:
diff changeset
2 //
4dff4c3f0fbb Introduce configuration file where account information is specified
Guido Berhoerster <guido+sievemgr@berhoerster.name>
parents:
diff changeset
3 // Permission is hereby granted, free of charge, to any person obtaining
4dff4c3f0fbb Introduce configuration file where account information is specified
Guido Berhoerster <guido+sievemgr@berhoerster.name>
parents:
diff changeset
4 // a copy of this software and associated documentation files (the
4dff4c3f0fbb Introduce configuration file where account information is specified
Guido Berhoerster <guido+sievemgr@berhoerster.name>
parents:
diff changeset
5 // "Software"), to deal in the Software without restriction, including
4dff4c3f0fbb Introduce configuration file where account information is specified
Guido Berhoerster <guido+sievemgr@berhoerster.name>
parents:
diff changeset
6 // without limitation the rights to use, copy, modify, merge, publish,
4dff4c3f0fbb Introduce configuration file where account information is specified
Guido Berhoerster <guido+sievemgr@berhoerster.name>
parents:
diff changeset
7 // distribute, sublicense, and/or sell copies of the Software, and to
4dff4c3f0fbb Introduce configuration file where account information is specified
Guido Berhoerster <guido+sievemgr@berhoerster.name>
parents:
diff changeset
8 // permit persons to whom the Software is furnished to do so, subject to
4dff4c3f0fbb Introduce configuration file where account information is specified
Guido Berhoerster <guido+sievemgr@berhoerster.name>
parents:
diff changeset
9 // the following conditions:
4dff4c3f0fbb Introduce configuration file where account information is specified
Guido Berhoerster <guido+sievemgr@berhoerster.name>
parents:
diff changeset
10 //
4dff4c3f0fbb Introduce configuration file where account information is specified
Guido Berhoerster <guido+sievemgr@berhoerster.name>
parents:
diff changeset
11 // The above copyright notice and this permission notice shall be included
4dff4c3f0fbb Introduce configuration file where account information is specified
Guido Berhoerster <guido+sievemgr@berhoerster.name>
parents:
diff changeset
12 // in all copies or substantial portions of the Software.
4dff4c3f0fbb Introduce configuration file where account information is specified
Guido Berhoerster <guido+sievemgr@berhoerster.name>
parents:
diff changeset
13 //
4dff4c3f0fbb Introduce configuration file where account information is specified
Guido Berhoerster <guido+sievemgr@berhoerster.name>
parents:
diff changeset
14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
4dff4c3f0fbb Introduce configuration file where account information is specified
Guido Berhoerster <guido+sievemgr@berhoerster.name>
parents:
diff changeset
15 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
4dff4c3f0fbb Introduce configuration file where account information is specified
Guido Berhoerster <guido+sievemgr@berhoerster.name>
parents:
diff changeset
16 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
4dff4c3f0fbb Introduce configuration file where account information is specified
Guido Berhoerster <guido+sievemgr@berhoerster.name>
parents:
diff changeset
17 // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
4dff4c3f0fbb Introduce configuration file where account information is specified
Guido Berhoerster <guido+sievemgr@berhoerster.name>
parents:
diff changeset
18 // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
4dff4c3f0fbb Introduce configuration file where account information is specified
Guido Berhoerster <guido+sievemgr@berhoerster.name>
parents:
diff changeset
19 // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
4dff4c3f0fbb Introduce configuration file where account information is specified
Guido Berhoerster <guido+sievemgr@berhoerster.name>
parents:
diff changeset
20 // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
4dff4c3f0fbb Introduce configuration file where account information is specified
Guido Berhoerster <guido+sievemgr@berhoerster.name>
parents:
diff changeset
21
4dff4c3f0fbb Introduce configuration file where account information is specified
Guido Berhoerster <guido+sievemgr@berhoerster.name>
parents:
diff changeset
22 package config
4dff4c3f0fbb Introduce configuration file where account information is specified
Guido Berhoerster <guido+sievemgr@berhoerster.name>
parents:
diff changeset
23
4dff4c3f0fbb Introduce configuration file where account information is specified
Guido Berhoerster <guido+sievemgr@berhoerster.name>
parents:
diff changeset
24 import (
4dff4c3f0fbb Introduce configuration file where account information is specified
Guido Berhoerster <guido+sievemgr@berhoerster.name>
parents:
diff changeset
25 "bufio"
4dff4c3f0fbb Introduce configuration file where account information is specified
Guido Berhoerster <guido+sievemgr@berhoerster.name>
parents:
diff changeset
26 "bytes"
4dff4c3f0fbb Introduce configuration file where account information is specified
Guido Berhoerster <guido+sievemgr@berhoerster.name>
parents:
diff changeset
27 "fmt"
4dff4c3f0fbb Introduce configuration file where account information is specified
Guido Berhoerster <guido+sievemgr@berhoerster.name>
parents:
diff changeset
28 "os"
4dff4c3f0fbb Introduce configuration file where account information is specified
Guido Berhoerster <guido+sievemgr@berhoerster.name>
parents:
diff changeset
29 "path/filepath"
4dff4c3f0fbb Introduce configuration file where account information is specified
Guido Berhoerster <guido+sievemgr@berhoerster.name>
parents:
diff changeset
30 )
4dff4c3f0fbb Introduce configuration file where account information is specified
Guido Berhoerster <guido+sievemgr@berhoerster.name>
parents:
diff changeset
31
4dff4c3f0fbb Introduce configuration file where account information is specified
Guido Berhoerster <guido+sievemgr@berhoerster.name>
parents:
diff changeset
32 const bom = '\ufeff'
4dff4c3f0fbb Introduce configuration file where account information is specified
Guido Berhoerster <guido+sievemgr@berhoerster.name>
parents:
diff changeset
33
4dff4c3f0fbb Introduce configuration file where account information is specified
Guido Berhoerster <guido+sievemgr@berhoerster.name>
parents:
diff changeset
34 type ParserError struct {
4dff4c3f0fbb Introduce configuration file where account information is specified
Guido Berhoerster <guido+sievemgr@berhoerster.name>
parents:
diff changeset
35 Message string
4dff4c3f0fbb Introduce configuration file where account information is specified
Guido Berhoerster <guido+sievemgr@berhoerster.name>
parents:
diff changeset
36 LineNo int
4dff4c3f0fbb Introduce configuration file where account information is specified
Guido Berhoerster <guido+sievemgr@berhoerster.name>
parents:
diff changeset
37 }
4dff4c3f0fbb Introduce configuration file where account information is specified
Guido Berhoerster <guido+sievemgr@berhoerster.name>
parents:
diff changeset
38
4dff4c3f0fbb Introduce configuration file where account information is specified
Guido Berhoerster <guido+sievemgr@berhoerster.name>
parents:
diff changeset
39 func (e *ParserError) Error() string {
4dff4c3f0fbb Introduce configuration file where account information is specified
Guido Berhoerster <guido+sievemgr@berhoerster.name>
parents:
diff changeset
40 if e.LineNo > 0 {
4dff4c3f0fbb Introduce configuration file where account information is specified
Guido Berhoerster <guido+sievemgr@berhoerster.name>
parents:
diff changeset
41 return fmt.Sprintf("error in line %d: %s", e.LineNo, e.Message)
4dff4c3f0fbb Introduce configuration file where account information is specified
Guido Berhoerster <guido+sievemgr@berhoerster.name>
parents:
diff changeset
42 }
4dff4c3f0fbb Introduce configuration file where account information is specified
Guido Berhoerster <guido+sievemgr@berhoerster.name>
parents:
diff changeset
43 return e.Message
4dff4c3f0fbb Introduce configuration file where account information is specified
Guido Berhoerster <guido+sievemgr@berhoerster.name>
parents:
diff changeset
44 }
4dff4c3f0fbb Introduce configuration file where account information is specified
Guido Berhoerster <guido+sievemgr@berhoerster.name>
parents:
diff changeset
45
4dff4c3f0fbb Introduce configuration file where account information is specified
Guido Berhoerster <guido+sievemgr@berhoerster.name>
parents:
diff changeset
46 func NewParserError(message string, lineNo int) *ParserError {
4dff4c3f0fbb Introduce configuration file where account information is specified
Guido Berhoerster <guido+sievemgr@berhoerster.name>
parents:
diff changeset
47 return &ParserError{message, lineNo}
4dff4c3f0fbb Introduce configuration file where account information is specified
Guido Berhoerster <guido+sievemgr@berhoerster.name>
parents:
diff changeset
48 }
4dff4c3f0fbb Introduce configuration file where account information is specified
Guido Berhoerster <guido+sievemgr@berhoerster.name>
parents:
diff changeset
49
4dff4c3f0fbb Introduce configuration file where account information is specified
Guido Berhoerster <guido+sievemgr@berhoerster.name>
parents:
diff changeset
50 type Configuration struct {
4dff4c3f0fbb Introduce configuration file where account information is specified
Guido Berhoerster <guido+sievemgr@berhoerster.name>
parents:
diff changeset
51 Accounts []*Account
4dff4c3f0fbb Introduce configuration file where account information is specified
Guido Berhoerster <guido+sievemgr@berhoerster.name>
parents:
diff changeset
52 Default *Account
4dff4c3f0fbb Introduce configuration file where account information is specified
Guido Berhoerster <guido+sievemgr@berhoerster.name>
parents:
diff changeset
53 }
4dff4c3f0fbb Introduce configuration file where account information is specified
Guido Berhoerster <guido+sievemgr@berhoerster.name>
parents:
diff changeset
54
4dff4c3f0fbb Introduce configuration file where account information is specified
Guido Berhoerster <guido+sievemgr@berhoerster.name>
parents:
diff changeset
55 type Account struct {
4dff4c3f0fbb Introduce configuration file where account information is specified
Guido Berhoerster <guido+sievemgr@berhoerster.name>
parents:
diff changeset
56 Name string
4dff4c3f0fbb Introduce configuration file where account information is specified
Guido Berhoerster <guido+sievemgr@berhoerster.name>
parents:
diff changeset
57 Host string
4dff4c3f0fbb Introduce configuration file where account information is specified
Guido Berhoerster <guido+sievemgr@berhoerster.name>
parents:
diff changeset
58 Port string
4dff4c3f0fbb Introduce configuration file where account information is specified
Guido Berhoerster <guido+sievemgr@berhoerster.name>
parents:
diff changeset
59 User string
4dff4c3f0fbb Introduce configuration file where account information is specified
Guido Berhoerster <guido+sievemgr@berhoerster.name>
parents:
diff changeset
60 Password string
4dff4c3f0fbb Introduce configuration file where account information is specified
Guido Berhoerster <guido+sievemgr@berhoerster.name>
parents:
diff changeset
61 Insecure bool
4dff4c3f0fbb Introduce configuration file where account information is specified
Guido Berhoerster <guido+sievemgr@berhoerster.name>
parents:
diff changeset
62 }
4dff4c3f0fbb Introduce configuration file where account information is specified
Guido Berhoerster <guido+sievemgr@berhoerster.name>
parents:
diff changeset
63
4dff4c3f0fbb Introduce configuration file where account information is specified
Guido Berhoerster <guido+sievemgr@berhoerster.name>
parents:
diff changeset
64 func Parse(data []byte, conf *Configuration) error {
4dff4c3f0fbb Introduce configuration file where account information is specified
Guido Berhoerster <guido+sievemgr@berhoerster.name>
parents:
diff changeset
65 rd := bytes.NewReader(data)
4dff4c3f0fbb Introduce configuration file where account information is specified
Guido Berhoerster <guido+sievemgr@berhoerster.name>
parents:
diff changeset
66 s := newScanner(bufio.NewReader(rd))
4dff4c3f0fbb Introduce configuration file where account information is specified
Guido Berhoerster <guido+sievemgr@berhoerster.name>
parents:
diff changeset
67 p := &parser{s: s}
4dff4c3f0fbb Introduce configuration file where account information is specified
Guido Berhoerster <guido+sievemgr@berhoerster.name>
parents:
diff changeset
68 return p.parse(conf)
4dff4c3f0fbb Introduce configuration file where account information is specified
Guido Berhoerster <guido+sievemgr@berhoerster.name>
parents:
diff changeset
69 }
4dff4c3f0fbb Introduce configuration file where account information is specified
Guido Berhoerster <guido+sievemgr@berhoerster.name>
parents:
diff changeset
70
4dff4c3f0fbb Introduce configuration file where account information is specified
Guido Berhoerster <guido+sievemgr@berhoerster.name>
parents:
diff changeset
71 func DefaultFilename() (string, error) {
4dff4c3f0fbb Introduce configuration file where account information is specified
Guido Berhoerster <guido+sievemgr@berhoerster.name>
parents:
diff changeset
72 dir, err := os.UserConfigDir()
4dff4c3f0fbb Introduce configuration file where account information is specified
Guido Berhoerster <guido+sievemgr@berhoerster.name>
parents:
diff changeset
73 if err != nil {
4dff4c3f0fbb Introduce configuration file where account information is specified
Guido Berhoerster <guido+sievemgr@berhoerster.name>
parents:
diff changeset
74 return "", fmt.Errorf("failed to determine the name of the configuration file: %s", err)
4dff4c3f0fbb Introduce configuration file where account information is specified
Guido Berhoerster <guido+sievemgr@berhoerster.name>
parents:
diff changeset
75 }
4dff4c3f0fbb Introduce configuration file where account information is specified
Guido Berhoerster <guido+sievemgr@berhoerster.name>
parents:
diff changeset
76 return filepath.Join(dir, "sievemgr", "sievemgr.conf"), nil
4dff4c3f0fbb Introduce configuration file where account information is specified
Guido Berhoerster <guido+sievemgr@berhoerster.name>
parents:
diff changeset
77 }
4dff4c3f0fbb Introduce configuration file where account information is specified
Guido Berhoerster <guido+sievemgr@berhoerster.name>
parents:
diff changeset
78
4dff4c3f0fbb Introduce configuration file where account information is specified
Guido Berhoerster <guido+sievemgr@berhoerster.name>
parents:
diff changeset
79 func ParseFile(filename string, conf *Configuration) error {
4dff4c3f0fbb Introduce configuration file where account information is specified
Guido Berhoerster <guido+sievemgr@berhoerster.name>
parents:
diff changeset
80 f, err := os.Open(filename)
4dff4c3f0fbb Introduce configuration file where account information is specified
Guido Berhoerster <guido+sievemgr@berhoerster.name>
parents:
diff changeset
81 if os.IsNotExist(err) {
4dff4c3f0fbb Introduce configuration file where account information is specified
Guido Berhoerster <guido+sievemgr@berhoerster.name>
parents:
diff changeset
82 return nil
4dff4c3f0fbb Introduce configuration file where account information is specified
Guido Berhoerster <guido+sievemgr@berhoerster.name>
parents:
diff changeset
83 } else if err != nil {
4dff4c3f0fbb Introduce configuration file where account information is specified
Guido Berhoerster <guido+sievemgr@berhoerster.name>
parents:
diff changeset
84 return fmt.Errorf("failed to open configuration file: %s", err)
4dff4c3f0fbb Introduce configuration file where account information is specified
Guido Berhoerster <guido+sievemgr@berhoerster.name>
parents:
diff changeset
85 }
4dff4c3f0fbb Introduce configuration file where account information is specified
Guido Berhoerster <guido+sievemgr@berhoerster.name>
parents:
diff changeset
86 defer f.Close()
4dff4c3f0fbb Introduce configuration file where account information is specified
Guido Berhoerster <guido+sievemgr@berhoerster.name>
parents:
diff changeset
87
4dff4c3f0fbb Introduce configuration file where account information is specified
Guido Berhoerster <guido+sievemgr@berhoerster.name>
parents:
diff changeset
88 // configutaion file must be a regular file with no more than 0600
4dff4c3f0fbb Introduce configuration file where account information is specified
Guido Berhoerster <guido+sievemgr@berhoerster.name>
parents:
diff changeset
89 // permissions
4dff4c3f0fbb Introduce configuration file where account information is specified
Guido Berhoerster <guido+sievemgr@berhoerster.name>
parents:
diff changeset
90 info, err := f.Stat()
4dff4c3f0fbb Introduce configuration file where account information is specified
Guido Berhoerster <guido+sievemgr@berhoerster.name>
parents:
diff changeset
91 if err != nil {
4dff4c3f0fbb Introduce configuration file where account information is specified
Guido Berhoerster <guido+sievemgr@berhoerster.name>
parents:
diff changeset
92 return fmt.Errorf("failed to stat configuration file: %s", err)
4dff4c3f0fbb Introduce configuration file where account information is specified
Guido Berhoerster <guido+sievemgr@berhoerster.name>
parents:
diff changeset
93 }
4dff4c3f0fbb Introduce configuration file where account information is specified
Guido Berhoerster <guido+sievemgr@berhoerster.name>
parents:
diff changeset
94 mode := info.Mode()
4dff4c3f0fbb Introduce configuration file where account information is specified
Guido Berhoerster <guido+sievemgr@berhoerster.name>
parents:
diff changeset
95 if !mode.IsRegular() {
4dff4c3f0fbb Introduce configuration file where account information is specified
Guido Berhoerster <guido+sievemgr@berhoerster.name>
parents:
diff changeset
96 return fmt.Errorf("configuration file is not a regular file")
4dff4c3f0fbb Introduce configuration file where account information is specified
Guido Berhoerster <guido+sievemgr@berhoerster.name>
parents:
diff changeset
97 }
4dff4c3f0fbb Introduce configuration file where account information is specified
Guido Berhoerster <guido+sievemgr@berhoerster.name>
parents:
diff changeset
98 if perm := mode.Perm(); perm&0077 != 0 {
4dff4c3f0fbb Introduce configuration file where account information is specified
Guido Berhoerster <guido+sievemgr@berhoerster.name>
parents:
diff changeset
99 return fmt.Errorf("permissions %04o on configuration file are too open", perm)
4dff4c3f0fbb Introduce configuration file where account information is specified
Guido Berhoerster <guido+sievemgr@berhoerster.name>
parents:
diff changeset
100 }
4dff4c3f0fbb Introduce configuration file where account information is specified
Guido Berhoerster <guido+sievemgr@berhoerster.name>
parents:
diff changeset
101
4dff4c3f0fbb Introduce configuration file where account information is specified
Guido Berhoerster <guido+sievemgr@berhoerster.name>
parents:
diff changeset
102 s := newScanner(bufio.NewReader(f))
4dff4c3f0fbb Introduce configuration file where account information is specified
Guido Berhoerster <guido+sievemgr@berhoerster.name>
parents:
diff changeset
103 p := &parser{s: s}
4dff4c3f0fbb Introduce configuration file where account information is specified
Guido Berhoerster <guido+sievemgr@berhoerster.name>
parents:
diff changeset
104 return p.parse(conf)
4dff4c3f0fbb Introduce configuration file where account information is specified
Guido Berhoerster <guido+sievemgr@berhoerster.name>
parents:
diff changeset
105 }