Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ go 1.24.0

require (
github.com/PaiGramTeam/proto-contracts v0.0.0-20260416033414-4016470bc78d
github.com/glebarez/sqlite v1.11.0
github.com/go-kratos/kratos/v2 v2.9.2
github.com/go-sql-driver/mysql v1.8.1
github.com/golang-jwt/jwt/v5 v5.3.1
Expand All @@ -21,15 +22,19 @@ require (
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
github.com/dustin/go-humanize v1.0.1 // indirect
github.com/fsnotify/fsnotify v1.6.0 // indirect
github.com/glebarez/go-sqlite v1.21.2 // indirect
github.com/go-kratos/aegis v0.2.0 // indirect
github.com/go-playground/form/v4 v4.2.0 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/gorilla/mux v1.8.1 // indirect
github.com/jinzhu/inflection v1.0.0 // indirect
github.com/jinzhu/now v1.1.5 // indirect
github.com/kr/text v0.2.0 // indirect
github.com/mattn/go-isatty v0.0.17 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
go.uber.org/atomic v1.11.0 // indirect
golang.org/x/net v0.33.0 // indirect
golang.org/x/sync v0.10.0 // indirect
Expand All @@ -38,4 +43,8 @@ require (
google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
modernc.org/libc v1.22.5 // indirect
modernc.org/mathutil v1.5.0 // indirect
modernc.org/memory v1.5.0 // indirect
modernc.org/sqlite v1.23.1 // indirect
)
26 changes: 24 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,18 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
github.com/envoyproxy/go-control-plane v0.12.0 h1:4X+VP1GHd1Mhj6IB5mMeGbLCleqxjletLK6K0rbxyZI=
github.com/envoyproxy/go-control-plane v0.12.0/go.mod h1:ZBTaoJ23lqITozF0M6G4/IragXCQKCnYbmlmtHvwRG0=
github.com/envoyproxy/protoc-gen-validate v1.0.4 h1:gVPz/FMfvh57HdSJQyvBtF00j8JU4zdyUgIUNhlgg0A=
github.com/envoyproxy/protoc-gen-validate v1.0.4/go.mod h1:qys6tmnRsYrQqIhm2bvKZH4Blx/1gTIZ2UKVY1M+Yew=
github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
github.com/glebarez/go-sqlite v1.21.2 h1:3a6LFC4sKahUunAmynQKLZceZCOzUthkRkEAl9gAXWo=
github.com/glebarez/go-sqlite v1.21.2/go.mod h1:sfxdZyhQjTM2Wry3gVYWaW072Ri1WMdWJi0k6+3382k=
github.com/glebarez/sqlite v1.11.0 h1:wSG0irqzP6VurnMEpFGer5Li19RpIRi2qvQz++w0GMw=
github.com/glebarez/sqlite v1.11.0/go.mod h1:h8/o8j5wiAsqSPoWELDUdJXhjAhsVliSn7bWZjOhrgQ=
github.com/go-kratos/aegis v0.2.0 h1:dObzCDWn3XVjUkgxyBp6ZeWtx/do0DPZ7LY3yNSJLUQ=
github.com/go-kratos/aegis v0.2.0/go.mod h1:v0R2m73WgEEYB3XYu6aE2WcMwsZkJ/Rzuf5eVccm7bI=
github.com/go-kratos/kratos/v2 v2.9.2 h1:px8GJQBeLpquDKQWQ9zohEWiLA8n4D/pv7aH3asvUvo=
Expand All @@ -41,6 +47,8 @@ github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 h1:Xim43kblpZXfIBQsbuBVKCudVG457BR2GZFIz3uw3hQ=
github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26/go.mod h1:dDKJzRmX4S37WGHujM7tX//fmj1uioxKzKxz3lo4HJo=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY=
Expand All @@ -49,16 +57,21 @@ github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4=
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
github.com/klauspost/cpuid/v2 v2.2.3 h1:sxCkb+qR91z4vsqw4vGGZlDgPz3G7gjaLyK3V8y70BU=
github.com/klauspost/cpuid/v2 v2.2.3/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng=
github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/redis/go-redis/v9 v9.18.0 h1:pMkxYPkEbMPwRdenAzUNyFNrDgHx9U+DrBabWNfSRQs=
github.com/redis/go-redis/v9 v9.18.0/go.mod h1:k3ufPphLU5YXwNTUcCRXGxUoF1fqxnhFQmscfkCoDA0=
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M=
github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA=
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
Expand All @@ -71,6 +84,7 @@ golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I=
golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ=
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
Expand All @@ -93,3 +107,11 @@ gorm.io/driver/mysql v1.6.0 h1:eNbLmNTpPpTOVZi8MMxCi2aaIm0ZpInbORNXDwyLGvg=
gorm.io/driver/mysql v1.6.0/go.mod h1:D/oCC2GWK3M/dqoLxnOlaNKmXz8WNTfcS9y5ovaSqKo=
gorm.io/gorm v1.31.1 h1:7CA8FTFz/gRfgqgpeKIBcervUn3xSyPUmr6B2WXJ7kg=
gorm.io/gorm v1.31.1/go.mod h1:XyQVbO2k6YkOis7C2437jSit3SsDK72s7n7rsSHd+Gs=
modernc.org/libc v1.22.5 h1:91BNch/e5B0uPbJFgqbxXuOnxBQjlS//icfQEGmvyjE=
modernc.org/libc v1.22.5/go.mod h1:jj+Z7dTNX8fBScMVNRAYZ/jF91K8fdT2hYMThc3YjBY=
modernc.org/mathutil v1.5.0 h1:rV0Ko/6SfM+8G+yKiyI830l3Wuz1zRutdslNoQ0kfiQ=
modernc.org/mathutil v1.5.0/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
modernc.org/memory v1.5.0 h1:N+/8c5rE6EqugZwHii4IFsaJ7MUhoWX07J5tC/iI5Ds=
modernc.org/memory v1.5.0/go.mod h1:PkUhL0Mugw21sHPeskwZW4D6VscE/GQJOnIpCnW6pSU=
modernc.org/sqlite v1.23.1 h1:nrSBg4aRQQwq59JpvGEQ15tNxoO5pX/kUjcRNwSAGQM=
modernc.org/sqlite v1.23.1/go.mod h1:OrDj17Mggn6MhE+iPbBNf7RGKODDE9NFT0f3EwDzJqk=
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
ALTER TABLE account_profiles
DROP INDEX idx_profile_binding_id,
DROP COLUMN binding_id;

ALTER TABLE credential_records
DROP INDEX uniq_credential_binding_id,
DROP COLUMN binding_id;
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
ALTER TABLE credential_records
ADD COLUMN binding_id BIGINT UNSIGNED NULL AFTER id;

UPDATE credential_records
SET binding_id = CASE
WHEN platform_account_id REGEXP '^binding_[1-9][0-9]*_.+$' THEN CAST(SUBSTRING_INDEX(SUBSTRING_INDEX(platform_account_id, '_', 2), '_', -1) AS UNSIGNED)
WHEN platform_account_id REGEXP '^hoyo_ref_[1-9][0-9]*_.+$' THEN CAST(SUBSTRING_INDEX(SUBSTRING_INDEX(platform_account_id, '_', 3), '_', -1) AS UNSIGNED)
END
WHERE binding_id IS NULL;

ALTER TABLE credential_records
MODIFY COLUMN binding_id BIGINT UNSIGNED NOT NULL,
ADD UNIQUE KEY uniq_credential_binding_id (binding_id);

ALTER TABLE account_profiles
ADD COLUMN binding_id BIGINT UNSIGNED NULL AFTER id;

UPDATE account_profiles
SET binding_id = CASE
WHEN platform_account_id REGEXP '^binding_[1-9][0-9]*_.+$' THEN CAST(SUBSTRING_INDEX(SUBSTRING_INDEX(platform_account_id, '_', 2), '_', -1) AS UNSIGNED)
WHEN platform_account_id REGEXP '^hoyo_ref_[1-9][0-9]*_.+$' THEN CAST(SUBSTRING_INDEX(SUBSTRING_INDEX(platform_account_id, '_', 3), '_', -1) AS UNSIGNED)
END
WHERE binding_id IS NULL;

ALTER TABLE account_profiles
MODIFY COLUMN binding_id BIGINT UNSIGNED NOT NULL,
ADD KEY idx_profile_binding_id (binding_id);
6 changes: 4 additions & 2 deletions integration/grpc_flow_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ func TestBindThenGetAuthKeyFlow(t *testing.T) {
require.NotEmpty(t, bindResp.PlatformAccountId)
require.NotEmpty(t, bindResp.Profiles)

authResp, err := client.GetAuthKey(testTicketForAccount(t, bindResp.PlatformAccountId), bindResp.PlatformAccountId, bindResp.Profiles[0].PlayerId)
authResp, err := client.GetAuthKey(testTicketForAccount(t, bindResp.PlatformAccountId, "mihomo.authkey.issue"), bindResp.PlatformAccountId, bindResp.Profiles[0].PlayerId)
require.NoError(t, err)
require.NotEmpty(t, authResp.Authkey)
}
Expand Down Expand Up @@ -206,7 +206,7 @@ func (c *testMihomoClient) DeleteCredential(serviceTicket string, platformAccoun
})
}

