2019-05-18 18:06:10 -04:00
|
|
|
package handlers
|
|
|
|
|
|
|
|
import (
|
2019-07-31 13:47:30 -08:00
|
|
|
"context"
|
|
|
|
"fmt"
|
2019-08-02 15:03:32 -08:00
|
|
|
"geeks-accelerator/oss/saas-starter-kit/internal/platform/notify"
|
2019-05-18 18:06:10 -04:00
|
|
|
"log"
|
|
|
|
"net/http"
|
|
|
|
"os"
|
|
|
|
|
2019-07-13 12:16:28 -08:00
|
|
|
"geeks-accelerator/oss/saas-starter-kit/internal/mid"
|
2019-07-31 13:47:30 -08:00
|
|
|
"geeks-accelerator/oss/saas-starter-kit/internal/platform/auth"
|
2019-07-13 12:16:28 -08:00
|
|
|
"geeks-accelerator/oss/saas-starter-kit/internal/platform/web"
|
2019-07-31 13:47:30 -08:00
|
|
|
"geeks-accelerator/oss/saas-starter-kit/internal/platform/web/webcontext"
|
|
|
|
"geeks-accelerator/oss/saas-starter-kit/internal/platform/web/weberror"
|
2019-07-31 18:34:27 -08:00
|
|
|
project_routes "geeks-accelerator/oss/saas-starter-kit/internal/project-routes"
|
2019-05-23 14:32:24 -05:00
|
|
|
"github.com/jmoiron/sqlx"
|
2019-07-13 16:32:29 -08:00
|
|
|
"gopkg.in/DataDog/dd-trace-go.v1/contrib/go-redis/redis"
|
2019-05-18 18:06:10 -04:00
|
|
|
)
|
|
|
|
|
2019-07-31 13:47:30 -08:00
|
|
|
const (
|
2019-08-01 16:17:47 -08:00
|
|
|
tmplLayoutBase = "base.gohtml"
|
2019-08-03 15:02:00 -08:00
|
|
|
tmplLayoutSite = "site.gohtml"
|
2019-07-31 13:47:30 -08:00
|
|
|
tmplContentErrorGeneric = "error-generic.gohtml"
|
|
|
|
)
|
2019-05-18 18:06:10 -04:00
|
|
|
|
|
|
|
// API returns a handler for a set of routes.
|
2019-08-02 15:03:32 -08:00
|
|
|
func APP(shutdown chan os.Signal, log *log.Logger, env webcontext.Env, staticDir, templateDir string, masterDB *sqlx.DB, redis *redis.Client, authenticator *auth.Authenticator, projectRoutes project_routes.ProjectRoutes, secretKey string, notifyEmail notify.Email, renderer web.Renderer, globalMids ...web.Middleware) http.Handler {
|
2019-07-12 11:41:41 -08:00
|
|
|
|
|
|
|
// Define base middlewares applied to all requests.
|
|
|
|
middlewares := []web.Middleware{
|
|
|
|
mid.Trace(), mid.Logger(log), mid.Errors(log), mid.Metrics(), mid.Panics(),
|
|
|
|
}
|
|
|
|
|
|
|
|
// Append any global middlewares if they were included.
|
|
|
|
if len(globalMids) > 0 {
|
|
|
|
middlewares = append(middlewares, globalMids...)
|
|
|
|
}
|
2019-05-18 18:06:10 -04:00
|
|
|
|
|
|
|
// Construct the web.App which holds all routes as well as common Middleware.
|
2019-07-31 13:47:30 -08:00
|
|
|
app := web.NewApp(shutdown, log, env, middlewares...)
|
2019-05-18 18:06:10 -04:00
|
|
|
|
2019-07-31 13:47:30 -08:00
|
|
|
// Register project management pages.
|
|
|
|
p := Projects{
|
2019-05-20 22:16:58 -05:00
|
|
|
MasterDB: masterDB,
|
2019-05-18 18:06:10 -04:00
|
|
|
Renderer: renderer,
|
|
|
|
}
|
2019-07-31 18:34:27 -08:00
|
|
|
app.Handle("GET", "/projects", p.Index, mid.AuthenticateSessionRequired(authenticator), mid.HasAuth())
|
2019-05-18 18:06:10 -04:00
|
|
|
|
|
|
|
// Register user management and authentication endpoints.
|
|
|
|
u := User{
|
2019-07-31 13:47:30 -08:00
|
|
|
MasterDB: masterDB,
|
|
|
|
Renderer: renderer,
|
|
|
|
Authenticator: authenticator,
|
2019-08-02 15:03:32 -08:00
|
|
|
ProjectRoutes: projectRoutes,
|
|
|
|
NotifyEmail: notifyEmail,
|
|
|
|
SecretKey: secretKey,
|
2019-05-18 18:06:10 -04:00
|
|
|
}
|
2019-07-31 13:47:30 -08:00
|
|
|
// This route is not authenticated
|
|
|
|
app.Handle("POST", "/user/login", u.Login)
|
|
|
|
app.Handle("GET", "/user/login", u.Login)
|
|
|
|
app.Handle("GET", "/user/logout", u.Logout)
|
2019-08-02 15:03:32 -08:00
|
|
|
app.Handle("POST", "/user/reset-password/:hash", u.ResetConfirm)
|
|
|
|
app.Handle("GET", "/user/reset-password/:hash", u.ResetConfirm)
|
|
|
|
app.Handle("POST", "/user/reset-password", u.ResetPassword)
|
|
|
|
app.Handle("GET", "/user/reset-password", u.ResetPassword)
|
2019-05-18 18:06:10 -04:00
|
|
|
|
2019-07-31 13:47:30 -08:00
|
|
|
// Register user management and authentication endpoints.
|
|
|
|
s := Signup{
|
|
|
|
MasterDB: masterDB,
|
|
|
|
Renderer: renderer,
|
|
|
|
Authenticator: authenticator,
|
|
|
|
}
|
2019-05-18 18:06:10 -04:00
|
|
|
// This route is not authenticated
|
2019-07-31 13:47:30 -08:00
|
|
|
app.Handle("POST", "/signup", s.Step1)
|
|
|
|
app.Handle("GET", "/signup", s.Step1)
|
2019-05-18 18:06:10 -04:00
|
|
|
|
2019-08-01 11:34:03 -08:00
|
|
|
// Register geo
|
|
|
|
g := Geo{
|
2019-08-01 13:45:38 -08:00
|
|
|
MasterDB: masterDB,
|
|
|
|
Redis: redis,
|
2019-08-01 11:34:03 -08:00
|
|
|
}
|
|
|
|
// These routes are not authenticated
|
|
|
|
app.Handle("GET", "/geo/regions/autocomplete", g.RegionsAutocomplete)
|
2019-08-01 13:45:38 -08:00
|
|
|
app.Handle("GET", "/geo/postal_codes/autocomplete", g.PostalCodesAutocomplete)
|
|
|
|
app.Handle("GET", "/geo/geonames/postal_code/:postalCode", g.GeonameByPostalCode)
|
|
|
|
app.Handle("GET", "/geo/country/:countryCode/timezones", g.CountryTimezones)
|
2019-08-01 11:34:03 -08:00
|
|
|
|
2019-05-18 18:06:10 -04:00
|
|
|
// Register root
|
|
|
|
r := Root{
|
2019-07-31 18:34:27 -08:00
|
|
|
MasterDB: masterDB,
|
|
|
|
Renderer: renderer,
|
|
|
|
ProjectRoutes: projectRoutes,
|
2019-05-18 18:06:10 -04:00
|
|
|
}
|
2019-08-03 15:02:00 -08:00
|
|
|
|
|
|
|
// These routes is not authenticated
|
|
|
|
app.Handle("GET", "/api", r.SitePage)
|
2019-08-03 17:36:17 -08:00
|
|
|
app.Handle("GET", "/pricing", r.SitePage)
|
2019-08-03 15:02:00 -08:00
|
|
|
app.Handle("GET", "/support", r.SitePage)
|
|
|
|
app.Handle("GET", "/legal/privacy", r.SitePage)
|
|
|
|
app.Handle("GET", "/legal/terms", r.SitePage)
|
2019-07-31 18:34:27 -08:00
|
|
|
app.Handle("GET", "/", r.Index, mid.AuthenticateSessionOptional(authenticator))
|
|
|
|
app.Handle("GET", "/index.html", r.IndexHtml)
|
|
|
|
app.Handle("GET", "/robots.txt", r.RobotTxt)
|
2019-05-18 18:06:10 -04:00
|
|
|
|
2019-07-31 13:47:30 -08:00
|
|
|
// Register health check endpoint. This route is not authenticated.
|
|
|
|
check := Check{
|
|
|
|
MasterDB: masterDB,
|
|
|
|
Redis: redis,
|
|
|
|
Renderer: renderer,
|
|
|
|
}
|
|
|
|
app.Handle("GET", "/v1/health", check.Health)
|
|
|
|
|
2019-07-31 18:34:27 -08:00
|
|
|
// Handle static files/pages. Render a custom 404 page when file not found.
|
2019-07-31 13:47:30 -08:00
|
|
|
static := func(ctx context.Context, w http.ResponseWriter, r *http.Request, params map[string]string) error {
|
|
|
|
err := web.StaticHandler(ctx, w, r, params, staticDir, "")
|
|
|
|
if err != nil {
|
|
|
|
if os.IsNotExist(err) {
|
|
|
|
rmsg := fmt.Sprintf("%s %s not found", r.Method, r.RequestURI)
|
|
|
|
err = weberror.NewErrorMessage(ctx, err, http.StatusNotFound, rmsg)
|
|
|
|
} else {
|
|
|
|
err = weberror.NewError(ctx, err, http.StatusInternalServerError)
|
|
|
|
}
|
|
|
|
|
|
|
|
return web.RenderError(ctx, w, r, err, renderer, tmplLayoutBase, tmplContentErrorGeneric, web.MIMETextHTMLCharsetUTF8)
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2019-05-18 18:06:10 -04:00
|
|
|
// Static file server
|
2019-07-31 13:47:30 -08:00
|
|
|
app.Handle("GET", "/*", static)
|
2019-05-18 18:06:10 -04:00
|
|
|
|
|
|
|
return app
|
|
|
|
}
|