1
0
mirror of https://github.com/raseels-repos/golang-saas-starter-kit.git synced 2025-06-08 23:56:37 +02:00
2019-08-05 13:27:23 -08:00

192 lines
9.1 KiB
Go

package handlers
import (
"context"
"fmt"
"log"
"net/http"
"os"
"geeks-accelerator/oss/saas-starter-kit/internal/mid"
"geeks-accelerator/oss/saas-starter-kit/internal/platform/auth"
"geeks-accelerator/oss/saas-starter-kit/internal/platform/notify"
"geeks-accelerator/oss/saas-starter-kit/internal/platform/web"
"geeks-accelerator/oss/saas-starter-kit/internal/platform/web/webcontext"
"geeks-accelerator/oss/saas-starter-kit/internal/platform/web/weberror"
project_routes "geeks-accelerator/oss/saas-starter-kit/internal/project-routes"
"github.com/jmoiron/sqlx"
"gopkg.in/DataDog/dd-trace-go.v1/contrib/go-redis/redis"
)
const (
TmplLayoutBase = "base.gohtml"
tmplLayoutSite = "site.gohtml"
TmplContentErrorGeneric = "error-generic.gohtml"
)
// API returns a handler for a set of routes.
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 {
// Define base middlewares applied to all requests.
middlewares := []web.Middleware{
mid.Trace(), mid.Logger(log), mid.Errors(log, renderer), mid.Metrics(), mid.Panics(),
}
// Append any global middlewares if they were included.
if len(globalMids) > 0 {
middlewares = append(middlewares, globalMids...)
}
// Construct the web.App which holds all routes as well as common Middleware.
app := web.NewApp(shutdown, log, env, middlewares...)
// Register project management pages.
p := Projects{
MasterDB: masterDB,
Redis: redis,
Renderer: renderer,
}
app.Handle("POST", "/projects/:project_id/update", p.Update, mid.AuthenticateSessionRequired(authenticator), mid.HasRole(auth.RoleAdmin))
app.Handle("GET", "/projects/:project_id/update", p.Update, mid.AuthenticateSessionRequired(authenticator), mid.HasRole(auth.RoleAdmin))
app.Handle("POST", "/projects/:project_id", p.View, mid.AuthenticateSessionRequired(authenticator), mid.HasRole(auth.RoleAdmin))
app.Handle("GET", "/projects/:project_id", p.View, mid.AuthenticateSessionRequired(authenticator), mid.HasAuth())
app.Handle("POST", "/projects/create", p.Create, mid.AuthenticateSessionRequired(authenticator), mid.HasRole(auth.RoleAdmin))
app.Handle("GET", "/projects/create", p.Create, mid.AuthenticateSessionRequired(authenticator), mid.HasRole(auth.RoleAdmin))
app.Handle("GET", "/projects", p.Index, mid.AuthenticateSessionRequired(authenticator), mid.HasAuth())
// Register user management pages.
us := Users{
MasterDB: masterDB,
Redis: redis,
Renderer: renderer,
Authenticator: authenticator,
ProjectRoutes: projectRoutes,
NotifyEmail: notifyEmail,
SecretKey: secretKey,
}
app.Handle("POST", "/users/:user_id/update", us.Update, mid.AuthenticateSessionRequired(authenticator), mid.HasRole(auth.RoleAdmin))
app.Handle("GET", "/users/:user_id/update", us.Update, mid.AuthenticateSessionRequired(authenticator), mid.HasRole(auth.RoleAdmin))
app.Handle("POST", "/users/:user_id", us.View, mid.AuthenticateSessionRequired(authenticator), mid.HasRole(auth.RoleAdmin))
app.Handle("GET", "/users/:user_id", us.View, mid.AuthenticateSessionRequired(authenticator), mid.HasAuth())
app.Handle("POST", "/users/invite/:hash", us.InviteAccept)
app.Handle("GET", "/users/invite/:hash", us.InviteAccept)
app.Handle("POST", "/users/invite", us.Invite, mid.AuthenticateSessionRequired(authenticator), mid.HasRole(auth.RoleAdmin))
app.Handle("GET", "/users/invite", us.Invite, mid.AuthenticateSessionRequired(authenticator), mid.HasRole(auth.RoleAdmin))
app.Handle("POST", "/users/create", us.Create, mid.AuthenticateSessionRequired(authenticator), mid.HasRole(auth.RoleAdmin))
app.Handle("GET", "/users/create", us.Create, mid.AuthenticateSessionRequired(authenticator), mid.HasRole(auth.RoleAdmin))
app.Handle("GET", "/users", us.Index, mid.AuthenticateSessionRequired(authenticator), mid.HasAuth())
// Register user management and authentication endpoints.
u := User{
MasterDB: masterDB,
Renderer: renderer,
Authenticator: authenticator,
ProjectRoutes: projectRoutes,
NotifyEmail: notifyEmail,
SecretKey: secretKey,
}
app.Handle("POST", "/user/login", u.Login)
app.Handle("GET", "/user/login", u.Login)
app.Handle("GET", "/user/logout", u.Logout)
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)
app.Handle("POST", "/user/update", u.Update, mid.AuthenticateSessionRequired(authenticator), mid.HasAuth())
app.Handle("GET", "/user/update", u.Update, mid.AuthenticateSessionRequired(authenticator), mid.HasAuth())
app.Handle("GET", "/user/account", u.Account, mid.AuthenticateSessionRequired(authenticator), mid.HasAuth())
app.Handle("GET", "/user/virtual-login/:user_id", u.VirtualLogin, mid.AuthenticateSessionRequired(authenticator), mid.HasRole(auth.RoleAdmin))
app.Handle("POST", "/user/virtual-login", u.VirtualLogin, mid.AuthenticateSessionRequired(authenticator), mid.HasRole(auth.RoleAdmin))
app.Handle("GET", "/user/virtual-login", u.VirtualLogin, mid.AuthenticateSessionRequired(authenticator), mid.HasRole(auth.RoleAdmin))
app.Handle("GET", "/user/virtual-logout", u.VirtualLogout, mid.AuthenticateSessionRequired(authenticator), mid.HasAuth())
app.Handle("GET", "/user/switch-account/:account_id", u.SwitchAccount, mid.AuthenticateSessionRequired(authenticator), mid.HasAuth())
app.Handle("POST", "/user/switch-account", u.SwitchAccount, mid.AuthenticateSessionRequired(authenticator), mid.HasAuth())
app.Handle("GET", "/user/switch-account", u.SwitchAccount, mid.AuthenticateSessionRequired(authenticator), mid.HasAuth())
app.Handle("POST", "/user", u.View, mid.AuthenticateSessionRequired(authenticator), mid.HasAuth())
app.Handle("GET", "/user", u.View, mid.AuthenticateSessionRequired(authenticator), mid.HasAuth())
// Register account management endpoints.
acc := Account{
MasterDB: masterDB,
Renderer: renderer,
Authenticator: authenticator,
}
app.Handle("POST", "/account/update", acc.Update, mid.AuthenticateSessionRequired(authenticator), mid.HasRole(auth.RoleAdmin))
app.Handle("GET", "/account/update", acc.Update, mid.AuthenticateSessionRequired(authenticator), mid.HasRole(auth.RoleAdmin))
app.Handle("POST", "/account", acc.View, mid.AuthenticateSessionRequired(authenticator), mid.HasRole(auth.RoleAdmin))
app.Handle("GET", "/account", acc.View, mid.AuthenticateSessionRequired(authenticator), mid.HasRole(auth.RoleAdmin))
// Register user management and authentication endpoints.
s := Signup{
MasterDB: masterDB,
Renderer: renderer,
Authenticator: authenticator,
}
// This route is not authenticated
app.Handle("POST", "/signup", s.Step1)
app.Handle("GET", "/signup", s.Step1)
// Register example endpoints.
ex := Examples{
Renderer: renderer,
}
app.Handle("POST", "/examples/flash-messages", ex.FlashMessages, mid.AuthenticateSessionOptional(authenticator))
app.Handle("GET", "/examples/flash-messages", ex.FlashMessages, mid.AuthenticateSessionOptional(authenticator))
app.Handle("GET", "/examples/images", ex.Images, mid.AuthenticateSessionOptional(authenticator))
// Register geo
g := Geo{
MasterDB: masterDB,
Redis: redis,
}
app.Handle("GET", "/geo/regions/autocomplete", g.RegionsAutocomplete)
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)
// Register root
r := Root{
MasterDB: masterDB,
Renderer: renderer,
ProjectRoutes: projectRoutes,
}
app.Handle("GET", "/api", r.SitePage)
app.Handle("GET", "/pricing", r.SitePage)
app.Handle("GET", "/support", r.SitePage)
app.Handle("GET", "/legal/privacy", r.SitePage)
app.Handle("GET", "/legal/terms", r.SitePage)
app.Handle("GET", "/", r.Index, mid.AuthenticateSessionOptional(authenticator))
app.Handle("GET", "/index.html", r.IndexHtml)
app.Handle("GET", "/robots.txt", r.RobotTxt)
// Register health check endpoint. This route is not authenticated.
check := Check{
MasterDB: masterDB,
Redis: redis,
Renderer: renderer,
}
app.Handle("GET", "/v1/health", check.Health)
// Handle static files/pages. Render a custom 404 page when file not found.
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
}
// Static file server
app.Handle("GET", "/*", static)
return app
}