mirror of
https://github.com/versia-pub/versia-go.git
synced 2026-03-13 20:49:15 +01:00
chore: init
This commit is contained in:
commit
320715f3e7
174 changed files with 42083 additions and 0 deletions
33
internal/handlers/follow_handler/handler.go
Normal file
33
internal/handlers/follow_handler/handler.go
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
package follow_handler
|
||||
|
||||
import (
|
||||
"github.com/go-logr/logr"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/lysand-org/versia-go/config"
|
||||
"github.com/lysand-org/versia-go/internal/service"
|
||||
"github.com/lysand-org/versia-go/pkg/webfinger"
|
||||
)
|
||||
|
||||
type Handler struct {
|
||||
followService service.FollowService
|
||||
federationService service.FederationService
|
||||
|
||||
hostMeta webfinger.HostMeta
|
||||
|
||||
log logr.Logger
|
||||
}
|
||||
|
||||
func New(followService service.FollowService, federationService service.FederationService, log logr.Logger) *Handler {
|
||||
return &Handler{
|
||||
followService: followService,
|
||||
federationService: federationService,
|
||||
|
||||
hostMeta: webfinger.NewHostMeta(config.C.PublicAddress),
|
||||
|
||||
log: log.WithName("users"),
|
||||
}
|
||||
}
|
||||
|
||||
func (i *Handler) Register(r fiber.Router) {
|
||||
r.Get("/api/follows/:id", i.GetLysandFollow)
|
||||
}
|
||||
28
internal/handlers/follow_handler/lysand_follow_get.go
Normal file
28
internal/handlers/follow_handler/lysand_follow_get.go
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
package follow_handler
|
||||
|
||||
import (
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/google/uuid"
|
||||
"github.com/lysand-org/versia-go/internal/api_schema"
|
||||
)
|
||||
|
||||
func (i *Handler) GetLysandFollow(c *fiber.Ctx) error {
|
||||
parsedRequestedFollowID, err := uuid.Parse(c.Params("id"))
|
||||
if err != nil {
|
||||
return api_schema.ErrBadRequest(map[string]any{"reason": "Invalid follow ID"})
|
||||
}
|
||||
|
||||
f, err := i.followService.GetFollow(c.UserContext(), parsedRequestedFollowID)
|
||||
if err != nil {
|
||||
i.log.Error(err, "Failed to query follow", "id", parsedRequestedFollowID)
|
||||
|
||||
return api_schema.ErrInternalServerError(map[string]any{"reason": "Failed to query follow"})
|
||||
}
|
||||
if f == nil {
|
||||
return c.Status(fiber.StatusNotFound).JSON(fiber.Map{
|
||||
"error": "Follow not found",
|
||||
})
|
||||
}
|
||||
|
||||
return c.JSON(f.ToLysand())
|
||||
}
|
||||
28
internal/handlers/meta_handler/handler.go
Normal file
28
internal/handlers/meta_handler/handler.go
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
package meta_handler
|
||||
|
||||
import (
|
||||
"github.com/go-logr/logr"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/lysand-org/versia-go/config"
|
||||
"github.com/lysand-org/versia-go/pkg/webfinger"
|
||||
)
|
||||
|
||||
type Handler struct {
|
||||
hostMeta webfinger.HostMeta
|
||||
|
||||
log logr.Logger
|
||||
}
|
||||
|
||||
func New(log logr.Logger) *Handler {
|
||||
return &Handler{
|
||||
hostMeta: webfinger.NewHostMeta(config.C.PublicAddress),
|
||||
|
||||
log: log.WithName("users"),
|
||||
}
|
||||
}
|
||||
|
||||
func (i *Handler) Register(r fiber.Router) {
|
||||
r.Get("/.well-known/lysand", i.GetLysandServerMetadata)
|
||||
r.Get("/.well-known/host-meta", i.GetHostMeta)
|
||||
r.Get("/.well-known/host-meta.json", i.GetHostMetaJSON)
|
||||
}
|
||||
28
internal/handlers/meta_handler/lysand_server_metadata_get.go
Normal file
28
internal/handlers/meta_handler/lysand_server_metadata_get.go
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
package meta_handler
|
||||
|
||||
import (
|
||||
"github.com/Masterminds/semver"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/lysand-org/versia-go/config"
|
||||
"github.com/lysand-org/versia-go/pkg/lysand"
|
||||
)
|
||||
|
||||
func (i *Handler) GetLysandServerMetadata(c *fiber.Ctx) error {
|
||||
return c.JSON(lysand.ServerMetadata{
|
||||
// TODO: Get version from build linker flags
|
||||
Version: semver.MustParse("0.0.0-dev"),
|
||||
|
||||
Name: config.C.InstanceName,
|
||||
Description: config.C.InstanceDescription,
|
||||
Website: lysand.URLFromStd(config.C.PublicAddress),
|
||||
|
||||
// TODO: Get more info
|
||||
Moderators: nil,
|
||||
Admins: nil,
|
||||
Logo: nil,
|
||||
Banner: nil,
|
||||
|
||||
SupportedExtensions: []string{},
|
||||
Extensions: map[string]any{},
|
||||
})
|
||||
}
|
||||
23
internal/handlers/meta_handler/wellknown_host_meta.go
Normal file
23
internal/handlers/meta_handler/wellknown_host_meta.go
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
package meta_handler
|
||||
|
||||
import (
|
||||
"github.com/gofiber/fiber/v2"
|
||||
)
|
||||
|
||||
func (i *Handler) GetHostMeta(c *fiber.Ctx) error {
|
||||
if c.Accepts(fiber.MIMEApplicationJSON) != "" {
|
||||
return i.GetHostMetaJSON(c)
|
||||
}
|
||||
|
||||
if c.Accepts(fiber.MIMEApplicationXML) != "" {
|
||||
c.Set(fiber.HeaderContentType, fiber.MIMEApplicationXMLCharsetUTF8)
|
||||
return c.Send(i.hostMeta.XML)
|
||||
}
|
||||
|
||||
return c.Status(fiber.StatusNotAcceptable).SendString("Not Acceptable")
|
||||
}
|
||||
|
||||
func (i *Handler) GetHostMetaJSON(c *fiber.Ctx) error {
|
||||
c.Set(fiber.HeaderContentType, fiber.MIMEApplicationJSONCharsetUTF8)
|
||||
return c.Send(i.hostMeta.JSON)
|
||||
}
|
||||
32
internal/handlers/note_handler/app_note_create.go
Normal file
32
internal/handlers/note_handler/app_note_create.go
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
package note_handler
|
||||
|
||||
import (
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/lysand-org/versia-go/internal/api_schema"
|
||||
)
|
||||
|
||||
func (i *Handler) CreateNote(c *fiber.Ctx) error {
|
||||
req := api_schema.CreateNoteRequest{}
|
||||
if err := c.BodyParser(&req); err != nil {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
|
||||
"error": "invalid request",
|
||||
})
|
||||
}
|
||||
if err := i.bodyValidator.Validate(req); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
n, err := i.noteService.CreateNote(c.UserContext(), req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if n == nil {
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
|
||||
"error": "failed to create note",
|
||||
})
|
||||
}
|
||||
|
||||
return c.Status(fiber.StatusCreated).JSON(api_schema.Note{
|
||||
ID: n.ID,
|
||||
})
|
||||
}
|
||||
28
internal/handlers/note_handler/app_note_get.go
Normal file
28
internal/handlers/note_handler/app_note_get.go
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
package note_handler
|
||||
|
||||
import (
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/google/uuid"
|
||||
"github.com/lysand-org/versia-go/internal/api_schema"
|
||||
)
|
||||
|
||||
func (i *Handler) GetNote(c *fiber.Ctx) error {
|
||||
parsedRequestedNoteID, err := uuid.Parse(c.Params("id"))
|
||||
if err != nil {
|
||||
return api_schema.ErrBadRequest(map[string]any{
|
||||
"reason": "Invalid note ID",
|
||||
})
|
||||
}
|
||||
|
||||
u, err := i.noteService.GetNote(c.UserContext(), parsedRequestedNoteID)
|
||||
if err != nil {
|
||||
i.log.Error(err, "Failed to query note", "id", parsedRequestedNoteID)
|
||||
|
||||
return api_schema.ErrInternalServerError(map[string]any{"reason": "Failed to query note"})
|
||||
}
|
||||
if u == nil {
|
||||
return api_schema.ErrNotFound(nil)
|
||||
}
|
||||
|
||||
return c.JSON(u.ToLysand())
|
||||
}
|
||||
35
internal/handlers/note_handler/handler.go
Normal file
35
internal/handlers/note_handler/handler.go
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
package note_handler
|
||||
|
||||
import (
|
||||
"github.com/go-logr/logr"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/lysand-org/versia-go/config"
|
||||
"github.com/lysand-org/versia-go/internal/service"
|
||||
"github.com/lysand-org/versia-go/internal/validators"
|
||||
"github.com/lysand-org/versia-go/pkg/webfinger"
|
||||
)
|
||||
|
||||
type Handler struct {
|
||||
noteService service.NoteService
|
||||
bodyValidator validators.BodyValidator
|
||||
|
||||
hostMeta webfinger.HostMeta
|
||||
|
||||
log logr.Logger
|
||||
}
|
||||
|
||||
func New(noteService service.NoteService, bodyValidator validators.BodyValidator, log logr.Logger) *Handler {
|
||||
return &Handler{
|
||||
noteService: noteService,
|
||||
bodyValidator: bodyValidator,
|
||||
|
||||
hostMeta: webfinger.NewHostMeta(config.C.PublicAddress),
|
||||
|
||||
log: log.WithName("users"),
|
||||
}
|
||||
}
|
||||
|
||||
func (i *Handler) Register(r fiber.Router) {
|
||||
r.Get("/api/app/notes/:id", i.GetNote)
|
||||
r.Post("/api/app/notes/", i.CreateNote)
|
||||
}
|
||||
35
internal/handlers/user_handler/app_user_create.go
Normal file
35
internal/handlers/user_handler/app_user_create.go
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
package user_handler
|
||||
|
||||
import (
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/lysand-org/versia-go/ent"
|
||||
"github.com/lysand-org/versia-go/internal/api_schema"
|
||||
)
|
||||
|
||||
func (i *Handler) CreateUser(c *fiber.Ctx) error {
|
||||
var req api_schema.CreateUserRequest
|
||||
if err := c.BodyParser(&req); err != nil {
|
||||
return api_schema.ErrInvalidRequestBody(nil)
|
||||
}
|
||||
|
||||
if err := i.bodyValidator.Validate(req); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
u, err := i.userService.NewUser(c.UserContext(), req.Username, req.Password)
|
||||
if err != nil {
|
||||
// TODO: Wrap this in a custom error
|
||||
if ent.IsConstraintError(err) {
|
||||
return api_schema.ErrUsernameTaken(nil)
|
||||
}
|
||||
|
||||
i.log.Error(err, "Failed to create user", "username", req.Username)
|
||||
|
||||
return api_schema.ErrInternalServerError(nil)
|
||||
}
|
||||
|
||||
return c.JSON(api_schema.User{
|
||||
ID: u.ID,
|
||||
Username: u.Username,
|
||||
})
|
||||
}
|
||||
31
internal/handlers/user_handler/app_user_get.go
Normal file
31
internal/handlers/user_handler/app_user_get.go
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
package user_handler
|
||||
|
||||
import (
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/google/uuid"
|
||||
"github.com/lysand-org/versia-go/internal/api_schema"
|
||||
)
|
||||
|
||||
func (i *Handler) GetUser(c *fiber.Ctx) error {
|
||||
parsedRequestedUserID, err := uuid.Parse(c.Params("id"))
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
|
||||
"error": "Invalid user ID",
|
||||
})
|
||||
}
|
||||
|
||||
u, err := i.userService.GetUserByID(c.UserContext(), parsedRequestedUserID)
|
||||
if err != nil {
|
||||
i.log.Error(err, "Failed to query user", "id", parsedRequestedUserID)
|
||||
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
|
||||
"error": "Failed to query user",
|
||||
})
|
||||
|
||||
}
|
||||
if u == nil {
|
||||
return api_schema.ErrNotFound(map[string]any{"id": parsedRequestedUserID})
|
||||
}
|
||||
|
||||
return c.JSON(u)
|
||||
}
|
||||
46
internal/handlers/user_handler/handler.go
Normal file
46
internal/handlers/user_handler/handler.go
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
package user_handler
|
||||
|
||||
import (
|
||||
"github.com/go-logr/logr"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/lysand-org/versia-go/internal/service"
|
||||
"github.com/lysand-org/versia-go/internal/validators"
|
||||
)
|
||||
|
||||
type Handler struct {
|
||||
userService service.UserService
|
||||
federationService service.FederationService
|
||||
inboxService service.InboxService
|
||||
|
||||
bodyValidator validators.BodyValidator
|
||||
requestValidator validators.RequestValidator
|
||||
|
||||
log logr.Logger
|
||||
}
|
||||
|
||||
func New(userService service.UserService, federationService service.FederationService, inboxService service.InboxService, bodyValidator validators.BodyValidator, requestValidator validators.RequestValidator, log logr.Logger) *Handler {
|
||||
return &Handler{
|
||||
userService: userService,
|
||||
federationService: federationService,
|
||||
inboxService: inboxService,
|
||||
|
||||
bodyValidator: bodyValidator,
|
||||
requestValidator: requestValidator,
|
||||
|
||||
log: log,
|
||||
}
|
||||
}
|
||||
|
||||
func (i *Handler) Register(r fiber.Router) {
|
||||
// TODO: Handle this differently
|
||||
// There might be other routes that might want to also add their stuff to the robots.txt
|
||||
r.Get("/robots.txt", i.RobotsTXT)
|
||||
|
||||
r.Get("/.well-known/webfinger", i.Webfinger)
|
||||
|
||||
r.Get("/api/app/users/:id", i.GetUser)
|
||||
r.Post("/api/app/users/", i.CreateUser)
|
||||
|
||||
r.Get("/api/users/:id", i.GetLysandUser)
|
||||
r.Post("/api/users/:id/inbox", i.LysandInbox)
|
||||
}
|
||||
57
internal/handlers/user_handler/lysand_inbox.go
Normal file
57
internal/handlers/user_handler/lysand_inbox.go
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
package user_handler
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/lysand-org/versia-go/internal/validators/val_impls"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/google/uuid"
|
||||
"github.com/lysand-org/versia-go/internal/api_schema"
|
||||
"github.com/lysand-org/versia-go/pkg/lysand"
|
||||
)
|
||||
|
||||
func (i *Handler) LysandInbox(c *fiber.Ctx) error {
|
||||
if err := i.requestValidator.ValidateFiberCtx(c.UserContext(), c); err != nil {
|
||||
if errors.Is(err, val_impls.ErrInvalidSignature) {
|
||||
i.log.Error(err, "Invalid signature")
|
||||
return c.SendStatus(fiber.StatusUnauthorized)
|
||||
}
|
||||
|
||||
i.log.Error(err, "Failed to validate signature")
|
||||
return err
|
||||
}
|
||||
|
||||
var raw json.RawMessage
|
||||
if err := json.Unmarshal(c.Body(), &raw); err != nil {
|
||||
i.log.Error(err, "Failed to unmarshal inbox object")
|
||||
return api_schema.ErrBadRequest(nil)
|
||||
}
|
||||
|
||||
obj, err := lysand.ParseInboxObject(raw)
|
||||
if err != nil {
|
||||
i.log.Error(err, "Failed to parse inbox object")
|
||||
|
||||
if errors.Is(err, lysand.ErrUnknownType{}) {
|
||||
return api_schema.ErrNotFound(map[string]any{
|
||||
"error": fmt.Sprintf("Unknown object type: %s", err.(lysand.ErrUnknownType).Type),
|
||||
})
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
userId, err := uuid.Parse(c.Params("id"))
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
|
||||
"error": "Invalid user ID",
|
||||
})
|
||||
}
|
||||
|
||||
if err := i.inboxService.Handle(c.UserContext(), obj, userId); err != nil {
|
||||
i.log.Error(err, "Failed to handle inbox", "user", userId)
|
||||
}
|
||||
|
||||
return c.SendStatus(fiber.StatusOK)
|
||||
}
|
||||
31
internal/handlers/user_handler/lysand_user_get.go
Normal file
31
internal/handlers/user_handler/lysand_user_get.go
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
package user_handler
|
||||
|
||||
import (
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/google/uuid"
|
||||
"github.com/lysand-org/versia-go/internal/api_schema"
|
||||
)
|
||||
|
||||
func (i *Handler) GetLysandUser(c *fiber.Ctx) error {
|
||||
parsedRequestedUserID, err := uuid.Parse(c.Params("id"))
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
|
||||
"error": "Invalid user ID",
|
||||
})
|
||||
}
|
||||
|
||||
u, err := i.userService.GetUserByID(c.UserContext(), parsedRequestedUserID)
|
||||
if err != nil {
|
||||
i.log.Error(err, "Failed to query user", "id", parsedRequestedUserID)
|
||||
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
|
||||
"error": "Failed to query user",
|
||||
"id": parsedRequestedUserID,
|
||||
})
|
||||
}
|
||||
if u == nil {
|
||||
return api_schema.ErrNotFound(map[string]any{"id": parsedRequestedUserID})
|
||||
}
|
||||
|
||||
return c.JSON(u.ToLysand())
|
||||
}
|
||||
9
internal/handlers/user_handler/robots_txt.go
Normal file
9
internal/handlers/user_handler/robots_txt.go
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
package user_handler
|
||||
|
||||
import (
|
||||
"github.com/gofiber/fiber/v2"
|
||||
)
|
||||
|
||||
func (i *Handler) RobotsTXT(c *fiber.Ctx) error {
|
||||
return c.SendString("")
|
||||
}
|
||||
32
internal/handlers/user_handler/wellknown_webfinger.go
Normal file
32
internal/handlers/user_handler/wellknown_webfinger.go
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
package user_handler
|
||||
|
||||
import (
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/lysand-org/versia-go/config"
|
||||
"github.com/lysand-org/versia-go/internal/helpers"
|
||||
"github.com/lysand-org/versia-go/pkg/webfinger"
|
||||
)
|
||||
|
||||
func (i *Handler) Webfinger(c *fiber.Ctx) error {
|
||||
userID, err := webfinger.ParseResource(c.Query("resource"))
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(webfinger.Response{
|
||||
Error: helpers.StringPtr(err.Error()),
|
||||
})
|
||||
}
|
||||
|
||||
if userID.Domain != config.C.PublicAddress.Host {
|
||||
return c.Status(fiber.StatusNotFound).JSON(webfinger.Response{
|
||||
Error: helpers.StringPtr("The requested user is a remote user"),
|
||||
})
|
||||
}
|
||||
|
||||
wf, err := i.userService.GetWebfingerForUser(c.UserContext(), userID.ID)
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(webfinger.Response{
|
||||
Error: helpers.StringPtr("Failed to query user"),
|
||||
})
|
||||
}
|
||||
|
||||
return c.JSON(wf.WebFingerResource())
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue