Step one: Copy the struct definitions over into a new, dedicated submodule Step two: Make a generator script Step three: Define helper functions for various queries
This commit is contained in:
parent
0639cde4f2
commit
714f528641
27 changed files with 983 additions and 0 deletions
64
storage-new/gormLogger.go
Normal file
64
storage-new/gormLogger.go
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
package storage
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/rs/zerolog"
|
||||||
|
"gorm.io/gorm/logger"
|
||||||
|
)
|
||||||
|
|
||||||
|
type gormLogger struct {
|
||||||
|
logger zerolog.Logger
|
||||||
|
}
|
||||||
|
|
||||||
|
func newGormLogger(zerologger zerolog.Logger) *gormLogger {
|
||||||
|
return &gormLogger{zerologger}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *gormLogger) LogMode(newLevel logger.LogLevel) logger.Interface {
|
||||||
|
switch newLevel {
|
||||||
|
case logger.Error:
|
||||||
|
g.logger = g.logger.Level(zerolog.ErrorLevel)
|
||||||
|
case logger.Warn:
|
||||||
|
g.logger = g.logger.Level(zerolog.WarnLevel)
|
||||||
|
case logger.Info:
|
||||||
|
g.logger = g.logger.Level(zerolog.InfoLevel)
|
||||||
|
case logger.Silent:
|
||||||
|
g.logger = g.logger.Level(zerolog.Disabled)
|
||||||
|
}
|
||||||
|
return g
|
||||||
|
}
|
||||||
|
func (g *gormLogger) Info(ctx context.Context, format string, args ...interface{}) {
|
||||||
|
g.logger.Info().Ctx(ctx).Msgf(format, args...)
|
||||||
|
}
|
||||||
|
func (g *gormLogger) Warn(ctx context.Context, format string, args ...interface{}) {
|
||||||
|
g.logger.Warn().Ctx(ctx).Msgf(format, args...)
|
||||||
|
}
|
||||||
|
func (g *gormLogger) Error(ctx context.Context, format string, args ...interface{}) {
|
||||||
|
g.logger.Error().Ctx(ctx).Msgf(format, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *gormLogger) Trace(
|
||||||
|
ctx context.Context,
|
||||||
|
begin time.Time,
|
||||||
|
fc func() (sql string, rowsAffected int64),
|
||||||
|
err error,
|
||||||
|
) {
|
||||||
|
sql, rowsAffected := fc()
|
||||||
|
g.logger.Trace().
|
||||||
|
Ctx(ctx).
|
||||||
|
Time("gorm-begin", begin).
|
||||||
|
Err(err).
|
||||||
|
Str("gorm-query", sql).
|
||||||
|
Int64("gorm-rows-affected", rowsAffected).
|
||||||
|
Send()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *gormLogger) OverwriteLoggingLevel(new zerolog.Level) {
|
||||||
|
g.logger = g.logger.Level(new)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *gormLogger) OverwriteLogger(new zerolog.Logger) {
|
||||||
|
g.logger = new
|
||||||
|
}
|
102
storage-new/migrations.go
Normal file
102
storage-new/migrations.go
Normal file
|
@ -0,0 +1,102 @@
|
||||||
|
package storage
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"git.mstar.dev/mstar/goutils/sliceutils"
|
||||||
|
"gorm.io/gorm"
|
||||||
|
|
||||||
|
"git.mstar.dev/mstar/linstrom/storage-new/models"
|
||||||
|
)
|
||||||
|
|
||||||
|
func migrateTypes(db *gorm.DB) error {
|
||||||
|
if err := db.AutoMigrate(
|
||||||
|
&models.Emote{},
|
||||||
|
&models.MediaMetadata{},
|
||||||
|
&models.Note{},
|
||||||
|
&models.NoteToAttachment{},
|
||||||
|
&models.NoteToEmote{},
|
||||||
|
&models.NoteToPing{},
|
||||||
|
&models.NoteTag{},
|
||||||
|
&models.Reaction{},
|
||||||
|
&models.RemoteServer{},
|
||||||
|
&models.Role{},
|
||||||
|
&models.User{},
|
||||||
|
&models.UserAuthMethod{},
|
||||||
|
&models.UserBeings{},
|
||||||
|
&models.UserInfoField{},
|
||||||
|
&models.UserRelation{},
|
||||||
|
&models.UserRemoteLinks{},
|
||||||
|
&models.UserRole{},
|
||||||
|
&models.UserTag{},
|
||||||
|
); err != nil {
|
||||||
|
return fmt.Errorf("storage: automigrate structs: %w", err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure the being enum exists for the user
|
||||||
|
func createBeingType(db *gorm.DB) error {
|
||||||
|
return migrateEnum(
|
||||||
|
db,
|
||||||
|
"being_type",
|
||||||
|
sliceutils.Map(models.AllBeings, func(t models.BeingType) string { return string(t) }),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func createAccountRelationType(db *gorm.DB) error {
|
||||||
|
return migrateEnum(
|
||||||
|
db,
|
||||||
|
"relation_type",
|
||||||
|
sliceutils.Map(
|
||||||
|
models.AllRelations,
|
||||||
|
func(t models.RelationType) string { return string(t) },
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func createAccountAuthMethodType(db *gorm.DB) error {
|
||||||
|
return migrateEnum(
|
||||||
|
db,
|
||||||
|
"auth_method_type",
|
||||||
|
sliceutils.Map(
|
||||||
|
models.AllAuthMethods,
|
||||||
|
func(t models.AuthenticationMethodType) string { return string(t) },
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func createRemoteServerSoftwareType(db *gorm.DB) error {
|
||||||
|
return migrateEnum(
|
||||||
|
db,
|
||||||
|
"server_software_type",
|
||||||
|
sliceutils.Map(
|
||||||
|
models.AllServerSoftwareTypes,
|
||||||
|
func(t models.ServerSoftwareType) string { return string(t) },
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper function for ensuring the existence of an enum with the given values
|
||||||
|
func migrateEnum(db *gorm.DB, name string, values []string) error {
|
||||||
|
if err := db.Exec("DROP TYPE IF EXISTS " + name).Error; err != nil {
|
||||||
|
return fmt.Errorf("storage: migrate %s: %w", name, err)
|
||||||
|
}
|
||||||
|
queryBuilder := strings.Builder{}
|
||||||
|
queryBuilder.WriteString("CREATE TYPE")
|
||||||
|
queryBuilder.WriteString(name)
|
||||||
|
queryBuilder.WriteString("AS ENUM (")
|
||||||
|
blen := len(values)
|
||||||
|
for i, btype := range values {
|
||||||
|
queryBuilder.WriteString("'" + string(btype) + "'")
|
||||||
|
// Append comma everywhere except last entry
|
||||||
|
if i+1 < blen {
|
||||||
|
queryBuilder.WriteString(",")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err := db.Exec(queryBuilder.String()).Error; err != nil {
|
||||||
|
return fmt.Errorf("storage: migrate %s: %w", name, err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
12
storage-new/models/Emote.go
Normal file
12
storage-new/models/Emote.go
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
package models
|
||||||
|
|
||||||
|
import "gorm.io/gorm"
|
||||||
|
|
||||||
|
type Emote struct {
|
||||||
|
gorm.Model
|
||||||
|
// Metadata MediaMetadata // `gorm:"foreignKey:MetadataId"`
|
||||||
|
MetadataId string
|
||||||
|
Name string
|
||||||
|
// Server RemoteServer // `gorm:"foreignKey:ServerId;references:ID"`
|
||||||
|
ServerId uint
|
||||||
|
}
|
29
storage-new/models/MediaMetadata.go
Normal file
29
storage-new/models/MediaMetadata.go
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
package models
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"gorm.io/gorm"
|
||||||
|
)
|
||||||
|
|
||||||
|
type MediaMetadata struct {
|
||||||
|
ID string `gorm:"primarykey"` // The unique ID of this media file
|
||||||
|
CreatedAt time.Time // When this entry was created
|
||||||
|
UpdatedAt time.Time // When this entry was last updated
|
||||||
|
// When this entry was deleted (for soft deletions)
|
||||||
|
// Soft delete means that this entry still exists in the db, but gorm won't include it anymore unless specifically told to
|
||||||
|
// If not null, this entry is marked as deleted
|
||||||
|
DeletedAt gorm.DeletedAt `gorm:"index"`
|
||||||
|
OwnedBy string // Account id this media belongs to
|
||||||
|
Remote bool // whether the attachment is a remote one
|
||||||
|
// Where the media is stored. Url
|
||||||
|
Location string
|
||||||
|
Type string // What media type this is following mime types, eg image/png
|
||||||
|
// Name of the file
|
||||||
|
// Could be <emote-name>.png, <server-name>.webp for example. Or the name the file was uploaded with
|
||||||
|
Name string
|
||||||
|
// Alternative description of the media file's content
|
||||||
|
AltText string
|
||||||
|
// Whether the media is to be blurred by default
|
||||||
|
Blurred bool
|
||||||
|
}
|
33
storage-new/models/Note.go
Normal file
33
storage-new/models/Note.go
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
package models
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"gorm.io/gorm"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Data defined in extra structs:
|
||||||
|
// - Attachments: models.NoteToAttachment
|
||||||
|
// - Emotes: models.NoteToEmote
|
||||||
|
// - Pings: models.NoteToPing
|
||||||
|
// - Tags: models.NoteTag
|
||||||
|
type Note struct {
|
||||||
|
ID string `gorm:"primarykey"` // Make ID a string (uuid) for other implementations
|
||||||
|
CreatedAt time.Time // When this entry was created
|
||||||
|
UpdatedAt time.Time // When this entry was last updated
|
||||||
|
// When this entry was deleted (for soft deletions)
|
||||||
|
// Soft delete means that this entry still exists in the db, but gorm won't include it anymore unless specifically told to
|
||||||
|
// If not null, this entry is marked as deleted
|
||||||
|
DeletedAt gorm.DeletedAt `gorm:"index"`
|
||||||
|
// Creator Account // `gorm:"foreignKey:CreatorId;references:ID"` // Account that created the post
|
||||||
|
CreatorId string
|
||||||
|
Remote bool // Whether the note is originally a remote one and just "cached"
|
||||||
|
// Raw content of the note. So without additional formatting applied
|
||||||
|
// Might already have formatting applied beforehand from the origin server
|
||||||
|
RawContent string
|
||||||
|
ContentWarning *string // Content warnings of the note, if it contains any
|
||||||
|
RepliesTo *string // Url of the message this replies to
|
||||||
|
Quotes *string // url of the message this note quotes
|
||||||
|
AccessLevel NoteAccessLevel // Where to send this message to (public, home, followers, dm)
|
||||||
|
OriginServer string // Url of the origin server. Also the primary key for those
|
||||||
|
}
|
28
storage-new/models/NoteAccessLevelType.go
Normal file
28
storage-new/models/NoteAccessLevelType.go
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
package models
|
||||||
|
|
||||||
|
import "database/sql/driver"
|
||||||
|
|
||||||
|
type NoteAccessLevel uint8
|
||||||
|
|
||||||
|
const (
|
||||||
|
// The note is intended for the public
|
||||||
|
NOTE_TARGET_PUBLIC NoteAccessLevel = 0
|
||||||
|
// The note is intended only for the home screen
|
||||||
|
// not really any idea what the difference is compared to public
|
||||||
|
// Maybe home notes don't show up on the server feed but still for everyone's home feed if it reaches them via follow or boost
|
||||||
|
NOTE_TARGET_HOME NoteAccessLevel = 1 << iota
|
||||||
|
// The note is intended only for followers
|
||||||
|
NOTE_TARGET_FOLLOWERS
|
||||||
|
// The note is intended only for a DM to one or more targets
|
||||||
|
NOTE_TARGET_DM
|
||||||
|
)
|
||||||
|
|
||||||
|
// Converts the NoteTarget value into a type the DB can use
|
||||||
|
func (n *NoteAccessLevel) Value() (driver.Value, error) {
|
||||||
|
return n, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ct *NoteAccessLevel) Scan(value any) error {
|
||||||
|
*ct = NoteAccessLevel(value.(uint8))
|
||||||
|
return nil
|
||||||
|
}
|
6
storage-new/models/NoteAttachments.go
Normal file
6
storage-new/models/NoteAttachments.go
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
package models
|
||||||
|
|
||||||
|
type NoteToAttachment struct {
|
||||||
|
UserId string
|
||||||
|
AttachmentId string
|
||||||
|
}
|
6
storage-new/models/NoteEmotes.go
Normal file
6
storage-new/models/NoteEmotes.go
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
package models
|
||||||
|
|
||||||
|
type NoteToEmote struct {
|
||||||
|
UserId string
|
||||||
|
EmoteId string
|
||||||
|
}
|
6
storage-new/models/NotePings.go
Normal file
6
storage-new/models/NotePings.go
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
package models
|
||||||
|
|
||||||
|
type NoteToPing struct {
|
||||||
|
UserId string
|
||||||
|
PingTargetId string
|
||||||
|
}
|
6
storage-new/models/NoteTags.go
Normal file
6
storage-new/models/NoteTags.go
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
package models
|
||||||
|
|
||||||
|
type NoteTag struct {
|
||||||
|
UserId string
|
||||||
|
Tag string
|
||||||
|
}
|
10
storage-new/models/Reaction.go
Normal file
10
storage-new/models/Reaction.go
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
package models
|
||||||
|
|
||||||
|
import "gorm.io/gorm"
|
||||||
|
|
||||||
|
type Reaction struct {
|
||||||
|
gorm.Model
|
||||||
|
NoteId string
|
||||||
|
ReactorId string
|
||||||
|
EmoteId uint
|
||||||
|
}
|
12
storage-new/models/RemoteServer.go
Normal file
12
storage-new/models/RemoteServer.go
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
package models
|
||||||
|
|
||||||
|
import "gorm.io/gorm"
|
||||||
|
|
||||||
|
type RemoteServer struct {
|
||||||
|
gorm.Model
|
||||||
|
ServerType ServerSoftwareType // What software the server is running. Useful for formatting
|
||||||
|
Domain string // `gorm:"primaryKey"` // Domain the server exists under. Additional primary key
|
||||||
|
Name string // What the server wants to be known as (usually same as url)
|
||||||
|
Icon string // ID of a media file
|
||||||
|
IsSelf bool // Whether this server is yours truly
|
||||||
|
}
|
37
storage-new/models/RemoteServerSoftwareType.go
Normal file
37
storage-new/models/RemoteServerSoftwareType.go
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
package models
|
||||||
|
|
||||||
|
import (
|
||||||
|
"database/sql/driver"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ServerSoftwareType string
|
||||||
|
|
||||||
|
const (
|
||||||
|
// Includes forks like glitch-soc, etc
|
||||||
|
ServerSoftwareMastodon = ServerSoftwareType("Mastodon")
|
||||||
|
// Includes forks like Ice Shrimp, Sharkey, Cutiekey, etc
|
||||||
|
ServerSoftwareMisskey = ServerSoftwareType("Misskey")
|
||||||
|
// Includes Akkoma
|
||||||
|
ServerSoftwarePlemora = ServerSoftwareType("Plemora")
|
||||||
|
// Wafrn is a new entry
|
||||||
|
ServerSoftwareWafrn = ServerSoftwareType("Wafrn")
|
||||||
|
// And of course, yours truly
|
||||||
|
ServerSoftwareLinstrom = ServerSoftwareType("Linstrom")
|
||||||
|
)
|
||||||
|
|
||||||
|
var AllServerSoftwareTypes = []ServerSoftwareType{
|
||||||
|
ServerSoftwareMastodon,
|
||||||
|
ServerSoftwareMisskey,
|
||||||
|
ServerSoftwarePlemora,
|
||||||
|
ServerSoftwareWafrn,
|
||||||
|
ServerSoftwareLinstrom,
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *ServerSoftwareType) Value() (driver.Value, error) {
|
||||||
|
return r, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ct *ServerSoftwareType) Scan(value any) error {
|
||||||
|
*ct = ServerSoftwareType(value.(string))
|
||||||
|
return nil
|
||||||
|
}
|
182
storage-new/models/Role.go
Normal file
182
storage-new/models/Role.go
Normal file
|
@ -0,0 +1,182 @@
|
||||||
|
package models
|
||||||
|
|
||||||
|
import (
|
||||||
|
"gorm.io/gorm"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Could I collapse all these go:generate command into more condensed ones?
|
||||||
|
// Yes
|
||||||
|
// Will I do that?
|
||||||
|
// No
|
||||||
|
// This is explicit in what is being done. And easier to understand
|
||||||
|
|
||||||
|
//go:generate go build -o RolesGenerator ../cmd/RolesGenerator/main.go
|
||||||
|
//go:generate ./RolesGenerator -input=roles.go -output=rolesUtil_generated.go
|
||||||
|
//go:generate rm RolesGenerator
|
||||||
|
|
||||||
|
//go:generate go build -o ApiGenerator ../cmd/RolesApiTypeGenerator/main.go
|
||||||
|
//go:generate ./ApiGenerator -input=roles.go -output=../server/apiLinstromTypes_generated.go
|
||||||
|
//go:generate rm ApiGenerator
|
||||||
|
|
||||||
|
//go:generate go build -o HelperGenerator ../cmd/RolesApiConverter/main.go
|
||||||
|
//go:generate ./HelperGenerator -input=roles.go -output=../server/apiLinstromTypeHelpers_generated.go
|
||||||
|
//go:generate rm HelperGenerator
|
||||||
|
|
||||||
|
//go:generate go build -o FrontendGenerator ../cmd/RolesFrontendGenerator/main.go
|
||||||
|
//go:generate ./FrontendGenerator -input=roles.go -output=../frontend-reactive/app/models/role.ts
|
||||||
|
//go:generate rm FrontendGenerator
|
||||||
|
|
||||||
|
// A role is, in concept, similar to how Discord handles roles
|
||||||
|
// Some permission can be either disallowed (&false), don't care (nil) or allowed (&true)
|
||||||
|
// Don't care just says to use the value from the next lower role where it is set
|
||||||
|
// Blocks are part of the user relations
|
||||||
|
type Role struct {
|
||||||
|
// TODO: More control options
|
||||||
|
// Extend upon whatever Masto, Akkoma and Misskey have
|
||||||
|
// Lots of details please
|
||||||
|
|
||||||
|
// --- Role metadata ---
|
||||||
|
|
||||||
|
// Include full db model stuff
|
||||||
|
gorm.Model
|
||||||
|
|
||||||
|
// Name of the role
|
||||||
|
Name string `gorm:"primaryKey;unique"`
|
||||||
|
|
||||||
|
// Priority of the role
|
||||||
|
// Lower priority gets applied first and thus overwritten by higher priority ones
|
||||||
|
// If two roles have the same priority, the order is undetermined and may be random
|
||||||
|
// Default priority for new roles is 1 to always overwrite default user
|
||||||
|
// And full admin has max priority possible
|
||||||
|
Priority uint32
|
||||||
|
// Whether this role is for a for a single user only (like custom, per user permissions in Discord)
|
||||||
|
// If yes, Name will be the id of the user in question
|
||||||
|
IsUserRole bool
|
||||||
|
|
||||||
|
// Whether this role is one built into Linstrom from the start or not
|
||||||
|
// Note: Built-in roles can't be modified
|
||||||
|
IsBuiltIn bool
|
||||||
|
|
||||||
|
// --- User permissions ---
|
||||||
|
CanSendMedia *bool // Local & remote
|
||||||
|
CanSendCustomEmotes *bool // Local & remote
|
||||||
|
CanSendCustomReactions *bool // Local & remote
|
||||||
|
CanSendPublicNotes *bool // Local & remote
|
||||||
|
CanSendLocalNotes *bool // Local & remote
|
||||||
|
CanSendFollowerOnlyNotes *bool // Local & remote
|
||||||
|
CanSendPrivateNotes *bool // Local & remote
|
||||||
|
CanSendReplies *bool // Local & remote
|
||||||
|
CanQuote *bool // Local only
|
||||||
|
CanBoost *bool // Local only
|
||||||
|
CanIncludeLinks *bool // Local & remote
|
||||||
|
CanIncludeSurvey *bool // Local
|
||||||
|
CanFederateFedi *bool // Local & remote
|
||||||
|
CanFederateBsky *bool // Local
|
||||||
|
|
||||||
|
CanChangeDisplayName *bool // Local
|
||||||
|
|
||||||
|
CanSubmitReports *bool // Local & remote
|
||||||
|
// If disabled, an account can no longer be interacted with. The owner can no longer change anything about it
|
||||||
|
// And the UI will show a notice (and maybe include that info in the AP data too)
|
||||||
|
// Only moderators and admins will be able to edit the account's roles
|
||||||
|
CanLogin *bool // Local
|
||||||
|
|
||||||
|
CanMentionOthers *bool // Local & remote
|
||||||
|
HasMentionCountLimit *bool // Local & remote
|
||||||
|
MentionLimit *uint32 // Local & remote
|
||||||
|
|
||||||
|
// CanViewBoosts *bool
|
||||||
|
// CanViewQuotes *bool
|
||||||
|
// CanViewMedia *bool
|
||||||
|
// CanViewCustomEmotes *bool
|
||||||
|
|
||||||
|
// --- Automod ---
|
||||||
|
AutoNsfwMedia *bool // Local & remote
|
||||||
|
AutoCwPosts *bool // Local & remote
|
||||||
|
AutoCwPostsText *string // Local & remote
|
||||||
|
ScanCreatedPublicNotes *bool // Local & remote
|
||||||
|
ScanCreatedLocalNotes *bool // Local & remote
|
||||||
|
ScanCreatedFollowerOnlyNotes *bool // Local & remote
|
||||||
|
ScanCreatedPrivateNotes *bool // Local & remote
|
||||||
|
// Blocks all interactions and federation between users with the role and all included ids/handles
|
||||||
|
// TODO: Decide whether this is a list of handles or of account ids
|
||||||
|
// Handles would increase the load due to having to search for them first
|
||||||
|
// while ids would require to store every single account mentioned
|
||||||
|
// which could cause escalating storage costs
|
||||||
|
DisallowInteractionsWith []string `gorm:"type:bytes;serializer:gob"` // Local & remote
|
||||||
|
|
||||||
|
WithholdNotesForManualApproval *bool // Local & remote
|
||||||
|
WithholdNotesBasedOnRegex *bool // Local & remote
|
||||||
|
WithholdNotesRegexes []string `gorm:"type:bytes;serializer:gob"` // Local & remote
|
||||||
|
|
||||||
|
// --- Admin perms ---
|
||||||
|
// If set, counts as all permissions being set as given and all restrictions being disabled
|
||||||
|
FullAdmin *bool // Local
|
||||||
|
CanAffectOtherAdmins *bool // Local
|
||||||
|
CanDeleteNotes *bool // Local
|
||||||
|
CanConfirmWithheldNotes *bool // Local
|
||||||
|
CanAssignRoles *bool // Local
|
||||||
|
CanSupressInteractionsBetweenUsers *bool // Local
|
||||||
|
CanOverwriteDisplayNames *bool // Local
|
||||||
|
CanManageCustomEmotes *bool // Local
|
||||||
|
CanViewDeletedNotes *bool // Local
|
||||||
|
CanRecoverDeletedNotes *bool // Local
|
||||||
|
CanManageAvatarDecorations *bool // Local
|
||||||
|
CanManageAds *bool // Local
|
||||||
|
CanSendAnnouncements *bool // Local
|
||||||
|
CanDeleteAccounts *bool // Local
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Mastodon permissions (highest permission to lowest):
|
||||||
|
- Admin
|
||||||
|
- Devops
|
||||||
|
- View Audit log
|
||||||
|
- View Dashboard
|
||||||
|
- Manage Reports
|
||||||
|
- Manage Federation
|
||||||
|
- Manage Settings
|
||||||
|
- Manage Blocks
|
||||||
|
- Manage Taxonomies
|
||||||
|
- Manage Appeals
|
||||||
|
- Manage Users
|
||||||
|
- Manage Invites
|
||||||
|
- Manage Rules
|
||||||
|
- Manage Announcements
|
||||||
|
- Manage Custom Emojis
|
||||||
|
- Manage Webhooks
|
||||||
|
- Invite Users
|
||||||
|
- Manage Roles
|
||||||
|
- Manage User Access
|
||||||
|
- Delete User Data
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Misskey "permissions" (no order):
|
||||||
|
- Global timeline available (interact with global timeline I think)
|
||||||
|
- Local timeline available (same as global, but for local)
|
||||||
|
- b-something timeline available
|
||||||
|
- Can send public notes
|
||||||
|
- How many mentions a note can have
|
||||||
|
- Can invite others
|
||||||
|
- How many invites can be sent
|
||||||
|
- InviteLimitCycle (whatever that means)
|
||||||
|
- Invite Expiration time (duration of how long invites stay valid I think)
|
||||||
|
- Manage custom emojis
|
||||||
|
- Manage custom avatar decorations
|
||||||
|
- Seach for notes
|
||||||
|
- Use translator
|
||||||
|
- Hide ads from self
|
||||||
|
- How much storage space the user has
|
||||||
|
- Whether to mark all posts from account as nsfw
|
||||||
|
- max number of pinned messages
|
||||||
|
- max number of antennas
|
||||||
|
- max number of muted words
|
||||||
|
- max number of webhooks
|
||||||
|
- max number of clips
|
||||||
|
- max number of notes contained in a clip (? I think. Don't know enough about clips)
|
||||||
|
- Max number of lists of users
|
||||||
|
- max number of users in a user list
|
||||||
|
- rate limit multiplier
|
||||||
|
- max number of applied avatar decorations
|
||||||
|
*/
|
240
storage-new/models/RolesDefaults.go
Normal file
240
storage-new/models/RolesDefaults.go
Normal file
|
@ -0,0 +1,240 @@
|
||||||
|
package models
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math"
|
||||||
|
|
||||||
|
"git.mstar.dev/mstar/goutils/other"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Default role every user has. Defines sane defaults for a normal user
|
||||||
|
// Will get overwritten by just about every other role due to every other role having higher priority
|
||||||
|
var DefaultUserRole = Role{
|
||||||
|
Name: "Default",
|
||||||
|
Priority: 0,
|
||||||
|
IsUserRole: false,
|
||||||
|
IsBuiltIn: true,
|
||||||
|
|
||||||
|
CanSendMedia: other.IntoPointer(true),
|
||||||
|
CanSendCustomEmotes: other.IntoPointer(true),
|
||||||
|
CanSendCustomReactions: other.IntoPointer(true),
|
||||||
|
CanSendPublicNotes: other.IntoPointer(true),
|
||||||
|
CanSendLocalNotes: other.IntoPointer(true),
|
||||||
|
CanSendFollowerOnlyNotes: other.IntoPointer(true),
|
||||||
|
CanSendPrivateNotes: other.IntoPointer(true),
|
||||||
|
CanSendReplies: other.IntoPointer(true),
|
||||||
|
CanQuote: other.IntoPointer(true),
|
||||||
|
CanBoost: other.IntoPointer(true),
|
||||||
|
CanIncludeLinks: other.IntoPointer(true),
|
||||||
|
CanIncludeSurvey: other.IntoPointer(true),
|
||||||
|
CanFederateFedi: other.IntoPointer(true),
|
||||||
|
CanFederateBsky: other.IntoPointer(true),
|
||||||
|
|
||||||
|
CanChangeDisplayName: other.IntoPointer(true),
|
||||||
|
|
||||||
|
CanSubmitReports: other.IntoPointer(true),
|
||||||
|
CanLogin: other.IntoPointer(true),
|
||||||
|
|
||||||
|
CanMentionOthers: other.IntoPointer(true),
|
||||||
|
HasMentionCountLimit: other.IntoPointer(false),
|
||||||
|
MentionLimit: other.IntoPointer(
|
||||||
|
uint32(math.MaxUint32),
|
||||||
|
), // Set this to max, even if not used due to *HasMentionCountLimit == false
|
||||||
|
|
||||||
|
AutoNsfwMedia: other.IntoPointer(false),
|
||||||
|
AutoCwPosts: other.IntoPointer(false),
|
||||||
|
AutoCwPostsText: nil,
|
||||||
|
WithholdNotesForManualApproval: other.IntoPointer(false),
|
||||||
|
ScanCreatedPublicNotes: other.IntoPointer(false),
|
||||||
|
ScanCreatedLocalNotes: other.IntoPointer(false),
|
||||||
|
ScanCreatedFollowerOnlyNotes: other.IntoPointer(false),
|
||||||
|
ScanCreatedPrivateNotes: other.IntoPointer(false),
|
||||||
|
DisallowInteractionsWith: []string{},
|
||||||
|
|
||||||
|
FullAdmin: other.IntoPointer(false),
|
||||||
|
CanAffectOtherAdmins: other.IntoPointer(false),
|
||||||
|
CanDeleteNotes: other.IntoPointer(false),
|
||||||
|
CanConfirmWithheldNotes: other.IntoPointer(false),
|
||||||
|
CanAssignRoles: other.IntoPointer(false),
|
||||||
|
CanSupressInteractionsBetweenUsers: other.IntoPointer(false),
|
||||||
|
CanOverwriteDisplayNames: other.IntoPointer(false),
|
||||||
|
CanManageCustomEmotes: other.IntoPointer(false),
|
||||||
|
CanViewDeletedNotes: other.IntoPointer(false),
|
||||||
|
CanRecoverDeletedNotes: other.IntoPointer(false),
|
||||||
|
CanManageAvatarDecorations: other.IntoPointer(false),
|
||||||
|
CanManageAds: other.IntoPointer(false),
|
||||||
|
CanSendAnnouncements: other.IntoPointer(false),
|
||||||
|
}
|
||||||
|
|
||||||
|
// Role providing maximum permissions
|
||||||
|
var FullAdminRole = Role{
|
||||||
|
Name: "fullAdmin",
|
||||||
|
Priority: math.MaxUint32,
|
||||||
|
IsUserRole: false,
|
||||||
|
IsBuiltIn: true,
|
||||||
|
|
||||||
|
CanSendMedia: other.IntoPointer(true),
|
||||||
|
CanSendCustomEmotes: other.IntoPointer(true),
|
||||||
|
CanSendCustomReactions: other.IntoPointer(true),
|
||||||
|
CanSendPublicNotes: other.IntoPointer(true),
|
||||||
|
CanSendLocalNotes: other.IntoPointer(true),
|
||||||
|
CanSendFollowerOnlyNotes: other.IntoPointer(true),
|
||||||
|
CanSendPrivateNotes: other.IntoPointer(true),
|
||||||
|
CanQuote: other.IntoPointer(true),
|
||||||
|
CanBoost: other.IntoPointer(true),
|
||||||
|
CanIncludeLinks: other.IntoPointer(true),
|
||||||
|
CanIncludeSurvey: other.IntoPointer(true),
|
||||||
|
|
||||||
|
CanChangeDisplayName: other.IntoPointer(true),
|
||||||
|
|
||||||
|
CanSubmitReports: other.IntoPointer(true),
|
||||||
|
CanLogin: other.IntoPointer(true),
|
||||||
|
|
||||||
|
CanMentionOthers: other.IntoPointer(true),
|
||||||
|
HasMentionCountLimit: other.IntoPointer(false),
|
||||||
|
MentionLimit: other.IntoPointer(
|
||||||
|
uint32(math.MaxUint32),
|
||||||
|
), // Set this to max, even if not used due to *HasMentionCountLimit == false
|
||||||
|
|
||||||
|
AutoNsfwMedia: other.IntoPointer(false),
|
||||||
|
AutoCwPosts: other.IntoPointer(false),
|
||||||
|
AutoCwPostsText: nil,
|
||||||
|
WithholdNotesForManualApproval: other.IntoPointer(false),
|
||||||
|
ScanCreatedPublicNotes: other.IntoPointer(false),
|
||||||
|
ScanCreatedLocalNotes: other.IntoPointer(false),
|
||||||
|
ScanCreatedFollowerOnlyNotes: other.IntoPointer(false),
|
||||||
|
ScanCreatedPrivateNotes: other.IntoPointer(false),
|
||||||
|
DisallowInteractionsWith: []string{},
|
||||||
|
|
||||||
|
FullAdmin: other.IntoPointer(true),
|
||||||
|
CanAffectOtherAdmins: other.IntoPointer(true),
|
||||||
|
CanDeleteNotes: other.IntoPointer(true),
|
||||||
|
CanConfirmWithheldNotes: other.IntoPointer(true),
|
||||||
|
CanAssignRoles: other.IntoPointer(true),
|
||||||
|
CanSupressInteractionsBetweenUsers: other.IntoPointer(true),
|
||||||
|
CanOverwriteDisplayNames: other.IntoPointer(true),
|
||||||
|
CanManageCustomEmotes: other.IntoPointer(true),
|
||||||
|
CanViewDeletedNotes: other.IntoPointer(true),
|
||||||
|
CanRecoverDeletedNotes: other.IntoPointer(true),
|
||||||
|
CanManageAvatarDecorations: other.IntoPointer(true),
|
||||||
|
CanManageAds: other.IntoPointer(true),
|
||||||
|
CanSendAnnouncements: other.IntoPointer(true),
|
||||||
|
}
|
||||||
|
|
||||||
|
// Role for totally freezing an account, blocking all activity from it
|
||||||
|
var AccountFreezeRole = Role{
|
||||||
|
Name: "accountFreeze",
|
||||||
|
Priority: math.MaxUint32 - 1,
|
||||||
|
IsUserRole: false,
|
||||||
|
IsBuiltIn: true,
|
||||||
|
|
||||||
|
CanSendMedia: other.IntoPointer(false),
|
||||||
|
CanSendCustomEmotes: other.IntoPointer(false),
|
||||||
|
CanSendCustomReactions: other.IntoPointer(false),
|
||||||
|
CanSendPublicNotes: other.IntoPointer(false),
|
||||||
|
CanSendLocalNotes: other.IntoPointer(false),
|
||||||
|
CanSendFollowerOnlyNotes: other.IntoPointer(false),
|
||||||
|
CanSendPrivateNotes: other.IntoPointer(false),
|
||||||
|
CanSendReplies: other.IntoPointer(false),
|
||||||
|
CanQuote: other.IntoPointer(false),
|
||||||
|
CanBoost: other.IntoPointer(false),
|
||||||
|
CanIncludeLinks: other.IntoPointer(false),
|
||||||
|
CanIncludeSurvey: other.IntoPointer(false),
|
||||||
|
CanFederateBsky: other.IntoPointer(false),
|
||||||
|
CanFederateFedi: other.IntoPointer(false),
|
||||||
|
|
||||||
|
CanChangeDisplayName: other.IntoPointer(false),
|
||||||
|
|
||||||
|
CanSubmitReports: other.IntoPointer(false),
|
||||||
|
CanLogin: other.IntoPointer(false),
|
||||||
|
|
||||||
|
CanMentionOthers: other.IntoPointer(false),
|
||||||
|
HasMentionCountLimit: other.IntoPointer(false),
|
||||||
|
MentionLimit: other.IntoPointer(
|
||||||
|
uint32(math.MaxUint32),
|
||||||
|
), // Set this to max, even if not used due to *HasMentionCountLimit == false
|
||||||
|
|
||||||
|
AutoNsfwMedia: other.IntoPointer(true),
|
||||||
|
AutoCwPosts: other.IntoPointer(false),
|
||||||
|
AutoCwPostsText: other.IntoPointer("Account frozen"),
|
||||||
|
WithholdNotesForManualApproval: other.IntoPointer(true),
|
||||||
|
ScanCreatedPublicNotes: other.IntoPointer(false),
|
||||||
|
ScanCreatedLocalNotes: other.IntoPointer(false),
|
||||||
|
ScanCreatedFollowerOnlyNotes: other.IntoPointer(false),
|
||||||
|
ScanCreatedPrivateNotes: other.IntoPointer(false),
|
||||||
|
DisallowInteractionsWith: []string{},
|
||||||
|
|
||||||
|
FullAdmin: other.IntoPointer(false),
|
||||||
|
CanAffectOtherAdmins: other.IntoPointer(false),
|
||||||
|
CanDeleteNotes: other.IntoPointer(false),
|
||||||
|
CanConfirmWithheldNotes: other.IntoPointer(false),
|
||||||
|
CanAssignRoles: other.IntoPointer(false),
|
||||||
|
CanSupressInteractionsBetweenUsers: other.IntoPointer(false),
|
||||||
|
CanOverwriteDisplayNames: other.IntoPointer(false),
|
||||||
|
CanManageCustomEmotes: other.IntoPointer(false),
|
||||||
|
CanViewDeletedNotes: other.IntoPointer(false),
|
||||||
|
CanRecoverDeletedNotes: other.IntoPointer(false),
|
||||||
|
CanManageAvatarDecorations: other.IntoPointer(false),
|
||||||
|
CanManageAds: other.IntoPointer(false),
|
||||||
|
CanSendAnnouncements: other.IntoPointer(false),
|
||||||
|
}
|
||||||
|
|
||||||
|
var ServerActorRole = Role{
|
||||||
|
Name: "ServerActor",
|
||||||
|
Priority: math.MaxUint32,
|
||||||
|
IsUserRole: true,
|
||||||
|
IsBuiltIn: true,
|
||||||
|
|
||||||
|
CanSendMedia: other.IntoPointer(true),
|
||||||
|
CanSendCustomEmotes: other.IntoPointer(true),
|
||||||
|
CanSendCustomReactions: other.IntoPointer(true),
|
||||||
|
CanSendPublicNotes: other.IntoPointer(true),
|
||||||
|
CanSendLocalNotes: other.IntoPointer(true),
|
||||||
|
CanSendFollowerOnlyNotes: other.IntoPointer(true),
|
||||||
|
CanSendPrivateNotes: other.IntoPointer(true),
|
||||||
|
CanQuote: other.IntoPointer(true),
|
||||||
|
CanBoost: other.IntoPointer(true),
|
||||||
|
CanIncludeLinks: other.IntoPointer(true),
|
||||||
|
CanIncludeSurvey: other.IntoPointer(true),
|
||||||
|
|
||||||
|
CanChangeDisplayName: other.IntoPointer(true),
|
||||||
|
|
||||||
|
CanSubmitReports: other.IntoPointer(true),
|
||||||
|
CanLogin: other.IntoPointer(true),
|
||||||
|
|
||||||
|
CanMentionOthers: other.IntoPointer(true),
|
||||||
|
HasMentionCountLimit: other.IntoPointer(false),
|
||||||
|
MentionLimit: other.IntoPointer(
|
||||||
|
uint32(math.MaxUint32),
|
||||||
|
), // Set this to max, even if not used due to *HasMentionCountLimit == false
|
||||||
|
|
||||||
|
AutoNsfwMedia: other.IntoPointer(false),
|
||||||
|
AutoCwPosts: other.IntoPointer(false),
|
||||||
|
AutoCwPostsText: nil,
|
||||||
|
WithholdNotesForManualApproval: other.IntoPointer(false),
|
||||||
|
ScanCreatedPublicNotes: other.IntoPointer(false),
|
||||||
|
ScanCreatedLocalNotes: other.IntoPointer(false),
|
||||||
|
ScanCreatedFollowerOnlyNotes: other.IntoPointer(false),
|
||||||
|
ScanCreatedPrivateNotes: other.IntoPointer(false),
|
||||||
|
DisallowInteractionsWith: []string{},
|
||||||
|
|
||||||
|
FullAdmin: other.IntoPointer(true),
|
||||||
|
CanAffectOtherAdmins: other.IntoPointer(true),
|
||||||
|
CanDeleteNotes: other.IntoPointer(true),
|
||||||
|
CanConfirmWithheldNotes: other.IntoPointer(true),
|
||||||
|
CanAssignRoles: other.IntoPointer(true),
|
||||||
|
CanSupressInteractionsBetweenUsers: other.IntoPointer(true),
|
||||||
|
CanOverwriteDisplayNames: other.IntoPointer(true),
|
||||||
|
CanManageCustomEmotes: other.IntoPointer(true),
|
||||||
|
CanViewDeletedNotes: other.IntoPointer(true),
|
||||||
|
CanRecoverDeletedNotes: other.IntoPointer(true),
|
||||||
|
CanManageAvatarDecorations: other.IntoPointer(true),
|
||||||
|
CanManageAds: other.IntoPointer(true),
|
||||||
|
CanSendAnnouncements: other.IntoPointer(true),
|
||||||
|
}
|
||||||
|
|
||||||
|
var allDefaultRoles = []*Role{
|
||||||
|
&DefaultUserRole,
|
||||||
|
&FullAdminRole,
|
||||||
|
&AccountFreezeRole,
|
||||||
|
&ServerActorRole,
|
||||||
|
}
|
53
storage-new/models/User.go
Normal file
53
storage-new/models/User.go
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
package models
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"gorm.io/gorm"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Data stored in external types:
|
||||||
|
// - Custom info fields
|
||||||
|
// - Being types
|
||||||
|
// - Tags
|
||||||
|
// - Relations
|
||||||
|
// - Pronouns
|
||||||
|
// - Roles
|
||||||
|
// - AP remote links
|
||||||
|
// - Auth methods and tokens (hashed pw, totp key, passkey id)
|
||||||
|
type User struct {
|
||||||
|
ID string `gorm:"primarykey"` // ID is a uuid for this account
|
||||||
|
// 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
|
||||||
|
// Would be an easy avenue to fuck with them though
|
||||||
|
Username string `gorm:"unique"`
|
||||||
|
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
|
||||||
|
UpdatedAt time.Time
|
||||||
|
// When this entry was deleted (for soft deletions)
|
||||||
|
// Soft delete means that this entry still exists in the db, but gorm won't include it anymore unless specifically told to
|
||||||
|
// If not null, this entry is marked as deleted
|
||||||
|
DeletedAt gorm.DeletedAt `gorm:"index"`
|
||||||
|
// Server RemoteServer // `gorm:"foreignKey:ServerId;references:ID"` // The server this user is from
|
||||||
|
ServerId uint // Id of the server this user is from, needed for including RemoteServer
|
||||||
|
DisplayName string // The display name of the user. Can be different from the handle
|
||||||
|
Description string // The description of a user account
|
||||||
|
IsBot bool // Whether to mark this account as a script controlled one
|
||||||
|
Icon string // ID of a media file used as icon
|
||||||
|
Background *string // ID of a media file used as background image
|
||||||
|
Banner *string // ID of a media file used as banner
|
||||||
|
Indexable bool // Whether this account can be found by crawlers
|
||||||
|
PublicKey []byte // The public key of the account
|
||||||
|
// Whether this account restricts following
|
||||||
|
// If true, the owner must approve of a follow request first
|
||||||
|
RestrictedFollow bool
|
||||||
|
|
||||||
|
Location *string
|
||||||
|
Birthday *time.Time
|
||||||
|
|
||||||
|
// --- And internal account stuff ---
|
||||||
|
// 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 remote users, if an account is not verified, any interactions it sends are discarded
|
||||||
|
Verified bool
|
||||||
|
}
|
7
storage-new/models/UserAuthentication.go
Normal file
7
storage-new/models/UserAuthentication.go
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
package models
|
||||||
|
|
||||||
|
type UserAuthMethod struct {
|
||||||
|
UserId string
|
||||||
|
AuthMethod AuthenticationMethodType `gorm:"type:auth_method_type"`
|
||||||
|
Token []byte
|
||||||
|
}
|
26
storage-new/models/UserAuthenticationMethod.go
Normal file
26
storage-new/models/UserAuthenticationMethod.go
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
package models
|
||||||
|
|
||||||
|
import "database/sql/driver"
|
||||||
|
|
||||||
|
type AuthenticationMethodType string
|
||||||
|
|
||||||
|
const (
|
||||||
|
AuthMethodPassword AuthenticationMethodType = "password"
|
||||||
|
AuthMethodGAuth AuthenticationMethodType = "g-auth" // Google Authenticator / totp
|
||||||
|
AuthMethodMail AuthenticationMethodType = "mail"
|
||||||
|
AuthMethodPasskey2fa AuthenticationMethodType = "passkey-2fa" // Passkey used as 2fa factor
|
||||||
|
AuthMethodPasskey AuthenticationMethodType = "passkey" // Passkey as only auth key
|
||||||
|
)
|
||||||
|
|
||||||
|
var AllAuthMethods = []AuthenticationMethodType{
|
||||||
|
AuthMethodPassword, AuthMethodGAuth, AuthMethodMail, AuthMethodPasskey, AuthMethodPasskey2fa,
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ct *AuthenticationMethodType) Scan(value any) error {
|
||||||
|
*ct = AuthenticationMethodType(value.([]byte))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ct AuthenticationMethodType) Value() (driver.Value, error) {
|
||||||
|
return string(ct), nil
|
||||||
|
}
|
27
storage-new/models/UserBeingType.go
Normal file
27
storage-new/models/UserBeingType.go
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
package models
|
||||||
|
|
||||||
|
import (
|
||||||
|
"database/sql/driver"
|
||||||
|
)
|
||||||
|
|
||||||
|
type BeingType string
|
||||||
|
|
||||||
|
const (
|
||||||
|
BEING_HUMAN = BeingType("human")
|
||||||
|
BEING_CAT = BeingType("cat")
|
||||||
|
BEING_FOX = BeingType("fox")
|
||||||
|
BEING_DOG = BeingType("dog")
|
||||||
|
BEING_ROBOT = BeingType("robot")
|
||||||
|
BEING_DOLL = BeingType("doll")
|
||||||
|
)
|
||||||
|
|
||||||
|
var AllBeings = []BeingType{BEING_HUMAN, BEING_CAT, BEING_FOX, BEING_DOG, BEING_ROBOT, BEING_DOLL}
|
||||||
|
|
||||||
|
func (ct *BeingType) Scan(value any) error {
|
||||||
|
*ct = BeingType(value.([]byte))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ct BeingType) Value() (driver.Value, error) {
|
||||||
|
return string(ct), nil
|
||||||
|
}
|
6
storage-new/models/UserBeings.go
Normal file
6
storage-new/models/UserBeings.go
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
package models
|
||||||
|
|
||||||
|
type UserBeings struct {
|
||||||
|
UserId string
|
||||||
|
Being BeingType `gorm:"type:being_type"`
|
||||||
|
}
|
19
storage-new/models/UserInfoField.go
Normal file
19
storage-new/models/UserInfoField.go
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
package models
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"gorm.io/gorm"
|
||||||
|
)
|
||||||
|
|
||||||
|
type UserInfoField struct {
|
||||||
|
gorm.Model // Can actually just embed this as is here as those are not something directly exposed :3
|
||||||
|
Name string
|
||||||
|
Value string
|
||||||
|
LastUrlCheckDate *time.Time // Used if the value is an url to somewhere. Empty if value is not an url
|
||||||
|
// If the value is an url, this attribute indicates whether Linstrom was able to verify ownership
|
||||||
|
// of the provided url via the common method of
|
||||||
|
// "Does the target url contain a rel='me' link to the owner's account"
|
||||||
|
Confirmed bool
|
||||||
|
UserId string // Id of account this info field belongs to
|
||||||
|
}
|
7
storage-new/models/UserRelation.go
Normal file
7
storage-new/models/UserRelation.go
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
package models
|
||||||
|
|
||||||
|
type UserRelation struct {
|
||||||
|
UserId string
|
||||||
|
TargetUserId string
|
||||||
|
Relation RelationType `gorm:"type:relation_type"`
|
||||||
|
}
|
31
storage-new/models/UserRelationType.go
Normal file
31
storage-new/models/UserRelationType.go
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
package models
|
||||||
|
|
||||||
|
import "database/sql/driver"
|
||||||
|
|
||||||
|
type RelationType string
|
||||||
|
|
||||||
|
const (
|
||||||
|
RelationFollow RelationType = "follow"
|
||||||
|
RelationMute RelationType = "mute"
|
||||||
|
RelationNoBoosts RelationType = "no-boosts"
|
||||||
|
RelationBlock RelationType = "block"
|
||||||
|
RelationPreventFollow RelationType = "prevent-follow"
|
||||||
|
)
|
||||||
|
|
||||||
|
// var AllBeings = []BeingType{BEING_HUMAN, BEING_CAT, BEING_FOX, BEING_DOG, BEING_ROBOT, BEING_DOLL}
|
||||||
|
var AllRelations = []RelationType{
|
||||||
|
RelationFollow,
|
||||||
|
RelationMute,
|
||||||
|
RelationNoBoosts,
|
||||||
|
RelationBlock,
|
||||||
|
RelationPreventFollow,
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ct *RelationType) Scan(value any) error {
|
||||||
|
*ct = RelationType(value.([]byte))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ct RelationType) Value() (driver.Value, error) {
|
||||||
|
return string(ct), nil
|
||||||
|
}
|
21
storage-new/models/UserRemote.go
Normal file
21
storage-new/models/UserRemote.go
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
package models
|
||||||
|
|
||||||
|
import "gorm.io/gorm"
|
||||||
|
|
||||||
|
type UserRemoteLinks struct {
|
||||||
|
// ---- Section: gorm
|
||||||
|
// Sets this struct up as a value that an Account may have
|
||||||
|
gorm.Model
|
||||||
|
UserId string
|
||||||
|
|
||||||
|
// Just about every link here is optional to accomodate for servers with only minimal accounts
|
||||||
|
// Minimal being handle, ap link and inbox
|
||||||
|
ApLink string
|
||||||
|
ViewLink *string
|
||||||
|
FollowersLink *string
|
||||||
|
FollowingLink *string
|
||||||
|
InboxLink string
|
||||||
|
OutboxLink *string
|
||||||
|
FeaturedLink *string
|
||||||
|
FeaturedTagsLink *string
|
||||||
|
}
|
6
storage-new/models/UserRoles.go
Normal file
6
storage-new/models/UserRoles.go
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
package models
|
||||||
|
|
||||||
|
type UserRole struct {
|
||||||
|
UserId string
|
||||||
|
RoleId uint
|
||||||
|
}
|
6
storage-new/models/UserTags.go
Normal file
6
storage-new/models/UserTags.go
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
package models
|
||||||
|
|
||||||
|
type UserTag struct {
|
||||||
|
UserId string
|
||||||
|
Tag string
|
||||||
|
}
|
1
storage-new/storage.go
Normal file
1
storage-new/storage.go
Normal file
|
@ -0,0 +1 @@
|
||||||
|
package storage
|
Loading…
Reference in a new issue