hatecomputers.club/api/serve.go

186 lines
12 KiB
Go
Raw Normal View History

2024-03-26 18:00:05 -04:00
package api
import (
"database/sql"
"fmt"
"log"
"net/http"
"time"
"git.hatecomputers.club/hatecomputers/hatecomputers.club/adapters/external_dns/cloudflare"
"git.hatecomputers.club/hatecomputers/hatecomputers.club/adapters/files/filesystem"
2024-04-03 19:53:50 -04:00
"git.hatecomputers.club/hatecomputers/hatecomputers.club/api/auth"
"git.hatecomputers.club/hatecomputers/hatecomputers.club/api/dns"
"git.hatecomputers.club/hatecomputers/hatecomputers.club/api/guestbook"
"git.hatecomputers.club/hatecomputers/hatecomputers.club/api/hcaptcha"
"git.hatecomputers.club/hatecomputers/hatecomputers.club/api/keys"
"git.hatecomputers.club/hatecomputers/hatecomputers.club/api/profiles"
2024-04-03 19:53:50 -04:00
"git.hatecomputers.club/hatecomputers/hatecomputers.club/api/template"
"git.hatecomputers.club/hatecomputers/hatecomputers.club/api/types"
2024-03-26 18:00:05 -04:00
"git.hatecomputers.club/hatecomputers/hatecomputers.club/args"
2024-03-27 17:02:31 -04:00
"git.hatecomputers.club/hatecomputers/hatecomputers.club/utils"
2024-03-26 18:00:05 -04:00
)
2024-04-03 19:53:50 -04:00
func LogRequestContinuation(context *types.RequestContext, req *http.Request, resp http.ResponseWriter) types.ContinuationChain {
return func(success types.Continuation, _failure types.Continuation) types.ContinuationChain {
2024-03-26 18:00:05 -04:00
context.Start = time.Now()
2024-03-27 17:02:31 -04:00
context.Id = utils.RandomId()
2024-03-26 18:00:05 -04:00
log.Println(req.Method, req.URL.Path, req.RemoteAddr, context.Id)
return success(context, req, resp)
}
}
2024-04-03 19:53:50 -04:00
func LogExecutionTimeContinuation(context *types.RequestContext, req *http.Request, resp http.ResponseWriter) types.ContinuationChain {
return func(success types.Continuation, _failure types.Continuation) types.ContinuationChain {
2024-03-26 18:00:05 -04:00
end := time.Now()
log.Println(context.Id, "took", end.Sub(context.Start))
return success(context, req, resp)
}
}
2024-04-03 19:53:50 -04:00
func HealthCheckContinuation(context *types.RequestContext, req *http.Request, resp http.ResponseWriter) types.ContinuationChain {
return func(success types.Continuation, _failure types.Continuation) types.ContinuationChain {
2024-03-26 18:00:05 -04:00
resp.WriteHeader(200)
resp.Write([]byte("healthy"))
return success(context, req, resp)
}
}
2024-04-03 19:53:50 -04:00
func FailurePassingContinuation(context *types.RequestContext, req *http.Request, resp http.ResponseWriter) types.ContinuationChain {
return func(_success types.Continuation, failure types.Continuation) types.ContinuationChain {
2024-03-26 18:00:05 -04:00
return failure(context, req, resp)
}
}
2024-04-03 19:53:50 -04:00
func IdContinuation(context *types.RequestContext, req *http.Request, resp http.ResponseWriter) types.ContinuationChain {
return func(success types.Continuation, _failure types.Continuation) types.ContinuationChain {
2024-03-26 18:00:05 -04:00
return success(context, req, resp)
}
}
2024-04-01 19:34:14 -04:00
func CacheControlMiddleware(next http.Handler, maxAge int) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
header := fmt.Sprintf("public, max-age=%d", maxAge)
w.Header().Set("Cache-Control", header)
next.ServeHTTP(w, r)
})
}
2024-03-26 18:00:05 -04:00
func MakeServer(argv *args.Arguments, dbConn *sql.DB) *http.Server {
mux := http.NewServeMux()
// "dependency injection"
2024-04-03 16:27:55 -04:00
cloudflareAdapter := &cloudflare.CloudflareExternalDNSAdapter{
APIToken: argv.CloudflareToken,
ZoneId: argv.CloudflareZone,
}
uploadAdapter := &filesystem.FilesystemAdapter{
BasePath: argv.UploadPath,
Permissions: 0777,
}
2024-04-03 16:27:55 -04:00
2024-04-03 19:53:50 -04:00
makeRequestContext := func() *types.RequestContext {
return &types.RequestContext{
2024-04-03 17:59:19 -04:00
DBConn: dbConn,
Args: argv,
2024-03-28 00:55:22 -04:00
TemplateData: &map[string]interface{}{},
2024-03-26 18:00:05 -04:00
}
}
staticFileServer := http.FileServer(http.Dir(argv.StaticPath))
uploadFileServer := http.FileServer(http.Dir(argv.UploadPath))
mux.Handle("GET /static/", http.StripPrefix("/static/", CacheControlMiddleware(staticFileServer, 3600)))
mux.Handle("GET /uploads/", http.StripPrefix("/uploads/", CacheControlMiddleware(uploadFileServer, 60)))
mux.HandleFunc("GET /", func(w http.ResponseWriter, r *http.Request) {
2024-03-26 18:00:05 -04:00
requestContext := makeRequestContext()
LogRequestContinuation(requestContext, r, w)(auth.VerifySessionContinuation, FailurePassingContinuation)(IdContinuation, IdContinuation)(auth.ListUsersContinuation, auth.ListUsersContinuation)(template.TemplateContinuation("home.html", true), FailurePassingContinuation)(LogExecutionTimeContinuation, LogExecutionTimeContinuation)(IdContinuation, IdContinuation)
2024-03-26 18:00:05 -04:00
})
2024-04-03 17:59:19 -04:00
mux.HandleFunc("GET /health", func(w http.ResponseWriter, r *http.Request) {
2024-03-26 18:00:05 -04:00
requestContext := makeRequestContext()
LogRequestContinuation(requestContext, r, w)(HealthCheckContinuation, FailurePassingContinuation)(LogExecutionTimeContinuation, LogExecutionTimeContinuation)(IdContinuation, IdContinuation)
})
2024-03-27 17:02:31 -04:00
mux.HandleFunc("GET /login", func(w http.ResponseWriter, r *http.Request) {
requestContext := makeRequestContext()
2024-04-03 19:53:50 -04:00
LogRequestContinuation(requestContext, r, w)(auth.StartSessionContinuation, FailurePassingContinuation)(LogExecutionTimeContinuation, LogExecutionTimeContinuation)(IdContinuation, IdContinuation)
2024-03-27 17:02:31 -04:00
})
mux.HandleFunc("GET /auth", func(w http.ResponseWriter, r *http.Request) {
requestContext := makeRequestContext()
2024-04-03 19:53:50 -04:00
LogRequestContinuation(requestContext, r, w)(auth.InterceptOauthCodeContinuation, FailurePassingContinuation)(LogExecutionTimeContinuation, LogExecutionTimeContinuation)(IdContinuation, IdContinuation)
2024-03-27 17:02:31 -04:00
})
mux.HandleFunc("GET /logout", func(w http.ResponseWriter, r *http.Request) {
requestContext := makeRequestContext()
2024-04-03 19:53:50 -04:00
LogRequestContinuation(requestContext, r, w)(auth.LogoutContinuation, FailurePassingContinuation)(LogExecutionTimeContinuation, LogExecutionTimeContinuation)(IdContinuation, IdContinuation)
2024-03-27 17:02:31 -04:00
})
mux.HandleFunc("GET /profile", func(w http.ResponseWriter, r *http.Request) {
requestContext := makeRequestContext()
LogRequestContinuation(requestContext, r, w)(auth.VerifySessionContinuation, FailurePassingContinuation)(profiles.GetProfileContinuation, auth.GoLoginContinuation)(template.TemplateContinuation("profile.html", true), template.TemplateContinuation("profile.html", true))(LogExecutionTimeContinuation, LogExecutionTimeContinuation)(IdContinuation, IdContinuation)
})
mux.HandleFunc("POST /profile", func(w http.ResponseWriter, r *http.Request) {
requestContext := makeRequestContext()
updateProfileContinuation := profiles.UpdateProfileContinuation(uploadAdapter, profiles.MaxAvatarSize, profiles.AvatarPath, profiles.AvatarPrefix)
LogRequestContinuation(requestContext, r, w)(auth.VerifySessionContinuation, FailurePassingContinuation)(updateProfileContinuation, auth.GoLoginContinuation)(profiles.GetProfileContinuation, FailurePassingContinuation)(template.TemplateContinuation("profile.html", true), template.TemplateContinuation("profile.html", true))(LogExecutionTimeContinuation, LogExecutionTimeContinuation)(IdContinuation, IdContinuation)
})
2024-03-28 00:55:22 -04:00
mux.HandleFunc("GET /dns", func(w http.ResponseWriter, r *http.Request) {
requestContext := makeRequestContext()
2024-04-03 19:53:50 -04:00
LogRequestContinuation(requestContext, r, w)(auth.VerifySessionContinuation, FailurePassingContinuation)(dns.ListDNSRecordsContinuation, auth.GoLoginContinuation)(template.TemplateContinuation("dns.html", true), FailurePassingContinuation)(LogExecutionTimeContinuation, LogExecutionTimeContinuation)(IdContinuation, IdContinuation)
2024-03-28 00:55:22 -04:00
})
mux.HandleFunc("POST /dns", func(w http.ResponseWriter, r *http.Request) {
requestContext := makeRequestContext()
2024-05-12 17:32:50 -04:00
createRecordContinuation := dns.CreateDNSRecordContinuation(cloudflareAdapter, dns.MaxUserRecords, dns.UserOwnedInternalFmtDomains)
LogRequestContinuation(requestContext, r, w)(auth.VerifySessionContinuation, FailurePassingContinuation)(dns.ListDNSRecordsContinuation, auth.GoLoginContinuation)(createRecordContinuation, FailurePassingContinuation)(dns.ListDNSRecordsContinuation, dns.ListDNSRecordsContinuation)(template.TemplateContinuation("dns.html", true), template.TemplateContinuation("dns.html", true))(LogExecutionTimeContinuation, LogExecutionTimeContinuation)(IdContinuation, IdContinuation)
})
mux.HandleFunc("POST /dns/delete", func(w http.ResponseWriter, r *http.Request) {
requestContext := makeRequestContext()
2024-04-04 17:08:50 -04:00
LogRequestContinuation(requestContext, r, w)(auth.VerifySessionContinuation, FailurePassingContinuation)(dns.DeleteDNSRecordContinuation(cloudflareAdapter), auth.GoLoginContinuation)(dns.ListDNSRecordsContinuation, dns.ListDNSRecordsContinuation)(template.TemplateContinuation("dns.html", true), template.TemplateContinuation("dns.html", true))(LogExecutionTimeContinuation, LogExecutionTimeContinuation)(IdContinuation, IdContinuation)
})
mux.HandleFunc("GET /keys", func(w http.ResponseWriter, r *http.Request) {
requestContext := makeRequestContext()
2024-04-03 19:53:50 -04:00
LogRequestContinuation(requestContext, r, w)(auth.VerifySessionContinuation, FailurePassingContinuation)(keys.ListAPIKeysContinuation, auth.GoLoginContinuation)(template.TemplateContinuation("api_keys.html", true), FailurePassingContinuation)(LogExecutionTimeContinuation, LogExecutionTimeContinuation)(IdContinuation, IdContinuation)
})
mux.HandleFunc("POST /keys", func(w http.ResponseWriter, r *http.Request) {
requestContext := makeRequestContext()
2024-04-03 19:53:50 -04:00
LogRequestContinuation(requestContext, r, w)(auth.VerifySessionContinuation, FailurePassingContinuation)(keys.CreateAPIKeyContinuation, auth.GoLoginContinuation)(keys.ListAPIKeysContinuation, keys.ListAPIKeysContinuation)(template.TemplateContinuation("api_keys.html", true), template.TemplateContinuation("api_keys.html", true))(LogExecutionTimeContinuation, LogExecutionTimeContinuation)(IdContinuation, IdContinuation)
})
mux.HandleFunc("POST /keys/delete", func(w http.ResponseWriter, r *http.Request) {
requestContext := makeRequestContext()
2024-04-06 15:36:13 -04:00
LogRequestContinuation(requestContext, r, w)(auth.VerifySessionContinuation, FailurePassingContinuation)(keys.DeleteAPIKeyContinuation, auth.GoLoginContinuation)(keys.ListAPIKeysContinuation, keys.ListAPIKeysContinuation)(template.TemplateContinuation("api_keys.html", true), template.TemplateContinuation("api_keys.html", true))(LogExecutionTimeContinuation, LogExecutionTimeContinuation)(IdContinuation, IdContinuation)
})
2024-03-29 18:35:04 -04:00
mux.HandleFunc("GET /guestbook", func(w http.ResponseWriter, r *http.Request) {
requestContext := makeRequestContext()
2024-04-03 19:53:50 -04:00
LogRequestContinuation(requestContext, r, w)(auth.VerifySessionContinuation, FailurePassingContinuation)(hcaptcha.CaptchaArgsContinuation, hcaptcha.CaptchaArgsContinuation)(guestbook.ListGuestbookContinuation, guestbook.ListGuestbookContinuation)(template.TemplateContinuation("guestbook.html", true), FailurePassingContinuation)(LogExecutionTimeContinuation, LogExecutionTimeContinuation)(IdContinuation, IdContinuation)
2024-03-29 18:35:04 -04:00
})
mux.HandleFunc("POST /guestbook", func(w http.ResponseWriter, r *http.Request) {
requestContext := makeRequestContext()
2024-04-03 19:53:50 -04:00
LogRequestContinuation(requestContext, r, w)(auth.VerifySessionContinuation, FailurePassingContinuation)(hcaptcha.CaptchaVerificationContinuation, hcaptcha.CaptchaVerificationContinuation)(guestbook.SignGuestbookContinuation, FailurePassingContinuation)(guestbook.ListGuestbookContinuation, guestbook.ListGuestbookContinuation)(hcaptcha.CaptchaArgsContinuation, hcaptcha.CaptchaArgsContinuation)(template.TemplateContinuation("guestbook.html", true), template.TemplateContinuation("guestbook.html", true))(LogExecutionTimeContinuation, LogExecutionTimeContinuation)(IdContinuation, IdContinuation)
2024-03-29 18:35:04 -04:00
})
2024-03-26 18:00:05 -04:00
mux.HandleFunc("GET /{name}", func(w http.ResponseWriter, r *http.Request) {
requestContext := makeRequestContext()
name := r.PathValue("name")
2024-04-03 19:53:50 -04:00
LogRequestContinuation(requestContext, r, w)(auth.VerifySessionContinuation, FailurePassingContinuation)(IdContinuation, IdContinuation)(template.TemplateContinuation(name+".html", true), FailurePassingContinuation)(LogExecutionTimeContinuation, LogExecutionTimeContinuation)(IdContinuation, IdContinuation)
2024-03-26 18:00:05 -04:00
})
return &http.Server{
Addr: ":" + fmt.Sprint(argv.Port),
Handler: mux,
}
}