Serverside stuff. Mostly shuffling things around

This commit is contained in:
Melody Becker 2024-10-26 11:42:51 +02:00
parent 90667d96c7
commit be70109c43
20 changed files with 513 additions and 71 deletions

2
.gitignore vendored
View file

@ -6,7 +6,7 @@ db.sqlite
/frontend/
config.toml
.air.toml
*/**/.null_*
*/.null_*
# --- Section ember frontend ---

View file

@ -17,8 +17,8 @@
3. Get webauthn options from response
4. Get passkey response
5. Send response to Server
6. Server checks and replies with session token
7. Frontend uses session token for authorisation of all requests afterwards
6. Server checks and gives ok or fail.
Ok also sets a server only cookie with an access token
## api

View file

@ -82,6 +82,11 @@ type ConfigMail struct {
TemplateOverwriteDirectory *string `toml:"template_overwrite_directory,omitempty"`
}
type ConfigSelf struct {
ServerActorDisplayName string `toml:"server_actor_display_name"`
ServerDisplayName string `toml:"server_display_name"`
}
type Config struct {
General ConfigGeneral `toml:"general"`
SSL ConfigSSL `toml:"ssl"`
@ -89,6 +94,7 @@ type Config struct {
Webauthn ConfigWebAuthn `toml:"webauthn"`
Storage ConfigStorage `toml:"storage"`
Mail ConfigMail `toml:"mail"`
Self ConfigSelf `toml:"self"`
}
var GlobalConfig Config

View file

@ -36,11 +36,6 @@ func main() {
Str("config-file", *flagConfigFile).
Msg("Failed to read config and couldn't write default")
}
// res, err := ap.GetAccountWebfinger("@aufricus_athudath@activitypub.academy")
// log.Info().
// Err(err).
// Any("webfinger", res).
// Msg("Webfinger request result for @aufricus_athudath@activitypub.academy")
storageCache, err := cache.NewCache(
config.GlobalConfig.Storage.MaxInMemoryCacheSize,
config.GlobalConfig.Storage.RedisUrl,
@ -79,8 +74,8 @@ func main() {
server := server.NewServer(
store,
pkey,
util.NewFSWrapper(reactiveFS, "frontend-reactive/dist/", true),
util.NewFSWrapper(nojsFS, "frontend-noscript/", true),
util.NewFSWrapper(reactiveFS, "frontend-reactive/dist/", false),
util.NewFSWrapper(nojsFS, "frontend-noscript/", false),
)
server.Start(":8000")
// TODO: Set up media server

View file

@ -0,0 +1 @@
package server

View file

@ -0,0 +1,5 @@
package server
import "net/http"
func getLinstromNote(w http.ResponseWriter, r *http.Request) {}

View file

@ -0,0 +1,8 @@
package server
import "net/http"
func setupApiFrontendRouter() http.Handler {
router := http.NewServeMux()
return router
}

286
server/apiRouter.go Normal file
View file

@ -0,0 +1,286 @@
package server
import "net/http"
// Mounted at /api
func setupApiRouter() http.Handler {
router := http.NewServeMux()
// Section MastoApi
router.HandleFunc("GET /oauth/authorize", placeholderEndpoint)
router.HandleFunc("POST /oauth/token", placeholderEndpoint)
router.HandleFunc("POST /oauth/revoke", placeholderEndpoint)
router.HandleFunc("GET /.well-known/oauth-authorization-server", placeholderEndpoint)
router.HandleFunc("POST /v1/apps", placeholderEndpoint)
router.HandleFunc("GET /v1/apps/verify_credentials", placeholderEndpoint)
router.HandleFunc("POST /v1/emails/confirmations", placeholderEndpoint)
router.HandleFunc("POST /v1/accounts", placeholderEndpoint)
router.HandleFunc("GET /v1/accounts/verify_credentials", placeholderEndpoint)
router.HandleFunc("PATCH /v1/accounts/update_credentials", placeholderEndpoint)
router.HandleFunc("GET /v1/accounts/{id}", placeholderEndpoint)
router.HandleFunc("GET /v1/accounts", placeholderEndpoint)
router.HandleFunc("GET /v1/accounts/{id}/statuses", placeholderEndpoint)
router.HandleFunc("GET /v1/accounts/{id}/followers", placeholderEndpoint)
router.HandleFunc("GET /v1/accounts/{id}/following", placeholderEndpoint)
router.HandleFunc("GET /v1/accounts/{id}/featured_tags", placeholderEndpoint)
router.HandleFunc("GET /v1/accounts/{id}/lists", placeholderEndpoint)
router.HandleFunc("POST /v1/accounts/{id}/follow", placeholderEndpoint)
router.HandleFunc("POST /v1/accounts/{id}/unfollow", placeholderEndpoint)
router.HandleFunc("POST /v1/accounts/{id}/remove_from_followers", placeholderEndpoint)
router.HandleFunc("POST /v1/accounts/{id}/block", placeholderEndpoint)
router.HandleFunc("POST /v1/accounts/{id}/unblock", placeholderEndpoint)
router.HandleFunc("POST /v1/accounts/{id}/mute", placeholderEndpoint)
router.HandleFunc("POST /v1/accounts/{id}/unmute", placeholderEndpoint)
router.HandleFunc("POST /v1/accounts/{id}/pin", placeholderEndpoint)
router.HandleFunc("POST /v1/accounts/{id}/unpin", placeholderEndpoint)
router.HandleFunc("POST /v1/accounts/{id}/note", placeholderEndpoint)
router.HandleFunc("GET /v1/accounts/relationships", placeholderEndpoint)
router.HandleFunc("GET /v1/accounts/familiar_followers", placeholderEndpoint)
router.HandleFunc("GET /v1/accounts/search", placeholderEndpoint)
router.HandleFunc("GET /v1/accounts/lookup", placeholderEndpoint)
router.HandleFunc("GET /v1/bookmarks", placeholderEndpoint)
router.HandleFunc("GET /v1/favourites", placeholderEndpoint)
router.HandleFunc("GET /v1/mutes", placeholderEndpoint)
router.HandleFunc("GET /v1/blocks", placeholderEndpoint)
router.HandleFunc("GET /v1/domain_blocks", placeholderEndpoint)
router.HandleFunc("POST /v1/domain_blocks", placeholderEndpoint)
router.HandleFunc("DELETE /v1/domain_blocks", placeholderEndpoint)
router.HandleFunc("GET /v2/filters", placeholderEndpoint)
router.HandleFunc("GET /v2/filters/{id}", placeholderEndpoint)
router.HandleFunc("POST /v2/filters", placeholderEndpoint)
router.HandleFunc("PUT /v2/filters/{id}", placeholderEndpoint)
router.HandleFunc("DELETE /v2/filters/{id}", placeholderEndpoint)
router.HandleFunc("GET /v2/filters/:filter_id/keywords", placeholderEndpoint)
router.HandleFunc("POST /v2/filters/:filter_id/keywords", placeholderEndpoint)
router.HandleFunc("GET /v2/filters/keywords/{id}", placeholderEndpoint)
router.HandleFunc("PUT /v2/filters/keywords/{id}", placeholderEndpoint)
router.HandleFunc("DELETE /v2/filters/keywords/{id}", placeholderEndpoint)
router.HandleFunc("GET /v2/filters/:filter_id/statuses", placeholderEndpoint)
router.HandleFunc("POST /v2/filters/:filter_id/statuses", placeholderEndpoint)
router.HandleFunc("GET /v2/filters/statuses/{id}", placeholderEndpoint)
router.HandleFunc("DELETE /v2/filters/statuses/{id}", placeholderEndpoint)
router.HandleFunc("POST /v1/reports", placeholderEndpoint)
router.HandleFunc("GET /v1/follow_requests", placeholderEndpoint)
router.HandleFunc("POST /v1/follow_requests/:account_id/authorize", placeholderEndpoint)
router.HandleFunc("POST /v1/follow_requests/:account_id/reject", placeholderEndpoint)
router.HandleFunc("GET /v1/endorsements", placeholderEndpoint)
router.HandleFunc("GET /v1/featured_tags", placeholderEndpoint)
router.HandleFunc("POST /v1/featured_tags", placeholderEndpoint)
router.HandleFunc("DELETE /v1/featured_tags/{id}", placeholderEndpoint)
router.HandleFunc("GET /v1/featured_tags/suggestions", placeholderEndpoint)
router.HandleFunc("GET /v1/preferences", placeholderEndpoint)
router.HandleFunc("GET /v1/followed_tags", placeholderEndpoint)
router.HandleFunc("GET /v2/suggestions", placeholderEndpoint)
router.HandleFunc("DELETE /v1/suggestions/:account_id", placeholderEndpoint)
router.HandleFunc("GET /v1/tags/{id}", placeholderEndpoint)
router.HandleFunc("POST /v1/tags/{id}/follow", placeholderEndpoint)
router.HandleFunc("POST /v1/tags/{id}/unfollow", placeholderEndpoint)
router.HandleFunc("DELETE /v1/profile/avatar", placeholderEndpoint)
router.HandleFunc("DELETE /v1/profile/header", placeholderEndpoint)
router.HandleFunc("POST /v1/statuses", placeholderEndpoint)
router.HandleFunc("GET /v1/statuses/{id}", placeholderEndpoint)
router.HandleFunc("GET /v1/statuses", placeholderEndpoint)
router.HandleFunc("DELETE /v1/statuses/{id}", placeholderEndpoint)
router.HandleFunc("GET /v1/statuses/{id}/context", placeholderEndpoint)
router.HandleFunc("POST /v1/statuses/{id}/translate", placeholderEndpoint)
router.HandleFunc("GET /v1/statuses/{id}/reblogged_by", placeholderEndpoint)
router.HandleFunc("GET /v1/statuses/{id}/favourited_by", placeholderEndpoint)
router.HandleFunc("POST /v1/statuses/{id}/favourite", placeholderEndpoint)
router.HandleFunc("POST /v1/statuses/{id}/unfavourite", placeholderEndpoint)
router.HandleFunc("POST /v1/statuses/{id}/reblog", placeholderEndpoint)
router.HandleFunc("POST /v1/statuses/{id}/unreblog", placeholderEndpoint)
router.HandleFunc("POST /v1/statuses/{id}/bookmark", placeholderEndpoint)
router.HandleFunc("POST /v1/statuses/{id}/unbookmark", placeholderEndpoint)
router.HandleFunc("POST /v1/statuses/{id}/mute", placeholderEndpoint)
router.HandleFunc("POST /v1/statuses/{id}/unmute", placeholderEndpoint)
router.HandleFunc("POST /v1/statuses/{id}/pin", placeholderEndpoint)
router.HandleFunc("POST /v1/statuses/{id}/unpin", placeholderEndpoint)
router.HandleFunc("PUT /v1/statuses/{id}", placeholderEndpoint)
router.HandleFunc("GET /v1/statuses/{id}/history", placeholderEndpoint)
router.HandleFunc("GET /v1/statuses/{id}/source", placeholderEndpoint)
router.HandleFunc("POST /v2/media", placeholderEndpoint)
router.HandleFunc("GET /v1/media/{id}", placeholderEndpoint)
router.HandleFunc("PUT /v1/media/{id}", placeholderEndpoint)
router.HandleFunc("GET /v1/polls/{id}", placeholderEndpoint)
router.HandleFunc("POST /v1/polls/{id}/votes", placeholderEndpoint)
router.HandleFunc("GET /v1/scheduled_statuses", placeholderEndpoint)
router.HandleFunc("GET /v1/scheduled_statuses/{id}", placeholderEndpoint)
router.HandleFunc("PUT /v1/scheduled_statuses/{id}", placeholderEndpoint)
router.HandleFunc("DELETE /v1/scheduled_statuses/{id}", placeholderEndpoint)
router.HandleFunc("GET /v1/timelines/public", placeholderEndpoint)
router.HandleFunc("GET /v1/timelines/tag/:hashtag", placeholderEndpoint)
router.HandleFunc("GET /v1/timelines/home", placeholderEndpoint)
router.HandleFunc("GET /v1/timelines/link", placeholderEndpoint) // ?url=:url
router.HandleFunc("GET /v1/timelines/list/:list_id", placeholderEndpoint)
router.HandleFunc("GET /v1/conversations", placeholderEndpoint)
router.HandleFunc("DELETE /v1/conversations/{id}", placeholderEndpoint)
router.HandleFunc("POST /v1/conversations/{id}/read", placeholderEndpoint)
router.HandleFunc("GET /v1/lists", placeholderEndpoint)
router.HandleFunc("GET /v1/lists/{id}", placeholderEndpoint)
router.HandleFunc("POST /v1/lists", placeholderEndpoint)
router.HandleFunc("PUT /v1/lists/{id}", placeholderEndpoint)
router.HandleFunc("DELETE /v1/lists/{id}", placeholderEndpoint)
router.HandleFunc("GET /v1/lists/{id}/accounts", placeholderEndpoint)
router.HandleFunc("POST /v1/lists/{id}/accounts", placeholderEndpoint)
router.HandleFunc("DELETE /v1/lists/{id}/accounts", placeholderEndpoint)
router.HandleFunc("GET /v1/markers", placeholderEndpoint)
router.HandleFunc("POST /v1/markers", placeholderEndpoint)
router.HandleFunc("GET /v1/streaming/health", placeholderEndpoint)
router.HandleFunc("GET /v1/streaming/user", placeholderEndpoint)
router.HandleFunc("GET /v1/streaming/user/notification", placeholderEndpoint)
router.HandleFunc("GET /v1/streaming/public", placeholderEndpoint)
router.HandleFunc("GET /v1/streaming/public/local", placeholderEndpoint)
router.HandleFunc("GET /v1/streaming/public/remote", placeholderEndpoint)
router.HandleFunc("GET /v1/streaming/hashtag", placeholderEndpoint)
router.HandleFunc("GET /v1/streaming/hashtag/local", placeholderEndpoint)
router.HandleFunc("GET /v1/streaming/list", placeholderEndpoint)
router.HandleFunc("GET /v1/streaming/direct", placeholderEndpoint)
router.HandleFunc("GET /v2/notifications", placeholderEndpoint)
router.HandleFunc("GET /v2/notifications/:group_key", placeholderEndpoint)
router.HandleFunc("POST /v2/notifications/:group_key/dismiss", placeholderEndpoint)
router.HandleFunc("GET /v2/notifications/:group_key/accounts", placeholderEndpoint)
router.HandleFunc("GET /v2/notifications/unread_count", placeholderEndpoint)
router.HandleFunc("GET /v1/notifications", placeholderEndpoint)
router.HandleFunc("GET /v1/notifications/{id}", placeholderEndpoint)
router.HandleFunc("POST /v1/notifications/clear", placeholderEndpoint)
router.HandleFunc("POST /v1/notifications/{id}/dismiss", placeholderEndpoint)
router.HandleFunc("GET /v1/notifications/unread_count", placeholderEndpoint)
router.HandleFunc("GET /v2/notifications/policy", placeholderEndpoint)
router.HandleFunc("PATCH /v2/notifications/policy", placeholderEndpoint)
router.HandleFunc("GET /v1/notifications/requests", placeholderEndpoint)
router.HandleFunc("GET /v1/notifications/requests/{id}", placeholderEndpoint)
router.HandleFunc("POST /v1/notifications/requests/{id}/accept", placeholderEndpoint)
router.HandleFunc("POST /v1/notifications/requests/{id}/dismiss", placeholderEndpoint)
router.HandleFunc("POST /v1/notifications/requests/accept", placeholderEndpoint)
router.HandleFunc("POST /v1/notifications/requests/dismiss", placeholderEndpoint)
router.HandleFunc("GET /v1/notifications/requests/merged", placeholderEndpoint)
router.HandleFunc("POST /v1/push/subscription", placeholderEndpoint)
router.HandleFunc("GET /v1/push/subscription", placeholderEndpoint)
router.HandleFunc("PUT /v1/push/subscription", placeholderEndpoint)
router.HandleFunc("DELETE /v1/push/subscription", placeholderEndpoint)
router.HandleFunc("GET /v2/search", placeholderEndpoint)
router.HandleFunc("GET /v2/instance", placeholderEndpoint)
router.HandleFunc("GET /v1/instance/peers", placeholderEndpoint)
router.HandleFunc("GET /v1/instance/activity", placeholderEndpoint)
router.HandleFunc("GET /v1/instance/rules", placeholderEndpoint)
router.HandleFunc("GET /v1/instance/domain_blocks", placeholderEndpoint)
router.HandleFunc("GET /v1/instance/extended_description", placeholderEndpoint)
router.HandleFunc("GET /v1/instance/translation_languages", placeholderEndpoint)
router.HandleFunc("GET /v1/trends/tags", placeholderEndpoint)
router.HandleFunc("GET /v1/trends/statuses", placeholderEndpoint)
router.HandleFunc("GET /v1/trends/links", placeholderEndpoint)
router.HandleFunc("GET /v1/directory", placeholderEndpoint)
router.HandleFunc("GET /v1/custom_emojis", placeholderEndpoint)
router.HandleFunc("GET /v1/announcements", placeholderEndpoint)
router.HandleFunc("POST /v1/announcements/{id}/dismiss", placeholderEndpoint)
router.HandleFunc("PUT /v1/announcements/{id}/reactions/:name", placeholderEndpoint)
router.HandleFunc("DELETE /v1/announcements/{id}/reactions/:name", placeholderEndpoint)
router.HandleFunc("GET /v1/admin/accounts", placeholderEndpoint)
router.HandleFunc("GET /v2/admin/accounts", placeholderEndpoint)
router.HandleFunc("GET /v1/admin/accounts/{id}", placeholderEndpoint)
router.HandleFunc("POST /v1/admin/accounts/{id}/approve", placeholderEndpoint)
router.HandleFunc("POST /v1/admin/accounts/{id}/reject", placeholderEndpoint)
router.HandleFunc("DELETE /v1/admin/accounts/{id}", placeholderEndpoint)
router.HandleFunc("POST /v1/admin/accounts/{id}/action", placeholderEndpoint)
router.HandleFunc("POST /v1/admin/accounts/{id}/enable", placeholderEndpoint)
router.HandleFunc("POST /v1/admin/accounts/{id}/unsilence", placeholderEndpoint)
router.HandleFunc("POST /v1/admin/accounts/{id}/unsuspend", placeholderEndpoint)
router.HandleFunc("POST /v1/admin/accounts/{id}/unsensitive", placeholderEndpoint)
router.HandleFunc("GET /v1/admin/canonical_email_blocks", placeholderEndpoint)
router.HandleFunc("GET /v1/admin/canonical_email_blocks/{id}", placeholderEndpoint)
router.HandleFunc("POST /v1/admin/canonical_email_blocks/test", placeholderEndpoint)
router.HandleFunc("POST /v1/admin/canonical_email_blocks", placeholderEndpoint)
router.HandleFunc("DELETE /v1/admin/canonical_email_blocks/{id}", placeholderEndpoint)
router.HandleFunc("POST /v1/admin/dimensions", placeholderEndpoint)
router.HandleFunc("GET /v1/admin/domain_allows", placeholderEndpoint)
router.HandleFunc("GET /v1/admin/domain_allows/{id}", placeholderEndpoint)
router.HandleFunc("POST /v1/admin/domain_allows", placeholderEndpoint)
router.HandleFunc("DELETE /v1/admin/domain_allows/{id}", placeholderEndpoint)
router.HandleFunc("GET /v1/admin/domain_blocks", placeholderEndpoint)
router.HandleFunc("GET /v1/admin/domain_blocks/{id}", placeholderEndpoint)
router.HandleFunc("POST /v1/admin/domain_blocks", placeholderEndpoint)
router.HandleFunc("PUT /v1/admin/domain_blocks/{id}", placeholderEndpoint)
router.HandleFunc("DELETE /v1/admin/domain_blocks/{id}", placeholderEndpoint)
router.HandleFunc("GET /v1/admin/email_domain_blocks", placeholderEndpoint)
router.HandleFunc("GET /v1/admin/email_domain_blocks/{id}", placeholderEndpoint)
router.HandleFunc("POST /v1/admin/email_domain_blocks", placeholderEndpoint)
router.HandleFunc("DELETE /v1/admin/email_domain_blocks/{id}", placeholderEndpoint)
router.HandleFunc("GET /v1/admin/ip_blocks", placeholderEndpoint)
router.HandleFunc("GET /v1/admin/ip_blocks/{id}", placeholderEndpoint)
router.HandleFunc("POST /v1/admin/ip_blocks", placeholderEndpoint)
router.HandleFunc("PUT /v1/admin/ip_blocks/{id}", placeholderEndpoint)
router.HandleFunc("DELETE /v1/admin/ip_blocks/{id}", placeholderEndpoint)
router.HandleFunc("POST /v1/admin/measures", placeholderEndpoint)
router.HandleFunc("GET /v1/admin/reports", placeholderEndpoint)
router.HandleFunc("GET /v1/admin/reports/{id}", placeholderEndpoint)
router.HandleFunc("PUT /v1/admin/reports/{id}", placeholderEndpoint)
router.HandleFunc("POST /v1/admin/reports/{id}/assign_to_self", placeholderEndpoint)
router.HandleFunc("POST /v1/admin/reports/{id}/unassign", placeholderEndpoint)
router.HandleFunc("POST /v1/admin/reports/{id}/resolve", placeholderEndpoint)
router.HandleFunc("POST /v1/admin/reports/{id}/reopen", placeholderEndpoint)
router.HandleFunc("POST /v1/admin/retention", placeholderEndpoint)
router.HandleFunc("GET /v1/admin/trends/links", placeholderEndpoint)
router.HandleFunc("GET /v1/admin/trends/statuses", placeholderEndpoint)
router.HandleFunc("GET /v1/admin/trends/tags", placeholderEndpoint)
router.HandleFunc("GET /oembed", placeholderEndpoint)
router.HandleFunc(
"GET /v1/accounts/{id}/identity_proofs",
placeholderEndpoint,
) // Deprecated
router.HandleFunc(
"GET /v1/filters",
placeholderEndpoint,
) // Deprecated
router.HandleFunc(
"GET /v1/filters/{id}",
placeholderEndpoint,
) // Deprecated
router.HandleFunc(
"POST /v1/filters",
placeholderEndpoint,
) // Deprecated
router.HandleFunc(
"PUT /v1/filters/{id}",
placeholderEndpoint,
) // Deprecated
router.HandleFunc(
"DELETE /v1/filters/{id}",
placeholderEndpoint,
) // Deprecated
router.HandleFunc(
"GET /v1/suggestions",
placeholderEndpoint,
) // Deprecated
router.HandleFunc(
"GET /v1/statuses/{id}/card",
placeholderEndpoint,
) // Deprecated
router.HandleFunc(
"POST /v1/media",
placeholderEndpoint,
) // Deprecated
router.HandleFunc(
"GET /v1/timelines/direct",
placeholderEndpoint,
) // Deprecated
router.HandleFunc(
"POST /v1/notifications/dismiss",
placeholderEndpoint,
) // Removed
router.HandleFunc(
"GET /v1/search",
placeholderEndpoint,
) // Removed
router.HandleFunc(
"GET /v1/instance",
placeholderEndpoint,
) // Deprecated
router.HandleFunc(
"GET /proofs",
placeholderEndpoint,
) // Removed
return router
}

View file

@ -1,14 +0,0 @@
package server
import (
"io/fs"
"net/http"
)
func setupFrontendRouter(interactiveFs, noscriptFs fs.FS) http.Handler {
router := http.NewServeMux()
router.Handle("/noscript/", http.StripPrefix("/noscript", http.FileServerFS(noscriptFs)))
router.Handle("/", http.FileServerFS(interactiveFs))
return router
}

22
server/frontendRouter.go Normal file
View file

@ -0,0 +1,22 @@
package server
import (
"io/fs"
"net/http"
)
// Mounted at /
func setupFrontendRouter(interactiveFs, noscriptFs fs.FS) http.Handler {
router := http.NewServeMux()
router.Handle("/noscript/", http.StripPrefix("/noscript", http.FileServerFS(noscriptFs)))
router.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
http.ServeFileFS(w, r, interactiveFs, "index.html")
})
router.Handle("/assets/", http.FileServerFS(interactiveFs))
router.HandleFunc(
"/robots.txt",
func(w http.ResponseWriter, r *http.Request) { http.ServeFileFS(w, r, interactiveFs, "robots.txt") },
)
return router
}

View file

@ -12,8 +12,10 @@ import (
"gitlab.com/mstarongitlab/goutils/other"
)
// Mounted at /profiling
func setupProfilingHandler() http.Handler {
router := http.NewServeMux()
router.HandleFunc("/", profilingRootHandler)
router.HandleFunc("GET /current-goroutines", metricActiveGoroutinesHandler)
router.HandleFunc("GET /memory", metricMemoryStatsHandler)
router.HandleFunc("GET /pprof/cpu", pprof.Profile)
@ -28,6 +30,13 @@ func isAliveHandler(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, "yup")
}
func profilingRootHandler(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(
w,
"Endpoints: /, /{memory,current-goroutines}, /pprof/{cpu,memory,goroutines,blockers}",
)
}
func metricActiveGoroutinesHandler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "{\"goroutines\": %d}", runtime.NumGoroutine())
}

