diff --git a/internal/trans/exporter.go b/internal/trans/exporter.go
new file mode 100644
index 000000000..ad7884d2d
--- /dev/null
+++ b/internal/trans/exporter.go
@@ -0,0 +1,39 @@
+/*
+ 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 .
+*/
+
+package trans
+
+import (
+ "context"
+
+ "github.com/superseriousbusiness/gotosocial/internal/db"
+)
+
+type Exporter interface {
+ ExportMinimal(ctx context.Context, path string) error
+}
+
+type exporter struct {
+ db db.DB
+}
+
+func NewExporter(db db.DB) Exporter {
+ return &exporter{
+ db: db,
+ }
+}
diff --git a/internal/trans/exportminimal.go b/internal/trans/exportminimal.go
new file mode 100644
index 000000000..a000a48f9
--- /dev/null
+++ b/internal/trans/exportminimal.go
@@ -0,0 +1,63 @@
+/*
+ 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 .
+*/
+
+package trans
+
+import (
+ "bufio"
+ "context"
+ "encoding/json"
+ "fmt"
+ "os"
+
+ "github.com/superseriousbusiness/gotosocial/internal/db"
+ transmodel "github.com/superseriousbusiness/gotosocial/internal/trans/model"
+)
+
+func (e *exporter) ExportMinimal(ctx context.Context, path string) error {
+ f, err := os.Create(path)
+ if err != nil {
+ return err
+ }
+
+ w := bufio.NewWriter(f)
+ encoder := json.NewEncoder(w)
+
+ accounts := []*transmodel.Account{}
+ if err := e.db.GetWhere(ctx, []db.Where{{Key: "domain", Value: nil}}, &accounts); err != nil {
+ return fmt.Errorf("error selecting accounts: %s", err)
+ }
+
+ for _, a := range accounts {
+ encoder.Encode(a)
+ }
+
+ return neatClose(w, f)
+}
+
+func neatClose(w *bufio.Writer, f *os.File) error {
+ if err := w.Flush(); err != nil {
+ return fmt.Errorf("error flushing writer: %s", err)
+ }
+
+ if err := f.Close(); err != nil {
+ return fmt.Errorf("error closing file: %s", err)
+ }
+
+ return nil
+}
diff --git a/internal/trans/exportminimal_test.go b/internal/trans/exportminimal_test.go
new file mode 100644
index 000000000..0e686cde5
--- /dev/null
+++ b/internal/trans/exportminimal_test.go
@@ -0,0 +1,54 @@
+/*
+ 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 .
+*/
+
+package trans_test
+
+import (
+ "context"
+ "fmt"
+ "os"
+ "testing"
+
+ "github.com/google/uuid"
+ "github.com/stretchr/testify/suite"
+ "github.com/superseriousbusiness/gotosocial/internal/trans"
+)
+
+type ExportMinimalTestSuite struct {
+ TransTestSuite
+}
+
+func (suite *ExportMinimalTestSuite) TestExportMinimalOK() {
+ // use a temporary file path that will be cleaned when the test is closed
+ tempFilePath := fmt.Sprintf("%s/%s", suite.T().TempDir(), uuid.NewString())
+
+ // export to the tempFilePath
+ exporter := trans.NewExporter(suite.db)
+ err := exporter.ExportMinimal(context.Background(), tempFilePath)
+ suite.NoError(err)
+
+ // we should have some bytes in that file now
+ b, err := os.ReadFile(tempFilePath)
+ suite.NoError(err)
+ suite.NotEmpty(b)
+ suite.T().Log(string(b))
+}
+
+func TestExportMinimalTestSuite(t *testing.T) {
+ suite.Run(t, &ExportMinimalTestSuite{})
+}
diff --git a/internal/trans/model/account.go b/internal/trans/model/account.go
new file mode 100644
index 000000000..26a06e5e3
--- /dev/null
+++ b/internal/trans/model/account.go
@@ -0,0 +1,48 @@
+/*
+ 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 .
+*/
+
+package trans
+
+import (
+ "crypto/rsa"
+ "time"
+)
+
+// Account represents the minimum viable representation of an account for export/import.
+type Account struct {
+ ID string `json:"id"`
+ CreatedAt *time.Time `json:"created_at"`
+ UpdatedAt *time.Time `json:"updated_at"`
+ Username string `json:"username"`
+ Domain string `json:"domain,omitempty"`
+ Locked bool `json:"locked"`
+ Language string `json:"language,omitempty"`
+ URI string `json:"uri"`
+ URL string `json:"url"`
+ InboxURI string `json:"inbox_uri"`
+ OutboxURI string `json:"outbox_uri"`
+ FollowingURI string `json:"following_uri"`
+ FollowersURI string `json:"followers_uri"`
+ FeaturedCollectionURI string `json:"featured_collection_uri"`
+ ActorType string `json:"actor_type"`
+ PrivateKey *rsa.PrivateKey `json:"private_key,omitempty"`
+ PublicKey *rsa.PublicKey `json:"public_key"`
+ PublicKeyURI string `json:"public_key_uri"`
+ SuspendedAt *time.Time `json:"suspended_at,omitempty"`
+ SuspensionOrigin string `json:"suspension_origin,omitempty"`
+}
diff --git a/internal/trans/model/account_test.go b/internal/trans/model/account_test.go
new file mode 100644
index 000000000..aa1f37f85
--- /dev/null
+++ b/internal/trans/model/account_test.go
@@ -0,0 +1,57 @@
+/*
+ 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 .
+*/
+
+package trans_test
+
+import (
+ "context"
+ "encoding/json"
+ "testing"
+
+ "github.com/stretchr/testify/suite"
+ trans "github.com/superseriousbusiness/gotosocial/internal/trans/model"
+)
+
+type AccountTestSuite struct {
+ ModelTestSuite
+}
+
+func (suite *AccountTestSuite) TestAccountsIdempotent() {
+ // we should be able to get all accounts with the simple trans.Account struct
+ accounts := []*trans.Account{}
+ err := suite.db.GetAll(context.Background(), &accounts)
+ suite.NoError(err)
+ suite.NotEmpty(accounts)
+
+ // we should be able to marshal the accounts to json with no problems
+ b, err := json.Marshal(&accounts)
+ suite.NoError(err)
+ suite.NotNil(b)
+ suite.T().Log(string(b))
+
+ // the json should be idempotent
+ mAccounts := []*trans.Account{}
+ err = json.Unmarshal(b, &mAccounts)
+ suite.NoError(err)
+ suite.NotEmpty(mAccounts)
+ suite.EqualValues(accounts, mAccounts)
+}
+
+func TestAccountTestSuite(t *testing.T) {
+ suite.Run(t, &AccountTestSuite{})
+}
diff --git a/internal/trans/model/block.go b/internal/trans/model/block.go
new file mode 100644
index 000000000..3306dac15
--- /dev/null
+++ b/internal/trans/model/block.go
@@ -0,0 +1,30 @@
+/*
+ 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 .
+*/
+
+package trans
+
+import "time"
+
+type Block struct {
+ ID string `json:"id"`
+ CreatedAt time.Time `json:"created_at"`
+ UpdatedAt time.Time `json:"updated_at"`
+ URI string `json:"uri"`
+ AccountID string `json:"account_id"`
+ TargetAccountID string `json:"target_account_id"`
+}
diff --git a/internal/trans/model/block_test.go b/internal/trans/model/block_test.go
new file mode 100644
index 000000000..9a3b78e1a
--- /dev/null
+++ b/internal/trans/model/block_test.go
@@ -0,0 +1,57 @@
+/*
+ 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 .
+*/
+
+package trans_test
+
+import (
+ "context"
+ "encoding/json"
+ "testing"
+
+ "github.com/stretchr/testify/suite"
+ trans "github.com/superseriousbusiness/gotosocial/internal/trans/model"
+)
+
+type BlockTestSuite struct {
+ ModelTestSuite
+}
+
+func (suite *AccountTestSuite) TestBlocksIdempotent() {
+ // we should be able to get all blocks with the simple trans.Block struct
+ blocks := []*trans.Block{}
+ err := suite.db.GetAll(context.Background(), &blocks)
+ suite.NoError(err)
+ suite.NotEmpty(blocks)
+
+ // we should be able to marshal the blocks to json with no problems
+ b, err := json.Marshal(&blocks)
+ suite.NoError(err)
+ suite.NotNil(b)
+ suite.T().Log(string(b))
+
+ // the json should be idempotent
+ mBlocks := []*trans.Block{}
+ err = json.Unmarshal(b, &mBlocks)
+ suite.NoError(err)
+ suite.NotEmpty(mBlocks)
+ suite.EqualValues(blocks, mBlocks)
+}
+
+func TestBlockTestSuite(t *testing.T) {
+ suite.Run(t, &BlockTestSuite{})
+}
diff --git a/internal/trans/model/domainblock.go b/internal/trans/model/domainblock.go
new file mode 100644
index 000000000..cc3e8924b
--- /dev/null
+++ b/internal/trans/model/domainblock.go
@@ -0,0 +1,3 @@
+package trans
+
+
diff --git a/internal/trans/model/model_test.go b/internal/trans/model/model_test.go
new file mode 100644
index 000000000..278ef4a9d
--- /dev/null
+++ b/internal/trans/model/model_test.go
@@ -0,0 +1,39 @@
+/*
+ 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 .
+*/
+
+package trans_test
+
+import (
+ "github.com/stretchr/testify/suite"
+ "github.com/superseriousbusiness/gotosocial/internal/db"
+ "github.com/superseriousbusiness/gotosocial/testrig"
+)
+
+type ModelTestSuite struct {
+ suite.Suite
+ db db.DB
+}
+
+func (suite *ModelTestSuite) SetupTest() {
+ suite.db = testrig.NewTestDB()
+ testrig.StandardDBSetup(suite.db, nil)
+}
+
+func (suite *ModelTestSuite) TearDownTest() {
+ testrig.StandardDBTeardown(suite.db)
+}
diff --git a/internal/trans/trans_test.go b/internal/trans/trans_test.go
new file mode 100644
index 000000000..5249fc6ff
--- /dev/null
+++ b/internal/trans/trans_test.go
@@ -0,0 +1,39 @@
+/*
+ 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 .
+*/
+
+package trans_test
+
+import (
+ "github.com/stretchr/testify/suite"
+ "github.com/superseriousbusiness/gotosocial/internal/db"
+ "github.com/superseriousbusiness/gotosocial/testrig"
+)
+
+type TransTestSuite struct {
+ suite.Suite
+ db db.DB
+}
+
+func (suite *TransTestSuite) SetupTest() {
+ suite.db = testrig.NewTestDB()
+ testrig.StandardDBSetup(suite.db, nil)
+}
+
+func (suite *TransTestSuite) TearDownTest() {
+ testrig.StandardDBTeardown(suite.db)
+}
diff --git a/testrig/db.go b/testrig/db.go
index 7cb4f7645..5798af5ce 100644
--- a/testrig/db.go
+++ b/testrig/db.go
@@ -72,6 +72,16 @@ func NewTestDB() db.DB {
return testDB
}
+// CreateTestTables creates prerequisite test tables in the database, but doesn't populate them.
+func CreateTestTables(db db.DB) {
+ ctx := context.Background()
+ for _, m := range testModels {
+ if err := db.CreateTable(ctx, m); err != nil {
+ logrus.Panicf("error creating table for %+v: %s", m, err)
+ }
+ }
+}
+
// StandardDBSetup populates a given db with all the necessary tables/models for perfoming tests.
//
// The accounts parameter is provided in case the db should be populated with a certain set of accounts.
@@ -85,13 +95,9 @@ func StandardDBSetup(db db.DB, accounts map[string]*gtsmodel.Account) {
logrus.Panic("db setup: db was nil")
}
- ctx := context.Background()
+ CreateTestTables(db)
- for _, m := range testModels {
- if err := db.CreateTable(ctx, m); err != nil {
- logrus.Panicf("error creating table for %+v: %s", m, err)
- }
- }
+ ctx := context.Background()
for _, v := range NewTestTokens() {
if err := db.Put(ctx, v); err != nil {
@@ -111,6 +117,12 @@ func StandardDBSetup(db db.DB, accounts map[string]*gtsmodel.Account) {
}
}
+ for _, v := range NewTestBlocks() {
+ if err := db.Put(ctx, v); err != nil {
+ logrus.Panic(err)
+ }
+ }
+
for _, v := range NewTestUsers() {
if err := db.Put(ctx, v); err != nil {
logrus.Panic(err)
diff --git a/testrig/testmodels.go b/testrig/testmodels.go
index e4daed12c..45f47f46a 100644
--- a/testrig/testmodels.go
+++ b/testrig/testmodels.go
@@ -1215,6 +1215,19 @@ func NewTestFollows() map[string]*gtsmodel.Follow {
}
}
+func NewTestBlocks() map[string]*gtsmodel.Block {
+ return map[string]*gtsmodel.Block{
+ "local_account_2_block_remote_account_1": {
+ ID: "01FEXXET6XXMF7G2V3ASZP3YQW",
+ CreatedAt: time.Now().Add(-1 * time.Hour),
+ UpdatedAt: time.Now().Add(-1 * time.Hour),
+ URI: "http://localhost:8080/users/1happyturtle/blocks/01FEXXET6XXMF7G2V3ASZP3YQW",
+ AccountID: "01F8MH5NBDF2MV7CTC4Q5128HF",
+ TargetAccountID: "01F8MH5ZK5VRH73AKHQM6Y9VNX",
+ },
+ }
+}
+
// ActivityWithSignature wraps a pub.Activity along with its signature headers, for testing.
type ActivityWithSignature struct {
Activity pub.Activity