Compare commits

...

7 commits

Author SHA1 Message Date
671d18d2ba
Add note info stuff to debug server. Also docs
Some checks are pending
/ test (push) Waiting to run
2025-04-08 16:33:47 +02:00
9990a205d8
Fix interface name typo 2025-04-08 16:33:37 +02:00
a7dab0fe43
Add note interface 2025-04-08 16:33:26 +02:00
a4ab7f0294
Fix parsing error 2025-04-08 16:32:38 +02:00
91ff8d2ea1
Regenerate 2025-04-08 16:32:31 +02:00
115a167e75
Formatting 2025-04-08 16:32:17 +02:00
b0db12490c
Fix optional types and access func 2025-04-08 16:31:47 +02:00
18 changed files with 267 additions and 23 deletions

View file

@ -49,6 +49,7 @@ func main() {
g.ApplyInterface(func(models.INotification) {}, models.Notification{}) g.ApplyInterface(func(models.INotification) {}, models.Notification{})
g.ApplyInterface(func(models.IUser) {}, models.User{}) g.ApplyInterface(func(models.IUser) {}, models.User{})
g.ApplyInterface(func(models.IAccessToken) {}, models.AccessToken{}) g.ApplyInterface(func(models.IAccessToken) {}, models.AccessToken{})
g.ApplyInterface(func(models.INote) {}, models.Note{})
log.Info().Msg("Extra features applied, starting generation") log.Info().Msg("Extra features applied, starting generation")
g.Execute() g.Execute()

View file

@ -4,6 +4,6 @@ type Clonable interface {
Clone() Clonable Clone() Clonable
} }
type Santisable interface { type Sanitisable interface {
Sanitize() Sanitize()
} }

View file