View file

@ -4,11 +4,13 @@ import (
"context"
"net/http"
"slices"
"strings"
"time"
"github.com/rs/zerolog/hlog"
"github.com/rs/zerolog/log"
"gitlab.com/mstarongitlab/goutils/other"
"gitlab.com/mstarongitlab/linstrom/config"
)
type HandlerBuilder func(http.Handler) http.Handler
@ -38,6 +40,9 @@ func LoggingMiddleware(handler http.Handler) http.Handler {
return ChainMiddlewares(handler,
hlog.NewHandler(log.Logger),
hlog.AccessHandler(func(r *http.Request, status, size int, duration time.Duration) {
if strings.HasPrefix(r.URL.Path, "/assets") {
return
}
hlog.FromRequest(r).Info().
Str("method", r.Method).
Stringer("url", r.URL).
@ -85,3 +90,13 @@ func passkeyIdToAccountIdTransformerMiddleware(handler http.Handler) http.Handle
handler.ServeHTTP(w, r)
})
}
func profilingAuthenticationMiddleware(handler http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.FormValue("password") != config.GlobalConfig.Admin.ProfilingPassword {
other.HttpErr(w, HttpErrIdNotAuthenticated, "Bad password", http.StatusUnauthorized)
return
}
handler.ServeHTTP(w, r)
})
}

