// cms is a free and open source content management system.
package main
import (
"context"
"log"
"net/http"
"os"
"strconv"
"time"
"git.sr.ht/~evanj/cms/internal/c"
"git.sr.ht/~evanj/cms/internal/c/content"
"git.sr.ht/~evanj/cms/internal/c/contenttype"
"git.sr.ht/~evanj/cms/internal/c/doc"
"git.sr.ht/~evanj/cms/internal/c/dynamic"
"git.sr.ht/~evanj/cms/internal/c/file"
"git.sr.ht/~evanj/cms/internal/c/hook"
"git.sr.ht/~evanj/cms/internal/c/invite"
"git.sr.ht/~evanj/cms/internal/c/redirect"
"git.sr.ht/~evanj/cms/internal/c/space"
"git.sr.ht/~evanj/cms/internal/c/stripe"
"git.sr.ht/~evanj/cms/internal/c/user"
"git.sr.ht/~evanj/cms/internal/s/cache"
"git.sr.ht/~evanj/cms/internal/s/db"
webhook "git.sr.ht/~evanj/cms/internal/s/hook"
"git.sr.ht/~evanj/cms/internal/s/rbac"
"git.sr.ht/~evanj/cms/internal/s/rl"
libstripe "git.sr.ht/~evanj/cms/internal/s/stripe"
"git.sr.ht/~evanj/cms/pkg/e3"
"git.sr.ht/~evanj/cms/pkg/skipper"
"git.sr.ht/~evanj/security"
)
var (
build string
port = os.Getenv("PORT")
dbtype = os.Getenv("DBTYPE")
dbcreds = os.Getenv("DB")
url = os.Getenv("URL")
secret = os.Getenv("SECRET")
memcacheKey = os.Getenv("MEMCACHE_KEY")
memcacheServer = os.Getenv("MEMCACHE_SERVER")
e3user = os.Getenv("E3_USER")
e3pass = os.Getenv("E3_PASS")
e3url = os.Getenv("E3_URL")
signupEnabled = os.Getenv("SIGNUP_ENABLE") == "true"
staticDir = os.Getenv("STATIC_DIR")
analyticsEnabled = os.Getenv("ANALYTICS_ENABLE") == "true"
stripeSuccessURL = os.Getenv("STRIPE_SUCCESS_URL")
stripeErrorURL = os.Getenv("STRIPE_ERROR_URL")
stripePK = os.Getenv("STRIPE_PK")
stripeSK = os.Getenv("STRIPE_SK")
dynamicContentUser = os.Getenv("DYNAMIC_CONTENT_USER")
dynamicContentPass = os.Getenv("DYNAMIC_CONTENT_PASS")
dynamicContentURL = os.Getenv("DYNAMIC_CONTENT_URL")
dynamicContentSpace = mustInt(os.Getenv("DYNAMIC_CONTENT_SPACE"))
dynamicContentContentType = mustInt(os.Getenv("DYNAMIC_CONTENT_CONTENTTYPE"))
)
func mustInt(val string) int {
i, err := strconv.Atoi(val)
if err != nil {
log.Fatal(err)
}
return i
}
func main() {
var (
w = os.Stdout
applogger = log.New(w, "[cms] ", 0)
db = db.New(
log.New(w, "[cms:db] ", 0),
dbtype,
dbcreds,
security.Default(secret),
)
cacher = cache.New(
log.New(w, "[cms:cache] ", 0),
db,
memcacheKey,
memcacheServer,
)
fs = e3.New(e3user, e3pass, e3url)
rl = rl.New(log.New(w, "[cms:ratelimit] ", 0), cacher, fs)
rbac = rbac.New(log.New(w, "[cms:rbac] ", 0), rl)
c = c.New(log.New(w, "[cms:content] ", 0), rbac, analyticsEnabled, build)
libs = libstripe.New(log.New(w, "[cms:stripe] ", 0), stripeSuccessURL, stripeErrorURL, stripePK, stripeSK, rbac)
app = &App{
applogger,
dynamic.New(
c,
log.New(w, "[cms:dynamic] ", 0),
skipper.New(
dynamicContentUser,
dynamicContentPass,
dynamicContentURL,
dynamicContentSpace,
),
dynamicContentContentType,
),
map[string]http.Handler{
"content": content.New(
c,
log.New(w, "[cms:content] ", 0),
rbac,
fs,
webhook.New(log.New(w, "[cms:hook] ", 0), rbac),
url,
),
"contenttype": contenttype.New(
c,
log.New(w, "[cms:contenttype] ", 0),
rbac,
),
"space": space.New(
c,
log.New(w, "[cms:space] ", 0),
rbac,
),
"user": user.New(
c,
log.New(w, "[cms:user] ", 0),
rbac,
signupEnabled,
libs,
),
"hook": hook.New(
c,
log.New(w, "[cms:hook] ", 0),
rbac,
),
"file": file.New(
c,
log.New(w, "[cms:file] ", 0),
rbac,
fs,
url,
),
"static": http.StripPrefix("/static", http.FileServer(http.Dir(staticDir))),
"redirect": redirect.New(
c,
log.New(w, "[cms:redirect] ", 0),
rbac,
),
"page": doc.New(
c,
log.New(w, "[cms:doc] ", 0),
),
"stripe": http.StripPrefix("/stripe", stripe.New(
c,
log.New(w, "[cms:stripe] ", 0),
libs,
)),
"invite": http.StripPrefix("/invite", invite.New(
c,
log.New(w, "[cms:doc] ", 0),
rbac,
)),
},
}
)
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
if err := db.Setup(ctx); err != nil {
app.log.Fatal(err)
}
if err := cacher.Setup(); err != nil {
app.log.Fatal(err)
}
app.log.Println("listening on", url)
app.log.Fatal(http.ListenAndServe(port, app))
}