too many changes to name honestly

This commit is contained in:
tsmethurst
2021-04-08 23:29:35 +02:00
parent e6c590c065
commit f210d39891
85 changed files with 1178 additions and 587 deletions

View File

@ -27,8 +27,7 @@ import (
"github.com/go-fed/activity/pub"
"github.com/sirupsen/logrus"
"github.com/superseriousbusiness/gotosocial/internal/config"
"github.com/superseriousbusiness/gotosocial/internal/db/model"
"github.com/superseriousbusiness/gotosocial/pkg/mastotypes"
"github.com/superseriousbusiness/gotosocial/internal/db/gtsmodel"
)
const dbTypePostgres string = "POSTGRES"
@ -115,38 +114,38 @@ type DB interface {
// GetAccountByUserID is a shortcut for the common action of fetching an account corresponding to a user ID.
// The given account pointer will be set to the result of the query, whatever it is.
// In case of no entries, a 'no entries' error will be returned
GetAccountByUserID(userID string, account *model.Account) error
GetAccountByUserID(userID string, account *gtsmodel.Account) error
// GetFollowRequestsForAccountID is a shortcut for the common action of fetching a list of follow requests targeting the given account ID.
// The given slice 'followRequests' will be set to the result of the query, whatever it is.
// In case of no entries, a 'no entries' error will be returned
GetFollowRequestsForAccountID(accountID string, followRequests *[]model.FollowRequest) error
GetFollowRequestsForAccountID(accountID string, followRequests *[]gtsmodel.FollowRequest) error
// GetFollowingByAccountID is a shortcut for the common action of fetching a list of accounts that accountID is following.
// The given slice 'following' will be set to the result of the query, whatever it is.
// In case of no entries, a 'no entries' error will be returned
GetFollowingByAccountID(accountID string, following *[]model.Follow) error
GetFollowingByAccountID(accountID string, following *[]gtsmodel.Follow) error
// GetFollowersByAccountID is a shortcut for the common action of fetching a list of accounts that accountID is followed by.
// The given slice 'followers' will be set to the result of the query, whatever it is.
// In case of no entries, a 'no entries' error will be returned
GetFollowersByAccountID(accountID string, followers *[]model.Follow) error
GetFollowersByAccountID(accountID string, followers *[]gtsmodel.Follow) error
// GetStatusesByAccountID is a shortcut for the common action of fetching a list of statuses produced by accountID.
// The given slice 'statuses' will be set to the result of the query, whatever it is.
// In case of no entries, a 'no entries' error will be returned
GetStatusesByAccountID(accountID string, statuses *[]model.Status) error
GetStatusesByAccountID(accountID string, statuses *[]gtsmodel.Status) error
// GetStatusesByTimeDescending is a shortcut for getting the most recent statuses. accountID is optional, if not provided
// then all statuses will be returned. If limit is set to 0, the size of the returned slice will not be limited. This can
// be very memory intensive so you probably shouldn't do this!
// In case of no entries, a 'no entries' error will be returned
GetStatusesByTimeDescending(accountID string, statuses *[]model.Status, limit int) error
GetStatusesByTimeDescending(accountID string, statuses *[]gtsmodel.Status, limit int) error
// GetLastStatusForAccountID simply gets the most recent status by the given account.
// The given slice 'status' pointer will be set to the result of the query, whatever it is.
// In case of no entries, a 'no entries' error will be returned
GetLastStatusForAccountID(accountID string, status *model.Status) error
GetLastStatusForAccountID(accountID string, status *gtsmodel.Status) error
// IsUsernameAvailable checks whether a given username is available on our domain.
// Returns an error if the username is already taken, or something went wrong in the db.
@ -161,18 +160,18 @@ type DB interface {
// NewSignup creates a new user in the database with the given parameters, with an *unconfirmed* email address.
// By the time this function is called, it should be assumed that all the parameters have passed validation!
NewSignup(username string, reason string, requireApproval bool, email string, password string, signUpIP net.IP, locale string, appID string) (*model.User, error)
NewSignup(username string, reason string, requireApproval bool, email string, password string, signUpIP net.IP, locale string, appID string) (*gtsmodel.User, error)
// SetHeaderOrAvatarForAccountID sets the header or avatar for the given accountID to the given media attachment.
SetHeaderOrAvatarForAccountID(mediaAttachment *model.MediaAttachment, accountID string) error
SetHeaderOrAvatarForAccountID(mediaAttachment *gtsmodel.MediaAttachment, accountID string) error
// GetHeaderAvatarForAccountID gets the current avatar for the given account ID.
// The passed mediaAttachment pointer will be populated with the value of the avatar, if it exists.
GetAvatarForAccountID(avatar *model.MediaAttachment, accountID string) error
GetAvatarForAccountID(avatar *gtsmodel.MediaAttachment, accountID string) error
// GetHeaderForAccountID gets the current header for the given account ID.
// The passed mediaAttachment pointer will be populated with the value of the header, if it exists.
GetHeaderForAccountID(header *model.MediaAttachment, accountID string) error
GetHeaderForAccountID(header *gtsmodel.MediaAttachment, accountID string) error
// Blocked checks whether a block exists in eiher direction between two accounts.
// That is, it returns true if account1 blocks account2, OR if account2 blocks account1.
@ -182,39 +181,30 @@ type DB interface {
USEFUL CONVERSION FUNCTIONS
*/
// AccountToMastoSensitive takes a db model account as a param, and returns a populated mastotype account, or an error
// if something goes wrong. The returned account should be ready to serialize on an API level, and may have sensitive fields,
// so serve it only to an authorized user who should have permission to see it.
AccountToMastoSensitive(account *model.Account) (*mastotypes.Account, error)
// AccountToMastoPublic takes a db model account as a param, and returns a populated mastotype account, or an error
// if something goes wrong. The returned account should be ready to serialize on an API level, and may NOT have sensitive fields.
// In other words, this is the public record that the server has of an account.
AccountToMastoPublic(account *model.Account) (*mastotypes.Account, error)
// MentionStringsToMentions takes a slice of deduplicated, lowercase account names in the form "@test@whatever.example.org", which have been
// mentioned in a status. It takes the id of the account that wrote the status, and the id of the status itself, and then
// MentionStringsToMentions takes a slice of deduplicated, lowercase account names in the form "@test@whatever.example.org" for a remote account,
// or @test for a local account, which have been mentioned in a status.
// It takes the id of the account that wrote the status, and the id of the status itself, and then
// checks in the database for the mentioned accounts, and returns a slice of mentions generated based on the given parameters.
//
// Note: this func doesn't/shouldn't do any manipulation of the accounts in the DB, it's just for checking if they exist
// and conveniently returning them.
MentionStringsToMentions(targetAccounts []string, originAccountID string, statusID string) ([]*model.Mention, error)
// Note: this func doesn't/shouldn't do any manipulation of the accounts in the DB, it's just for checking
// if they exist in the db and conveniently returning them.
MentionStringsToMentions(targetAccounts []string, originAccountID string, statusID string) ([]*gtsmodel.Mention, error)
// TagStringsToTags takes a slice of deduplicated, lowercase tags in the form "somehashtag", which have been
// used in a status. It takes the id of the account that wrote the status, and the id of the status itself, and then
// returns a slice of *model.Tag corresponding to the given tags.
//
// Note: this func doesn't/shouldn't do any manipulation of the tags in the DB, it's just for checking if they exist
// and conveniently returning them.
TagStringsToTags(tags []string, originAccountID string, statusID string) ([]*model.Tag, error)
// Note: this func doesn't/shouldn't do any manipulation of the tags in the DB, it's just for checking
// if they exist in the db and conveniently returning them.
TagStringsToTags(tags []string, originAccountID string, statusID string) ([]*gtsmodel.Tag, error)
// EmojiStringsToEmojis takes a slice of deduplicated, lowercase emojis in the form ":emojiname:", which have been
// used in a status. It takes the id of the account that wrote the status, and the id of the status itself, and then
// returns a slice of *model.Emoji corresponding to the given emojis.
//
// Note: this func doesn't/shouldn't do any manipulation of the emoji in the DB, it's just for checking if they exist
// and conveniently returning them.
EmojiStringsToEmojis(emojis []string, originAccountID string, statusID string) ([]*model.Emoji, error)
// Note: this func doesn't/shouldn't do any manipulation of the emoji in the DB, it's just for checking
// if they exist in the db and conveniently returning them.
EmojiStringsToEmojis(emojis []string, originAccountID string, statusID string) ([]*gtsmodel.Emoji, error)
}
// New returns a new database service that satisfies the DB interface and, by extension,

View File

@ -16,11 +16,11 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// Package model contains types used *internally* by GoToSocial and added/removed/selected from the database.
// Package gtsmodel contains types used *internally* by GoToSocial and added/removed/selected from the database.
// These types should never be serialized and/or sent out via public APIs, as they contain sensitive information.
// The annotation used on these structs is for handling them via the go-pg ORM (hence why they're in this db subdir).
// See here for more info on go-pg model annotations: https://pg.uptrace.dev/models/
package model
package gtsmodel
import (
"crypto/rsa"
@ -38,7 +38,7 @@ type Account struct {
// Username of the account, should just be a string of [a-z0-9_]. Can be added to domain to create the full username in the form ``[username]@[domain]`` eg., ``user_96@example.org``
Username string `pg:",notnull,unique:userdomain"` // username and domain should be unique *with* each other
// Domain of the account, will be null if this is a local account, otherwise something like ``example.org`` or ``mastodon.social``. Should be unique with username.
Domain string `pg:"default:null,unique:userdomain"` // username and domain should be unique *with* each other
Domain string `pg:",unique:userdomain"` // username and domain should be unique *with* each other
/*
ACCOUNT METADATA

View File

@ -16,7 +16,7 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package model
package gtsmodel
// ActivityStreamsObject refers to https://www.w3.org/TR/activitystreams-vocabulary/#object-types
type ActivityStreamsObject string

View File

@ -16,9 +16,7 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package model
import "github.com/superseriousbusiness/gotosocial/pkg/mastotypes"
package gtsmodel
// Application represents an application that can perform actions on behalf of a user.
// It is used to authorize tokens etc, and is associated with an oauth client id in the database.
@ -40,23 +38,3 @@ type Application struct {
// a vapid key generated for this app when it was created
VapidKey string
}
// ToMastoSensitive returns this application as a mastodon api type, ready for serialization
func (a *Application) ToMastoSensitive() *mastotypes.Application {
return &mastotypes.Application{
ID: a.ID,
Name: a.Name,
Website: a.Website,
RedirectURI: a.RedirectURI,
ClientID: a.ClientID,
ClientSecret: a.ClientSecret,
VapidKey: a.VapidKey,
}
}
func (a *Application) ToMastoPublic() *mastotypes.Application {
return &mastotypes.Application{
Name: a.Name,
Website: a.Website,
}
}

View File

@ -1,4 +1,4 @@
package model
package gtsmodel
import "time"

View File

@ -16,7 +16,7 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package model
package gtsmodel
import "time"

View File

@ -16,7 +16,7 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package model
package gtsmodel
import "time"

View File

@ -16,7 +16,7 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package model
package gtsmodel
import "time"

View File

@ -16,7 +16,7 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package model
package gtsmodel
import "time"

View File

@ -16,7 +16,7 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package model
package gtsmodel
import "time"

View File

@ -16,7 +16,7 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package model
package gtsmodel
import (
"time"
@ -29,7 +29,9 @@ type MediaAttachment struct {
ID string `pg:"type:uuid,default:gen_random_uuid(),pk,notnull,unique"`
// ID of the status to which this is attached
StatusID string
// Where can the attachment be retrieved on a remote server
// Where can the attachment be retrieved on *this* server
URL string
// Where can the attachment be retrieved on a remote server (empty for local media)
RemoteURL string
// When was the attachment created
CreatedAt time.Time `pg:"type:timestamp,notnull,default:now()"`
@ -81,7 +83,9 @@ type Thumbnail struct {
FileSize int
// When was the file last updated
UpdatedAt time.Time `pg:"type:timestamp,notnull,default:now()"`
// What is the remote URL of the thumbnail
// What is the URL of the thumbnail on the local server
URL string
// What is the remote URL of the thumbnail (empty for local media)
RemoteURL string
}
@ -106,11 +110,13 @@ const (
// FileTypeImage is for jpegs and pngs
FileTypeImage FileType = "image"
// FileTypeGif is for native gifs and soundless videos that have been converted to gifs
FileTypeGif FileType = "gif"
FileTypeGif FileType = "gifv"
// FileTypeAudio is for audio-only files (no video)
FileTypeAudio FileType = "audio"
// FileTypeVideo is for files with audio + visual
FileTypeVideo FileType = "video"
// FileTypeUnknown is for unknown file types (surprise surprise!)
FileTypeUnknown FileType = "unknown"
)
// FileMeta describes metadata about the actual contents of the file.
@ -119,7 +125,7 @@ type FileMeta struct {
Small Small
}
// Small implements SmallMeta and can be used for a thumbnail of any media type
// Small can be used for a thumbnail of any media type
type Small struct {
Width int
Height int
@ -127,7 +133,7 @@ type Small struct {
Aspect float64
}
// ImageOriginal implements OriginalMeta for still images
// Original can be used for original metadata for any media type
type Original struct {
Width int
Height int

View File

@ -16,7 +16,7 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package model
package gtsmodel
import "time"

View File

@ -0,0 +1,21 @@
/*
GoToSocial
Copyright (C) 2021 GoToSocial Authors admin@gotosocial.org
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gtsmodel

View File

@ -16,7 +16,7 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package model
package gtsmodel
import "time"
@ -40,6 +40,8 @@ type Status struct {
AccountID string
// id of the status this status is a reply to
InReplyToID string
// id of the account that this status replies to
InReplyToAccountID string
// id of the status this status is a boost of
BoostOfID string
// cw string for this status

View File

@ -16,7 +16,7 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package model
package gtsmodel
import "time"

View File

@ -16,7 +16,7 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package model
package gtsmodel
import (
"net"

View File

@ -6,9 +6,7 @@ import (
context "context"
mock "github.com/stretchr/testify/mock"
mastotypes "github.com/superseriousbusiness/gotosocial/pkg/mastotypes"
model "github.com/superseriousbusiness/gotosocial/internal/db/model"
gtsmodel "github.com/superseriousbusiness/gotosocial/internal/db/gtsmodel"
net "net"
@ -20,52 +18,6 @@ type MockDB struct {
mock.Mock
}
// AccountToMastoPublic provides a mock function with given fields: account
func (_m *MockDB) AccountToMastoPublic(account *model.Account) (*mastotypes.Account, error) {
ret := _m.Called(account)
var r0 *mastotypes.Account
if rf, ok := ret.Get(0).(func(*model.Account) *mastotypes.Account); ok {
r0 = rf(account)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(*mastotypes.Account)
}
}
var r1 error
if rf, ok := ret.Get(1).(func(*model.Account) error); ok {
r1 = rf(account)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// AccountToMastoSensitive provides a mock function with given fields: account
func (_m *MockDB) AccountToMastoSensitive(account *model.Account) (*mastotypes.Account, error) {
ret := _m.Called(account)
var r0 *mastotypes.Account
if rf, ok := ret.Get(0).(func(*model.Account) *mastotypes.Account); ok {
r0 = rf(account)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(*mastotypes.Account)
}
}
var r1 error
if rf, ok := ret.Get(1).(func(*model.Account) error); ok {
r1 = rf(account)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// Blocked provides a mock function with given fields: account1, account2
func (_m *MockDB) Blocked(account1 string, account2 string) (bool, error) {
ret := _m.Called(account1, account2)
@ -144,15 +96,15 @@ func (_m *MockDB) DropTable(i interface{}) error {
}
// EmojiStringsToEmojis provides a mock function with given fields: emojis, originAccountID, statusID
func (_m *MockDB) EmojiStringsToEmojis(emojis []string, originAccountID string, statusID string) ([]*model.Emoji, error) {
func (_m *MockDB) EmojiStringsToEmojis(emojis []string, originAccountID string, statusID string) ([]*gtsmodel.Emoji, error) {
ret := _m.Called(emojis, originAccountID, statusID)
var r0 []*model.Emoji
if rf, ok := ret.Get(0).(func([]string, string, string) []*model.Emoji); ok {
var r0 []*gtsmodel.Emoji
if rf, ok := ret.Get(0).(func([]string, string, string) []*gtsmodel.Emoji); ok {
r0 = rf(emojis, originAccountID, statusID)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).([]*model.Emoji)
r0 = ret.Get(0).([]*gtsmodel.Emoji)
}
}
@ -183,11 +135,11 @@ func (_m *MockDB) Federation() pub.Database {
}
// GetAccountByUserID provides a mock function with given fields: userID, account
func (_m *MockDB) GetAccountByUserID(userID string, account *model.Account) error {
func (_m *MockDB) GetAccountByUserID(userID string, account *gtsmodel.Account) error {
ret := _m.Called(userID, account)
var r0 error
if rf, ok := ret.Get(0).(func(string, *model.Account) error); ok {
if rf, ok := ret.Get(0).(func(string, *gtsmodel.Account) error); ok {
r0 = rf(userID, account)
} else {
r0 = ret.Error(0)
@ -211,11 +163,11 @@ func (_m *MockDB) GetAll(i interface{}) error {
}
// GetAvatarForAccountID provides a mock function with given fields: avatar, accountID
func (_m *MockDB) GetAvatarForAccountID(avatar *model.MediaAttachment, accountID string) error {
func (_m *MockDB) GetAvatarForAccountID(avatar *gtsmodel.MediaAttachment, accountID string) error {
ret := _m.Called(avatar, accountID)
var r0 error
if rf, ok := ret.Get(0).(func(*model.MediaAttachment, string) error); ok {
if rf, ok := ret.Get(0).(func(*gtsmodel.MediaAttachment, string) error); ok {
r0 = rf(avatar, accountID)
} else {
r0 = ret.Error(0)
@ -239,11 +191,11 @@ func (_m *MockDB) GetByID(id string, i interface{}) error {
}
// GetFollowRequestsForAccountID provides a mock function with given fields: accountID, followRequests
func (_m *MockDB) GetFollowRequestsForAccountID(accountID string, followRequests *[]model.FollowRequest) error {
func (_m *MockDB) GetFollowRequestsForAccountID(accountID string, followRequests *[]gtsmodel.FollowRequest) error {
ret := _m.Called(accountID, followRequests)
var r0 error
if rf, ok := ret.Get(0).(func(string, *[]model.FollowRequest) error); ok {
if rf, ok := ret.Get(0).(func(string, *[]gtsmodel.FollowRequest) error); ok {
r0 = rf(accountID, followRequests)
} else {
r0 = ret.Error(0)
@ -253,11 +205,11 @@ func (_m *MockDB) GetFollowRequestsForAccountID(accountID string, followRequests
}
// GetFollowersByAccountID provides a mock function with given fields: accountID, followers
func (_m *MockDB) GetFollowersByAccountID(accountID string, followers *[]model.Follow) error {
func (_m *MockDB) GetFollowersByAccountID(accountID string, followers *[]gtsmodel.Follow) error {
ret := _m.Called(accountID, followers)
var r0 error
if rf, ok := ret.Get(0).(func(string, *[]model.Follow) error); ok {
if rf, ok := ret.Get(0).(func(string, *[]gtsmodel.Follow) error); ok {
r0 = rf(accountID, followers)
} else {
r0 = ret.Error(0)
@ -267,11 +219,11 @@ func (_m *MockDB) GetFollowersByAccountID(accountID string, followers *[]model.F
}
// GetFollowingByAccountID provides a mock function with given fields: accountID, following
func (_m *MockDB) GetFollowingByAccountID(accountID string, following *[]model.Follow) error {
func (_m *MockDB) GetFollowingByAccountID(accountID string, following *[]gtsmodel.Follow) error {
ret := _m.Called(accountID, following)
var r0 error
if rf, ok := ret.Get(0).(func(string, *[]model.Follow) error); ok {
if rf, ok := ret.Get(0).(func(string, *[]gtsmodel.Follow) error); ok {
r0 = rf(accountID, following)
} else {
r0 = ret.Error(0)
@ -281,11 +233,11 @@ func (_m *MockDB) GetFollowingByAccountID(accountID string, following *[]model.F
}
// GetHeaderForAccountID provides a mock function with given fields: header, accountID
func (_m *MockDB) GetHeaderForAccountID(header *model.MediaAttachment, accountID string) error {
func (_m *MockDB) GetHeaderForAccountID(header *gtsmodel.MediaAttachment, accountID string) error {
ret := _m.Called(header, accountID)
var r0 error
if rf, ok := ret.Get(0).(func(*model.MediaAttachment, string) error); ok {
if rf, ok := ret.Get(0).(func(*gtsmodel.MediaAttachment, string) error); ok {
r0 = rf(header, accountID)
} else {
r0 = ret.Error(0)
@ -295,11 +247,11 @@ func (_m *MockDB) GetHeaderForAccountID(header *model.MediaAttachment, accountID
}
// GetLastStatusForAccountID provides a mock function with given fields: accountID, status
func (_m *MockDB) GetLastStatusForAccountID(accountID string, status *model.Status) error {
func (_m *MockDB) GetLastStatusForAccountID(accountID string, status *gtsmodel.Status) error {
ret := _m.Called(accountID, status)
var r0 error
if rf, ok := ret.Get(0).(func(string, *model.Status) error); ok {
if rf, ok := ret.Get(0).(func(string, *gtsmodel.Status) error); ok {
r0 = rf(accountID, status)
} else {
r0 = ret.Error(0)
@ -309,11 +261,11 @@ func (_m *MockDB) GetLastStatusForAccountID(accountID string, status *model.Stat
}
// GetStatusesByAccountID provides a mock function with given fields: accountID, statuses
func (_m *MockDB) GetStatusesByAccountID(accountID string, statuses *[]model.Status) error {
func (_m *MockDB) GetStatusesByAccountID(accountID string, statuses *[]gtsmodel.Status) error {
ret := _m.Called(accountID, statuses)
var r0 error
if rf, ok := ret.Get(0).(func(string, *[]model.Status) error); ok {
if rf, ok := ret.Get(0).(func(string, *[]gtsmodel.Status) error); ok {
r0 = rf(accountID, statuses)
} else {
r0 = ret.Error(0)
@ -323,11 +275,11 @@ func (_m *MockDB) GetStatusesByAccountID(accountID string, statuses *[]model.Sta
}
// GetStatusesByTimeDescending provides a mock function with given fields: accountID, statuses, limit
func (_m *MockDB) GetStatusesByTimeDescending(accountID string, statuses *[]model.Status, limit int) error {
func (_m *MockDB) GetStatusesByTimeDescending(accountID string, statuses *[]gtsmodel.Status, limit int) error {
ret := _m.Called(accountID, statuses, limit)
var r0 error
if rf, ok := ret.Get(0).(func(string, *[]model.Status, int) error); ok {
if rf, ok := ret.Get(0).(func(string, *[]gtsmodel.Status, int) error); ok {
r0 = rf(accountID, statuses, limit)
} else {
r0 = ret.Error(0)
@ -393,15 +345,15 @@ func (_m *MockDB) IsUsernameAvailable(username string) error {
}
// MentionStringsToMentions provides a mock function with given fields: targetAccounts, originAccountID, statusID
func (_m *MockDB) MentionStringsToMentions(targetAccounts []string, originAccountID string, statusID string) ([]*model.Mention, error) {
func (_m *MockDB) MentionStringsToMentions(targetAccounts []string, originAccountID string, statusID string) ([]*gtsmodel.Mention, error) {
ret := _m.Called(targetAccounts, originAccountID, statusID)
var r0 []*model.Mention
if rf, ok := ret.Get(0).(func([]string, string, string) []*model.Mention); ok {
var r0 []*gtsmodel.Mention
if rf, ok := ret.Get(0).(func([]string, string, string) []*gtsmodel.Mention); ok {
r0 = rf(targetAccounts, originAccountID, statusID)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).([]*model.Mention)
r0 = ret.Get(0).([]*gtsmodel.Mention)
}
}
@ -416,15 +368,15 @@ func (_m *MockDB) MentionStringsToMentions(targetAccounts []string, originAccoun
}
// NewSignup provides a mock function with given fields: username, reason, requireApproval, email, password, signUpIP, locale, appID
func (_m *MockDB) NewSignup(username string, reason string, requireApproval bool, email string, password string, signUpIP net.IP, locale string, appID string) (*model.User, error) {
func (_m *MockDB) NewSignup(username string, reason string, requireApproval bool, email string, password string, signUpIP net.IP, locale string, appID string) (*gtsmodel.User, error) {
ret := _m.Called(username, reason, requireApproval, email, password, signUpIP, locale, appID)
var r0 *model.User
if rf, ok := ret.Get(0).(func(string, string, bool, string, string, net.IP, string, string) *model.User); ok {
var r0 *gtsmodel.User
if rf, ok := ret.Get(0).(func(string, string, bool, string, string, net.IP, string, string) *gtsmodel.User); ok {
r0 = rf(username, reason, requireApproval, email, password, signUpIP, locale, appID)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(*model.User)
r0 = ret.Get(0).(*gtsmodel.User)
}
}
@ -453,11 +405,11 @@ func (_m *MockDB) Put(i interface{}) error {
}
// SetHeaderOrAvatarForAccountID provides a mock function with given fields: mediaAttachment, accountID
func (_m *MockDB) SetHeaderOrAvatarForAccountID(mediaAttachment *model.MediaAttachment, accountID string) error {
func (_m *MockDB) SetHeaderOrAvatarForAccountID(mediaAttachment *gtsmodel.MediaAttachment, accountID string) error {
ret := _m.Called(mediaAttachment, accountID)
var r0 error
if rf, ok := ret.Get(0).(func(*model.MediaAttachment, string) error); ok {
if rf, ok := ret.Get(0).(func(*gtsmodel.MediaAttachment, string) error); ok {
r0 = rf(mediaAttachment, accountID)
} else {
r0 = ret.Error(0)
@ -481,15 +433,15 @@ func (_m *MockDB) Stop(ctx context.Context) error {
}
// TagStringsToTags provides a mock function with given fields: tags, originAccountID, statusID
func (_m *MockDB) TagStringsToTags(tags []string, originAccountID string, statusID string) ([]*model.Tag, error) {
func (_m *MockDB) TagStringsToTags(tags []string, originAccountID string, statusID string) ([]*gtsmodel.Tag, error) {
ret := _m.Called(tags, originAccountID, statusID)
var r0 []*model.Tag
if rf, ok := ret.Get(0).(func([]string, string, string) []*model.Tag); ok {
var r0 []*gtsmodel.Tag
if rf, ok := ret.Get(0).(func([]string, string, string) []*gtsmodel.Tag); ok {
r0 = rf(tags, originAccountID, statusID)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).([]*model.Tag)
r0 = ret.Get(0).([]*gtsmodel.Tag)
}
}

View File

@ -36,9 +36,9 @@ import (
"github.com/go-pg/pg/v10/orm"
"github.com/sirupsen/logrus"
"github.com/superseriousbusiness/gotosocial/internal/config"
"github.com/superseriousbusiness/gotosocial/internal/db/model"
"github.com/superseriousbusiness/gotosocial/internal/db/gtsmodel"
mastotypes "github.com/superseriousbusiness/gotosocial/internal/mastotypes/mastomodel"
"github.com/superseriousbusiness/gotosocial/internal/util"
"github.com/superseriousbusiness/gotosocial/pkg/mastotypes"
"golang.org/x/crypto/bcrypt"
)
@ -214,9 +214,9 @@ func (ps *postgresService) IsHealthy(ctx context.Context) error {
func (ps *postgresService) CreateSchema(ctx context.Context) error {
models := []interface{}{
(*model.Account)(nil),
(*model.Status)(nil),
(*model.User)(nil),
(*gtsmodel.Account)(nil),
(*gtsmodel.Status)(nil),
(*gtsmodel.User)(nil),
}
ps.log.Info("creating db schema")
@ -312,8 +312,8 @@ func (ps *postgresService) DeleteWhere(key string, value interface{}, i interfac
HANDY SHORTCUTS
*/
func (ps *postgresService) GetAccountByUserID(userID string, account *model.Account) error {
user := &model.User{
func (ps *postgresService) GetAccountByUserID(userID string, account *gtsmodel.Account) error {
user := &gtsmodel.User{
ID: userID,
}
if err := ps.conn.Model(user).Where("id = ?", userID).Select(); err != nil {
@ -331,7 +331,7 @@ func (ps *postgresService) GetAccountByUserID(userID string, account *model.Acco
return nil
}
func (ps *postgresService) GetFollowRequestsForAccountID(accountID string, followRequests *[]model.FollowRequest) error {
func (ps *postgresService) GetFollowRequestsForAccountID(accountID string, followRequests *[]gtsmodel.FollowRequest) error {
if err := ps.conn.Model(followRequests).Where("target_account_id = ?", accountID).Select(); err != nil {
if err == pg.ErrNoRows {
return ErrNoEntries{}
@ -341,7 +341,7 @@ func (ps *postgresService) GetFollowRequestsForAccountID(accountID string, follo
return nil
}
func (ps *postgresService) GetFollowingByAccountID(accountID string, following *[]model.Follow) error {
func (ps *postgresService) GetFollowingByAccountID(accountID string, following *[]gtsmodel.Follow) error {
if err := ps.conn.Model(following).Where("account_id = ?", accountID).Select(); err != nil {
if err == pg.ErrNoRows {
return ErrNoEntries{}
@ -351,7 +351,7 @@ func (ps *postgresService) GetFollowingByAccountID(accountID string, following *
return nil
}
func (ps *postgresService) GetFollowersByAccountID(accountID string, followers *[]model.Follow) error {
func (ps *postgresService) GetFollowersByAccountID(accountID string, followers *[]gtsmodel.Follow) error {
if err := ps.conn.Model(followers).Where("target_account_id = ?", accountID).Select(); err != nil {
if err == pg.ErrNoRows {
return ErrNoEntries{}
@ -361,7 +361,7 @@ func (ps *postgresService) GetFollowersByAccountID(accountID string, followers *
return nil
}
func (ps *postgresService) GetStatusesByAccountID(accountID string, statuses *[]model.Status) error {
func (ps *postgresService) GetStatusesByAccountID(accountID string, statuses *[]gtsmodel.Status) error {
if err := ps.conn.Model(statuses).Where("account_id = ?", accountID).Select(); err != nil {
if err == pg.ErrNoRows {
return ErrNoEntries{}
@ -371,7 +371,7 @@ func (ps *postgresService) GetStatusesByAccountID(accountID string, statuses *[]
return nil
}
func (ps *postgresService) GetStatusesByTimeDescending(accountID string, statuses *[]model.Status, limit int) error {
func (ps *postgresService) GetStatusesByTimeDescending(accountID string, statuses *[]gtsmodel.Status, limit int) error {
q := ps.conn.Model(statuses).Order("created_at DESC")
if limit != 0 {
q = q.Limit(limit)
@ -388,7 +388,7 @@ func (ps *postgresService) GetStatusesByTimeDescending(accountID string, statuse
return nil
}
func (ps *postgresService) GetLastStatusForAccountID(accountID string, status *model.Status) error {
func (ps *postgresService) GetLastStatusForAccountID(accountID string, status *gtsmodel.Status) error {
if err := ps.conn.Model(status).Order("created_at DESC").Limit(1).Where("account_id = ?", accountID).Select(); err != nil {
if err == pg.ErrNoRows {
return ErrNoEntries{}
@ -403,7 +403,7 @@ func (ps *postgresService) IsUsernameAvailable(username string) error {
// if no error we fail because it means we found something
// if error but it's not pg.ErrNoRows then we fail
// if err is pg.ErrNoRows we're good, we found nothing so continue
if err := ps.conn.Model(&model.Account{}).Where("username = ?", username).Where("domain = ?", nil).Select(); err == nil {
if err := ps.conn.Model(&gtsmodel.Account{}).Where("username = ?", username).Where("domain = ?", nil).Select(); err == nil {
return fmt.Errorf("username %s already in use", username)
} else if err != pg.ErrNoRows {
return fmt.Errorf("db error: %s", err)
@ -420,7 +420,7 @@ func (ps *postgresService) IsEmailAvailable(email string) error {
domain := strings.Split(m.Address, "@")[1] // domain will always be the second part after @
// check if the email domain is blocked
if err := ps.conn.Model(&model.EmailDomainBlock{}).Where("domain = ?", domain).Select(); err == nil {
if err := ps.conn.Model(&gtsmodel.EmailDomainBlock{}).Where("domain = ?", domain).Select(); err == nil {
// fail because we found something
return fmt.Errorf("email domain %s is blocked", domain)
} else if err != pg.ErrNoRows {
@ -429,7 +429,7 @@ func (ps *postgresService) IsEmailAvailable(email string) error {
}
// check if this email is associated with a user already
if err := ps.conn.Model(&model.User{}).Where("email = ?", email).WhereOr("unconfirmed_email = ?", email).Select(); err == nil {
if err := ps.conn.Model(&gtsmodel.User{}).Where("email = ?", email).WhereOr("unconfirmed_email = ?", email).Select(); err == nil {
// fail because we found something
return fmt.Errorf("email %s already in use", email)
} else if err != pg.ErrNoRows {
@ -439,7 +439,7 @@ func (ps *postgresService) IsEmailAvailable(email string) error {
return nil
}
func (ps *postgresService) NewSignup(username string, reason string, requireApproval bool, email string, password string, signUpIP net.IP, locale string, appID string) (*model.User, error) {
func (ps *postgresService) NewSignup(username string, reason string, requireApproval bool, email string, password string, signUpIP net.IP, locale string, appID string) (*gtsmodel.User, error) {
key, err := rsa.GenerateKey(rand.Reader, 2048)
if err != nil {
ps.log.Errorf("error creating new rsa key: %s", err)
@ -448,14 +448,14 @@ func (ps *postgresService) NewSignup(username string, reason string, requireAppr
uris := util.GenerateURIs(username, ps.config.Protocol, ps.config.Host)
a := &model.Account{
a := &gtsmodel.Account{
Username: username,
DisplayName: username,
Reason: reason,
URL: uris.UserURL,
PrivateKey: key,
PublicKey: &key.PublicKey,
ActorType: model.ActivityStreamsPerson,
ActorType: gtsmodel.ActivityStreamsPerson,
URI: uris.UserURI,
InboxURL: uris.InboxURI,
OutboxURL: uris.OutboxURI,
@ -470,7 +470,7 @@ func (ps *postgresService) NewSignup(username string, reason string, requireAppr
if err != nil {
return nil, fmt.Errorf("error hashing password: %s", err)
}
u := &model.User{
u := &gtsmodel.User{
AccountID: a.ID,
EncryptedPassword: string(pw),
SignUpIP: signUpIP,
@ -486,12 +486,12 @@ func (ps *postgresService) NewSignup(username string, reason string, requireAppr
return u, nil
}
func (ps *postgresService) SetHeaderOrAvatarForAccountID(mediaAttachment *model.MediaAttachment, accountID string) error {
func (ps *postgresService) SetHeaderOrAvatarForAccountID(mediaAttachment *gtsmodel.MediaAttachment, accountID string) error {
_, err := ps.conn.Model(mediaAttachment).Insert()
return err
}
func (ps *postgresService) GetHeaderForAccountID(header *model.MediaAttachment, accountID string) error {
func (ps *postgresService) GetHeaderForAccountID(header *gtsmodel.MediaAttachment, accountID string) error {
if err := ps.conn.Model(header).Where("account_id = ?", accountID).Where("header = ?", true).Select(); err != nil {
if err == pg.ErrNoRows {
return ErrNoEntries{}
@ -501,7 +501,7 @@ func (ps *postgresService) GetHeaderForAccountID(header *model.MediaAttachment,
return nil
}
func (ps *postgresService) GetAvatarForAccountID(avatar *model.MediaAttachment, accountID string) error {
func (ps *postgresService) GetAvatarForAccountID(avatar *gtsmodel.MediaAttachment, accountID string) error {
if err := ps.conn.Model(avatar).Where("account_id = ?", accountID).Where("avatar = ?", true).Select(); err != nil {
if err == pg.ErrNoRows {
return ErrNoEntries{}
@ -513,12 +513,13 @@ func (ps *postgresService) GetAvatarForAccountID(avatar *model.MediaAttachment,
func (ps *postgresService) Blocked(account1 string, account2 string) (bool, error) {
var blocked bool
if err := ps.conn.Model(&model.Block{}).
if err := ps.conn.Model(&gtsmodel.Block{}).
Where("account_id = ?", account1).Where("target_account_id = ?", account2).
WhereOr("target_account_id = ?", account1).Where("account_id = ?", account2).
Select(); err != nil {
if err == pg.ErrNoRows {
blocked = false
return blocked, nil
} else {
return blocked, err
}
@ -535,7 +536,7 @@ func (ps *postgresService) Blocked(account1 string, account2 string) (bool, erro
// The resulting account fits the specifications for the path /api/v1/accounts/verify_credentials, as described here:
// https://docs.joinmastodon.org/methods/accounts/. Note that it's *sensitive* because it's only meant to be exposed to the user
// that the account actually belongs to.
func (ps *postgresService) AccountToMastoSensitive(a *model.Account) (*mastotypes.Account, error) {
func (ps *postgresService) AccountToMastoSensitive(a *gtsmodel.Account) (*mastotypes.Account, error) {
// we can build this sensitive account easily by first getting the public account....
mastoAccount, err := ps.AccountToMastoPublic(a)
if err != nil {
@ -545,7 +546,7 @@ func (ps *postgresService) AccountToMastoSensitive(a *model.Account) (*mastotype
// then adding the Source object to it...
// check pending follow requests aimed at this account
fr := []model.FollowRequest{}
fr := []gtsmodel.FollowRequest{}
if err := ps.GetFollowRequestsForAccountID(a.ID, &fr); err != nil {
if _, ok := err.(ErrNoEntries); !ok {
return nil, fmt.Errorf("error getting follow requests: %s", err)
@ -568,9 +569,9 @@ func (ps *postgresService) AccountToMastoSensitive(a *model.Account) (*mastotype
return mastoAccount, nil
}
func (ps *postgresService) AccountToMastoPublic(a *model.Account) (*mastotypes.Account, error) {
func (ps *postgresService) AccountToMastoPublic(a *gtsmodel.Account) (*mastotypes.Account, error) {
// count followers
followers := []model.Follow{}
followers := []gtsmodel.Follow{}
if err := ps.GetFollowersByAccountID(a.ID, &followers); err != nil {
if _, ok := err.(ErrNoEntries); !ok {
return nil, fmt.Errorf("error getting followers: %s", err)
@ -582,7 +583,7 @@ func (ps *postgresService) AccountToMastoPublic(a *model.Account) (*mastotypes.A
}
// count following
following := []model.Follow{}
following := []gtsmodel.Follow{}
if err := ps.GetFollowingByAccountID(a.ID, &following); err != nil {
if _, ok := err.(ErrNoEntries); !ok {
return nil, fmt.Errorf("error getting following: %s", err)
@ -594,7 +595,7 @@ func (ps *postgresService) AccountToMastoPublic(a *model.Account) (*mastotypes.A
}
// count statuses
statuses := []model.Status{}
statuses := []gtsmodel.Status{}
if err := ps.GetStatusesByAccountID(a.ID, &statuses); err != nil {
if _, ok := err.(ErrNoEntries); !ok {
return nil, fmt.Errorf("error getting last statuses: %s", err)
@ -606,7 +607,7 @@ func (ps *postgresService) AccountToMastoPublic(a *model.Account) (*mastotypes.A
}
// check when the last status was
lastStatus := &model.Status{}
lastStatus := &gtsmodel.Status{}
if err := ps.GetLastStatusForAccountID(a.ID, lastStatus); err != nil {
if _, ok := err.(ErrNoEntries); !ok {
return nil, fmt.Errorf("error getting last status: %s", err)
@ -618,7 +619,7 @@ func (ps *postgresService) AccountToMastoPublic(a *model.Account) (*mastotypes.A
}
// build the avatar and header URLs
avi := &model.MediaAttachment{}
avi := &gtsmodel.MediaAttachment{}
if err := ps.GetAvatarForAccountID(avi, a.ID); err != nil {
if _, ok := err.(ErrNoEntries); !ok {
return nil, fmt.Errorf("error getting avatar: %s", err)
@ -627,7 +628,7 @@ func (ps *postgresService) AccountToMastoPublic(a *model.Account) (*mastotypes.A
aviURL := avi.File.Path
aviURLStatic := avi.Thumbnail.Path
header := &model.MediaAttachment{}
header := &gtsmodel.MediaAttachment{}
if err := ps.GetHeaderForAccountID(avi, a.ID); err != nil {
if _, ok := err.(ErrNoEntries); !ok {
return nil, fmt.Errorf("error getting header: %s", err)
@ -681,11 +682,12 @@ func (ps *postgresService) AccountToMastoPublic(a *model.Account) (*mastotypes.A
}, nil
}
func (ps *postgresService) MentionStringsToMentions(targetAccounts []string, originAccountID string, statusID string) ([]*model.Mention, error) {
menchies := []*model.Mention{}
func (ps *postgresService) MentionStringsToMentions(targetAccounts []string, originAccountID string, statusID string) ([]*gtsmodel.Mention, error) {
menchies := []*gtsmodel.Mention{}
for _, a := range targetAccounts {
// A mentioned account looks like "@test@example.org" -- we can guarantee this from the regex that targetAccounts should have been derived from.
// But we still need to do a bit of fiddling to get what we need here -- the username and domain.
// A mentioned account looks like "@test@example.org" or just "@test" for a local account
// -- we can guarantee this from the regex that targetAccounts should have been derived from.
// But we still need to do a bit of fiddling to get what we need here -- the username and domain (if given).
// 1. trim off the first @
t := strings.TrimPrefix(a, "@")
@ -693,41 +695,51 @@ func (ps *postgresService) MentionStringsToMentions(targetAccounts []string, ori
// 2. split the username and domain
s := strings.Split(t, "@")
// 3. it should *always* be length 2 so if it's not then something is seriously wrong
if len(s) != 2 {
return nil, fmt.Errorf("mentioned account format %s was not valid", a)
// 3. if it's length 1 it's a local account, length 2 means remote, anything else means something is wrong
var local bool
switch len(s) {
case 1:
local = true
case 2:
local = false
default:
return nil, fmt.Errorf("mentioned account format '%s' was not valid", a)
}
var username, domain string
username = s[0]
if !local {
domain = s[1]
}
username := s[0]
domain := s[1]
// 4. check we now have a proper username and domain
if username == "" || domain == "" {
return nil, fmt.Errorf("username or domain for %s was nil", a)
if username == "" || (!local && domain == "") {
return nil, fmt.Errorf("username or domain for '%s' was nil", a)
}
// okay we're good now, we can start pulling accounts out of the database
mentionedAccount := &model.Account{}
mentionedAccount := &gtsmodel.Account{}
var err error
if domain == ps.config.Host {
if local {
// local user -- should have a null domain
err = ps.conn.Model(mentionedAccount).Where("id = ?", username).Where("domain = null").Select()
err = ps.conn.Model(mentionedAccount).Where("username = ?", username).Where("? IS NULL", pg.Ident("domain")).Select()
} else {
// remote user -- should have domain defined
err = ps.conn.Model(mentionedAccount).Where("id = ?", username).Where("domain = ?", domain).Select()
err = ps.conn.Model(mentionedAccount).Where("username = ?", username).Where("? = ?", pg.Ident("domain"), domain).Select()
}
if err != nil {
if err == pg.ErrNoRows {
// no result found for this username/domain so just don't include it as a mencho and carry on about our business
ps.log.Debugf("no account found with username %s and domain %s, skipping it", username, domain)
ps.log.Debugf("no account found with username '%s' and domain '%s', skipping it", username, domain)
continue
}
// a serious error has happened so bail
return nil, fmt.Errorf("error getting account with username %s and domain %s: %s", username, domain, err)
return nil, fmt.Errorf("error getting account with username '%s' and domain '%s': %s", username, domain, err)
}
// id, createdAt and updatedAt will be populated by the db, so we have everything we need!
menchies = append(menchies, &model.Mention{
menchies = append(menchies, &gtsmodel.Mention{
StatusID: statusID,
OriginAccountID: originAccountID,
TargetAccountID: mentionedAccount.ID,
@ -737,26 +749,26 @@ func (ps *postgresService) MentionStringsToMentions(targetAccounts []string, ori
}
// for now this function doesn't really use the database, but it's here because:
// A) it might later and
// A) it probably will later and
// B) it's v. similar to MentionStringsToMentions
func (ps *postgresService) TagStringsToTags(tags []string, originAccountID string, statusID string) ([]*model.Tag, error) {
newTags := []*model.Tag{}
func (ps *postgresService) TagStringsToTags(tags []string, originAccountID string, statusID string) ([]*gtsmodel.Tag, error) {
newTags := []*gtsmodel.Tag{}
for _, t := range tags {
newTags = append(newTags, &model.Tag{
newTags = append(newTags, &gtsmodel.Tag{
Name: t,
})
}
return newTags, nil
}
func (ps *postgresService) EmojiStringsToEmojis(emojis []string, originAccountID string, statusID string) ([]*model.Emoji, error) {
newEmojis := []*model.Emoji{}
func (ps *postgresService) EmojiStringsToEmojis(emojis []string, originAccountID string, statusID string) ([]*gtsmodel.Emoji, error) {
newEmojis := []*gtsmodel.Emoji{}
for _, e := range emojis {
emoji := &model.Emoji{}
emoji := &gtsmodel.Emoji{}
err := ps.conn.Model(emoji).Where("shortcode = ?", e).Where("visible_in_picker = true").Where("disabled = false").Select()
if err != nil {
if err == pg.ErrNoRows {
// no result found for this username/domain so just don't include it as a mencho and carry on about our business
// no result found for this username/domain so just don't include it as an emoji and carry on about our business
ps.log.Debugf("no emoji found with shortcode %s, skipping it", e)
continue
}