3
0
Files
corteza/sam/start.go
Denis Arh 500e8e317c Improve SMTP
API can now be started without properly configured SMTP (it complains when it is used)
Send() function can now use alternative dialers (mostly used for testing)
Added mailhog service (make mailhog.up) to ease mail testing
Add default .env example that points to localhost:1025 (mailhog) setup
Proper unit testing
2019-01-13 14:45:27 +01:00

120 lines
2.9 KiB
Go

package service
import (
"fmt"
"log"
"net"
"net/http"
"github.com/SentimensRG/ctx"
"github.com/SentimensRG/ctx/sigctx"
"github.com/go-chi/chi"
"github.com/go-chi/cors"
"github.com/pkg/errors"
"github.com/titpetric/factory"
"github.com/titpetric/factory/resputil"
"github.com/crusttech/crust/internal/mail"
migrate "github.com/crusttech/crust/sam/db"
"github.com/crusttech/crust/sam/rest"
samService "github.com/crusttech/crust/sam/service"
"github.com/crusttech/crust/sam/websocket"
systemService "github.com/crusttech/crust/system/service"
"github.com/crusttech/crust/internal/auth"
"github.com/crusttech/crust/internal/metrics"
"github.com/crusttech/crust/internal/version"
)
func Init() error {
// validate configuration
if err := flags.Validate(); err != nil {
return err
}
mail.SetupDialer(flags.smtp)
// start/configure database connection
factory.Database.Add("default", flags.db.DSN)
db, err := factory.Database.Get()
if err != nil {
return err
}
// @todo: profiling as an external service?
switch flags.db.Profiler {
case "stdout":
db.Profiler = &factory.Database.ProfilerStdout
default:
fmt.Println("No database query profiler selected")
}
// migrate database schema
if err := migrate.Migrate(db); err != nil {
return err
}
// configure resputil options
resputil.SetConfig(resputil.Options{
Pretty: flags.http.Pretty,
Trace: flags.http.Tracing,
Logger: func(err error) {
// @todo: error logging
},
})
systemService.Init()
samService.Init()
return nil
}
func Start() error {
deadline := sigctx.New()
log.Printf("Starting sam, version: %v, built on: %v", version.Version, version.BuildTime)
log.Println("Starting http server on address " + flags.http.Addr)
listener, err := net.Listen("tcp", flags.http.Addr)
if err != nil {
return errors.Wrap(err, fmt.Sprintf("Can't listen on addr %s", flags.http.Addr))
}
// JWT Auth
jwtAuth, err := auth.JWT()
if err != nil {
return errors.Wrap(err, "Error creating JWT Auth object")
}
r := chi.NewRouter()
r.Use(handleCORS)
// Only protect application routes with JWT
r.Group(func(r chi.Router) {
r.Use(jwtAuth.Verifier(), jwtAuth.Authenticator())
mountRoutes(r, flags.http, rest.MountRoutes(), websocket.MountRoutes(ctx.AsContext(deadline), flags.repository))
})
printRoutes(r, flags.http)
mountSystemRoutes(r, flags.http)
if flags.monitor.Interval > 0 {
go metrics.NewMonitor(flags.monitor.Interval)
}
go http.Serve(listener, r)
<-deadline.Done()
return nil
}
// Sets up default CORS rules to use as a middleware
func handleCORS(next http.Handler) http.Handler {
return cors.New(cors.Options{
AllowedOrigins: []string{"*"},
AllowedMethods: []string{"GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS"},
AllowedHeaders: []string{"Accept", "Authorization", "Content-Type", "X-CSRF-Token"},
AllowCredentials: true,
MaxAge: 300, // Maximum value not ignored by any of major browsers
}).Handler(next)
}