View file

@ -7,7 +7,6 @@ import (
"github.com/mstarongithub/passkey"
"github.com/rs/zerolog/log"
"gitlab.com/mstarongitlab/goutils/other"
"gitlab.com/mstarongitlab/linstrom/config"
"gitlab.com/mstarongitlab/linstrom/storage"
)
@ -33,17 +32,13 @@ func buildRootHandler(pkey *passkey.Passkey, reactiveFS, staticFS fs.FS) http.Ha
mux.Handle("/", setupFrontendRouter(reactiveFS, staticFS))
mux.Handle("/pk/", http.StripPrefix("/pk", http.FileServer(http.Dir("pk-auth"))))
mux.HandleFunc("/alive", isAliveHandler)
mux.Handle("/api/", http.StripPrefix("/api", setupApiRouter()))
profilingHandler := setupProfilingHandler()
mux.Handle("/profiling/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// Only allow access to profiling if a password is provided and it matches the one in the config
if r.FormValue("password") != config.GlobalConfig.Admin.ProfilingPassword {
// Specifically reply with a plain 404
http.Error(w, "", 404)
return
}
profilingHandler.ServeHTTP(w, r)
}))
mux.Handle(
"/profiling/",
http.StripPrefix("/profiling", profilingAuthenticationMiddleware(setupProfilingHandler())),
)
// temporary until proper route structure exists
mux.Handle(
"/authonly/",
pkey.Auth(

33
server/utils.go Normal file
View file

@ -0,0 +1,33 @@
package server
import (
"net/http"
"github.com/rs/zerolog/hlog"
"gitlab.com/mstarongitlab/goutils/other"
"gitlab.com/mstarongitlab/linstrom/storage"
)
func placeholderEndpoint(w http.ResponseWriter, r *http.Request) {
hlog.FromRequest(r).Error().Stringer("url", r.URL).Msg("Placeholder endpoint accessed")
other.HttpErr(
w,
HttpErrIdPlaceholder,
"Endpoint not implemented yet, this is a placeholder",
http.StatusInternalServerError,
)
}
func getStorageFromRequest(w http.ResponseWriter, r *http.Request) *storage.Storage {
store, ok := r.Context().Value(ContextKeyStorage).(*storage.Storage)
if !ok {
other.HttpErr(
w,
HttpErrIdMissingContextValue,
"Missing storage in context",
http.StatusInternalServerError,
)
return nil
}
return store
}

12
storage/emote.go Normal file
View file

@ -0,0 +1,12 @@
package storage
import "gorm.io/gorm"
type Emote struct {
gorm.Model
// Metadata MediaMetadata // `gorm:"foreignKey:MetadataId"`
MetadataId string
Name string
// Server RemoteServer // `gorm:"foreignKey:ServerId;references:ID"`
ServerId string
}

View file

@ -22,7 +22,8 @@ type Note struct {
// Soft delete means that this entry still exists in the db, but gorm won't include it anymore unless specifically told to
// If not null, this entry is marked as deleted
DeletedAt gorm.DeletedAt `gorm:"index"`
Creator string // Id of the author in the db, not the handle
// Creator Account // `gorm:"foreignKey:CreatorId;references:ID"` // Account that created the post
CreatorId string
Remote bool // Whether the note is originally a remote one and just "cached"
// Raw content of the note. So without additional formatting applied
// Might already have formatting applied beforehand from the origin server

View file

@ -1,30 +1,21 @@
package storage
import (
"time"
"gorm.io/gorm"
)
type RemoteServer struct {
ID string `gorm:"primarykey"` // ID is also server url
CreatedAt time.Time // When this entry was created
UpdatedAt time.Time // When this entry was last updated
// When this entry was deleted (for soft deletions)
// Soft delete means that this entry still exists in the db, but gorm won't include it anymore unless specifically told to
// If not null, this entry is marked as deleted
DeletedAt gorm.DeletedAt `gorm:"index"`
gorm.Model
ServerType RemoteServerType // What software the server is running. Useful for formatting
Domain string // `gorm:"primaryKey"` // Domain the server exists under. Additional primary key
Name string // What the server wants to be known as (usually same as url)
Icon string // ID of a media file
IsSelf bool // Whether this server is yours truly
}
func (s *Storage) FindRemoteServer(url string) (*RemoteServer, error) {
server := RemoteServer{
ID: url,
}
err := s.db.First(&server).Error
server := RemoteServer{}
err := s.db.Where("domain = ?").First(&server).Error
switch err {
case nil:
return &server, nil
@ -63,7 +54,7 @@ func (s *Storage) NewRemoteServer(
return nil, err
}
server := RemoteServer{
ID: url,
Domain: url,
Name: displayName,
Icon: icon,
ServerType: serverType,

View file

@ -22,7 +22,7 @@ type Role struct {
gorm.Model
// Name of the role
Name string
Name string `gorm:"primaryKey"`
// Priority of the role
// Lower priority gets applied first and thus overwritten by higher priority ones

View file

@ -6,12 +6,21 @@
package storage
import (
"crypto/ed25519"
"fmt"
"github.com/rs/zerolog/log"
"gitlab.com/mstarongitlab/linstrom/config"
"gitlab.com/mstarongitlab/linstrom/storage/cache"
"gorm.io/driver/postgres"
"gorm.io/gorm"
)
// Always keep a reference of the server's own RemoteServer entry here
// Removes the need to perform a db request every time a new local anything
// is created
var serverSelf RemoteServer
// Storage is responsible for all database, cache and media related actions
// and serves as the lowest layer of the cake
type Storage struct {
@ -36,10 +45,78 @@ func NewStorage(dbUrl string, cache *cache.Cache) (*Storage, error) {
InboundJob{},
OutboundJob{},
AccessToken{},
Emote{},
)
if err != nil {
return nil, fmt.Errorf("failed to apply migrations: %w", err)
}
s := &Storage{db, cache}
if err = s.insertSelfFromConfig(); err != nil {
return nil, err
}
return &Storage{db, cache}, nil
return s, nil
}
func (s *Storage) insertSelfFromConfig() error {
const ServerActorId = "self"
var err error
// Insert server info
serverData := RemoteServer{}
err = s.db.Where("id = 1").
Attrs(RemoteServer{
Domain: config.GlobalConfig.General.GetFullDomain(),
}).
Assign(RemoteServer{
IsSelf: true,
Name: config.GlobalConfig.Self.ServerDisplayName,
// Icon: "", // TODO: Set to server icon media
}).FirstOrCreate(&serverData).Error
if err != nil {
return err
}
// Set module specific global var
serverSelf = serverData
// Insert server actor
serverActor := Account{}
serverActorPublicKey, serverActorPrivateKey, err := ed25519.GenerateKey(nil)
if err != nil {
return err
}
err = s.db.Where(Account{ID: ServerActorId}).
// Values to always (re)set after launch
Assign(Account{
DisplayName: config.GlobalConfig.Self.ServerActorDisplayName,
// Server: serverData,
ServerId: serverData.ID,
// CustomFields: []uint{},
Description: "Server actor of a Linstrom server",
// Tags: []string{},
IsBot: true,
// Followers: []string{},
// Follows: []string{},
// Icon: "", // TODO: Replace with reference to server icon
// Background: "", // TODO: Replace with reference to background media
// Banner: "", // TODO: Replace with reference to banner media
Indexable: false,
RestrictedFollow: false,
IdentifiesAs: []Being{},
Gender: []string{},
Roles: []string{}, // TODO: Add server actor role once created
}).
// Values that'll only be set on first creation
Attrs(Account{
PublicKey: serverActorPublicKey,
PrivateKey: serverActorPrivateKey,
}).
FirstOrCreate(&serverActor).Error
if err != nil {
return err
}
return nil
}

View file

@ -32,8 +32,8 @@ type Account struct {
// Soft delete means that this entry still exists in the db, but gorm won't include it anymore unless specifically told to
// If not null, this entry is marked as deleted
DeletedAt gorm.DeletedAt `gorm:"index"`
Remote bool // Whether the account is a local or remote one
Server string // The url of the server this account is from
// Server RemoteServer // `gorm:"foreignKey:ServerId;references:ID"` // The server this user is from
ServerId uint // Id of the server this user is from, needed for including RemoteServer
DisplayName string // The display name of the user. Can be different from the handle
CustomFields []uint `gorm:"serializer:json"` // IDs to the custom fields a user has
Description string // The description of a user account
@ -346,8 +346,8 @@ func (s *Storage) NewLocalAccount(handle string) (*Account, error) {
return nil, err
}
acc.Username = handle
acc.Server = config.GlobalConfig.General.GetFullDomain()
acc.Remote = false
// acc.Server = serverSelf
acc.ServerId = serverSelf.ID
acc.DisplayName = handle
publicKey, privateKey, err := ed25519.GenerateKey(nil)
@ -419,7 +419,7 @@ func (s *Storage) GetOrCreateUser(userID string) passkey.User {
Str("account-handle", userID).
Msg("Looking for or creating account for passkey stuff")
acc := &Account{}
res := s.db.Where(Account{Username: userID, Server: config.GlobalConfig.General.GetFullDomain()}).
res := s.db.Where(Account{Username: userID, ServerId: serverSelf.ID}).
First(acc)
if errors.Is(res.Error, gorm.ErrRecordNotFound) {
log.Debug().Str("account-handle", userID)