Rename cavage singing func, add import for server
All checks were successful
/ docker (push) Successful in 4m1s

This commit is contained in:
Melody Becker 2025-04-15 14:51:07 +02:00
parent 5e13817563
commit 08f6de0bd7
Signed by: mstar
SSH key fingerprint: SHA256:9VAo09aaVNTWKzPW7Hq2LW+ox9OdwmTSHRoD4mlz1yI
39 changed files with 2035 additions and 364 deletions

View file

@ -3,20 +3,34 @@ package activitypub
import ( import (
"encoding/json" "encoding/json"
"errors" "errors"
"fmt"
"io" "io"
"net/http" "net/http"
"strings"
"time" "time"
"git.mstar.dev/mstar/goutils/other" "git.mstar.dev/mstar/goutils/other"
"git.mstar.dev/mstar/goutils/sliceutils" "git.mstar.dev/mstar/goutils/sliceutils"
"github.com/rs/zerolog/log" "github.com/rs/zerolog/log"
"gorm.io/gorm"
"git.mstar.dev/mstar/linstrom/config"
"git.mstar.dev/mstar/linstrom/storage-new/dbgen" "git.mstar.dev/mstar/linstrom/storage-new/dbgen"
"git.mstar.dev/mstar/linstrom/storage-new/models" "git.mstar.dev/mstar/linstrom/storage-new/models"
webshared "git.mstar.dev/mstar/linstrom/web/shared" webshared "git.mstar.dev/mstar/linstrom/web/shared"
) )
var interestingMetadata = []string{
"nodeDescription",
"maintainer",
"tosUrl",
"nodeAdmins",
"privacyPolicyUrl",
"inquiryUrl",
"impressumUrl",
"donationUrl",
"staffAccounts",
}
func ImportRemoteAccount(targetName string) (string, error) { func ImportRemoteAccount(targetName string) (string, error) {
type InboundUserKey struct { type InboundUserKey struct {
Id string `json:"id"` Id string `json:"id"`
@ -62,70 +76,363 @@ func ImportRemoteAccount(targetName string) (string, error) {
// Server actor key for signing // Server actor key for signing
linstromActor, err := dbgen.User.Where(dbgen.User.Username.Eq("linstrom")).First() linstromActor, err := dbgen.User.Where(dbgen.User.Username.Eq("linstrom")).First()
if err != nil { if err != nil {
return "", err return "", other.Error("activitypub", "failed to get server actor", err)
} }
var response *http.Response var response *http.Response
// if config.GlobalConfig.Experimental.UseEd25519Keys { response, err = webshared.RequestSignedCavage("GET", *APLink.Href, nil, linstromActor)
// response, err = webshared.RequestSignedCavage(
// "GET",
// *APLink.Href,
// nil,
// config.GlobalConfig.General.GetFullPublicUrl()+"/api/activitypub/user/"+linstromActor.ID+"#main-key",
// linstromActor.PrivateKeyEd,
// true,
// )
// } else {
// response, err = webshared.RequestSignedCavage(
// "GET",
// *APLink.Href,
// nil,
// config.GlobalConfig.General.GetFullPublicUrl()+"/api/activitypub/user/"+linstromActor.ID+"#main-key",
// linstromActor.PrivateKeyRsa,
// false,
// )
// }
response, err = customReq(*APLink.Href, linstromActor)
if err != nil { if err != nil {
return "", err return "", other.Error("activitypub", "failed to complete cavage signed request", err)
} }
defer response.Body.Close() defer response.Body.Close()
body, _ := io.ReadAll(response.Body) body, _ := io.ReadAll(response.Body)
log.Debug(). log.Trace().
Int("status", response.StatusCode). Int("status", response.StatusCode).
Bytes("body", body). Bytes("body", body).
Any("headers", response.Header). Any("headers", response.Header).
Msg("Response information") Msg("Response information")
if response.StatusCode != 200 { if response.StatusCode != 200 {
return "", errors.New("bad status") return "", fmt.Errorf("activitypub: invalid status code: %v", response.StatusCode)
} }
var data InboundUser var data InboundUser
err = json.Unmarshal(body, &data) err = json.Unmarshal(body, &data)
if err != nil { if err != nil {
return "", err return "", other.Error("activitypub", "failed to unmarshal response", err)
} }
log.Info().Any("received-data", data).Msg("Response data") log.Debug().Any("received-data", data).Msg("Response data")
log.Info().Str("user", targetName).Msg("Import completed")
return "", nil return "", nil
} }
func customReq(target string, linstromActor *models.User) (*http.Response, error) { func ImportRemoteServer(host string) (uint, error) {
req, err := webshared.NewRequest("GET", target, nil) // Nodeinfo is not locked behind authentication, so don't do it
if err != nil {
return nil, err
}
req.Header.Add("Accept", "application/activity+json")
var keyBytes []byte req, err := webshared.NewRequest("GET", "https://"+host+"/.well-known/nodeinfo", nil)
if config.GlobalConfig.Experimental.UseEd25519Keys { if err != nil {
keyBytes = linstromActor.PrivateKeyEd return 0, other.Error("activitypub", "failed to create overview request", err)
}
response, err := webshared.RequestClient.Do(req)
if err != nil {
return 0, other.Error("activitypub", "overview request failed", err)
}
var nodeInfoOverview webshared.NodeInfoOverview
decoder := json.NewDecoder(response.Body)
err = decoder.Decode(&nodeInfoOverview)
if err != nil {
return 0, other.Error("activitypub", "overview unmarshal failed", err)
}
relevantInfos := sliceutils.Filter(nodeInfoOverview.Links, func(t webshared.NodeInfoLink) bool {
return strings.HasSuffix(t.Rel, "schema/2.0") || strings.HasSuffix(t.Rel, "schema/2.1")
})
var data webshared.NodeInfo2
v21Slice := sliceutils.Filter(relevantInfos, func(t webshared.NodeInfoLink) bool {
return strings.HasSuffix(t.Rel, "schema/2.1")
})
if len(v21Slice) > 0 {
req, err = webshared.NewRequest("GET", v21Slice[0].Href, nil)
if err != nil {
return 0, other.Error("activitypub", "info 2.1 request creation failed", err)
}
} else { } else {
keyBytes = linstromActor.PrivateKeyRsa req, err = webshared.NewRequest("GET", relevantInfos[0].Href, nil)
if err != nil {
return 0, other.Error("activitypub", "info 2.0 request creation failed", err)
}
}
res, err := webshared.RequestClient.Do(req)
if err != nil {
return 0, other.Error("activitypub", "info request failed to complete", err)
}
decoder = json.NewDecoder(res.Body)
err = decoder.Decode(&data)
if err != nil {
return 0, other.Error("activitypub", "failed to unmarshal info", err)
}
log.Debug().Any("nodeinfo", data).Msg("Server info received")
rs := dbgen.RemoteServer
// rsm := dbgen.RemoteServerMetadata
serverModelType := webshared.MapNodeServerTypeToModelType(data.Software.Name)
existingEntry, err := rs.Where(rs.Domain.Eq(host)).Preload(rs.Metadata).First()
switch err {
case gorm.ErrRecordNotFound:
existingEntry = &models.RemoteServer{
ServerType: serverModelType,
Version: data.Version,
Domain: host,
SpecificType: data.Software.Name,
}
if err = rs.Create(existingEntry); err != nil {
return 0, other.Error("activitypub", "failed to create new server entry", err)
}
case nil:
default:
return 0, other.Error("activitypub", "db failure", err)
}
existingEntry.SpecificType = data.Software.Name
existingEntry.IsSelf = false
existingEntry.ServerType = serverModelType
existingEntry.Version = data.Version
if name, ok := data.Metadata["nodeName"].(string); ok {
existingEntry.Name = name
} else {
existingEntry.Name = host
}
// Cast without check for existence is ok here
// Default value for `Any` is `nil`, which fails to cast to a valid string
if description, ok := data.Metadata["nodeDescription"].(string); ok {
log.Debug().Msg("Description found")
targets := sliceutils.Filter(
existingEntry.Metadata,
func(t models.RemoteServerMetadata) bool {
return t.Key == "description"
},
)
if len(targets) > 0 {
targets[0].Value = description
} else {
err := rs.Metadata.Model(existingEntry).Append(&models.RemoteServerMetadata{
Value: description,
Key: "description",
})
if err != nil {
log.Warn().
Err(err).
Uint("server-id", existingEntry.ID).
Str("key", "description").
Str("value", description).
Msg("Failed to append new metadata to server")
}
}
}
if maintainer, ok := data.Metadata["maintainer"].(map[string]any); ok {
log.Debug().Msg("Maintainer found")
name, nameOk := maintainer["name"].(string)
email, emailOk := maintainer["email"].(string)
if nameOk && emailOk {
targets := sliceutils.Filter(
existingEntry.Metadata,
func(t models.RemoteServerMetadata) bool {
return t.Key == "maintainer"
},
)
val := fmt.Sprintf("%s <%s>", name, email)
if len(targets) > 0 {
targets[0].Value = val
} else {
err = rs.Metadata.Model(existingEntry).Append(&models.RemoteServerMetadata{
Key: "maintainer",
Value: val,
})
if err != nil {
log.Warn().
Err(err).
Uint("server-id", existingEntry.ID).
Str("key", "maintainer").
Str("value", val).
Msg("Failed to append new metadata to server")
}
}
}
}
if tosUrl, ok := data.Metadata["tosUrl"].(string); ok {
log.Debug().Msg("Tos url found")
targets := sliceutils.Filter(
existingEntry.Metadata,
func(t models.RemoteServerMetadata) bool {
return t.Key == "tosUrl"
},
)
if len(targets) > 0 {
targets[0].Value = tosUrl
} else {
err := rs.Metadata.Model(existingEntry).Append(&models.RemoteServerMetadata{
Value: tosUrl,
Key: "tosUrl",
})
if err != nil {
log.Warn().
Err(err).
Uint("server-id", existingEntry.ID).
Str("key", "tosUrl").
Str("value", tosUrl).
Msg("Failed to append new metadata to server")
}
}
}
if nodeAdmins, ok := data.Metadata["nodeAdmins"].([]map[string]any); ok {
log.Debug().Msg("Node admins url found")
targets := sliceutils.Filter(
existingEntry.Metadata,
func(t models.RemoteServerMetadata) bool {
return t.Key == "nodeAdmins"
},
)
valueBuilder := strings.Builder{}
for _, v := range nodeAdmins {
name, nameOk := v["name"].(string)
email, emailOk := v["email"].(string)
if nameOk && emailOk {
valueBuilder.WriteString(name)
valueBuilder.WriteString(" <")
valueBuilder.WriteString(email)
valueBuilder.WriteString(">;")
}
}
if len(targets) > 0 {
targets[0].Value = valueBuilder.String()
} else {
err := rs.Metadata.Model(existingEntry).Append(&models.RemoteServerMetadata{
Value: valueBuilder.String(),
Key: "nodeAdmins",
})
if err != nil {
log.Warn().
Err(err).
Uint("server-id", existingEntry.ID).
Str("key", "nodeAdmins").
Str("value", valueBuilder.String()).
Msg("Failed to append new metadata to server")
}
}
}
if privacyPolicyUrl, ok := data.Metadata["privacyPolicyUrl"].(string); ok {
log.Debug().Msg("Privacy policy url found")
targets := sliceutils.Filter(
existingEntry.Metadata,
func(t models.RemoteServerMetadata) bool {
return t.Key == "privacyPolicyUrl"
},
)
if len(targets) > 0 {
targets[0].Value = privacyPolicyUrl
} else {
err := rs.Metadata.Model(existingEntry).Append(&models.RemoteServerMetadata{
Value: privacyPolicyUrl,
Key: "privacyPolicyUrl",
})
if err != nil {
log.Warn().
Err(err).
Uint("server-id", existingEntry.ID).
Str("key", "privacyPolicyUrl").
Str("value", privacyPolicyUrl).
Msg("Failed to append new metadata to server")
}
}
}
if inquiryUrl, ok := data.Metadata["inquiryUrl"].(string); ok {
log.Debug().Msg("Inquiry found")
targets := sliceutils.Filter(
existingEntry.Metadata,
func(t models.RemoteServerMetadata) bool {
return t.Key == "inquiryUrl"
},
)
if len(targets) > 0 {
targets[0].Value = inquiryUrl
} else {
err := rs.Metadata.Model(existingEntry).Append(&models.RemoteServerMetadata{
Value: inquiryUrl,
Key: "inquiryUrl",
})
if err != nil {
log.Warn().
Err(err).
Uint("server-id", existingEntry.ID).
Str("key", "inquiryUrl").
Str("value", inquiryUrl).
Msg("Failed to append new metadata to server")
}
}
}
if impressumUrl, ok := data.Metadata["impressumUrl"].(string); ok {
log.Debug().Msg("Impressum url found")
targets := sliceutils.Filter(
existingEntry.Metadata,
func(t models.RemoteServerMetadata) bool {
return t.Key == "impressumUrl"
},
)
if len(targets) > 0 {
targets[0].Value = impressumUrl
} else {
err := rs.Metadata.Model(existingEntry).Append(&models.RemoteServerMetadata{
Value: impressumUrl,
Key: "impressumUrl",
})
if err != nil {
log.Warn().
Err(err).
Uint("server-id", existingEntry.ID).
Str("key", "impressumUrl").
Str("value", impressumUrl).
Msg("Failed to append new metadata to server")
}
}
}
if donationUrl, ok := data.Metadata["donationUrl"].(string); ok {
log.Debug().Msg("Donation url found")
targets := sliceutils.Filter(
existingEntry.Metadata,
func(t models.RemoteServerMetadata) bool {
return t.Key == "donationUrl"
},
)
if len(targets) > 0 {
targets[0].Value = donationUrl
} else {
err := rs.Metadata.Model(existingEntry).Append(&models.RemoteServerMetadata{
Value: donationUrl,
Key: "donationUrl",
})
if err != nil {
log.Warn().
Err(err).
Uint("server-id", existingEntry.ID).
Str("key", "donationUrl").
Str("value", donationUrl).
Msg("Failed to append new metadata to server")
}
}
}
if staffAccounts, ok := data.Metadata["nodeAdmins"].([]any); ok {
log.Debug().Msg("Node admins url found")
targets := sliceutils.Filter(
existingEntry.Metadata,
func(t models.RemoteServerMetadata) bool {
return t.Key == "staffAccounts"
},
)
valueBuilder := strings.Builder{}
for _, v := range staffAccounts {
if acc, ok := v.(string); ok {
valueBuilder.WriteString(acc)
valueBuilder.WriteString(";")
}
}
if len(targets) > 0 {
targets[0].Value = valueBuilder.String()
} else {
err := rs.Metadata.Model(existingEntry).Append(&models.RemoteServerMetadata{
Value: valueBuilder.String(),
Key: "staffAccounts",
})
if err != nil {
log.Warn().
Err(err).
Uint("server-id", existingEntry.ID).
Str("key", "staffAccounts").
Str("value", valueBuilder.String()).
Msg("Failed to append new metadata to server")
}
}
} }
// Sign and send id := existingEntry.ID
err = webshared.SignRequest(req, linstromActor.ID+"#main-key", keyBytes, nil) existingEntry.ID = 0
// err = webshared.SignRequestWithHttpsig(req, linstromActor.ID+"#main-key", keyBytes, nil) _, err = rs.Where(rs.ID.Eq(id)).UpdateColumns(existingEntry)
if err != nil { if err != nil {
return nil, err return 0, other.Error("activitypub", "failed to store update in db", err)
} }
return webshared.RequestClient.Do(req) return id, nil
} }

View file

@ -40,6 +40,12 @@ func newAccessToken(db *gorm.DB, opts ...gen.DOOption) accessToken {
Icon struct { Icon struct {
field.RelationField field.RelationField
} }
Metadata struct {
field.RelationField
RemoteServer struct {
field.RelationField
}
}
}{ }{
RelationField: field.NewRelation("User.Server", "models.RemoteServer"), RelationField: field.NewRelation("User.Server", "models.RemoteServer"),
Icon: struct { Icon: struct {
@ -47,6 +53,19 @@ func newAccessToken(db *gorm.DB, opts ...gen.DOOption) accessToken {
}{ }{
RelationField: field.NewRelation("User.Server.Icon", "models.MediaMetadata"), RelationField: field.NewRelation("User.Server.Icon", "models.MediaMetadata"),
}, },
Metadata: struct {
field.RelationField
RemoteServer struct {
field.RelationField
}
}{
RelationField: field.NewRelation("User.Server.Metadata", "models.RemoteServerMetadata"),
RemoteServer: struct {
field.RelationField
}{
RelationField: field.NewRelation("User.Server.Metadata.RemoteServer", "models.RemoteServer"),
},
},
}, },
Icon: struct { Icon: struct {
field.RelationField field.RelationField
@ -263,6 +282,12 @@ type accessTokenBelongsToUser struct {
Icon struct { Icon struct {
field.RelationField field.RelationField
} }
Metadata struct {
field.RelationField
RemoteServer struct {
field.RelationField
}
}
} }
Icon struct { Icon struct {
field.RelationField field.RelationField

View file

@ -48,6 +48,19 @@ func newEmote(db *gorm.DB, opts ...gen.DOOption) emote {
}{ }{
RelationField: field.NewRelation("Server.Icon", "models.MediaMetadata"), RelationField: field.NewRelation("Server.Icon", "models.MediaMetadata"),
}, },
Metadata: struct {
field.RelationField
RemoteServer struct {
field.RelationField
}
}{
RelationField: field.NewRelation("Server.Metadata", "models.RemoteServerMetadata"),
RemoteServer: struct {
field.RelationField
}{
RelationField: field.NewRelation("Server.Metadata.RemoteServer", "models.RemoteServer"),
},
},
} }
_emote.fillFieldMap() _emote.fillFieldMap()
@ -208,6 +221,12 @@ type emoteBelongsToServer struct {
Icon struct { Icon struct {
field.RelationField field.RelationField
} }
Metadata struct {
field.RelationField
RemoteServer struct {
field.RelationField
}
}
} }
func (a emoteBelongsToServer) Where(conds ...field.Expr) *emoteBelongsToServer { func (a emoteBelongsToServer) Where(conds ...field.Expr) *emoteBelongsToServer {

View file

@ -43,6 +43,12 @@ func newFeed(db *gorm.DB, opts ...gen.DOOption) feed {
Icon struct { Icon struct {
field.RelationField field.RelationField
} }
Metadata struct {
field.RelationField
RemoteServer struct {
field.RelationField
}
}
}{ }{
RelationField: field.NewRelation("Owner.Server", "models.RemoteServer"), RelationField: field.NewRelation("Owner.Server", "models.RemoteServer"),
Icon: struct { Icon: struct {
@ -50,6 +56,19 @@ func newFeed(db *gorm.DB, opts ...gen.DOOption) feed {
}{ }{
RelationField: field.NewRelation("Owner.Server.Icon", "models.MediaMetadata"), RelationField: field.NewRelation("Owner.Server.Icon", "models.MediaMetadata"),
}, },
Metadata: struct {
field.RelationField
RemoteServer struct {
field.RelationField
}
}{
RelationField: field.NewRelation("Owner.Server.Metadata", "models.RemoteServerMetadata"),
RemoteServer: struct {
field.RelationField
}{
RelationField: field.NewRelation("Owner.Server.Metadata.RemoteServer", "models.RemoteServer"),
},
},
}, },
Icon: struct { Icon: struct {
field.RelationField field.RelationField
@ -278,6 +297,12 @@ type feedBelongsToOwner struct {
Icon struct { Icon struct {
field.RelationField field.RelationField
} }
Metadata struct {
field.RelationField
RemoteServer struct {
field.RelationField
}
}
} }
Icon struct { Icon struct {
field.RelationField field.RelationField

View file

@ -16,32 +16,33 @@ import (
) )
var ( var (
Q = new(Query) Q = new(Query)
AccessToken *accessToken AccessToken *accessToken
Emote *emote Emote *emote
Feed *feed Feed *feed
LoginProcessToken *loginProcessToken LoginProcessToken *loginProcessToken
MediaMetadata *mediaMetadata MediaMetadata *mediaMetadata
Note *note Note *note
NoteTag *noteTag NoteTag *noteTag
NoteToAttachment *noteToAttachment NoteToAttachment *noteToAttachment
NoteToBoost *noteToBoost NoteToBoost *noteToBoost
NoteToEmote *noteToEmote NoteToEmote *noteToEmote
NoteToFeed *noteToFeed NoteToFeed *noteToFeed
NoteToPing *noteToPing NoteToPing *noteToPing
Notification *notification Notification *notification
Reaction *reaction Reaction *reaction
RemoteServer *remoteServer RemoteServer *remoteServer
Role *role RemoteServerMetadata *remoteServerMetadata
User *user Role *role
UserAuthMethod *userAuthMethod User *user
UserInfoField *userInfoField UserAuthMethod *userAuthMethod
UserRemoteLinks *userRemoteLinks UserInfoField *userInfoField
UserToBeing *userToBeing UserRemoteLinks *userRemoteLinks
UserToPronoun *userToPronoun UserToBeing *userToBeing
UserToRole *userToRole UserToPronoun *userToPronoun
UserToTag *userToTag UserToRole *userToRole
UserToUserRelation *userToUserRelation UserToTag *userToTag
UserToUserRelation *userToUserRelation
) )
func SetDefault(db *gorm.DB, opts ...gen.DOOption) { func SetDefault(db *gorm.DB, opts ...gen.DOOption) {
@ -61,6 +62,7 @@ func SetDefault(db *gorm.DB, opts ...gen.DOOption) {
Notification = &Q.Notification Notification = &Q.Notification
Reaction = &Q.Reaction Reaction = &Q.Reaction
RemoteServer = &Q.RemoteServer RemoteServer = &Q.RemoteServer
RemoteServerMetadata = &Q.RemoteServerMetadata
Role = &Q.Role Role = &Q.Role
User = &Q.User User = &Q.User
UserAuthMethod = &Q.UserAuthMethod UserAuthMethod = &Q.UserAuthMethod
@ -75,95 +77,98 @@ func SetDefault(db *gorm.DB, opts ...gen.DOOption) {
func Use(db *gorm.DB, opts ...gen.DOOption) *Query { func Use(db *gorm.DB, opts ...gen.DOOption) *Query {
return &Query{ return &Query{
db: db, db: db,
AccessToken: newAccessToken(db, opts...), AccessToken: newAccessToken(db, opts...),
Emote: newEmote(db, opts...), Emote: newEmote(db, opts...),
Feed: newFeed(db, opts...), Feed: newFeed(db, opts...),
LoginProcessToken: newLoginProcessToken(db, opts...), LoginProcessToken: newLoginProcessToken(db, opts...),
MediaMetadata: newMediaMetadata(db, opts...), MediaMetadata: newMediaMetadata(db, opts...),
Note: newNote(db, opts...), Note: newNote(db, opts...),
NoteTag: newNoteTag(db, opts...), NoteTag: newNoteTag(db, opts...),
NoteToAttachment: newNoteToAttachment(db, opts...), NoteToAttachment: newNoteToAttachment(db, opts...),
NoteToBoost: newNoteToBoost(db, opts...), NoteToBoost: newNoteToBoost(db, opts...),
NoteToEmote: newNoteToEmote(db, opts...), NoteToEmote: newNoteToEmote(db, opts...),
NoteToFeed: newNoteToFeed(db, opts...), NoteToFeed: newNoteToFeed(db, opts...),
NoteToPing: newNoteToPing(db, opts...), NoteToPing: newNoteToPing(db, opts...),
Notification: newNotification(db, opts...), Notification: newNotification(db, opts...),
Reaction: newReaction(db, opts...), Reaction: newReaction(db, opts...),
RemoteServer: newRemoteServer(db, opts...), RemoteServer: newRemoteServer(db, opts...),
Role: newRole(db, opts...), RemoteServerMetadata: newRemoteServerMetadata(db, opts...),
User: newUser(db, opts...), Role: newRole(db, opts...),
UserAuthMethod: newUserAuthMethod(db, opts...), User: newUser(db, opts...),
UserInfoField: newUserInfoField(db, opts...), UserAuthMethod: newUserAuthMethod(db, opts...),
UserRemoteLinks: newUserRemoteLinks(db, opts...), UserInfoField: newUserInfoField(db, opts...),
UserToBeing: newUserToBeing(db, opts...), UserRemoteLinks: newUserRemoteLinks(db, opts...),
UserToPronoun: newUserToPronoun(db, opts...), UserToBeing: newUserToBeing(db, opts...),
UserToRole: newUserToRole(db, opts...), UserToPronoun: newUserToPronoun(db, opts...),
UserToTag: newUserToTag(db, opts...), UserToRole: newUserToRole(db, opts...),
UserToUserRelation: newUserToUserRelation(db, opts...), UserToTag: newUserToTag(db, opts...),
UserToUserRelation: newUserToUserRelation(db, opts...),
} }
} }
type Query struct { type Query struct {
db *gorm.DB db *gorm.DB
AccessToken accessToken AccessToken accessToken
Emote emote Emote emote
Feed feed Feed feed
LoginProcessToken loginProcessToken LoginProcessToken loginProcessToken
MediaMetadata mediaMetadata MediaMetadata mediaMetadata
Note note Note note
NoteTag noteTag NoteTag noteTag
NoteToAttachment noteToAttachment NoteToAttachment noteToAttachment
NoteToBoost noteToBoost NoteToBoost noteToBoost
NoteToEmote noteToEmote NoteToEmote noteToEmote
NoteToFeed noteToFeed NoteToFeed noteToFeed
NoteToPing noteToPing NoteToPing noteToPing
Notification notification Notification notification
Reaction reaction Reaction reaction
RemoteServer remoteServer RemoteServer remoteServer
Role role RemoteServerMetadata remoteServerMetadata
User user Role role
UserAuthMethod userAuthMethod User user
UserInfoField userInfoField UserAuthMethod userAuthMethod
UserRemoteLinks userRemoteLinks UserInfoField userInfoField
UserToBeing userToBeing UserRemoteLinks userRemoteLinks
UserToPronoun userToPronoun UserToBeing userToBeing
UserToRole userToRole UserToPronoun userToPronoun
UserToTag userToTag UserToRole userToRole
UserToUserRelation userToUserRelation UserToTag userToTag
UserToUserRelation userToUserRelation
} }
func (q *Query) Available() bool { return q.db != nil } func (q *Query) Available() bool { return q.db != nil }
func (q *Query) clone(db *gorm.DB) *Query { func (q *Query) clone(db *gorm.DB) *Query {
return &Query{ return &Query{
db: db, db: db,
AccessToken: q.AccessToken.clone(db), AccessToken: q.AccessToken.clone(db),
Emote: q.Emote.clone(db), Emote: q.Emote.clone(db),
Feed: q.Feed.clone(db), Feed: q.Feed.clone(db),
LoginProcessToken: q.LoginProcessToken.clone(db), LoginProcessToken: q.LoginProcessToken.clone(db),
MediaMetadata: q.MediaMetadata.clone(db), MediaMetadata: q.MediaMetadata.clone(db),
Note: q.Note.clone(db), Note: q.Note.clone(db),
NoteTag: q.NoteTag.clone(db), NoteTag: q.NoteTag.clone(db),
NoteToAttachment: q.NoteToAttachment.clone(db), NoteToAttachment: q.NoteToAttachment.clone(db),
NoteToBoost: q.NoteToBoost.clone(db), NoteToBoost: q.NoteToBoost.clone(db),
NoteToEmote: q.NoteToEmote.clone(db), NoteToEmote: q.NoteToEmote.clone(db),
NoteToFeed: q.NoteToFeed.clone(db), NoteToFeed: q.NoteToFeed.clone(db),
NoteToPing: q.NoteToPing.clone(db), NoteToPing: q.NoteToPing.clone(db),
Notification: q.Notification.clone(db), Notification: q.Notification.clone(db),
Reaction: q.Reaction.clone(db), Reaction: q.Reaction.clone(db),
RemoteServer: q.RemoteServer.clone(db), RemoteServer: q.RemoteServer.clone(db),
Role: q.Role.clone(db), RemoteServerMetadata: q.RemoteServerMetadata.clone(db),
User: q.User.clone(db), Role: q.Role.clone(db),
UserAuthMethod: q.UserAuthMethod.clone(db), User: q.User.clone(db),
UserInfoField: q.UserInfoField.clone(db), UserAuthMethod: q.UserAuthMethod.clone(db),
UserRemoteLinks: q.UserRemoteLinks.clone(db), UserInfoField: q.UserInfoField.clone(db),
UserToBeing: q.UserToBeing.clone(db), UserRemoteLinks: q.UserRemoteLinks.clone(db),
UserToPronoun: q.UserToPronoun.clone(db), UserToBeing: q.UserToBeing.clone(db),
UserToRole: q.UserToRole.clone(db), UserToPronoun: q.UserToPronoun.clone(db),
UserToTag: q.UserToTag.clone(db), UserToRole: q.UserToRole.clone(db),
UserToUserRelation: q.UserToUserRelation.clone(db), UserToTag: q.UserToTag.clone(db),
UserToUserRelation: q.UserToUserRelation.clone(db),
} }
} }
@ -177,90 +182,93 @@ func (q *Query) WriteDB() *Query {
func (q *Query) ReplaceDB(db *gorm.DB) *Query { func (q *Query) ReplaceDB(db *gorm.DB) *Query {
return &Query{ return &Query{
db: db, db: db,
AccessToken: q.AccessToken.replaceDB(db), AccessToken: q.AccessToken.replaceDB(db),
Emote: q.Emote.replaceDB(db), Emote: q.Emote.replaceDB(db),
Feed: q.Feed.replaceDB(db), Feed: q.Feed.replaceDB(db),
LoginProcessToken: q.LoginProcessToken.replaceDB(db), LoginProcessToken: q.LoginProcessToken.replaceDB(db),
MediaMetadata: q.MediaMetadata.replaceDB(db), MediaMetadata: q.MediaMetadata.replaceDB(db),
Note: q.Note.replaceDB(db), Note: q.Note.replaceDB(db),
NoteTag: q.NoteTag.replaceDB(db), NoteTag: q.NoteTag.replaceDB(db),
NoteToAttachment: q.NoteToAttachment.replaceDB(db), NoteToAttachment: q.NoteToAttachment.replaceDB(db),
NoteToBoost: q.NoteToBoost.replaceDB(db), NoteToBoost: q.NoteToBoost.replaceDB(db),
NoteToEmote: q.NoteToEmote.replaceDB(db), NoteToEmote: q.NoteToEmote.replaceDB(db),
NoteToFeed: q.NoteToFeed.replaceDB(db), NoteToFeed: q.NoteToFeed.replaceDB(db),
NoteToPing: q.NoteToPing.replaceDB(db), NoteToPing: q.NoteToPing.replaceDB(db),
Notification: q.Notification.replaceDB(db), Notification: q.Notification.replaceDB(db),
Reaction: q.Reaction.replaceDB(db), Reaction: q.Reaction.replaceDB(db),
RemoteServer: q.RemoteServer.replaceDB(db), RemoteServer: q.RemoteServer.replaceDB(db),
Role: q.Role.replaceDB(db), RemoteServerMetadata: q.RemoteServerMetadata.replaceDB(db),
User: q.User.replaceDB(db), Role: q.Role.replaceDB(db),
UserAuthMethod: q.UserAuthMethod.replaceDB(db), User: q.User.replaceDB(db),
UserInfoField: q.UserInfoField.replaceDB(db), UserAuthMethod: q.UserAuthMethod.replaceDB(db),
UserRemoteLinks: q.UserRemoteLinks.replaceDB(db), UserInfoField: q.UserInfoField.replaceDB(db),
UserToBeing: q.UserToBeing.replaceDB(db), UserRemoteLinks: q.UserRemoteLinks.replaceDB(db),
UserToPronoun: q.UserToPronoun.replaceDB(db), UserToBeing: q.UserToBeing.replaceDB(db),
UserToRole: q.UserToRole.replaceDB(db), UserToPronoun: q.UserToPronoun.replaceDB(db),
UserToTag: q.UserToTag.replaceDB(db), UserToRole: q.UserToRole.replaceDB(db),
UserToUserRelation: q.UserToUserRelation.replaceDB(db), UserToTag: q.UserToTag.replaceDB(db),
UserToUserRelation: q.UserToUserRelation.replaceDB(db),
} }
} }
type queryCtx struct { type queryCtx struct {
AccessToken IAccessTokenDo AccessToken IAccessTokenDo
Emote IEmoteDo Emote IEmoteDo
Feed IFeedDo Feed IFeedDo
LoginProcessToken ILoginProcessTokenDo LoginProcessToken ILoginProcessTokenDo
MediaMetadata IMediaMetadataDo MediaMetadata IMediaMetadataDo
Note INoteDo Note INoteDo
NoteTag INoteTagDo NoteTag INoteTagDo
NoteToAttachment INoteToAttachmentDo NoteToAttachment INoteToAttachmentDo
NoteToBoost INoteToBoostDo NoteToBoost INoteToBoostDo
NoteToEmote INoteToEmoteDo NoteToEmote INoteToEmoteDo
NoteToFeed INoteToFeedDo NoteToFeed INoteToFeedDo
NoteToPing INoteToPingDo NoteToPing INoteToPingDo
Notification INotificationDo Notification INotificationDo
Reaction IReactionDo Reaction IReactionDo
RemoteServer IRemoteServerDo RemoteServer IRemoteServerDo
Role IRoleDo RemoteServerMetadata IRemoteServerMetadataDo
User IUserDo Role IRoleDo
UserAuthMethod IUserAuthMethodDo User IUserDo
UserInfoField IUserInfoFieldDo UserAuthMethod IUserAuthMethodDo
UserRemoteLinks IUserRemoteLinksDo UserInfoField IUserInfoFieldDo
UserToBeing IUserToBeingDo UserRemoteLinks IUserRemoteLinksDo
UserToPronoun IUserToPronounDo UserToBeing IUserToBeingDo
UserToRole IUserToRoleDo UserToPronoun IUserToPronounDo
UserToTag IUserToTagDo UserToRole IUserToRoleDo
UserToUserRelation IUserToUserRelationDo UserToTag IUserToTagDo
UserToUserRelation IUserToUserRelationDo
} }
func (q *Query) WithContext(ctx context.Context) *queryCtx { func (q *Query) WithContext(ctx context.Context) *queryCtx {
return &queryCtx{ return &queryCtx{
AccessToken: q.AccessToken.WithContext(ctx), AccessToken: q.AccessToken.WithContext(ctx),
Emote: q.Emote.WithContext(ctx), Emote: q.Emote.WithContext(ctx),
Feed: q.Feed.WithContext(ctx), Feed: q.Feed.WithContext(ctx),
LoginProcessToken: q.LoginProcessToken.WithContext(ctx), LoginProcessToken: q.LoginProcessToken.WithContext(ctx),
MediaMetadata: q.MediaMetadata.WithContext(ctx), MediaMetadata: q.MediaMetadata.WithContext(ctx),
Note: q.Note.WithContext(ctx), Note: q.Note.WithContext(ctx),
NoteTag: q.NoteTag.WithContext(ctx), NoteTag: q.NoteTag.WithContext(ctx),
NoteToAttachment: q.NoteToAttachment.WithContext(ctx), NoteToAttachment: q.NoteToAttachment.WithContext(ctx),
NoteToBoost: q.NoteToBoost.WithContext(ctx), NoteToBoost: q.NoteToBoost.WithContext(ctx),
NoteToEmote: q.NoteToEmote.WithContext(ctx), NoteToEmote: q.NoteToEmote.WithContext(ctx),
NoteToFeed: q.NoteToFeed.WithContext(ctx), NoteToFeed: q.NoteToFeed.WithContext(ctx),
NoteToPing: q.NoteToPing.WithContext(ctx), NoteToPing: q.NoteToPing.WithContext(ctx),
Notification: q.Notification.WithContext(ctx), Notification: q.Notification.WithContext(ctx),
Reaction: q.Reaction.WithContext(ctx), Reaction: q.Reaction.WithContext(ctx),
RemoteServer: q.RemoteServer.WithContext(ctx), RemoteServer: q.RemoteServer.WithContext(ctx),
Role: q.Role.WithContext(ctx), RemoteServerMetadata: q.RemoteServerMetadata.WithContext(ctx),
User: q.User.WithContext(ctx), Role: q.Role.WithContext(ctx),
UserAuthMethod: q.UserAuthMethod.WithContext(ctx), User: q.User.WithContext(ctx),
UserInfoField: q.UserInfoField.WithContext(ctx), UserAuthMethod: q.UserAuthMethod.WithContext(ctx),
UserRemoteLinks: q.UserRemoteLinks.WithContext(ctx), UserInfoField: q.UserInfoField.WithContext(ctx),
UserToBeing: q.UserToBeing.WithContext(ctx), UserRemoteLinks: q.UserRemoteLinks.WithContext(ctx),
UserToPronoun: q.UserToPronoun.WithContext(ctx), UserToBeing: q.UserToBeing.WithContext(ctx),
UserToRole: q.UserToRole.WithContext(ctx), UserToPronoun: q.UserToPronoun.WithContext(ctx),
UserToTag: q.UserToTag.WithContext(ctx), UserToRole: q.UserToRole.WithContext(ctx),
UserToUserRelation: q.UserToUserRelation.WithContext(ctx), UserToTag: q.UserToTag.WithContext(ctx),
UserToUserRelation: q.UserToUserRelation.WithContext(ctx),
} }
} }

View file

@ -40,6 +40,12 @@ func newLoginProcessToken(db *gorm.DB, opts ...gen.DOOption) loginProcessToken {
Icon struct { Icon struct {
field.RelationField field.RelationField
} }
Metadata struct {
field.RelationField
RemoteServer struct {
field.RelationField
}
}
}{ }{
RelationField: field.NewRelation("User.Server", "models.RemoteServer"), RelationField: field.NewRelation("User.Server", "models.RemoteServer"),
Icon: struct { Icon: struct {
@ -47,6 +53,19 @@ func newLoginProcessToken(db *gorm.DB, opts ...gen.DOOption) loginProcessToken {
}{ }{
RelationField: field.NewRelation("User.Server.Icon", "models.MediaMetadata"), RelationField: field.NewRelation("User.Server.Icon", "models.MediaMetadata"),
}, },
Metadata: struct {
field.RelationField
RemoteServer struct {
field.RelationField
}
}{
RelationField: field.NewRelation("User.Server.Metadata", "models.RemoteServerMetadata"),
RemoteServer: struct {
field.RelationField
}{
RelationField: field.NewRelation("User.Server.Metadata.RemoteServer", "models.RemoteServer"),
},
},
}, },
Icon: struct { Icon: struct {
field.RelationField field.RelationField
@ -266,6 +285,12 @@ type loginProcessTokenBelongsToUser struct {
Icon struct { Icon struct {
field.RelationField field.RelationField
} }
Metadata struct {
field.RelationField
RemoteServer struct {
field.RelationField
}
}
} }
Icon struct { Icon struct {
field.RelationField field.RelationField

View file

@ -40,6 +40,12 @@ func newNoteTag(db *gorm.DB, opts ...gen.DOOption) noteTag {
Icon struct { Icon struct {
field.RelationField field.RelationField
} }
Metadata struct {
field.RelationField
RemoteServer struct {
field.RelationField
}
}
} }
Icon struct { Icon struct {
field.RelationField field.RelationField
@ -111,6 +117,12 @@ func newNoteTag(db *gorm.DB, opts ...gen.DOOption) noteTag {
Icon struct { Icon struct {
field.RelationField field.RelationField
} }
Metadata struct {
field.RelationField
RemoteServer struct {
field.RelationField
}
}
}{ }{
RelationField: field.NewRelation("Note.Creator.Server", "models.RemoteServer"), RelationField: field.NewRelation("Note.Creator.Server", "models.RemoteServer"),
Icon: struct { Icon: struct {
@ -118,6 +130,19 @@ func newNoteTag(db *gorm.DB, opts ...gen.DOOption) noteTag {
}{ }{
RelationField: field.NewRelation("Note.Creator.Server.Icon", "models.MediaMetadata"), RelationField: field.NewRelation("Note.Creator.Server.Icon", "models.MediaMetadata"),
}, },
Metadata: struct {
field.RelationField
RemoteServer struct {
field.RelationField
}
}{
RelationField: field.NewRelation("Note.Creator.Server.Metadata", "models.RemoteServerMetadata"),
RemoteServer: struct {
field.RelationField
}{
RelationField: field.NewRelation("Note.Creator.Server.Metadata.RemoteServer", "models.RemoteServer"),
},
},
}, },
Icon: struct { Icon: struct {
field.RelationField field.RelationField
@ -437,6 +462,12 @@ type noteTagBelongsToNote struct {
Icon struct { Icon struct {
field.RelationField field.RelationField
} }
Metadata struct {
field.RelationField
RemoteServer struct {
field.RelationField
}
}
} }
Icon struct { Icon struct {
field.RelationField field.RelationField

View file

@ -40,6 +40,12 @@ func newNoteToAttachment(db *gorm.DB, opts ...gen.DOOption) noteToAttachment {
Icon struct { Icon struct {
field.RelationField field.RelationField
} }
Metadata struct {
field.RelationField
RemoteServer struct {
field.RelationField
}
}
} }
Icon struct { Icon struct {
field.RelationField field.RelationField
@ -111,6 +117,12 @@ func newNoteToAttachment(db *gorm.DB, opts ...gen.DOOption) noteToAttachment {
Icon struct { Icon struct {
field.RelationField field.RelationField
} }
Metadata struct {
field.RelationField
RemoteServer struct {
field.RelationField
}
}
}{ }{
RelationField: field.NewRelation("Note.Creator.Server", "models.RemoteServer"), RelationField: field.NewRelation("Note.Creator.Server", "models.RemoteServer"),
Icon: struct { Icon: struct {
@ -118,6 +130,19 @@ func newNoteToAttachment(db *gorm.DB, opts ...gen.DOOption) noteToAttachment {
}{ }{
RelationField: field.NewRelation("Note.Creator.Server.Icon", "models.MediaMetadata"), RelationField: field.NewRelation("Note.Creator.Server.Icon", "models.MediaMetadata"),
}, },
Metadata: struct {
field.RelationField
RemoteServer struct {
field.RelationField
}
}{
RelationField: field.NewRelation("Note.Creator.Server.Metadata", "models.RemoteServerMetadata"),
RemoteServer: struct {
field.RelationField
}{
RelationField: field.NewRelation("Note.Creator.Server.Metadata.RemoteServer", "models.RemoteServer"),
},
},
}, },
Icon: struct { Icon: struct {
field.RelationField field.RelationField
@ -445,6 +470,12 @@ type noteToAttachmentBelongsToNote struct {
Icon struct { Icon struct {
field.RelationField field.RelationField
} }
Metadata struct {
field.RelationField
RemoteServer struct {
field.RelationField
}
}
} }
Icon struct { Icon struct {
field.RelationField field.RelationField

View file

@ -39,6 +39,12 @@ func newNoteToBoost(db *gorm.DB, opts ...gen.DOOption) noteToBoost {
Icon struct { Icon struct {
field.RelationField field.RelationField
} }
Metadata struct {
field.RelationField
RemoteServer struct {
field.RelationField
}
}
}{ }{
RelationField: field.NewRelation("User.Server", "models.RemoteServer"), RelationField: field.NewRelation("User.Server", "models.RemoteServer"),
Icon: struct { Icon: struct {
@ -46,6 +52,19 @@ func newNoteToBoost(db *gorm.DB, opts ...gen.DOOption) noteToBoost {
}{ }{
RelationField: field.NewRelation("User.Server.Icon", "models.MediaMetadata"), RelationField: field.NewRelation("User.Server.Icon", "models.MediaMetadata"),
}, },
Metadata: struct {
field.RelationField
RemoteServer struct {
field.RelationField
}
}{
RelationField: field.NewRelation("User.Server.Metadata", "models.RemoteServerMetadata"),
RemoteServer: struct {
field.RelationField
}{
RelationField: field.NewRelation("User.Server.Metadata.RemoteServer", "models.RemoteServer"),
},
},
}, },
Icon: struct { Icon: struct {
field.RelationField field.RelationField
@ -378,6 +397,12 @@ type noteToBoostBelongsToUser struct {
Icon struct { Icon struct {
field.RelationField field.RelationField
} }
Metadata struct {
field.RelationField
RemoteServer struct {
field.RelationField
}
}
} }
Icon struct { Icon struct {
field.RelationField field.RelationField

View file

@ -40,6 +40,12 @@ func newNoteToEmote(db *gorm.DB, opts ...gen.DOOption) noteToEmote {
Icon struct { Icon struct {
field.RelationField field.RelationField
} }
Metadata struct {
field.RelationField
RemoteServer struct {
field.RelationField
}
}
} }
Icon struct { Icon struct {
field.RelationField field.RelationField
@ -111,6 +117,12 @@ func newNoteToEmote(db *gorm.DB, opts ...gen.DOOption) noteToEmote {
Icon struct { Icon struct {
field.RelationField field.RelationField
} }
Metadata struct {
field.RelationField
RemoteServer struct {
field.RelationField
}
}
}{ }{
RelationField: field.NewRelation("Note.Creator.Server", "models.RemoteServer"), RelationField: field.NewRelation("Note.Creator.Server", "models.RemoteServer"),
Icon: struct { Icon: struct {
@ -118,6 +130,19 @@ func newNoteToEmote(db *gorm.DB, opts ...gen.DOOption) noteToEmote {
}{ }{
RelationField: field.NewRelation("Note.Creator.Server.Icon", "models.MediaMetadata"), RelationField: field.NewRelation("Note.Creator.Server.Icon", "models.MediaMetadata"),
}, },
Metadata: struct {
field.RelationField
RemoteServer struct {
field.RelationField
}
}{
RelationField: field.NewRelation("Note.Creator.Server.Metadata", "models.RemoteServerMetadata"),
RemoteServer: struct {
field.RelationField
}{
RelationField: field.NewRelation("Note.Creator.Server.Metadata.RemoteServer", "models.RemoteServer"),
},
},
}, },
Icon: struct { Icon: struct {
field.RelationField field.RelationField
@ -445,6 +470,12 @@ type noteToEmoteBelongsToNote struct {
Icon struct { Icon struct {
field.RelationField field.RelationField
} }
Metadata struct {
field.RelationField
RemoteServer struct {
field.RelationField
}
}
} }
Icon struct { Icon struct {
field.RelationField field.RelationField

View file

@ -40,6 +40,12 @@ func newNoteToFeed(db *gorm.DB, opts ...gen.DOOption) noteToFeed {
Icon struct { Icon struct {
field.RelationField field.RelationField
} }
Metadata struct {
field.RelationField
RemoteServer struct {
field.RelationField
}
}
} }
Icon struct { Icon struct {
field.RelationField field.RelationField
@ -111,6 +117,12 @@ func newNoteToFeed(db *gorm.DB, opts ...gen.DOOption) noteToFeed {
Icon struct { Icon struct {
field.RelationField field.RelationField
} }
Metadata struct {
field.RelationField
RemoteServer struct {
field.RelationField
}
}
}{ }{
RelationField: field.NewRelation("Note.Creator.Server", "models.RemoteServer"), RelationField: field.NewRelation("Note.Creator.Server", "models.RemoteServer"),
Icon: struct { Icon: struct {
@ -118,6 +130,19 @@ func newNoteToFeed(db *gorm.DB, opts ...gen.DOOption) noteToFeed {
}{ }{
RelationField: field.NewRelation("Note.Creator.Server.Icon", "models.MediaMetadata"), RelationField: field.NewRelation("Note.Creator.Server.Icon", "models.MediaMetadata"),
}, },
Metadata: struct {
field.RelationField
RemoteServer struct {
field.RelationField
}
}{
RelationField: field.NewRelation("Note.Creator.Server.Metadata", "models.RemoteServerMetadata"),
RemoteServer: struct {
field.RelationField
}{
RelationField: field.NewRelation("Note.Creator.Server.Metadata.RemoteServer", "models.RemoteServer"),
},
},
}, },
Icon: struct { Icon: struct {
field.RelationField field.RelationField
@ -437,6 +462,12 @@ type noteToFeedBelongsToNote struct {
Icon struct { Icon struct {
field.RelationField field.RelationField
} }
Metadata struct {
field.RelationField
RemoteServer struct {
field.RelationField
}
}
} }
Icon struct { Icon struct {
field.RelationField field.RelationField

View file

@ -40,6 +40,12 @@ func newNoteToPing(db *gorm.DB, opts ...gen.DOOption) noteToPing {
Icon struct { Icon struct {
field.RelationField field.RelationField
} }
Metadata struct {
field.RelationField
RemoteServer struct {
field.RelationField
}
}
} }
Icon struct { Icon struct {
field.RelationField field.RelationField
@ -111,6 +117,12 @@ func newNoteToPing(db *gorm.DB, opts ...gen.DOOption) noteToPing {
Icon struct { Icon struct {
field.RelationField field.RelationField
} }
Metadata struct {
field.RelationField
RemoteServer struct {
field.RelationField
}
}
}{ }{
RelationField: field.NewRelation("Note.Creator.Server", "models.RemoteServer"), RelationField: field.NewRelation("Note.Creator.Server", "models.RemoteServer"),
Icon: struct { Icon: struct {
@ -118,6 +130,19 @@ func newNoteToPing(db *gorm.DB, opts ...gen.DOOption) noteToPing {
}{ }{
RelationField: field.NewRelation("Note.Creator.Server.Icon", "models.MediaMetadata"), RelationField: field.NewRelation("Note.Creator.Server.Icon", "models.MediaMetadata"),
}, },
Metadata: struct {
field.RelationField
RemoteServer struct {
field.RelationField
}
}{
RelationField: field.NewRelation("Note.Creator.Server.Metadata", "models.RemoteServerMetadata"),
RemoteServer: struct {
field.RelationField
}{
RelationField: field.NewRelation("Note.Creator.Server.Metadata.RemoteServer", "models.RemoteServer"),
},
},
}, },
Icon: struct { Icon: struct {
field.RelationField field.RelationField
@ -445,6 +470,12 @@ type noteToPingBelongsToNote struct {
Icon struct { Icon struct {
field.RelationField field.RelationField
} }
Metadata struct {
field.RelationField
RemoteServer struct {
field.RelationField
}
}
} }
Icon struct { Icon struct {
field.RelationField field.RelationField

View file

@ -52,6 +52,12 @@ func newNote(db *gorm.DB, opts ...gen.DOOption) note {
Icon struct { Icon struct {
field.RelationField field.RelationField
} }
Metadata struct {
field.RelationField
RemoteServer struct {
field.RelationField
}
}
} }
Icon struct { Icon struct {
field.RelationField field.RelationField
@ -162,6 +168,12 @@ func newNote(db *gorm.DB, opts ...gen.DOOption) note {
Icon struct { Icon struct {
field.RelationField field.RelationField
} }
Metadata struct {
field.RelationField
RemoteServer struct {
field.RelationField
}
}
} }
Icon struct { Icon struct {
field.RelationField field.RelationField
@ -233,6 +245,12 @@ func newNote(db *gorm.DB, opts ...gen.DOOption) note {
Icon struct { Icon struct {
field.RelationField field.RelationField
} }
Metadata struct {
field.RelationField
RemoteServer struct {
field.RelationField
}
}
}{ }{
RelationField: field.NewRelation("AttachmentRelations.Note.Creator.Server", "models.RemoteServer"), RelationField: field.NewRelation("AttachmentRelations.Note.Creator.Server", "models.RemoteServer"),
Icon: struct { Icon: struct {
@ -240,6 +258,19 @@ func newNote(db *gorm.DB, opts ...gen.DOOption) note {
}{ }{
RelationField: field.NewRelation("AttachmentRelations.Note.Creator.Server.Icon", "models.MediaMetadata"), RelationField: field.NewRelation("AttachmentRelations.Note.Creator.Server.Icon", "models.MediaMetadata"),
}, },
Metadata: struct {
field.RelationField
RemoteServer struct {
field.RelationField
}
}{
RelationField: field.NewRelation("AttachmentRelations.Note.Creator.Server.Metadata", "models.RemoteServerMetadata"),
RemoteServer: struct {
field.RelationField
}{
RelationField: field.NewRelation("AttachmentRelations.Note.Creator.Server.Metadata.RemoteServer", "models.RemoteServer"),
},
},
}, },
Icon: struct { Icon: struct {
field.RelationField field.RelationField
@ -618,6 +649,12 @@ type noteHasManyAttachmentRelations struct {
Icon struct { Icon struct {
field.RelationField field.RelationField
} }
Metadata struct {
field.RelationField
RemoteServer struct {
field.RelationField
}
}
} }
Icon struct { Icon struct {
field.RelationField field.RelationField

View file

@ -45,6 +45,12 @@ func newNotification(db *gorm.DB, opts ...gen.DOOption) notification {
Icon struct { Icon struct {
field.RelationField field.RelationField
} }
Metadata struct {
field.RelationField
RemoteServer struct {
field.RelationField
}
}
}{ }{
RelationField: field.NewRelation("ForUser.Server", "models.RemoteServer"), RelationField: field.NewRelation("ForUser.Server", "models.RemoteServer"),
Icon: struct { Icon: struct {
@ -52,6 +58,19 @@ func newNotification(db *gorm.DB, opts ...gen.DOOption) notification {
}{ }{
RelationField: field.NewRelation("ForUser.Server.Icon", "models.MediaMetadata"), RelationField: field.NewRelation("ForUser.Server.Icon", "models.MediaMetadata"),
}, },
Metadata: struct {
field.RelationField
RemoteServer struct {
field.RelationField
}
}{
RelationField: field.NewRelation("ForUser.Server.Metadata", "models.RemoteServerMetadata"),
RemoteServer: struct {
field.RelationField
}{
RelationField: field.NewRelation("ForUser.Server.Metadata.RemoteServer", "models.RemoteServer"),
},
},
}, },
Icon: struct { Icon: struct {
field.RelationField field.RelationField
@ -407,6 +426,12 @@ type notificationBelongsToForUser struct {
Icon struct { Icon struct {
field.RelationField field.RelationField
} }
Metadata struct {
field.RelationField
RemoteServer struct {
field.RelationField
}
}
} }
Icon struct { Icon struct {
field.RelationField field.RelationField

View file

@ -44,6 +44,12 @@ func newReaction(db *gorm.DB, opts ...gen.DOOption) reaction {
Icon struct { Icon struct {
field.RelationField field.RelationField
} }
Metadata struct {
field.RelationField
RemoteServer struct {
field.RelationField
}
}
} }
Icon struct { Icon struct {
field.RelationField field.RelationField
@ -115,6 +121,12 @@ func newReaction(db *gorm.DB, opts ...gen.DOOption) reaction {
Icon struct { Icon struct {
field.RelationField field.RelationField
} }
Metadata struct {
field.RelationField
RemoteServer struct {
field.RelationField
}
}
}{ }{
RelationField: field.NewRelation("Note.Creator.Server", "models.RemoteServer"), RelationField: field.NewRelation("Note.Creator.Server", "models.RemoteServer"),
Icon: struct { Icon: struct {
@ -122,6 +134,19 @@ func newReaction(db *gorm.DB, opts ...gen.DOOption) reaction {
}{ }{
RelationField: field.NewRelation("Note.Creator.Server.Icon", "models.MediaMetadata"), RelationField: field.NewRelation("Note.Creator.Server.Icon", "models.MediaMetadata"),
}, },
Metadata: struct {
field.RelationField
RemoteServer struct {
field.RelationField
}
}{
RelationField: field.NewRelation("Note.Creator.Server.Metadata", "models.RemoteServerMetadata"),
RemoteServer: struct {
field.RelationField
}{
RelationField: field.NewRelation("Note.Creator.Server.Metadata.RemoteServer", "models.RemoteServer"),
},
},
}, },
Icon: struct { Icon: struct {
field.RelationField field.RelationField
@ -469,6 +494,12 @@ type reactionBelongsToNote struct {
Icon struct { Icon struct {
field.RelationField field.RelationField
} }
Metadata struct {
field.RelationField
RemoteServer struct {
field.RelationField
}
}
} }
Icon struct { Icon struct {
field.RelationField field.RelationField

View file

@ -0,0 +1,509 @@
// Code generated by gorm.io/gen. DO NOT EDIT.
// Code generated by gorm.io/gen. DO NOT EDIT.
// Code generated by gorm.io/gen. DO NOT EDIT.
package dbgen
import (
"context"
"git.mstar.dev/mstar/linstrom/storage-new/models"
"gorm.io/gorm"
"gorm.io/gorm/clause"
"gorm.io/gorm/schema"
"gorm.io/gen"
"gorm.io/gen/field"
"gorm.io/plugin/dbresolver"
)
func newRemoteServerMetadata(db *gorm.DB, opts ...gen.DOOption) remoteServerMetadata {
_remoteServerMetadata := remoteServerMetadata{}
_remoteServerMetadata.remoteServerMetadataDo.UseDB(db, opts...)
_remoteServerMetadata.remoteServerMetadataDo.UseModel(&models.RemoteServerMetadata{})
tableName := _remoteServerMetadata.remoteServerMetadataDo.TableName()
_remoteServerMetadata.ALL = field.NewAsterisk(tableName)
_remoteServerMetadata.ID = field.NewUint(tableName, "id")
_remoteServerMetadata.CreatedAt = field.NewTime(tableName, "created_at")
_remoteServerMetadata.UpdatedAt = field.NewTime(tableName, "updated_at")
_remoteServerMetadata.DeletedAt = field.NewField(tableName, "deleted_at")
_remoteServerMetadata.RemoteServerId = field.NewUint(tableName, "remote_server_id")
_remoteServerMetadata.Key = field.NewString(tableName, "key")
_remoteServerMetadata.Value = field.NewString(tableName, "value")
_remoteServerMetadata.RemoteServer = remoteServerMetadataBelongsToRemoteServer{
db: db.Session(&gorm.Session{}),
RelationField: field.NewRelation("RemoteServer", "models.RemoteServer"),
Icon: struct {
field.RelationField
}{
RelationField: field.NewRelation("RemoteServer.Icon", "models.MediaMetadata"),
},
Metadata: struct {
field.RelationField
RemoteServer struct {
field.RelationField
}
}{
RelationField: field.NewRelation("RemoteServer.Metadata", "models.RemoteServerMetadata"),
RemoteServer: struct {
field.RelationField
}{
RelationField: field.NewRelation("RemoteServer.Metadata.RemoteServer", "models.RemoteServer"),
},
},
}
_remoteServerMetadata.fillFieldMap()
return _remoteServerMetadata
}
type remoteServerMetadata struct {
remoteServerMetadataDo
ALL field.Asterisk
ID field.Uint
CreatedAt field.Time
UpdatedAt field.Time
DeletedAt field.Field
RemoteServerId field.Uint
Key field.String
Value field.String
RemoteServer remoteServerMetadataBelongsToRemoteServer
fieldMap map[string]field.Expr
}
func (r remoteServerMetadata) Table(newTableName string) *remoteServerMetadata {
r.remoteServerMetadataDo.UseTable(newTableName)
return r.updateTableName(newTableName)
}
func (r remoteServerMetadata) As(alias string) *remoteServerMetadata {
r.remoteServerMetadataDo.DO = *(r.remoteServerMetadataDo.As(alias).(*gen.DO))
return r.updateTableName(alias)
}
func (r *remoteServerMetadata) updateTableName(table string) *remoteServerMetadata {
r.ALL = field.NewAsterisk(table)
r.ID = field.NewUint(table, "id")
r.CreatedAt = field.NewTime(table, "created_at")
r.UpdatedAt = field.NewTime(table, "updated_at")
r.DeletedAt = field.NewField(table, "deleted_at")
r.RemoteServerId = field.NewUint(table, "remote_server_id")
r.Key = field.NewString(table, "key")
r.Value = field.NewString(table, "value")
r.fillFieldMap()
return r
}
func (r *remoteServerMetadata) GetFieldByName(fieldName string) (field.OrderExpr, bool) {
_f, ok := r.fieldMap[fieldName]
if !ok || _f == nil {
return nil, false
}
_oe, ok := _f.(field.OrderExpr)
return _oe, ok
}
func (r *remoteServerMetadata) fillFieldMap() {
r.fieldMap = make(map[string]field.Expr, 8)
r.fieldMap["id"] = r.ID
r.fieldMap["created_at"] = r.CreatedAt
r.fieldMap["updated_at"] = r.UpdatedAt
r.fieldMap["deleted_at"] = r.DeletedAt
r.fieldMap["remote_server_id"] = r.RemoteServerId
r.fieldMap["key"] = r.Key
r.fieldMap["value"] = r.Value
}
func (r remoteServerMetadata) clone(db *gorm.DB) remoteServerMetadata {
r.remoteServerMetadataDo.ReplaceConnPool(db.Statement.ConnPool)
return r
}
func (r remoteServerMetadata) replaceDB(db *gorm.DB) remoteServerMetadata {
r.remoteServerMetadataDo.ReplaceDB(db)
return r
}
type remoteServerMetadataBelongsToRemoteServer struct {
db *gorm.DB
field.RelationField
Icon struct {
field.RelationField
}
Metadata struct {
field.RelationField
RemoteServer struct {
field.RelationField
}
}
}
func (a remoteServerMetadataBelongsToRemoteServer) Where(conds ...field.Expr) *remoteServerMetadataBelongsToRemoteServer {
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 remoteServerMetadataBelongsToRemoteServer) WithContext(ctx context.Context) *remoteServerMetadataBelongsToRemoteServer {
a.db = a.db.WithContext(ctx)
return &a
}
func (a remoteServerMetadataBelongsToRemoteServer) Session(session *gorm.Session) *remoteServerMetadataBelongsToRemoteServer {
a.db = a.db.Session(session)
return &a
}
func (a remoteServerMetadataBelongsToRemoteServer) Model(m *models.RemoteServerMetadata) *remoteServerMetadataBelongsToRemoteServerTx {
return &remoteServerMetadataBelongsToRemoteServerTx{a.db.Model(m).Association(a.Name())}
}
type remoteServerMetadataBelongsToRemoteServerTx struct{ tx *gorm.Association }
func (a remoteServerMetadataBelongsToRemoteServerTx) Find() (result *models.RemoteServer, err error) {
return result, a.tx.Find(&result)
}
func (a remoteServerMetadataBelongsToRemoteServerTx) 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 remoteServerMetadataBelongsToRemoteServerTx) 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 remoteServerMetadataBelongsToRemoteServerTx) 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 remoteServerMetadataBelongsToRemoteServerTx) Clear() error {
return a.tx.Clear()
}
func (a remoteServerMetadataBelongsToRemoteServerTx) Count() int64 {
return a.tx.Count()
}
type remoteServerMetadataDo struct{ gen.DO }
type IRemoteServerMetadataDo interface {
gen.SubQuery
Debug() IRemoteServerMetadataDo
WithContext(ctx context.Context) IRemoteServerMetadataDo
WithResult(fc func(tx gen.Dao)) gen.ResultInfo
ReplaceDB(db *gorm.DB)
ReadDB() IRemoteServerMetadataDo
WriteDB() IRemoteServerMetadataDo
As(alias string) gen.Dao
Session(config *gorm.Session) IRemoteServerMetadataDo
Columns(cols ...field.Expr) gen.Columns
Clauses(conds ...clause.Expression) IRemoteServerMetadataDo
Not(conds ...gen.Condition) IRemoteServerMetadataDo
Or(conds ...gen.Condition) IRemoteServerMetadataDo
Select(conds ...field.Expr) IRemoteServerMetadataDo
Where(conds ...gen.Condition) IRemoteServerMetadataDo
Order(conds ...field.Expr) IRemoteServerMetadataDo
Distinct(cols ...field.Expr) IRemoteServerMetadataDo
Omit(cols ...field.Expr) IRemoteServerMetadataDo
Join(table schema.Tabler, on ...field.Expr) IRemoteServerMetadataDo
LeftJoin(table schema.Tabler, on ...field.Expr) IRemoteServerMetadataDo
RightJoin(table schema.Tabler, on ...field.Expr) IRemoteServerMetadataDo
Group(cols ...field.Expr) IRemoteServerMetadataDo
Having(conds ...gen.Condition) IRemoteServerMetadataDo
Limit(limit int) IRemoteServerMetadataDo
Offset(offset int) IRemoteServerMetadataDo
Count() (count int64, err error)
Scopes(funcs ...func(gen.Dao) gen.Dao) IRemoteServerMetadataDo
Unscoped() IRemoteServerMetadataDo
Create(values ...*models.RemoteServerMetadata) error
CreateInBatches(values []*models.RemoteServerMetadata, batchSize int) error
Save(values ...*models.RemoteServerMetadata) error
First() (*models.RemoteServerMetadata, error)
Take() (*models.RemoteServerMetadata, error)
Last() (*models.RemoteServerMetadata, error)
Find() ([]*models.RemoteServerMetadata, error)
FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*models.RemoteServerMetadata, err error)
FindInBatches(result *[]*models.RemoteServerMetadata, batchSize int, fc func(tx gen.Dao, batch int) error) error
Pluck(column field.Expr, dest interface{}) error
Delete(...*models.RemoteServerMetadata) (info gen.ResultInfo, err error)
Update(column field.Expr, value interface{}) (info gen.ResultInfo, err error)
UpdateSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error)
Updates(value interface{}) (info gen.ResultInfo, err error)
UpdateColumn(column field.Expr, value interface{}) (info gen.ResultInfo, err error)
UpdateColumnSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error)
UpdateColumns(value interface{}) (info gen.ResultInfo, err error)
UpdateFrom(q gen.SubQuery) gen.Dao
Attrs(attrs ...field.AssignExpr) IRemoteServerMetadataDo
Assign(attrs ...field.AssignExpr) IRemoteServerMetadataDo
Joins(fields ...field.RelationField) IRemoteServerMetadataDo
Preload(fields ...field.RelationField) IRemoteServerMetadataDo
FirstOrInit() (*models.RemoteServerMetadata, error)
FirstOrCreate() (*models.RemoteServerMetadata, error)
FindByPage(offset int, limit int) (result []*models.RemoteServerMetadata, count int64, err error)
ScanByPage(result interface{}, offset int, limit int) (count int64, err error)
Scan(result interface{}) (err error)
Returning(value interface{}, columns ...string) IRemoteServerMetadataDo
UnderlyingDB() *gorm.DB
schema.Tabler
}
func (r remoteServerMetadataDo) Debug() IRemoteServerMetadataDo {
return r.withDO(r.DO.Debug())
}
func (r remoteServerMetadataDo) WithContext(ctx context.Context) IRemoteServerMetadataDo {
return r.withDO(r.DO.WithContext(ctx))
}
func (r remoteServerMetadataDo) ReadDB() IRemoteServerMetadataDo {
return r.Clauses(dbresolver.Read)
}
func (r remoteServerMetadataDo) WriteDB() IRemoteServerMetadataDo {
return r.Clauses(dbresolver.Write)
}
func (r remoteServerMetadataDo) Session(config *gorm.Session) IRemoteServerMetadataDo {
return r.withDO(r.DO.Session(config))
}
func (r remoteServerMetadataDo) Clauses(conds ...clause.Expression) IRemoteServerMetadataDo {
return r.withDO(r.DO.Clauses(conds...))
}
func (r remoteServerMetadataDo) Returning(value interface{}, columns ...string) IRemoteServerMetadataDo {
return r.withDO(r.DO.Returning(value, columns...))
}
func (r remoteServerMetadataDo) Not(conds ...gen.Condition) IRemoteServerMetadataDo {
return r.withDO(r.DO.Not(conds...))
}
func (r remoteServerMetadataDo) Or(conds ...gen.Condition) IRemoteServerMetadataDo {
return r.withDO(r.DO.Or(conds...))
}
func (r remoteServerMetadataDo) Select(conds ...field.Expr) IRemoteServerMetadataDo {
return r.withDO(r.DO.Select(conds...))
}
func (r remoteServerMetadataDo) Where(conds ...gen.Condition) IRemoteServerMetadataDo {
return r.withDO(r.DO.Where(conds...))
}
func (r remoteServerMetadataDo) Order(conds ...field.Expr) IRemoteServerMetadataDo {
return r.withDO(r.DO.Order(conds...))
}
func (r remoteServerMetadataDo) Distinct(cols ...field.Expr) IRemoteServerMetadataDo {
return r.withDO(r.DO.Distinct(cols...))
}
func (r remoteServerMetadataDo) Omit(cols ...field.Expr) IRemoteServerMetadataDo {
return r.withDO(r.DO.Omit(cols...))
}
func (r remoteServerMetadataDo) Join(table schema.Tabler, on ...field.Expr) IRemoteServerMetadataDo {
return r.withDO(r.DO.Join(table, on...))
}
func (r remoteServerMetadataDo) LeftJoin(table schema.Tabler, on ...field.Expr) IRemoteServerMetadataDo {
return r.withDO(r.DO.LeftJoin(table, on...))
}
func (r remoteServerMetadataDo) RightJoin(table schema.Tabler, on ...field.Expr) IRemoteServerMetadataDo {
return r.withDO(r.DO.RightJoin(table, on...))
}
func (r remoteServerMetadataDo) Group(cols ...field.Expr) IRemoteServerMetadataDo {
return r.withDO(r.DO.Group(cols...))
}
func (r remoteServerMetadataDo) Having(conds ...gen.Condition) IRemoteServerMetadataDo {
return r.withDO(r.DO.Having(conds...))
}
func (r remoteServerMetadataDo) Limit(limit int) IRemoteServerMetadataDo {
return r.withDO(r.DO.Limit(limit))
}
func (r remoteServerMetadataDo) Offset(offset int) IRemoteServerMetadataDo {
return r.withDO(r.DO.Offset(offset))
}
func (r remoteServerMetadataDo) Scopes(funcs ...func(gen.Dao) gen.Dao) IRemoteServerMetadataDo {
return r.withDO(r.DO.Scopes(funcs...))
}
func (r remoteServerMetadataDo) Unscoped() IRemoteServerMetadataDo {
return r.withDO(r.DO.Unscoped())
}
func (r remoteServerMetadataDo) Create(values ...*models.RemoteServerMetadata) error {
if len(values) == 0 {
return nil
}
return r.DO.Create(values)
}
func (r remoteServerMetadataDo) CreateInBatches(values []*models.RemoteServerMetadata, batchSize int) error {
return r.DO.CreateInBatches(values, batchSize)
}
// Save : !!! underlying implementation is different with GORM
// The method is equivalent to executing the statement: db.Clauses(clause.OnConflict{UpdateAll: true}).Create(values)
func (r remoteServerMetadataDo) Save(values ...*models.RemoteServerMetadata) error {
if len(values) == 0 {
return nil
}
return r.DO.Save(values)
}
func (r remoteServerMetadataDo) First() (*models.RemoteServerMetadata, error) {
if result, err := r.DO.First(); err != nil {
return nil, err
} else {
return result.(*models.RemoteServerMetadata), nil
}
}
func (r remoteServerMetadataDo) Take() (*models.RemoteServerMetadata, error) {
if result, err := r.DO.Take(); err != nil {
return nil, err
} else {
return result.(*models.RemoteServerMetadata), nil
}
}
func (r remoteServerMetadataDo) Last() (*models.RemoteServerMetadata, error) {
if result, err := r.DO.Last(); err != nil {
return nil, err
} else {
return result.(*models.RemoteServerMetadata), nil
}
}
func (r remoteServerMetadataDo) Find() ([]*models.RemoteServerMetadata, error) {
result, err := r.DO.Find()
return result.([]*models.RemoteServerMetadata), err
}
func (r remoteServerMetadataDo) FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*models.RemoteServerMetadata, err error) {
buf := make([]*models.RemoteServerMetadata, 0, batchSize)
err = r.DO.FindInBatches(&buf, batchSize, func(tx gen.Dao, batch int) error {
defer func() { results = append(results, buf...) }()
return fc(tx, batch)
})
return results, err
}
func (r remoteServerMetadataDo) FindInBatches(result *[]*models.RemoteServerMetadata, batchSize int, fc func(tx gen.Dao, batch int) error) error {
return r.DO.FindInBatches(result, batchSize, fc)
}
func (r remoteServerMetadataDo) Attrs(attrs ...field.AssignExpr) IRemoteServerMetadataDo {
return r.withDO(r.DO.Attrs(attrs...))
}
func (r remoteServerMetadataDo) Assign(attrs ...field.AssignExpr) IRemoteServerMetadataDo {
return r.withDO(r.DO.Assign(attrs...))
}
func (r remoteServerMetadataDo) Joins(fields ...field.RelationField) IRemoteServerMetadataDo {
for _, _f := range fields {
r = *r.withDO(r.DO.Joins(_f))
}
return &r
}
func (r remoteServerMetadataDo) Preload(fields ...field.RelationField) IRemoteServerMetadataDo {
for _, _f := range fields {
r = *r.withDO(r.DO.Preload(_f))
}
return &r
}
func (r remoteServerMetadataDo) FirstOrInit() (*models.RemoteServerMetadata, error) {
if result, err := r.DO.FirstOrInit(); err != nil {
return nil, err
} else {
return result.(*models.RemoteServerMetadata), nil
}
}
func (r remoteServerMetadataDo) FirstOrCreate() (*models.RemoteServerMetadata, error) {
if result, err := r.DO.FirstOrCreate(); err != nil {
return nil, err
} else {
return result.(*models.RemoteServerMetadata), nil
}
}
func (r remoteServerMetadataDo) FindByPage(offset int, limit int) (result []*models.RemoteServerMetadata, count int64, err error) {
result, err = r.Offset(offset).Limit(limit).Find()
if err != nil {
return
}
if size := len(result); 0 < limit && 0 < size && size < limit {
count = int64(size + offset)
return
}
count, err = r.Offset(-1).Limit(-1).Count()
return
}
func (r remoteServerMetadataDo) ScanByPage(result interface{}, offset int, limit int) (count int64, err error) {
count, err = r.Count()
if err != nil {
return
}
err = r.Offset(offset).Limit(limit).Scan(result)
return
}
func (r remoteServerMetadataDo) Scan(result interface{}) (err error) {
return r.DO.Scan(result)
}
func (r remoteServerMetadataDo) Delete(models ...*models.RemoteServerMetadata) (result gen.ResultInfo, err error) {
return r.DO.Delete(models)
}
func (r *remoteServerMetadataDo) withDO(do gen.Dao) *remoteServerMetadataDo {
r.DO = *do.(*gen.DO)
return r
}

View file

@ -31,10 +31,39 @@ func newRemoteServer(db *gorm.DB, opts ...gen.DOOption) remoteServer {
_remoteServer.UpdatedAt = field.NewTime(tableName, "updated_at") _remoteServer.UpdatedAt = field.NewTime(tableName, "updated_at")
_remoteServer.DeletedAt = field.NewField(tableName, "deleted_at") _remoteServer.DeletedAt = field.NewField(tableName, "deleted_at")
_remoteServer.ServerType = field.NewField(tableName, "server_type") _remoteServer.ServerType = field.NewField(tableName, "server_type")
_remoteServer.SpecificType = field.NewString(tableName, "specific_type")
_remoteServer.Version = field.NewString(tableName, "version")
_remoteServer.Domain = field.NewString(tableName, "domain") _remoteServer.Domain = field.NewString(tableName, "domain")
_remoteServer.Name = field.NewString(tableName, "name") _remoteServer.Name = field.NewString(tableName, "name")
_remoteServer.IconId = field.NewField(tableName, "icon_id") _remoteServer.IconId = field.NewField(tableName, "icon_id")
_remoteServer.IsSelf = field.NewBool(tableName, "is_self") _remoteServer.IsSelf = field.NewBool(tableName, "is_self")
_remoteServer.Metadata = remoteServerHasManyMetadata{
db: db.Session(&gorm.Session{}),
RelationField: field.NewRelation("Metadata", "models.RemoteServerMetadata"),
RemoteServer: struct {
field.RelationField
Icon struct {
field.RelationField
}
Metadata struct {
field.RelationField
}
}{
RelationField: field.NewRelation("Metadata.RemoteServer", "models.RemoteServer"),
Icon: struct {
field.RelationField
}{
RelationField: field.NewRelation("Metadata.RemoteServer.Icon", "models.MediaMetadata"),
},
Metadata: struct {
field.RelationField
}{
RelationField: field.NewRelation("Metadata.RemoteServer.Metadata", "models.RemoteServerMetadata"),
},
},
}
_remoteServer.Icon = remoteServerBelongsToIcon{ _remoteServer.Icon = remoteServerBelongsToIcon{
db: db.Session(&gorm.Session{}), db: db.Session(&gorm.Session{}),
@ -49,17 +78,21 @@ func newRemoteServer(db *gorm.DB, opts ...gen.DOOption) remoteServer {
type remoteServer struct { type remoteServer struct {
remoteServerDo remoteServerDo
ALL field.Asterisk ALL field.Asterisk
ID field.Uint ID field.Uint
CreatedAt field.Time CreatedAt field.Time
UpdatedAt field.Time UpdatedAt field.Time
DeletedAt field.Field DeletedAt field.Field
ServerType field.Field ServerType field.Field
Domain field.String SpecificType field.String
Name field.String Version field.String
IconId field.Field Domain field.String
IsSelf field.Bool Name field.String
Icon remoteServerBelongsToIcon IconId field.Field
IsSelf field.Bool
Metadata remoteServerHasManyMetadata
Icon remoteServerBelongsToIcon
fieldMap map[string]field.Expr fieldMap map[string]field.Expr
} }
@ -81,6 +114,8 @@ func (r *remoteServer) updateTableName(table string) *remoteServer {
r.UpdatedAt = field.NewTime(table, "updated_at") r.UpdatedAt = field.NewTime(table, "updated_at")
r.DeletedAt = field.NewField(table, "deleted_at") r.DeletedAt = field.NewField(table, "deleted_at")
r.ServerType = field.NewField(table, "server_type") r.ServerType = field.NewField(table, "server_type")
r.SpecificType = field.NewString(table, "specific_type")
r.Version = field.NewString(table, "version")
r.Domain = field.NewString(table, "domain") r.Domain = field.NewString(table, "domain")
r.Name = field.NewString(table, "name") r.Name = field.NewString(table, "name")
r.IconId = field.NewField(table, "icon_id") r.IconId = field.NewField(table, "icon_id")
@ -101,12 +136,14 @@ func (r *remoteServer) GetFieldByName(fieldName string) (field.OrderExpr, bool)
} }
func (r *remoteServer) fillFieldMap() { func (r *remoteServer) fillFieldMap() {
r.fieldMap = make(map[string]field.Expr, 10) r.fieldMap = make(map[string]field.Expr, 13)
r.fieldMap["id"] = r.ID r.fieldMap["id"] = r.ID
r.fieldMap["created_at"] = r.CreatedAt r.fieldMap["created_at"] = r.CreatedAt
r.fieldMap["updated_at"] = r.UpdatedAt r.fieldMap["updated_at"] = r.UpdatedAt
r.fieldMap["deleted_at"] = r.DeletedAt r.fieldMap["deleted_at"] = r.DeletedAt
r.fieldMap["server_type"] = r.ServerType r.fieldMap["server_type"] = r.ServerType
r.fieldMap["specific_type"] = r.SpecificType
r.fieldMap["version"] = r.Version
r.fieldMap["domain"] = r.Domain r.fieldMap["domain"] = r.Domain
r.fieldMap["name"] = r.Name r.fieldMap["name"] = r.Name
r.fieldMap["icon_id"] = r.IconId r.fieldMap["icon_id"] = r.IconId
@ -124,6 +161,87 @@ func (r remoteServer) replaceDB(db *gorm.DB) remoteServer {
return r return r
} }
type remoteServerHasManyMetadata struct {
db *gorm.DB
field.RelationField
RemoteServer struct {
field.RelationField
Icon struct {
field.RelationField
}
Metadata struct {
field.RelationField
}
}
}
func (a remoteServerHasManyMetadata) Where(conds ...field.Expr) *remoteServerHasManyMetadata {
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 remoteServerHasManyMetadata) WithContext(ctx context.Context) *remoteServerHasManyMetadata {
a.db = a.db.WithContext(ctx)
return &a
}
func (a remoteServerHasManyMetadata) Session(session *gorm.Session) *remoteServerHasManyMetadata {
a.db = a.db.Session(session)
return &a
}
func (a remoteServerHasManyMetadata) Model(m *models.RemoteServer) *remoteServerHasManyMetadataTx {
return &remoteServerHasManyMetadataTx{a.db.Model(m).Association(a.Name())}
}
type remoteServerHasManyMetadataTx struct{ tx *gorm.Association }
func (a remoteServerHasManyMetadataTx) Find() (result []*models.RemoteServerMetadata, err error) {
return result, a.tx.Find(&result)
}
func (a remoteServerHasManyMetadataTx) Append(values ...*models.RemoteServerMetadata) (err error) {
targetValues := make([]interface{}, len(values))
for i, v := range values {
targetValues[i] = v
}
return a.tx.Append(targetValues...)
}
func (a remoteServerHasManyMetadataTx) Replace(values ...*models.RemoteServerMetadata) (err error) {
targetValues := make([]interface{}, len(values))
for i, v := range values {
targetValues[i] = v
}
return a.tx.Replace(targetValues...)
}
func (a remoteServerHasManyMetadataTx) Delete(values ...*models.RemoteServerMetadata) (err error) {
targetValues := make([]interface{}, len(values))
for i, v := range values {
targetValues[i] = v
}
return a.tx.Delete(targetValues...)
}
func (a remoteServerHasManyMetadataTx) Clear() error {
return a.tx.Clear()
}
func (a remoteServerHasManyMetadataTx) Count() int64 {
return a.tx.Count()
}
type remoteServerBelongsToIcon struct { type remoteServerBelongsToIcon struct {
db *gorm.DB db *gorm.DB

View file

@ -43,6 +43,12 @@ func newUserAuthMethod(db *gorm.DB, opts ...gen.DOOption) userAuthMethod {
Icon struct { Icon struct {
field.RelationField field.RelationField
} }
Metadata struct {
field.RelationField
RemoteServer struct {
field.RelationField
}
}
}{ }{
RelationField: field.NewRelation("User.Server", "models.RemoteServer"), RelationField: field.NewRelation("User.Server", "models.RemoteServer"),
Icon: struct { Icon: struct {
@ -50,6 +56,19 @@ func newUserAuthMethod(db *gorm.DB, opts ...gen.DOOption) userAuthMethod {
}{ }{
RelationField: field.NewRelation("User.Server.Icon", "models.MediaMetadata"), RelationField: field.NewRelation("User.Server.Icon", "models.MediaMetadata"),
}, },
Metadata: struct {
field.RelationField
RemoteServer struct {
field.RelationField
}
}{
RelationField: field.NewRelation("User.Server.Metadata", "models.RemoteServerMetadata"),
RemoteServer: struct {
field.RelationField
}{
RelationField: field.NewRelation("User.Server.Metadata.RemoteServer", "models.RemoteServer"),
},
},
}, },
Icon: struct { Icon: struct {
field.RelationField field.RelationField
@ -278,6 +297,12 @@ type userAuthMethodBelongsToUser struct {
Icon struct { Icon struct {
field.RelationField field.RelationField
} }
Metadata struct {
field.RelationField
RemoteServer struct {
field.RelationField
}
}
} }
Icon struct { Icon struct {
field.RelationField field.RelationField

View file

@ -44,6 +44,12 @@ func newUserInfoField(db *gorm.DB, opts ...gen.DOOption) userInfoField {
Icon struct { Icon struct {
field.RelationField field.RelationField
} }
Metadata struct {
field.RelationField
RemoteServer struct {
field.RelationField
}
}
}{ }{
RelationField: field.NewRelation("User.Server", "models.RemoteServer"), RelationField: field.NewRelation("User.Server", "models.RemoteServer"),
Icon: struct { Icon: struct {
@ -51,6 +57,19 @@ func newUserInfoField(db *gorm.DB, opts ...gen.DOOption) userInfoField {
}{ }{
RelationField: field.NewRelation("User.Server.Icon", "models.MediaMetadata"), RelationField: field.NewRelation("User.Server.Icon", "models.MediaMetadata"),
}, },
Metadata: struct {
field.RelationField
RemoteServer struct {
field.RelationField
}
}{
RelationField: field.NewRelation("User.Server.Metadata", "models.RemoteServerMetadata"),
RemoteServer: struct {
field.RelationField
}{
RelationField: field.NewRelation("User.Server.Metadata.RemoteServer", "models.RemoteServer"),
},
},
}, },
Icon: struct { Icon: struct {
field.RelationField field.RelationField
@ -282,6 +301,12 @@ type userInfoFieldBelongsToUser struct {
Icon struct { Icon struct {
field.RelationField field.RelationField
} }
Metadata struct {
field.RelationField
RemoteServer struct {
field.RelationField
}
}
} }
Icon struct { Icon struct {
field.RelationField field.RelationField

View file

@ -48,6 +48,12 @@ func newUserRemoteLinks(db *gorm.DB, opts ...gen.DOOption) userRemoteLinks {
Icon struct { Icon struct {
field.RelationField field.RelationField
} }
Metadata struct {
field.RelationField
RemoteServer struct {
field.RelationField
}
}
}{ }{
RelationField: field.NewRelation("User.Server", "models.RemoteServer"), RelationField: field.NewRelation("User.Server", "models.RemoteServer"),
Icon: struct { Icon: struct {
@ -55,6 +61,19 @@ func newUserRemoteLinks(db *gorm.DB, opts ...gen.DOOption) userRemoteLinks {
}{ }{
RelationField: field.NewRelation("User.Server.Icon", "models.MediaMetadata"), RelationField: field.NewRelation("User.Server.Icon", "models.MediaMetadata"),
}, },
Metadata: struct {
field.RelationField
RemoteServer struct {
field.RelationField
}
}{
RelationField: field.NewRelation("User.Server.Metadata", "models.RemoteServerMetadata"),
RemoteServer: struct {
field.RelationField
}{
RelationField: field.NewRelation("User.Server.Metadata.RemoteServer", "models.RemoteServer"),
},
},
}, },
Icon: struct { Icon: struct {
field.RelationField field.RelationField
@ -298,6 +317,12 @@ type userRemoteLinksBelongsToUser struct {
Icon struct { Icon struct {
field.RelationField field.RelationField
} }
Metadata struct {
field.RelationField
RemoteServer struct {
field.RelationField
}
}
} }
Icon struct { Icon struct {
field.RelationField field.RelationField

View file

@ -38,6 +38,12 @@ func newUserToBeing(db *gorm.DB, opts ...gen.DOOption) userToBeing {
Icon struct { Icon struct {
field.RelationField field.RelationField
} }
Metadata struct {
field.RelationField
RemoteServer struct {
field.RelationField
}
}
}{ }{
RelationField: field.NewRelation("User.Server", "models.RemoteServer"), RelationField: field.NewRelation("User.Server", "models.RemoteServer"),
Icon: struct { Icon: struct {
@ -45,6 +51,19 @@ func newUserToBeing(db *gorm.DB, opts ...gen.DOOption) userToBeing {
}{ }{
RelationField: field.NewRelation("User.Server.Icon", "models.MediaMetadata"), RelationField: field.NewRelation("User.Server.Icon", "models.MediaMetadata"),
}, },
Metadata: struct {
field.RelationField
RemoteServer struct {
field.RelationField
}
}{
RelationField: field.NewRelation("User.Server.Metadata", "models.RemoteServerMetadata"),
RemoteServer: struct {
field.RelationField
}{
RelationField: field.NewRelation("User.Server.Metadata.RemoteServer", "models.RemoteServer"),
},
},
}, },
Icon: struct { Icon: struct {
field.RelationField field.RelationField
@ -258,6 +277,12 @@ type userToBeingBelongsToUser struct {
Icon struct { Icon struct {
field.RelationField field.RelationField
} }
Metadata struct {
field.RelationField
RemoteServer struct {
field.RelationField
}
}
} }
Icon struct { Icon struct {
field.RelationField field.RelationField

View file

@ -38,6 +38,12 @@ func newUserToPronoun(db *gorm.DB, opts ...gen.DOOption) userToPronoun {
Icon struct { Icon struct {
field.RelationField field.RelationField
} }
Metadata struct {
field.RelationField
RemoteServer struct {
field.RelationField
}
}
}{ }{
RelationField: field.NewRelation("User.Server", "models.RemoteServer"), RelationField: field.NewRelation("User.Server", "models.RemoteServer"),
Icon: struct { Icon: struct {
@ -45,6 +51,19 @@ func newUserToPronoun(db *gorm.DB, opts ...gen.DOOption) userToPronoun {
}{ }{
RelationField: field.NewRelation("User.Server.Icon", "models.MediaMetadata"), RelationField: field.NewRelation("User.Server.Icon", "models.MediaMetadata"),
}, },
Metadata: struct {
field.RelationField
RemoteServer struct {
field.RelationField
}
}{
RelationField: field.NewRelation("User.Server.Metadata", "models.RemoteServerMetadata"),
RemoteServer: struct {
field.RelationField
}{
RelationField: field.NewRelation("User.Server.Metadata.RemoteServer", "models.RemoteServer"),
},
},
}, },
Icon: struct { Icon: struct {
field.RelationField field.RelationField
@ -258,6 +277,12 @@ type userToPronounBelongsToUser struct {
Icon struct { Icon struct {
field.RelationField field.RelationField
} }
Metadata struct {
field.RelationField
RemoteServer struct {
field.RelationField
}
}
} }
Icon struct { Icon struct {
field.RelationField field.RelationField

View file

@ -38,6 +38,12 @@ func newUserToRole(db *gorm.DB, opts ...gen.DOOption) userToRole {
Icon struct { Icon struct {
field.RelationField field.RelationField
} }
Metadata struct {
field.RelationField
RemoteServer struct {
field.RelationField
}
}
}{ }{
RelationField: field.NewRelation("User.Server", "models.RemoteServer"), RelationField: field.NewRelation("User.Server", "models.RemoteServer"),
Icon: struct { Icon: struct {
@ -45,6 +51,19 @@ func newUserToRole(db *gorm.DB, opts ...gen.DOOption) userToRole {
}{ }{
RelationField: field.NewRelation("User.Server.Icon", "models.MediaMetadata"), RelationField: field.NewRelation("User.Server.Icon", "models.MediaMetadata"),
}, },
Metadata: struct {
field.RelationField
RemoteServer struct {
field.RelationField
}
}{
RelationField: field.NewRelation("User.Server.Metadata", "models.RemoteServerMetadata"),
RemoteServer: struct {
field.RelationField
}{
RelationField: field.NewRelation("User.Server.Metadata.RemoteServer", "models.RemoteServer"),
},
},
}, },
Icon: struct { Icon: struct {
field.RelationField field.RelationField
@ -266,6 +285,12 @@ type userToRoleBelongsToUser struct {
Icon struct { Icon struct {
field.RelationField field.RelationField
} }
Metadata struct {
field.RelationField
RemoteServer struct {
field.RelationField
}
}
} }
Icon struct { Icon struct {
field.RelationField field.RelationField

View file

@ -38,6 +38,12 @@ func newUserToTag(db *gorm.DB, opts ...gen.DOOption) userToTag {
Icon struct { Icon struct {
field.RelationField field.RelationField
} }
Metadata struct {
field.RelationField
RemoteServer struct {
field.RelationField
}
}
}{ }{
RelationField: field.NewRelation("User.Server", "models.RemoteServer"), RelationField: field.NewRelation("User.Server", "models.RemoteServer"),
Icon: struct { Icon: struct {
@ -45,6 +51,19 @@ func newUserToTag(db *gorm.DB, opts ...gen.DOOption) userToTag {
}{ }{
RelationField: field.NewRelation("User.Server.Icon", "models.MediaMetadata"), RelationField: field.NewRelation("User.Server.Icon", "models.MediaMetadata"),
}, },
Metadata: struct {
field.RelationField
RemoteServer struct {
field.RelationField
}
}{
RelationField: field.NewRelation("User.Server.Metadata", "models.RemoteServerMetadata"),
RemoteServer: struct {
field.RelationField
}{
RelationField: field.NewRelation("User.Server.Metadata.RemoteServer", "models.RemoteServer"),
},
},
}, },
Icon: struct { Icon: struct {
field.RelationField field.RelationField
@ -258,6 +277,12 @@ type userToTagBelongsToUser struct {
Icon struct { Icon struct {
field.RelationField field.RelationField
} }
Metadata struct {
field.RelationField
RemoteServer struct {
field.RelationField
}
}
} }
Icon struct { Icon struct {
field.RelationField field.RelationField

View file

@ -39,6 +39,12 @@ func newUserToUserRelation(db *gorm.DB, opts ...gen.DOOption) userToUserRelation
Icon struct { Icon struct {
field.RelationField field.RelationField
} }
Metadata struct {
field.RelationField
RemoteServer struct {
field.RelationField
}
}
}{ }{
RelationField: field.NewRelation("User.Server", "models.RemoteServer"), RelationField: field.NewRelation("User.Server", "models.RemoteServer"),
Icon: struct { Icon: struct {
@ -46,6 +52,19 @@ func newUserToUserRelation(db *gorm.DB, opts ...gen.DOOption) userToUserRelation
}{ }{
RelationField: field.NewRelation("User.Server.Icon", "models.MediaMetadata"), RelationField: field.NewRelation("User.Server.Icon", "models.MediaMetadata"),
}, },
Metadata: struct {
field.RelationField
RemoteServer struct {
field.RelationField
}
}{
RelationField: field.NewRelation("User.Server.Metadata", "models.RemoteServerMetadata"),
RemoteServer: struct {
field.RelationField
}{
RelationField: field.NewRelation("User.Server.Metadata.RemoteServer", "models.RemoteServer"),
},
},
}, },
Icon: struct { Icon: struct {
field.RelationField field.RelationField
@ -270,6 +289,12 @@ type userToUserRelationBelongsToUser struct {
Icon struct { Icon struct {
field.RelationField field.RelationField
} }
Metadata struct {
field.RelationField
RemoteServer struct {
field.RelationField
}
}
} }
Icon struct { Icon struct {
field.RelationField field.RelationField

View file

@ -61,6 +61,12 @@ func newUser(db *gorm.DB, opts ...gen.DOOption) user {
Icon struct { Icon struct {
field.RelationField field.RelationField
} }
Metadata struct {
field.RelationField
RemoteServer struct {
field.RelationField
}
}
} }
Icon struct { Icon struct {
field.RelationField field.RelationField
@ -129,6 +135,12 @@ func newUser(db *gorm.DB, opts ...gen.DOOption) user {
Icon struct { Icon struct {
field.RelationField field.RelationField
} }
Metadata struct {
field.RelationField
RemoteServer struct {
field.RelationField
}
}
}{ }{
RelationField: field.NewRelation("RemoteInfo.User.Server", "models.RemoteServer"), RelationField: field.NewRelation("RemoteInfo.User.Server", "models.RemoteServer"),
Icon: struct { Icon: struct {
@ -136,6 +148,19 @@ func newUser(db *gorm.DB, opts ...gen.DOOption) user {
}{ }{
RelationField: field.NewRelation("RemoteInfo.User.Server.Icon", "models.MediaMetadata"), RelationField: field.NewRelation("RemoteInfo.User.Server.Icon", "models.MediaMetadata"),
}, },
Metadata: struct {
field.RelationField
RemoteServer struct {
field.RelationField
}
}{
RelationField: field.NewRelation("RemoteInfo.User.Server.Metadata", "models.RemoteServerMetadata"),
RemoteServer: struct {
field.RelationField
}{
RelationField: field.NewRelation("RemoteInfo.User.Server.Metadata.RemoteServer", "models.RemoteServer"),
},
},
}, },
Icon: struct { Icon: struct {
field.RelationField field.RelationField
@ -492,6 +517,12 @@ type userHasOneRemoteInfo struct {
Icon struct { Icon struct {
field.RelationField field.RelationField
} }
Metadata struct {
field.RelationField
RemoteServer struct {
field.RelationField
}
}
} }
Icon struct { Icon struct {
field.RelationField field.RelationField

View file

@ -15,6 +15,7 @@ var AllTypes = []any{
&Notification{}, &Notification{},
&Reaction{}, &Reaction{},
&RemoteServer{}, &RemoteServer{},
&RemoteServerMetadata{},
&Role{}, &Role{},
&AccessToken{}, &AccessToken{},
&LoginProcessToken{}, &LoginProcessToken{},

View file

@ -10,10 +10,15 @@ import (
// This includes self too // This includes self too
type RemoteServer struct { type RemoteServer struct {
gorm.Model gorm.Model
ServerType ServerSoftwareType // What software the server is running. Useful for formatting // What software type the server is running. Useful for formatting.
Domain string // `gorm:"primaryKey"` // Domain the server exists under. Additional primary key // Groups various types together (ex. firefish, iceshrimp, sharkey, misskey => misskey)
Name string // What the server wants to be known as (usually same as url) ServerType ServerSoftwareType
Icon *MediaMetadata // The icon used by the server. May be empty SpecificType string // Specific type
IconId sql.NullString // ID of a media file Version string
IsSelf bool // Whether this server is yours truly 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 *MediaMetadata // The icon used by the server. May be empty
IconId sql.NullString // ID of a media file
IsSelf bool // Whether this server is yours truly
Metadata []RemoteServerMetadata
} }

View file

@ -0,0 +1,13 @@
package models
import (
"gorm.io/gorm"
)
type RemoteServerMetadata struct {
gorm.Model
RemoteServer RemoteServer
RemoteServerId uint
Key string
Value string
}

View file

@ -25,60 +25,60 @@ type User struct {
// identifier for users and other servers, especially when changing the username // identifier for users and other servers, especially when changing the username
// (username != display name) might be a future feature // (username != display name) might be a future feature
// Same also applies for other types that use a UUID as primary key // Same also applies for other types that use a UUID as primary key
ID string `gorm:"primarykey;default:gen_random_uuid()" json:"id"` ID string `gorm:"primarykey;default:gen_random_uuid()"`
// Username of the user (eg "max" if the full username is @max@example.com) // Username of the user (eg "max" if the full username is @max@example.com)
// Assume unchangable (once set by a user) to be kind to other implementations // Assume unchangable (once set by a user) to be kind to other implementations
// Would be an easy avenue to fuck with them though // Would be an easy avenue to fuck with them though
Username string `gorm:"unique" json:"username"` Username string `gorm:"unique"`
CreatedAt time.Time ` json:"created_at"` // When this entry was created. Automatically set by gorm CreatedAt time.Time // When this entry was created. Automatically set by gorm
// When this account was last updated. Will also be used for refreshing remote accounts. Automatically set by gorm // When this account was last updated. Will also be used for refreshing remote accounts. Automatically set by gorm
UpdatedAt time.Time ` json:"updated_at"` UpdatedAt time.Time
// When this entry was deleted (for soft deletions) // 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 // 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 // If not null, this entry is marked as deleted
DeletedAt gorm.DeletedAt `gorm:"index" json:"deleted_at"` DeletedAt gorm.DeletedAt `gorm:"index"`
Server RemoteServer ` json:"-"` Server RemoteServer
ServerId uint ` json:"server_id"` // Id of the server this user is from, needed for including RemoteServer ServerId uint // Id of the server this user is from, needed for including RemoteServer
DisplayName string ` json:"display_name"` // The display name of the user. Can be different from the handle DisplayName string // The display name of the user. Can be different from the handle
Description string ` json:"description"` // The description of a user account Description string // The description of a user account
IsBot bool ` json:"is_bot"` // Whether to mark this account as a script controlled one IsBot bool // Whether to mark this account as a script controlled one
Icon *MediaMetadata ` json:"-"` Icon *MediaMetadata
IconId sql.NullString ` json:"icon_id"` // ID of a media file used as icon IconId sql.NullString // ID of a media file used as icon
Background *MediaMetadata ` json:"-"` Background *MediaMetadata
BackgroundId sql.NullString ` json:"background_id"` // ID of a media file used as background image BackgroundId sql.NullString // ID of a media file used as background image
Banner *MediaMetadata ` json:"-"` Banner *MediaMetadata
BannerId sql.NullString ` json:"banner_id"` // ID of a media file used as banner BannerId sql.NullString // ID of a media file used as banner
Indexable bool ` json:"indexable"` // Whether this account can be found by crawlers Indexable bool // Whether this account can be found by crawlers
PublicKeyRsa []byte ` json:"public_key_rsa"` // The public RSA key of the account PublicKeyRsa []byte // The public RSA key of the account
PublicKeyEd []byte ` json:"public_key_ed"` // The public Ed25519 key of the account PublicKeyEd []byte // The public Ed25519 key of the account
// Whether this account restricts following // Whether this account restricts following
// If true, the owner must approve of a follow request first // If true, the owner must approve of a follow request first
RestrictedFollow bool ` json:"restricted_follow"` RestrictedFollow bool
Location sql.NullString `json:"location"` Location sql.NullString
Birthday sql.NullTime `json:"birthday"` Birthday sql.NullTime
// Whether the account got verified and is allowed to be active // Whether the account got verified and is allowed to be active
// For local accounts being active means being allowed to login and perform interactions // For local accounts being active means being allowed to login and perform interactions
// For remote users, if an account is not verified, any interactions it sends are discarded // For remote users, if an account is not verified, any interactions it sends are discarded
Verified bool `json:"verified"` Verified bool
// 64 byte unique id for passkeys, because UUIDs are 128 bytes and passkey spec says 64 bytes max // 64 byte unique id for passkeys, because UUIDs are 128 bytes and passkey spec says 64 bytes max
// In theory, could also slash Id in half, but that would be a lot more calculations than the // In theory, could also slash Id in half, but that would be a lot more calculations than the
// saved space is worth // saved space is worth
PasskeyId []byte `json:"-"` PasskeyId []byte
FinishedRegistration bool `json:"-"` // Whether this account has completed registration yet FinishedRegistration bool // Whether this account has completed registration yet
PrivateKeyRsa []byte `json:"-"` PrivateKeyRsa []byte
PrivateKeyEd []byte `json:"-"` PrivateKeyEd []byte
// ---- "Remote" linked values // ---- "Remote" linked values
InfoFields []UserInfoField `json:"-"` InfoFields []UserInfoField
BeingTypes []UserToBeing `json:"-"` BeingTypes []UserToBeing
Tags []UserToTag `json:"-"` Tags []UserToTag
Relations []UserToUserRelation `json:"-"` Relations []UserToUserRelation
Pronouns []UserToPronoun `json:"-"` Pronouns []UserToPronoun
Roles []UserToRole `json:"-"` Roles []UserToRole
RemoteInfo *UserRemoteLinks `json:"-"` RemoteInfo *UserRemoteLinks
AuthMethods []UserAuthMethod `json:"-"` AuthMethods []UserAuthMethod
} }
type IUser interface { type IUser interface {

View file

@ -70,24 +70,26 @@ func insertDefaultDuck() (*models.MediaMetadata, error) {
} }
func insertServer(duck *models.MediaMetadata) (*models.RemoteServer, error) { func insertServer(duck *models.MediaMetadata) (*models.RemoteServer, error) {
dbServer, err := dbgen.RemoteServer.Where(dbgen.RemoteServer.ID.Eq(1)).First() // dbServer, err := dbgen.RemoteServer.Where(dbgen.RemoteServer.ID.Eq(1)).First()
if err == nil { // if err == nil {
return dbServer, nil // return dbServer, nil
} else if err != gorm.ErrRecordNotFound { // } else if err != gorm.ErrRecordNotFound {
return nil, err // return nil, err
} // }
server := models.RemoteServer{ server := models.RemoteServer{
Model: gorm.Model{ Model: gorm.Model{
ID: 1, ID: 1,
}, },
ServerType: models.ServerSoftwareLinstrom, ServerType: models.ServerSoftwareLinstrom,
Domain: config.GlobalConfig.General.GetFullDomain(), SpecificType: "linstrom",
Name: config.GlobalConfig.Self.ServerDisplayName, Version: shared.Version,
Icon: duck, Domain: config.GlobalConfig.General.GetFullDomain(),
IconId: sql.NullString{String: duck.ID, Valid: true}, Name: config.GlobalConfig.Self.ServerDisplayName,
IsSelf: true, Icon: duck,
IconId: sql.NullString{String: duck.ID, Valid: true},
IsSelf: true,
} }
err = dbgen.RemoteServer.Save(&server) err := dbgen.RemoteServer.Save(&server)
if err != nil { if err != nil {
return nil, err return nil, err
} }

16
web/debug/remoteServer.go Normal file
View file

@ -0,0 +1,16 @@
package webdebug
import (
"net/http"
"github.com/rs/zerolog/hlog"
"git.mstar.dev/mstar/linstrom/activitypub"
)
func importServerInfo(w http.ResponseWriter, r *http.Request) {
target := r.FormValue("target")
if _, err := activitypub.ImportRemoteServer(target); err != nil {
hlog.FromRequest(r).Error().Err(err).Msg("Failed to import")
}
}

View file

@ -27,8 +27,9 @@ func New(addr string) *Server {
handler.HandleFunc("GET /delete", deleteUser) handler.HandleFunc("GET /delete", deleteUser)
handler.HandleFunc("POST /post-as", postAs) handler.HandleFunc("POST /post-as", postAs)
handler.HandleFunc("GET /notes-for", notesFrom) handler.HandleFunc("GET /notes-for", notesFrom)
handler.HandleFunc("GET /import", issueUserImport) handler.HandleFunc("GET /import-user", issueUserImport)
handler.HandleFunc("GET /keys-for", returnKeypair) handler.HandleFunc("GET /keys-for", returnKeypair)
handler.HandleFunc("GET /import-server", importServerInfo)
web := http.Server{ web := http.Server{
Addr: addr, Addr: addr,
Handler: webutils.ChainMiddlewares( Handler: webutils.ChainMiddlewares(

View file

@ -38,6 +38,7 @@ func users(w http.ResponseWriter, r *http.Request) {
Type string `json:"type"` Type string `json:"type"`
PreferredUsername string `json:"preferredUsername"` PreferredUsername string `json:"preferredUsername"`
Inbox string `json:"inbox"` Inbox string `json:"inbox"`
Outboux string `json:"outbox"`
PublicKey OutboundKey `json:"publicKey"` PublicKey OutboundKey `json:"publicKey"`
Published time.Time `json:"published"` Published time.Time `json:"published"`
DisplayName string `json:"name"` DisplayName string `json:"name"`
@ -82,6 +83,7 @@ func users(w http.ResponseWriter, r *http.Request) {
Type: "Person", Type: "Person",
PreferredUsername: user.Username, PreferredUsername: user.Username,
Inbox: apUrl + "/inbox", Inbox: apUrl + "/inbox",
Outboux: apUrl + "/outbox",
PublicKey: OutboundKey{ PublicKey: OutboundKey{
Id: apUrl + "#main-key", Id: apUrl + "#main-key",
Owner: apUrl, Owner: apUrl,

View file

@ -15,6 +15,7 @@ import (
"git.mstar.dev/mstar/linstrom/shared" "git.mstar.dev/mstar/linstrom/shared"
"git.mstar.dev/mstar/linstrom/storage-new" "git.mstar.dev/mstar/linstrom/storage-new"
"git.mstar.dev/mstar/linstrom/storage-new/dbgen" "git.mstar.dev/mstar/linstrom/storage-new/dbgen"
webshared "git.mstar.dev/mstar/linstrom/web/shared"
) )
var webfingerResourceRegex = regexp.MustCompile(`acct:(?P<username>[\w-]+)@(?<domain>[\w\.-]+)`) var webfingerResourceRegex = regexp.MustCompile(`acct:(?P<username>[\w-]+)@(?<domain>[\w\.-]+)`)
@ -103,7 +104,23 @@ func WellKnownWebfinger(w http.ResponseWriter, r *http.Request) {
webutils.SendJson(w, &data) webutils.SendJson(w, &data)
} }
func Nodeinfo(w http.ResponseWriter, r *http.Request) { func NodeInfoOverview(w http.ResponseWriter, r *http.Request) {
data := webshared.NodeInfoOverview{
Links: []webshared.NodeInfoLink{
{
Rel: "http://nodeinfo.diaspora.software/ns/schema/2.1",
Href: config.GlobalConfig.General.GetFullPublicUrl() + "/nodeinfo/2.1",
},
{
Rel: "http://nodeinfo.diaspora.software/ns/schema/2.0",
Href: config.GlobalConfig.General.GetFullPublicUrl() + "/nodeinfo/2.0",
},
},
}
webutils.SendJson(w, data)
}
func NodeInfo21(w http.ResponseWriter, r *http.Request) {
u := dbgen.User u := dbgen.User
log := hlog.FromRequest(r) log := hlog.FromRequest(r)
userCount, err := u.Where(u.DeletedAt.IsNull(), u.Verified.Is(true)).Count() userCount, err := u.Where(u.DeletedAt.IsNull(), u.Verified.Is(true)).Count()
@ -128,42 +145,81 @@ func Nodeinfo(w http.ResponseWriter, r *http.Request) {
return return
} }
data := map[string]any{ data := webshared.NodeInfo2{
"version": "2.1", Version: "2.1",
"software": map[string]string{ Software: webshared.NodeInfo2Software{
"name": "linstrom", Name: "linstrom",
"version": shared.Version, Version: shared.Version,
"homepage": "https://git.mstar.dev/mstar/linstrom", Homepage: other.IntoPointer("https://git.mstar.dev/mstar/linstrom"),
"repository": "https://git.mstar.dev/mstar/linstrom", Repository: other.IntoPointer("https://git.mstar.dev/mstar/linstrom"),
}, },
"protocols": []string{"activitypub"}, Protocols: []string{"activitypub"},
"services": map[string]any{ Services: map[string][]string{
"inbound": []string{}, "inbound": {},
"outbound": []string{}, "outbound": {},
}, },
"openRegistrations": config.GlobalConfig.Admin.AllowRegistration, OpenRegistrations: config.GlobalConfig.Admin.AllowRegistration,
"usage": map[string]any{ Usage: webshared.NodeInfo2Usage{
"users": map[string]any{ Users: webshared.NodeInfo2UsageUsers{
"total": userCount, Total: uint(userCount),
"activeHalfyear": nil, ActiveHalfYear: nil,
"activeMonth": nil, ActiveMonth: nil,
}, },
"localPosts": noteCount, LocalPosts: uint(noteCount),
"localComments": 0, LocalComments: 0},
}, Metadata: map[string]any{},
"metadata": map[string]any{},
} }
webutils.SendJson(w, data) webutils.SendJson(w, data)
} }
func WellKnownNodeinfo(w http.ResponseWriter, r *http.Request) { func NodeInfo20(w http.ResponseWriter, r *http.Request) {
data := map[string]any{ u := dbgen.User
"links": []map[string]any{ log := hlog.FromRequest(r)
{ userCount, err := u.Where(u.DeletedAt.IsNull(), u.Verified.Is(true)).Count()
"rel": "http://nodeinfo.diaspora.software/ns/schema/2.1", if err != nil {
"href": config.GlobalConfig.General.GetFullPublicUrl() + "/nodeinfo/2.1", webutils.ProblemDetails(w, 500, "/errors/db-failure", "internal database failure", nil, nil)
}, if storage.HandleReconnectError(err) {
}, log.Warn().Msg("Connection to db lost. Reconnect attempt started")
} else {
log.Error().Err(err).Msg("Failed to get total user count from db")
}
return
} }
n := dbgen.Note
noteCount, err := n.Where(n.DeletedAt.IsNull(), n.OriginId.Eq(1)).Count()
if err != nil {
webutils.ProblemDetails(w, 500, "/errors/db-failure", "internal database failure", nil, nil)
if storage.HandleReconnectError(err) {
log.Warn().Msg("Connection to db lost. Reconnect attempt started")
} else {
log.Error().Err(err).Msg("Failed to get total user count from db")
}
return
}
data := webshared.NodeInfo2{
Version: "2.1",
Software: webshared.NodeInfo2Software{
Name: "linstrom",
Version: shared.Version,
Homepage: nil,
Repository: nil,
},
Protocols: []string{"activitypub"},
Services: map[string][]string{
"inbound": {},
"outbound": {},
},
OpenRegistrations: config.GlobalConfig.Admin.AllowRegistration,
Usage: webshared.NodeInfo2Usage{
Users: webshared.NodeInfo2UsageUsers{
Total: uint(userCount),
ActiveHalfYear: nil,
ActiveMonth: nil,
},
LocalPosts: uint(noteCount),
LocalComments: 0},
Metadata: map[string]any{},
}
webutils.SendJson(w, data) webutils.SendJson(w, data)
} }

View file

@ -48,8 +48,9 @@ func New(addr string, duckImg *string) *Server {
}) })
handler.Handle("/api/", http.StripPrefix("/api", api.BuildApiRouter())) handler.Handle("/api/", http.StripPrefix("/api", api.BuildApiRouter()))
handler.HandleFunc("GET /.well-known/webfinger", api.WellKnownWebfinger) handler.HandleFunc("GET /.well-known/webfinger", api.WellKnownWebfinger)
handler.HandleFunc("GET /.well-known/nodeinfo", api.WellKnownNodeinfo) handler.HandleFunc("GET /.well-known/nodeinfo", api.NodeInfoOverview)
handler.HandleFunc("GET /nodeinfo/2.1", api.Nodeinfo) handler.HandleFunc("GET /nodeinfo/2.1", api.NodeInfo21)
handler.HandleFunc("GET /nodeinfo/2.0", api.NodeInfo20)
handler.HandleFunc("GET /errors/{name}", errorTypeHandler) handler.HandleFunc("GET /errors/{name}", errorTypeHandler)
handler.HandleFunc("GET /default-image", func(w http.ResponseWriter, r *http.Request) { handler.HandleFunc("GET /default-image", func(w http.ResponseWriter, r *http.Request) {
w.Header().Add("Content-Type", "image/web") w.Header().Add("Content-Type", "image/web")

60
web/shared/Nodeinfo.go Normal file
View file

@ -0,0 +1,60 @@
package webshared
import (
"git.mstar.dev/mstar/goutils/sliceutils"
"git.mstar.dev/mstar/linstrom/storage-new/models"
)
type NodeInfoLink struct {
Rel string
Href string
}
type NodeInfoOverview struct {
Links []NodeInfoLink
}
type NodeInfo2Software struct {
Name string `json:"name"`
Version string `json:"version"`
Homepage *string `json:"homepage,omitempty"`
Repository *string `json:"repository,omitempty"`
}
type NodeInfo2UsageUsers struct {
Total uint `json:"total"`
ActiveHalfYear *uint `json:"active_half_year"`
ActiveMonth *uint `json:"active_month"`
}
type NodeInfo2Usage struct {
Users NodeInfo2UsageUsers `json:"users"`
LocalPosts uint `json:"local_posts"`
LocalComments uint `json:"local_comments"`
}
type NodeInfo2 struct {
Version string `json:"version"`
Software NodeInfo2Software `json:"software"`
Protocols []string `json:"protocols"`
Services map[string][]string `json:"services"`
OpenRegistrations bool `json:"open_registrations"`
Usage NodeInfo2Usage `json:"usage"`
Metadata map[string]any `json:"metadata"`
}
func MapNodeServerTypeToModelType(nodeType string) models.ServerSoftwareType {
if sliceutils.Contains([]string{"mastodon"}, nodeType) {
return models.ServerSoftwareMastodon
} else if sliceutils.Contains([]string{"sharkey", "misskey", "iceshrimp", "firefish"}, nodeType) {
return models.ServerSoftwareMisskey
} else if sliceutils.Contains([]string{"linstrom"}, nodeType) {
return models.ServerSoftwareLinstrom
} else if sliceutils.Contains([]string{"akkoma"}, nodeType) {
return models.ServerSoftwarePlemora
} else if sliceutils.Contains([]string{"wafrn"}, nodeType) {
return models.ServerSoftwareWafrn
}
return models.ServerSoftwareUnknown
}

View file

@ -2,8 +2,6 @@ package webshared
import ( import (
"bytes" "bytes"
"crypto"
"crypto/ed25519"
"crypto/sha256" "crypto/sha256"
"crypto/x509" "crypto/x509"
"encoding/base64" "encoding/base64"
@ -11,12 +9,11 @@ import (
"slices" "slices"
"time" "time"
"github.com/go-fed/httpsig"
"github.com/rs/zerolog/log"
"github.com/yaronf/httpsign" "github.com/yaronf/httpsign"
"git.mstar.dev/mstar/linstrom/config" "git.mstar.dev/mstar/linstrom/config"
"git.mstar.dev/mstar/linstrom/shared" "git.mstar.dev/mstar/linstrom/shared"
"git.mstar.dev/mstar/linstrom/storage-new/models"
) )
/* /*
@ -78,55 +75,32 @@ func RequestSignedRFC9421(
func RequestSignedCavage( func RequestSignedCavage(
method, target string, method, target string,
body []byte, body []byte,
keyId string, actor *models.User,
privateKeyBytes []byte,
useEd bool,
) (*http.Response, error) { ) (*http.Response, error) {
req, err := http.NewRequest(method, target, bytes.NewBuffer(slices.Clone(body))) req, err := NewRequest(method, target, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
applyDefaultHeaders(req) req.Header.Add("Accept", "application/activity+json")
var prefs []httpsig.Algorithm
var key crypto.PrivateKey var keyBytes []byte
if useEd { if config.GlobalConfig.Experimental.UseEd25519Keys {
log.Debug().Msg("Using ed25519 cavage") keyBytes = actor.PrivateKeyEd
prefs = append(prefs, httpsig.ED25519)
key = ed25519.PrivateKey(privateKeyBytes)
} else { } else {
log.Debug().Msg("Using RSA cavage") keyBytes = actor.PrivateKeyRsa
// prefs = append(prefs, httpsig.RSA_SHA512, httpsig.RSA_SHA256)
prefs = append(prefs, httpsig.RSA_SHA256)
tempKey, err := x509.ParsePKCS1PrivateKey(privateKeyBytes)
if err != nil {
return nil, err
}
key = tempKey
} }
digestAlgorithm := httpsig.DigestSha256
headersToSign := []string{httpsig.RequestTarget, "date", "host", "user-agent"} // Sign and send
if len(body) > 0 { err = SignRequest(
headersToSign = append(headersToSign, "digest") req,
log.Debug().Msg("Non-empty body, adding digest") actor.ID+"#main-key",
} else { keyBytes,
// Just to ensure the signer doesn't fuck up body,
body = nil
}
signer, chosenAlgorithm, err := httpsig.NewSigner(
prefs,
digestAlgorithm,
headersToSign,
httpsig.Signature,
int64(time.Hour),
) )
// err = webshared.SignRequestWithHttpsig(req, linstromActor.ID+"#main-key", keyBytes, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
log.Debug().Any("algorithm", chosenAlgorithm).Msg("Signer chose algorithm")
if err = signer.SignRequest(key, keyId, req, body); err != nil {
return nil, err
}
log.Debug().Any("headers", req.Header).Msg("Request post signing")
return RequestClient.Do(req) return RequestClient.Do(req)
} }

View file

@ -27,7 +27,7 @@ func CreateSignatureRSA(
return "", nil, err return "", nil, err
} }
encoded := base64.StdEncoding.EncodeToString(signed) encoded := base64.StdEncoding.EncodeToString(signed)
log.Debug(). log.Trace().
Str("raw-message", message). Str("raw-message", message).
Bytes("signed", signed). Bytes("signed", signed).
Str("encoded", encoded). Str("encoded", encoded).