-
Notifications
You must be signed in to change notification settings - Fork 499
/
main.go
139 lines (118 loc) · 3.25 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
package main
import (
"fmt"
"os"
"github.com/go-chi/chi"
"github.com/spf13/cobra"
"github.com/stellar/go/handlers/federation"
"github.com/stellar/go/support/app"
"github.com/stellar/go/support/config"
"github.com/stellar/go/support/db"
"github.com/stellar/go/support/errors"
"github.com/stellar/go/support/http"
"github.com/stellar/go/support/log"
)
// Config represents the configuration of a federation server
type Config struct {
Port int `valid:"required"`
Database struct {
Type string `valid:"matches(^sqlite3|postgres$)"`
DSN string `valid:"required"`
} `valid:"required"`
Queries struct {
Federation string `valid:"required"`
ReverseFederation string `toml:"reverse-federation" valid:"optional"`
} `valid:"required"`
TLS *config.TLS `valid:"optional"`
}
func main() {
rootCmd := &cobra.Command{
Use: "federation",
Short: "stellar federation server",
Long: `
The stellar federation server let's you easily integrate the stellar federation
protocol with your organization. This is achieved by connecting the
application to your customer database and providing the appropriate queries in
the config file.
`,
Run: run,
}
rootCmd.PersistentFlags().String("conf", "./federation.cfg", "config file path")
rootCmd.Execute()
}
func run(cmd *cobra.Command, args []string) {
var (
cfg Config
cfgPath = cmd.PersistentFlags().Lookup("conf").Value.String()
)
log.SetLevel(log.InfoLevel)
err := config.Read(cfgPath, &cfg)
if err != nil {
switch cause := errors.Cause(err).(type) {
case *config.InvalidConfigError:
log.Error("config file: ", cause)
default:
log.Error(err)
}
os.Exit(1)
}
driver, err := initDriver(cfg)
if err != nil {
log.Error(err)
os.Exit(1)
}
mux := initMux(driver)
addr := fmt.Sprintf("0.0.0.0:%d", cfg.Port)
http.Run(http.Config{
ListenAddr: addr,
Handler: mux,
TLS: cfg.TLS,
OnStarting: func() {
log.Infof("starting federation server - %s", app.Version())
log.Infof("listening on %s", addr)
},
})
}
func initDriver(cfg Config) (federation.Driver, error) {
var dialect string
switch cfg.Database.Type {
case "mysql":
return nil, errors.Errorf("Invalid db type: %s, mysql support is discontinued", cfg.Database.Type)
case "postgres":
dialect = "postgres"
case "sqlite3":
dialect = "sqlite3"
default:
return nil, errors.Errorf("Invalid db type: %s", cfg.Database.Type)
}
repo, err := db.Open(dialect, cfg.Database.DSN)
if err != nil {
return nil, errors.Wrap(err, "db open failed")
}
sqld := federation.SQLDriver{
DB: repo.DB.DB, // unwrap the repo to the bare *sql.DB instance,
Dialect: dialect,
LookupRecordQuery: cfg.Queries.Federation,
}
if cfg.Queries.ReverseFederation == "" {
return &sqld, nil
}
rsqld := federation.ReverseSQLDriver{
SQLDriver: federation.SQLDriver{
DB: repo.DB.DB,
Dialect: dialect,
LookupRecordQuery: cfg.Queries.Federation,
},
LookupReverseRecordQuery: cfg.Queries.ReverseFederation,
}
return &rsqld, nil
}
func initMux(driver federation.Driver) *chi.Mux {
mux := http.NewAPIMux(log.DefaultLogger)
fed := &federation.Handler{
Driver: driver,
}
mux.Get("/federation", fed.ServeHTTP)
mux.Get("/federation/", fed.ServeHTTP)
return mux
}