start with export/import code

This commit is contained in:
tsmethurst 2021-09-06 18:52:25 +02:00
commit 2ec36349c7
12 changed files with 460 additions and 6 deletions

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
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,
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
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
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
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{})
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
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"`
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
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{})
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
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"`
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
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{})
}

View file

@ -0,0 +1,3 @@
package trans

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
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)
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
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)
}