func testTicket(t *testing.T) string { return testTicketForAccount(t, "") }
func testTicket(t *testing.T) string { return testTicketForAccount(t, "", "mihomo.credential.bind") }

func testTicketForAccount(t *testing.T, platformAccountID string, scopes ...string) string {
t.Helper()
Expand All @@ -217,8 +217,10 @@ func testTicketForAccount(t *testing.T, platformAccountID string, scopes ...stri
"actor_type": "bot",
"actor_id": "bot-paigram",
"owner_user_id": float64(1),
"binding_id": float64(101),
"bot_id": "bot-paigram",
"platform": "mihomo",
"user_id": float64(1),
"platform_service_key": integrationTicketAudience,
"platform_account_ref_id": float64(101),
"exp": time.Now().Add(time.Minute).Unix(),
Expand Down
64 changes: 59 additions & 5 deletions integration/migration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"path/filepath"
"runtime"
"sort"
"strings"
"testing"

"github.com/go-sql-driver/mysql"
Expand Down Expand Up @@ -38,6 +39,40 @@ func TestMigrationsCreateCoreTables(t *testing.T) {
requireTableExists(t, stack.SQLDB, stack.DatabaseCfg.Dbname, "runtime_artifacts")
}

func TestBindingMigrationRejectsUnknownLegacyPlatformAccountIDs(t *testing.T) {
stack := newIntegrationStack(t)
t.Cleanup(stack.cleanup)

applyMigrationFile(t, stack.SQLDB, migrationPath(t, "000001_create_credential_records.up.sql"))
applyMigrationFile(t, stack.SQLDB, migrationPath(t, "000003_create_account_profiles.up.sql"))

_, err := stack.SQLDB.Exec(`
INSERT INTO credential_records (
platform_account_id, platform, account_id, region, credential_blob, credential_version, status
) VALUES (?, ?, ?, ?, ?, ?, ?)
`, "legacy_10001", "mihomo", "10001", "cn_gf01", "{}", "v1", "active")
if err != nil {
t.Fatalf("insert legacy credential row: %v", err)
}

_, err = stack.SQLDB.Exec(`
INSERT INTO account_profiles (
platform_account_id, game_biz, region, player_id, nickname, level, is_default
) VALUES (?, ?, ?, ?, ?, ?, ?)
`, "legacy_10001", "hk4e_cn", "cn_gf01", "1008611", "Traveler", 1, true)
if err != nil {
t.Fatalf("insert legacy profile row: %v", err)
}

err = execMigrationFile(stack.SQLDB, migrationPath(t, "000005_add_binding_id_to_credentials_and_profiles.up.sql"))
if err == nil {
t.Fatal("expected binding migration to fail for unknown legacy platform_account_id")
}
if !strings.Contains(err.Error(), "Invalid use of NULL value") {
t.Fatalf("expected binding migration to fail on NULL binding_id backfill, got: %v", err)
}
}

func newIntegrationStack(t *testing.T) *integrationStack {
t.Helper()

Expand Down Expand Up @@ -153,16 +188,35 @@ func requireMigrationsApplied(t *testing.T, db *sql.DB) {
sort.Strings(files)

for _, path := range files {
statement, err := os.ReadFile(path)
if err != nil {
t.Fatalf("read migration %q: %v", path, err)
}
if _, err := db.Exec(string(statement)); err != nil {
if err := execMigrationFile(db, path); err != nil {
t.Fatalf("apply migration %q: %v", path, err)
}
}
}

func migrationPath(t *testing.T, name string) string {
t.Helper()
return filepath.Join(repoRoot(t), "initialize", "migrate", "sql", name)
}

func applyMigrationFile(t *testing.T, db *sql.DB, path string) {
t.Helper()
if err := execMigrationFile(db, path); err != nil {
t.Fatalf("apply migration %q: %v", path, err)
}
}

func execMigrationFile(db *sql.DB, path string) error {
statement, err := os.ReadFile(path)
if err != nil {
return fmt.Errorf("read migration %q: %w", path, err)
}
if _, err := db.Exec(string(statement)); err != nil {
return err
}
return nil
}

func requireTableExists(t *testing.T, db *sql.DB, schema string, table string) {
t.Helper()

Expand Down
2 changes: 2 additions & 0 deletions internal/biz/credential.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
)

type Credential struct {
BindingID uint64
PlatformAccountID string
Platform string
AccountID string
Expand All @@ -20,6 +21,7 @@ type Credential struct {

type CredentialRepository interface {
Save(ctx context.Context, credential *Credential) error
GetByBindingID(ctx context.Context, bindingID uint64) (*Credential, error)
GetByPlatformAccountID(ctx context.Context, platformAccountID string) (*Credential, error)
DeleteByPlatformAccountID(ctx context.Context, platformAccountID string) error
}
2 changes: 2 additions & 0 deletions internal/biz/profile.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ type ProfileIdentity struct {

type Profile struct {
ID uint64
BindingID uint64
PlatformAccountID string
GameBiz string
Region string
Expand All @@ -24,6 +25,7 @@ type Profile struct {

type ProfileRepository interface {
Save(ctx context.Context, profile *Profile) error
ListByBindingID(ctx context.Context, bindingID uint64) ([]*Profile, error)
ListByPlatformAccountID(ctx context.Context, platformAccountID string) ([]*Profile, error)
DeleteByPlatformAccountID(ctx context.Context, platformAccountID string) error
DeleteMissingByPlatformAccountID(ctx context.Context, platformAccountID string, keep []ProfileIdentity) error
Expand Down
16 changes: 12 additions & 4 deletions internal/biz/ticket.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,20 @@ type ServiceTicketClaims struct {
ActorType string
ActorID string
OwnerUserID uint64
BotID string
UserID uint64
BindingID uint64
Platform string
PlatformServiceKey string
PlatformAccountID string
PlatformAccountRefID uint64
Consumer string
ProfileID uint64
Scopes []string
Audience string
BotID string
UserID uint64
PlatformServiceKey string
PlatformAccountRefID uint64

// PlatformAccountRefID is a read-only legacy alias for BindingID so
// downstream callers can migrate incrementally. New tickets should use
// BindingID; if a token still carries platform_account_ref_id, verifier
// code requires it to match binding_id.
}
30 changes: 24 additions & 6 deletions internal/data/credential_repo.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ func NewCredentialRepo(db *gorm.DB) *CredentialRepo {

func (r *CredentialRepo) Save(ctx context.Context, credential *biz.Credential) error {
record := model.CredentialRecord{
BindingID: credential.BindingID,
PlatformAccountID: credential.PlatformAccountID,
Platform: credential.Platform,
AccountID: credential.AccountID,
Expand All @@ -34,11 +35,23 @@ func (r *CredentialRepo) Save(ctx context.Context, credential *biz.Credential) e
}

return r.db.WithContext(ctx).Clauses(clause.OnConflict{
Columns: []clause.Column{{Name: "platform_account_id"}},
Columns: []clause.Column{{Name: "binding_id"}},
UpdateAll: true,
}).Create(&record).Error
}

func (r *CredentialRepo) GetByBindingID(ctx context.Context, bindingID uint64) (*biz.Credential, error) {
var record model.CredentialRecord
if err := r.db.WithContext(ctx).Where("binding_id = ?", bindingID).Order("id asc").Take(&record).Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, nil
}
return nil, err
}

return credentialFromRecord(record), nil
}

func (r *CredentialRepo) GetByPlatformAccountID(ctx context.Context, platformAccountID string) (*biz.Credential, error) {
var record model.CredentialRecord
if err := r.db.WithContext(ctx).Where("platform_account_id = ?", platformAccountID).Take(&record).Error; err != nil {
Expand All @@ -48,7 +61,16 @@ func (r *CredentialRepo) GetByPlatformAccountID(ctx context.Context, platformAcc
return nil, err
}

return credentialFromRecord(record), nil
}

func (r *CredentialRepo) DeleteByPlatformAccountID(ctx context.Context, platformAccountID string) error {
return r.db.WithContext(ctx).Where("platform_account_id = ?", platformAccountID).Delete(&model.CredentialRecord{}).Error
}

func credentialFromRecord(record model.CredentialRecord) *biz.Credential {
return &biz.Credential{
BindingID: record.BindingID,
PlatformAccountID: record.PlatformAccountID,
Platform: record.Platform,
AccountID: record.AccountID,
Expand All @@ -59,9 +81,5 @@ func (r *CredentialRepo) GetByPlatformAccountID(ctx context.Context, platformAcc
LastValidatedAt: record.LastValidatedAt,
LastRefreshedAt: record.LastRefreshedAt,
ExpiresAt: record.ExpiresAt,
}, nil
}

func (r *CredentialRepo) DeleteByPlatformAccountID(ctx context.Context, platformAccountID string) error {
return r.db.WithContext(ctx).Where("platform_account_id = ?", platformAccountID).Delete(&model.CredentialRecord{}).Error
}
}
Loading
Loading