@ -255,6 +255,11 @@ func newNoteTag(db *gorm.DB, opts ...gen.DOOption) noteTag {
}, },
}, },
}, },
Origin: struct {
field.RelationField
}{
RelationField: field.NewRelation("Note.Origin", "models.RemoteServer"),
},
AttachmentRelations: struct { AttachmentRelations: struct {
field.RelationField field.RelationField
Note struct { Note struct {
@ -497,6 +502,9 @@ type noteTagBelongsToNote struct {
} }
} }
} }
Origin struct {
field.RelationField
}
AttachmentRelations struct { AttachmentRelations struct {
field.RelationField field.RelationField
Note struct { Note struct {

View file

@ -255,6 +255,11 @@ func newNoteToAttachment(db *gorm.DB, opts ...gen.DOOption) noteToAttachment {
}, },
}, },
}, },
Origin: struct {
field.RelationField
}{
RelationField: field.NewRelation("Note.Origin", "models.RemoteServer"),
},
AttachmentRelations: struct { AttachmentRelations: struct {
field.RelationField field.RelationField
Note struct { Note struct {
@ -505,6 +510,9 @@ type noteToAttachmentBelongsToNote struct {
} }
} }
} }
Origin struct {
field.RelationField
}
AttachmentRelations struct { AttachmentRelations struct {
field.RelationField field.RelationField
Note struct { Note struct {

View file

@ -193,6 +193,11 @@ func newNoteToBoost(db *gorm.DB, opts ...gen.DOOption) noteToBoost {
}{ }{
RelationField: field.NewRelation("Note.Creator", "models.User"), RelationField: field.NewRelation("Note.Creator", "models.User"),
}, },
Origin: struct {
field.RelationField
}{
RelationField: field.NewRelation("Note.Origin", "models.RemoteServer"),
},
AttachmentRelations: struct { AttachmentRelations: struct {
field.RelationField field.RelationField
Note struct { Note struct {
@ -512,6 +517,9 @@ type noteToBoostBelongsToNote struct {
Creator struct { Creator struct {
field.RelationField field.RelationField
} }
Origin struct {
field.RelationField
}
AttachmentRelations struct { AttachmentRelations struct {
field.RelationField field.RelationField
Note struct { Note struct {

View file

@ -255,6 +255,11 @@ func newNoteToEmote(db *gorm.DB, opts ...gen.DOOption) noteToEmote {
}, },
}, },
}, },
Origin: struct {
field.RelationField
}{
RelationField: field.NewRelation("Note.Origin", "models.RemoteServer"),
},
AttachmentRelations: struct { AttachmentRelations: struct {
field.RelationField field.RelationField
Note struct { Note struct {
@ -505,6 +510,9 @@ type noteToEmoteBelongsToNote struct {
} }
} }
} }
Origin struct {
field.RelationField
}
AttachmentRelations struct { AttachmentRelations struct {
field.RelationField field.RelationField
Note struct { Note struct {

View file

@ -255,6 +255,11 @@ func newNoteToFeed(db *gorm.DB, opts ...gen.DOOption) noteToFeed {
}, },
}, },
}, },
Origin: struct {
field.RelationField
}{
RelationField: field.NewRelation("Note.Origin", "models.RemoteServer"),
},
AttachmentRelations: struct { AttachmentRelations: struct {
field.RelationField field.RelationField
Note struct { Note struct {
@ -497,6 +502,9 @@ type noteToFeedBelongsToNote struct {
} }
} }
} }
Origin struct {
field.RelationField
}
AttachmentRelations struct { AttachmentRelations struct {
field.RelationField field.RelationField
Note struct { Note struct {

View file

@ -255,6 +255,11 @@ func newNoteToPing(db *gorm.DB, opts ...gen.DOOption) noteToPing {
}, },
}, },
}, },
Origin: struct {
field.RelationField
}{
RelationField: field.NewRelation("Note.Origin", "models.RemoteServer"),
},
AttachmentRelations: struct { AttachmentRelations: struct {
field.RelationField field.RelationField
Note struct { Note struct {
@ -505,6 +510,9 @@ type noteToPingBelongsToNote struct {
} }
} }
} }
Origin struct {
field.RelationField
}
AttachmentRelations struct { AttachmentRelations struct {
field.RelationField field.RelationField
Note struct { Note struct {

View file

@ -6,6 +6,7 @@ package dbgen
import ( import (
"context" "context"
"strings"
"git.mstar.dev/mstar/linstrom/storage-new/models" "git.mstar.dev/mstar/linstrom/storage-new/models"
"gorm.io/gorm" "gorm.io/gorm"
@ -33,11 +34,11 @@ func newNote(db *gorm.DB, opts ...gen.DOOption) note {
_note.CreatorId = field.NewString(tableName, "creator_id") _note.CreatorId = field.NewString(tableName, "creator_id")
_note.Remote = field.NewBool(tableName, "remote") _note.Remote = field.NewBool(tableName, "remote")
_note.RawContent = field.NewString(tableName, "raw_content") _note.RawContent = field.NewString(tableName, "raw_content")
_note.ContentWarning = field.NewString(tableName, "content_warning") _note.ContentWarning = field.NewField(tableName, "content_warning")
_note.RepliesTo = field.NewString(tableName, "replies_to") _note.RepliesTo = field.NewField(tableName, "replies_to")
_note.Quotes = field.NewString(tableName, "quotes") _note.Quotes = field.NewField(tableName, "quotes")
_note.AccessLevel = field.NewField(tableName, "access_level") _note.AccessLevel = field.NewField(tableName, "access_level")
_note.OriginServer = field.NewString(tableName, "origin_server") _note.OriginId = field.NewUint(tableName, "origin_id")
_note.AttachmentRelations = noteHasManyAttachmentRelations{ _note.AttachmentRelations = noteHasManyAttachmentRelations{
db: db.Session(&gorm.Session{}), db: db.Session(&gorm.Session{}),
@ -116,6 +117,9 @@ func newNote(db *gorm.DB, opts ...gen.DOOption) note {
} }
} }
} }
Origin struct {
field.RelationField
}
AttachmentRelations struct { AttachmentRelations struct {
field.RelationField field.RelationField
} }
@ -373,6 +377,11 @@ func newNote(db *gorm.DB, opts ...gen.DOOption) note {
}, },
}, },
}, },
Origin: struct {
field.RelationField
}{
RelationField: field.NewRelation("AttachmentRelations.Note.Origin", "models.RemoteServer"),
},
AttachmentRelations: struct { AttachmentRelations: struct {
field.RelationField field.RelationField
}{ }{
@ -487,6 +496,12 @@ func newNote(db *gorm.DB, opts ...gen.DOOption) note {
RelationField: field.NewRelation("Creator", "models.User"), RelationField: field.NewRelation("Creator", "models.User"),
} }
_note.Origin = noteBelongsToOrigin{
db: db.Session(&gorm.Session{}),
RelationField: field.NewRelation("Origin", "models.RemoteServer"),
}
_note.fillFieldMap() _note.fillFieldMap()
return _note return _note
@ -503,11 +518,11 @@ type note struct {
CreatorId field.String CreatorId field.String
Remote field.Bool Remote field.Bool
RawContent field.String RawContent field.String
ContentWarning field.String ContentWarning field.Field
RepliesTo field.String RepliesTo field.Field
Quotes field.String Quotes field.Field
AccessLevel field.Field AccessLevel field.Field
OriginServer field.String OriginId field.Uint
AttachmentRelations noteHasManyAttachmentRelations AttachmentRelations noteHasManyAttachmentRelations
EmoteRelations noteHasManyEmoteRelations EmoteRelations noteHasManyEmoteRelations
@ -518,6 +533,8 @@ type note struct {
Creator noteBelongsToCreator Creator noteBelongsToCreator
Origin noteBelongsToOrigin
fieldMap map[string]field.Expr fieldMap map[string]field.Expr
} }
@ -540,11 +557,11 @@ func (n *note) updateTableName(table string) *note {
n.CreatorId = field.NewString(table, "creator_id") n.CreatorId = field.NewString(table, "creator_id")
n.Remote = field.NewBool(table, "remote") n.Remote = field.NewBool(table, "remote")
n.RawContent = field.NewString(table, "raw_content") n.RawContent = field.NewString(table, "raw_content")
n.ContentWarning = field.NewString(table, "content_warning") n.ContentWarning = field.NewField(table, "content_warning")
n.RepliesTo = field.NewString(table, "replies_to") n.RepliesTo = field.NewField(table, "replies_to")
n.Quotes = field.NewString(table, "quotes") n.Quotes = field.NewField(table, "quotes")
n.AccessLevel = field.NewField(table, "access_level") n.AccessLevel = field.NewField(table, "access_level")
n.OriginServer = field.NewString(table, "origin_server") n.OriginId = field.NewUint(table, "origin_id")
n.fillFieldMap() n.fillFieldMap()
@ -561,7 +578,7 @@ func (n *note) GetFieldByName(fieldName string) (field.OrderExpr, bool) {
} }
func (n *note) fillFieldMap() { func (n *note) fillFieldMap() {
n.fieldMap = make(map[string]field.Expr, 17) n.fieldMap = make(map[string]field.Expr, 18)
n.fieldMap["id"] = n.ID n.fieldMap["id"] = n.ID
n.fieldMap["created_at"] = n.CreatedAt n.fieldMap["created_at"] = n.CreatedAt
n.fieldMap["updated_at"] = n.UpdatedAt n.fieldMap["updated_at"] = n.UpdatedAt
@ -573,7 +590,7 @@ func (n *note) fillFieldMap() {
n.fieldMap["replies_to"] = n.RepliesTo n.fieldMap["replies_to"] = n.RepliesTo
n.fieldMap["quotes"] = n.Quotes n.fieldMap["quotes"] = n.Quotes
n.fieldMap["access_level"] = n.AccessLevel n.fieldMap["access_level"] = n.AccessLevel
n.fieldMap["origin_server"] = n.OriginServer n.fieldMap["origin_id"] = n.OriginId
} }
@ -666,6 +683,9 @@ type noteHasManyAttachmentRelations struct {
} }
} }
} }
Origin struct {
field.RelationField
}
AttachmentRelations struct { AttachmentRelations struct {
field.RelationField field.RelationField
} }
@ -1054,6 +1074,77 @@ func (a noteBelongsToCreatorTx) Count() int64 {
return a.tx.Count() return a.tx.Count()
} }
type noteBelongsToOrigin struct {
db *gorm.DB
field.RelationField
}
func (a noteBelongsToOrigin) Where(conds ...field.Expr) *noteBelongsToOrigin {
if len(conds) == 0 {
return &a
}
exprs := make([]clause.Expression, 0, len(conds))
for _, cond := range conds {
exprs = append(exprs, cond.BeCond().(clause.Expression))
}
a.db = a.db.Clauses(clause.Where{Exprs: exprs})
return &a
}
func (a noteBelongsToOrigin) WithContext(ctx context.Context) *noteBelongsToOrigin {
a.db = a.db.WithContext(ctx)
return &a
}
func (a noteBelongsToOrigin) Session(session *gorm.Session) *noteBelongsToOrigin {
a.db = a.db.Session(session)
return &a
}
func (a noteBelongsToOrigin) Model(m *models.Note) *noteBelongsToOriginTx {
return &noteBelongsToOriginTx{a.db.Model(m).Association(a.Name())}
}
type noteBelongsToOriginTx struct{ tx *gorm.Association }
func (a noteBelongsToOriginTx) Find() (result *models.RemoteServer, err error) {
return result, a.tx.Find(&result)
}
func (a noteBelongsToOriginTx) Append(values ...*models.RemoteServer) (err error) {
targetValues := make([]interface{}, len(values))
for i, v := range values {
targetValues[i] = v
}
return a.tx.Append(targetValues...)
}
func (a noteBelongsToOriginTx) Replace(values ...*models.RemoteServer) (err error) {
targetValues := make([]interface{}, len(values))
for i, v := range values {
targetValues[i] = v
}
return a.tx.Replace(targetValues...)
}
func (a noteBelongsToOriginTx) Delete(values ...*models.RemoteServer) (err error) {
targetValues := make([]interface{}, len(values))
for i, v := range values {
targetValues[i] = v
}
return a.tx.Delete(targetValues...)
}
func (a noteBelongsToOriginTx) Clear() error {
return a.tx.Clear()
}
func (a noteBelongsToOriginTx) Count() int64 {
return a.tx.Count()
}
type noteDo struct{ gen.DO } type noteDo struct{ gen.DO }
type INoteDo interface { type INoteDo interface {
@ -1115,6 +1206,30 @@ type INoteDo interface {
Returning(value interface{}, columns ...string) INoteDo Returning(value interface{}, columns ...string) INoteDo
UnderlyingDB() *gorm.DB UnderlyingDB() *gorm.DB
schema.Tabler schema.Tabler
GetNotesPaged(userId string, pageNr uint, accessLevel uint8) (result []models.Note, err error)
}
// Get all notes by a user, paged, that are a specific access level.
// Ordered by age, descending (newest first)
//
// SELECT * FROM @@table
// WHERE creator_id = @userId AND access_level = @accessLevel
// ORDER BY created_at DESC LIMIT 50 OFFSET @pageNr * 50
func (n noteDo) GetNotesPaged(userId string, pageNr uint, accessLevel uint8) (result []models.Note, err error) {
var params []interface{}
var generateSQL strings.Builder
params = append(params, userId)
params = append(params, accessLevel)
params = append(params, pageNr)
generateSQL.WriteString("SELECT * FROM notes WHERE creator_id = ? AND access_level = ? ORDER BY created_at DESC LIMIT 50 OFFSET ? * 50 ")
var executeSQL *gorm.DB
executeSQL = n.UnderlyingDB().Raw(generateSQL.String(), params...).Find(&result) // ignore_security_alert
err = executeSQL.Error
return
} }
func (n noteDo) Debug() INoteDo { func (n noteDo) Debug() INoteDo {

View file

@ -199,6 +199,11 @@ func newNotification(db *gorm.DB, opts ...gen.DOOption) notification {
}{ }{
RelationField: field.NewRelation("SourceNote.Creator", "models.User"), RelationField: field.NewRelation("SourceNote.Creator", "models.User"),
}, },
Origin: struct {
field.RelationField
}{
RelationField: field.NewRelation("SourceNote.Origin", "models.RemoteServer"),
},
AttachmentRelations: struct { AttachmentRelations: struct {
field.RelationField field.RelationField
Note struct { Note struct {
@ -541,6 +546,9 @@ type notificationBelongsToSourceNote struct {
Creator struct { Creator struct {
field.RelationField field.RelationField
} }
Origin struct {
field.RelationField
}
AttachmentRelations struct { AttachmentRelations struct {
field.RelationField field.RelationField
Note struct { Note struct {

View file

@ -259,6 +259,11 @@ func newReaction(db *gorm.DB, opts ...gen.DOOption) reaction {
}, },
}, },
}, },
Origin: struct {
field.RelationField
}{
RelationField: field.NewRelation("Note.Origin", "models.RemoteServer"),
},
AttachmentRelations: struct { AttachmentRelations: struct {
field.RelationField field.RelationField
Note struct { Note struct {
@ -529,6 +534,9 @@ type reactionBelongsToNote struct {
} }
} }
} }
Origin struct {
field.RelationField
}
AttachmentRelations struct { AttachmentRelations struct {
field.RelationField field.RelationField
Note struct { Note struct {

View file

@ -1,6 +1,7 @@
package models package models
import ( import (
"database/sql"
"time" "time"
"gorm.io/gorm" "gorm.io/gorm"
@ -21,14 +22,25 @@ type Note struct {
// Raw content of the note. So without additional formatting applied // Raw content of the note. So without additional formatting applied
// Might already have formatting applied beforehand from the origin server // Might already have formatting applied beforehand from the origin server
RawContent string RawContent string
ContentWarning *string // Content warnings of the note, if it contains any ContentWarning sql.NullString // Content warnings of the note, if it contains any
RepliesTo *string // Url of the message this replies to RepliesTo sql.NullString // Url of the message this replies to
Quotes *string // url of the message this note quotes Quotes sql.NullString // url of the message this note quotes
AccessLevel NoteAccessLevel // Where to send this message to (public, home, followers, dm) AccessLevel NoteAccessLevel // Where to send this message to (public, home, followers, dm)
OriginServer string // Url of the origin server. Also the primary key for those Origin RemoteServer
OriginId uint
AttachmentRelations []NoteToAttachment `gorm:"foreignKey:NoteId"` // Attachments added on to this note AttachmentRelations []NoteToAttachment `gorm:"foreignKey:NoteId"` // Attachments added on to this note
EmoteRelations []NoteToEmote `gorm:"foreignKey:NoteId"` // Emotes used in this note EmoteRelations []NoteToEmote `gorm:"foreignKey:NoteId"` // Emotes used in this note
PingRelations []NoteToPing `gorm:"foreignKey:NoteId"` // Pings/mentions this note performs PingRelations []NoteToPing `gorm:"foreignKey:NoteId"` // Pings/mentions this note performs
Tags []NoteTag `gorm:"foreignKey:NoteId"` // Tags this note contains Tags []NoteTag `gorm:"foreignKey:NoteId"` // Tags this note contains
} }
type INote interface {
// Get all notes by a user, paged, that are a specific access level.
// Ordered by age, descending (newest first)
//
// SELECT * FROM @@table
// WHERE creator_id = @userId AND access_level = @accessLevel
// ORDER BY created_at DESC LIMIT 50 OFFSET @pageNr * 50
GetNotesPaged(userId string, pageNr uint, accessLevel uint8) ([]Note, error)
}

View file

@ -24,6 +24,6 @@ func (n *NoteAccessLevel) Value() (driver.Value, error) {
} }
func (ct *NoteAccessLevel) Scan(value any) error { func (ct *NoteAccessLevel) Scan(value any) error {
*ct = NoteAccessLevel(value.(uint8)) *ct = NoteAccessLevel(value.(int64))
return nil return nil
} }

View file

@ -84,6 +84,7 @@ type IUser interface {
// //
// SELECT * FROM @@table WHERE username = @username AND deleted_at IS NULL LIMIT 1 // SELECT * FROM @@table WHERE username = @username AND deleted_at IS NULL LIMIT 1
GetByUsername(username string) (*gen.T, error) GetByUsername(username string) (*gen.T, error)
// Get all true public accounts (verified & no restricted follow & indexable) // Get all true public accounts (verified & no restricted follow & indexable)
// in a paged manner, sorted by date saved // in a paged manner, sorted by date saved
// //
@ -96,6 +97,7 @@ type IUser interface {
// LIMIT 50 // LIMIT 50
// OFFSET @pageNr * 50 // OFFSET @pageNr * 50
GetPagedTruePublic(pageNr uint) ([]gen.T, error) GetPagedTruePublic(pageNr uint) ([]gen.T, error)
// Get all deleted accounts in a paged manner, sorted by date saved // Get all deleted accounts in a paged manner, sorted by date saved
// //
// SELECT * FROM @@table WHERE // SELECT * FROM @@table WHERE
@ -104,6 +106,7 @@ type IUser interface {
// LIMIT 50 // LIMIT 50
// OFFSET @pageNr * 50 // OFFSET @pageNr * 50
GetPagedAllDeleted(pageNr uint) ([]gen.T, error) GetPagedAllDeleted(pageNr uint) ([]gen.T, error)
// Get all accounts that aren't deleted in a paged manner, sorted by date saved // Get all accounts that aren't deleted in a paged manner, sorted by date saved
// //
// SELECT * FROM @@table WHERE // SELECT * FROM @@table WHERE
@ -112,6 +115,7 @@ type IUser interface {
// LIMIT 50 // LIMIT 50
// OFFSET @pageNr * 50 // OFFSET @pageNr * 50
GetPagedAllNonDeleted(pageNr uint) ([]gen.T, error) GetPagedAllNonDeleted(pageNr uint) ([]gen.T, error)
// Gdpr deleted users // Gdpr deleted users
// //
// DELETE FROM @@table WHERE deleted_at IS NOT NULL AND deleted_at + interval '30 days' < NOW() // DELETE FROM @@table WHERE deleted_at IS NOT NULL AND deleted_at + interval '30 days' < NOW()

View file

@ -7,7 +7,6 @@ import (
"git.mstar.dev/mstar/goutils/other" "git.mstar.dev/mstar/goutils/other"
"github.com/google/uuid" "github.com/google/uuid"
"github.com/rs/zerolog/log"
"gorm.io/gorm" "gorm.io/gorm"
"git.mstar.dev/mstar/linstrom/config" "git.mstar.dev/mstar/linstrom/config"
@ -27,7 +26,6 @@ func InsertSelf() error {
if err != nil { if err != nil {
return other.Error("storage", "failed to save/update self server", err) return other.Error("storage", "failed to save/update self server", err)
} }
log.Debug().Any("server", server).Send()
user, err := insertUser(server) user, err := insertUser(server)
if err != nil { if err != nil {
return other.Error("storage", "failed to save/update self user", err) return other.Error("storage", "failed to save/update self user", err)
@ -35,6 +33,9 @@ func InsertSelf() error {
if err = insertUserPronoun(user); err != nil { if err = insertUserPronoun(user); err != nil {
return other.Error("storage", "failed to save/update self user pronoun", err) return other.Error("storage", "failed to save/update self user pronoun", err)
} }
if err = attachUserToRole(user); err != nil {
return other.Error("storage", "failed to save/update self user to full admin role", err)
}
return nil return nil
} }
@ -152,3 +153,13 @@ func insertUserPronoun(user *models.User) error {
return err return err
} }
} }
func attachUserToRole(user *models.User) error {
u2r := models.UserToRole{
User: *user,
UserId: user.ID,
Role: models.FullAdminRole,
RoleId: models.FullAdminRole.ID,
}
return dbgen.UserToRole.Save(&u2r)
}

View file

@ -1,3 +1,12 @@
// Package webdebug provides a http server for local debugging.
// The server is explicitly for localhost only as it offers
// a lot more control and access than the public one.
// Additionally, there is no guarantee for functional authentication
// and authorisation of requests.
// Using it can be considered a security risk.
//
// There is no guarantee for API stability. It might change drastically
// across versions or even commits and doesn't need announcements
package webdebug package webdebug
import ( import (
@ -16,6 +25,8 @@ func New() *Server {
handler.HandleFunc("GET /non-deleted", getNonDeletedUsers) handler.HandleFunc("GET /non-deleted", getNonDeletedUsers)
handler.HandleFunc("POST /local-user", createLocalUser) handler.HandleFunc("POST /local-user", createLocalUser)
handler.HandleFunc("GET /delete", deleteUser) handler.HandleFunc("GET /delete", deleteUser)
handler.HandleFunc("POST /post-as", postAs)
handler.HandleFunc("GET /notes-for", notesFrom)
web := http.Server{ web := http.Server{
Addr: DebugAddr, Addr: DebugAddr,
Handler: handler, Handler: handler,

View file

@ -1,3 +1,29 @@
// Package webpublic contains the public webserver
// which provides the primary and only intended access point
// for interacting with the system.
//
// # Sections
//
// - Frontend: Serves the various web frontend versions
// - Main: The original Linstrom specific frontend
// - NoJs: An entirely serverside rendered frontend, no JS included
// - Custom: Custom frontend files will be served here
//
// - API: Endpoints for the actual interactions
// - Frontend: The API used by the main frontend
// - Masto: Mastodon compatible adapter for internal structures
// - ActivityPub: For integration with the Fediverse via ActivityPub
// - Linstrom-RPC: For Linstrom to Linstrom server communication
//
// # Guarantees
//
// - The Masto and ActivityPub API will remain stable
// - Frontend API might change, but the intended consumer (Main frontend)
// will always be up to date with the changes
// - Linstrom-RPC API is versioned and will keep
// a few versions of backwards compatibility
//
// TODO: Decide how long the Linstrom-RPC API will remain backwards compatible
package webpublic package webpublic
import "net/http" import "net/http"

View file

@ -39,7 +39,7 @@ type User struct {
} }
// Compiler assertations for interface implementations // Compiler assertations for interface implementations
var _ shared.Santisable = &User{} var _ shared.Sanitisable = &User{}
var _ shared.Clonable = &User{} var _ shared.Clonable = &User{}
func (u *User) Sanitize() { func (u *User) Sanitize() {