Skip to content

Commit

Permalink
Add delete account client function.
Browse files Browse the repository at this point in the history
  • Loading branch information
ftkg authored and zyro committed Dec 19, 2022
1 parent fa2b725 commit c7200ba
Show file tree
Hide file tree
Showing 17 changed files with 1,732 additions and 1,600 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ The format is based on [keep a changelog](http://keepachangelog.com) and this pr
- Allow devconsole group view to add new members.
- Allow `DELETE` and `HEAD` methods in runtime HTTP request functions.
- Add In-App Purchase notification callback functions to runtimes.
- Add `DeleteAccount` client API function.
- Add `DeleteAccount` before and after hook functions to runtimes.

### Changed
- Stricter validation of limit in runtime storage list operations.
Expand Down
1,246 changes: 627 additions & 619 deletions apigrpc/apigrpc.pb.go

Large diffs are not rendered by default.

1,849 changes: 877 additions & 972 deletions apigrpc/apigrpc.pb.gw.go

Large diffs are not rendered by default.

5 changes: 5 additions & 0 deletions apigrpc/apigrpc.proto
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,11 @@ service Nakama {
};
}

// Delete the current user's account.
rpc DeleteAccount (google.protobuf.Empty) returns (google.protobuf.Empty) {
option (google.api.http).delete = "/v2/account";
}

// Delete one or more users by ID or username.
rpc DeleteFriends (api.DeleteFriendsRequest) returns (google.protobuf.Empty) {
option (google.api.http).delete = "/v2/friend";
Expand Down
21 changes: 21 additions & 0 deletions apigrpc/apigrpc.swagger.json
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,27 @@
"Nakama"
]
},
"delete": {
"summary": "Delete the current user's account.",
"operationId": "Nakama_DeleteAccount",
"responses": {
"200": {
"description": "A successful response.",
"schema": {
"properties": {}
}
},
"default": {
"description": "An unexpected error response.",
"schema": {
"$ref": "#/definitions/rpcStatus"
}
}
},
"tags": [
"Nakama"
]
},
"put": {
"summary": "Update fields in the current user's account.",
"operationId": "Nakama_UpdateAccount",
Expand Down
38 changes: 38 additions & 0 deletions apigrpc/apigrpc_grpc.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 1 addition & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ require (
github.com/gorilla/mux v1.8.0
github.com/gorilla/websocket v1.5.0
github.com/grpc-ecosystem/grpc-gateway/v2 v2.11.3
github.com/heroiclabs/nakama-common v1.25.1-0.20221216144801-a8d20fc7642c
github.com/heroiclabs/nakama-common v1.25.1-0.20221219151417-cdbd41fec766
github.com/jackc/pgconn v1.13.0
github.com/jackc/pgerrcode v0.0.0-20220416144525-469b46aa5efa
github.com/jackc/pgtype v1.12.0
Expand All @@ -24,7 +24,6 @@ require (
go.uber.org/atomic v1.10.0
go.uber.org/zap v1.23.0
golang.org/x/crypto v0.0.0-20221012134737-56aed061732a
golang.org/x/oauth2 v0.0.0-20221006150949-b44042a4b9c1
google.golang.org/genproto v0.0.0-20220822174746-9e6da59bd2fc
google.golang.org/grpc v1.50.0
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.2.0
Expand Down
6 changes: 2 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -285,8 +285,8 @@ github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO
github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ=
github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I=
github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
github.com/heroiclabs/nakama-common v1.25.1-0.20221216144801-a8d20fc7642c h1:lt0PG4F50Ij0lQvsVmHH64BtWcwozEc2w4BN6g0BAto=
github.com/heroiclabs/nakama-common v1.25.1-0.20221216144801-a8d20fc7642c/go.mod h1:zdYggBBPmykSfz4zYFJmBDX5wyURSPAGANtJPEDdbx8=
github.com/heroiclabs/nakama-common v1.25.1-0.20221219151417-cdbd41fec766 h1:4vYyKXKYyf8KAIJYYuyREGapuutHlWzRsMFZNdUqlGQ=
github.com/heroiclabs/nakama-common v1.25.1-0.20221219151417-cdbd41fec766/go.mod h1:zdYggBBPmykSfz4zYFJmBDX5wyURSPAGANtJPEDdbx8=
github.com/huandu/xstrings v1.3.1/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
github.com/huandu/xstrings v1.3.2/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
Expand Down Expand Up @@ -676,8 +676,6 @@ golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ
golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20221006150949-b44042a4b9c1 h1:3VPzK7eqH25j7GYw5w6g/GzNRc0/fYtrxz27z1gD4W0=
golang.org/x/oauth2 v0.0.0-20221006150949-b44042a4b9c1/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
Expand Down
2 changes: 2 additions & 0 deletions server/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ type ApiServer struct {
leaderboardCache LeaderboardCache
leaderboardRankCache LeaderboardRankCache
sessionCache SessionCache
sessionRegistry SessionRegistry
statusRegistry *StatusRegistry
matchRegistry MatchRegistry
tracker Tracker
Expand Down Expand Up @@ -119,6 +120,7 @@ func StartApiServer(logger *zap.Logger, startupLogger *zap.Logger, db *sql.DB, p
leaderboardCache: leaderboardCache,
leaderboardRankCache: leaderboardRankCache,
sessionCache: sessionCache,
sessionRegistry: sessionRegistry,
statusRegistry: statusRegistry,
matchRegistry: matchRegistry,
tracker: tracker,
Expand Down
52 changes: 52 additions & 0 deletions server/api_account.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,58 @@ func (s *ApiServer) GetAccount(ctx context.Context, in *emptypb.Empty) (*api.Acc
return account, nil
}

func (s *ApiServer) DeleteAccount(ctx context.Context, in *emptypb.Empty) (*emptypb.Empty, error) {
userID := ctx.Value(ctxUserIDKey{}).(uuid.UUID)

// Before hook.
if fn := s.runtime.BeforeDeleteAccount(); fn != nil {
beforeFn := func(clientIP, clientPort string) error {
err, code := fn(ctx, s.logger, userID.String(), ctx.Value(ctxUsernameKey{}).(string), ctx.Value(ctxVarsKey{}).(map[string]string), ctx.Value(ctxExpiryKey{}).(int64), clientIP, clientPort)
if err != nil {
return status.Error(code, err.Error())
}
// Empty input never overridden.
return nil
}

// Execute the before function lambda wrapped in a trace for stats measurement.
err := traceApiBefore(ctx, s.logger, s.metrics, ctx.Value(ctxFullMethodKey{}).(string), beforeFn)
if err != nil {
return nil, err
}
}

if err := DeleteAccount(ctx, s.logger, s.db, s.leaderboardRankCache, userID, false); err != nil {
if err == ErrAccountNotFound {
return nil, status.Error(codes.NotFound, "Account not found.")
}
return nil, status.Error(codes.Internal, "Error deleting user account.")
}
// Logout and disconnect.
err := SessionLogout(s.config, s.sessionCache, userID, "", "")
if err != nil {
return nil, err
}
for _, presence := range s.tracker.ListPresenceIDByStream(PresenceStream{Mode: StreamModeNotifications, Subject: userID}) {
err = s.sessionRegistry.Disconnect(ctx, presence.SessionID)
if err != nil {
return nil, err
}
}

// After hook.
if fn := s.runtime.AfterDeleteAccount(); fn != nil {
afterFn := func(clientIP, clientPort string) error {
return fn(ctx, s.logger, userID.String(), ctx.Value(ctxUsernameKey{}).(string), ctx.Value(ctxVarsKey{}).(map[string]string), ctx.Value(ctxExpiryKey{}).(int64), clientIP, clientPort)
}

// Execute the after function lambda wrapped in a trace for stats measurement.
traceApiAfter(ctx, s.logger, s.metrics, ctx.Value(ctxFullMethodKey{}).(string), afterFn)
}

return &emptypb.Empty{}, nil
}

func (s *ApiServer) UpdateAccount(ctx context.Context, in *api.UpdateAccountRequest) (*emptypb.Empty, error) {
userID := ctx.Value(ctxUserIDKey{}).(uuid.UUID)

Expand Down
34 changes: 34 additions & 0 deletions server/runtime.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ type (
RuntimeAfterGetAccountFunction func(ctx context.Context, logger *zap.Logger, userID, username string, vars map[string]string, expiry int64, clientIP, clientPort string, out *api.Account) error
RuntimeBeforeUpdateAccountFunction func(ctx context.Context, logger *zap.Logger, userID, username string, vars map[string]string, expiry int64, clientIP, clientPort string, in *api.UpdateAccountRequest) (*api.UpdateAccountRequest, error, codes.Code)
RuntimeAfterUpdateAccountFunction func(ctx context.Context, logger *zap.Logger, userID, username string, vars map[string]string, expiry int64, clientIP, clientPort string, in *api.UpdateAccountRequest) error
RuntimeBeforeDeleteAccountFunction func(ctx context.Context, logger *zap.Logger, userID, username string, vars map[string]string, expiry int64, clientIP, clientPort string) (error, codes.Code)
RuntimeAfterDeleteAccountFunction func(ctx context.Context, logger *zap.Logger, userID, username string, vars map[string]string, expiry int64, clientIP, clientPort string) error
RuntimeBeforeSessionRefreshFunction func(ctx context.Context, logger *zap.Logger, userID, username string, vars map[string]string, expiry int64, clientIP, clientPort string, in *api.SessionRefreshRequest) (*api.SessionRefreshRequest, error, codes.Code)
RuntimeAfterSessionRefreshFunction func(ctx context.Context, logger *zap.Logger, userID, username string, vars map[string]string, expiry int64, clientIP, clientPort string, out *api.Session, in *api.SessionRefreshRequest) error
RuntimeBeforeSessionLogoutFunction func(ctx context.Context, logger *zap.Logger, userID, username string, vars map[string]string, expiry int64, clientIP, clientPort string, in *api.SessionLogoutRequest) (*api.SessionLogoutRequest, error, codes.Code)
Expand Down Expand Up @@ -323,6 +325,7 @@ type RuntimeInfo struct {
type RuntimeBeforeReqFunctions struct {
beforeGetAccountFunction RuntimeBeforeGetAccountFunction
beforeUpdateAccountFunction RuntimeBeforeUpdateAccountFunction
beforeDeleteAccountFunction RuntimeBeforeDeleteAccountFunction
beforeSessionRefreshFunction RuntimeBeforeSessionRefreshFunction
beforeSessionLogoutFunction RuntimeBeforeSessionLogoutFunction
beforeAuthenticateAppleFunction RuntimeBeforeAuthenticateAppleFunction
Expand Down Expand Up @@ -402,6 +405,7 @@ type RuntimeBeforeReqFunctions struct {
type RuntimeAfterReqFunctions struct {
afterGetAccountFunction RuntimeAfterGetAccountFunction
afterUpdateAccountFunction RuntimeAfterUpdateAccountFunction
afterDeleteAccountFunction RuntimeAfterDeleteAccountFunction
afterSessionRefreshFunction RuntimeAfterSessionRefreshFunction
afterSessionLogoutFunction RuntimeAfterSessionLogoutFunction
afterAuthenticateAppleFunction RuntimeAfterAuthenticateAppleFunction
Expand Down Expand Up @@ -717,6 +721,9 @@ func NewRuntime(ctx context.Context, logger, startupLogger *zap.Logger, db *sql.
if allBeforeReqFunctions.beforeUpdateAccountFunction != nil {
startupLogger.Info("Registered JavaScript runtime Before function invocation", zap.String("id", "updateaccount"))
}
if allBeforeReqFunctions.beforeDeleteAccountFunction != nil {
startupLogger.Info("Registered JavaScript runtime Before function invocation", zap.String("id", "deleteaccount"))
}
if allBeforeReqFunctions.beforeSessionRefreshFunction != nil {
startupLogger.Info("Registered JavaScript runtime Before function invocation", zap.String("id", "sessionrefresh"))
}
Expand Down Expand Up @@ -949,6 +956,10 @@ func NewRuntime(ctx context.Context, logger, startupLogger *zap.Logger, db *sql.
allBeforeReqFunctions.beforeUpdateAccountFunction = luaBeforeReqFns.beforeUpdateAccountFunction
startupLogger.Info("Registered Lua runtime Before function invocation", zap.String("id", "updateaccount"))
}
if luaBeforeReqFns.beforeDeleteAccountFunction != nil {
allBeforeReqFunctions.beforeDeleteAccountFunction = luaBeforeReqFns.beforeDeleteAccountFunction
startupLogger.Info("Registered Lua runtime Before function invocation", zap.String("id", "deleteaccount"))
}
if luaBeforeReqFns.beforeSessionRefreshFunction != nil {
allBeforeReqFunctions.beforeSessionRefreshFunction = luaBeforeReqFns.beforeSessionRefreshFunction
startupLogger.Info("Registered Lua runtime Before function invocation", zap.String("id", "sessionrefresh"))
Expand Down Expand Up @@ -1251,6 +1262,10 @@ func NewRuntime(ctx context.Context, logger, startupLogger *zap.Logger, db *sql.
allBeforeReqFunctions.beforeUpdateAccountFunction = goBeforeReqFns.beforeUpdateAccountFunction
startupLogger.Info("Registered Go runtime Before function invocation", zap.String("id", "updateaccount"))
}
if goBeforeReqFns.beforeDeleteAccountFunction != nil {
allBeforeReqFunctions.beforeDeleteAccountFunction = goBeforeReqFns.beforeDeleteAccountFunction
startupLogger.Info("Registered Go runtime Before function invocation", zap.String("id", "deleteaccount"))
}
if goBeforeReqFns.beforeSessionRefreshFunction != nil {
allBeforeReqFunctions.beforeSessionRefreshFunction = goBeforeReqFns.beforeSessionRefreshFunction
startupLogger.Info("Registered Go runtime Before function invocation", zap.String("id", "sessionrefresh"))
Expand Down Expand Up @@ -1556,6 +1571,9 @@ func NewRuntime(ctx context.Context, logger, startupLogger *zap.Logger, db *sql.
if allAfterReqFunctions.afterUpdateAccountFunction != nil {
startupLogger.Info("Registered JavaScript runtime After function invocation", zap.String("id", "updateaccount"))
}
if allAfterReqFunctions.afterDeleteAccountFunction != nil {
startupLogger.Info("Registered JavaScript runtime After function invocation", zap.String("id", "deleteaccount"))
}
if allAfterReqFunctions.afterSessionRefreshFunction != nil {
startupLogger.Info("Registered JavaScript runtime After function invocation", zap.String("id", "sessionrefresh"))
}
Expand Down Expand Up @@ -1788,6 +1806,10 @@ func NewRuntime(ctx context.Context, logger, startupLogger *zap.Logger, db *sql.
allAfterReqFunctions.afterUpdateAccountFunction = luaAfterReqFns.afterUpdateAccountFunction
startupLogger.Info("Registered Lua runtime After function invocation", zap.String("id", "updateaccount"))
}
if luaAfterReqFns.afterDeleteAccountFunction != nil {
allAfterReqFunctions.afterDeleteAccountFunction = luaAfterReqFns.afterDeleteAccountFunction
startupLogger.Info("Registered Lua runtime After function invocation", zap.String("id", "deleteaccount"))
}
if luaAfterReqFns.afterSessionRefreshFunction != nil {
allAfterReqFunctions.afterSessionRefreshFunction = luaAfterReqFns.afterSessionRefreshFunction
startupLogger.Info("Registered Lua runtime After function invocation", zap.String("id", "sessionrefresh"))
Expand Down Expand Up @@ -2090,6 +2112,10 @@ func NewRuntime(ctx context.Context, logger, startupLogger *zap.Logger, db *sql.
allAfterReqFunctions.afterUpdateAccountFunction = goAfterReqFns.afterUpdateAccountFunction
startupLogger.Info("Registered Go runtime After function invocation", zap.String("id", "updateaccount"))
}
if goAfterReqFns.afterDeleteAccountFunction != nil {
allAfterReqFunctions.afterDeleteAccountFunction = goAfterReqFns.afterDeleteAccountFunction
startupLogger.Info("Registered Go runtime After function invocation", zap.String("id", "deleteaccount"))
}
if goAfterReqFns.afterSessionRefreshFunction != nil {
allAfterReqFunctions.afterSessionRefreshFunction = goAfterReqFns.afterSessionRefreshFunction
startupLogger.Info("Registered Go runtime After function invocation", zap.String("id", "sessionrefresh"))
Expand Down Expand Up @@ -2621,6 +2647,14 @@ func (r *Runtime) AfterUpdateAccount() RuntimeAfterUpdateAccountFunction {
return r.afterReqFunctions.afterUpdateAccountFunction
}

func (r *Runtime) BeforeDeleteAccount() RuntimeBeforeDeleteAccountFunction {
return r.beforeReqFunctions.beforeDeleteAccountFunction
}

func (r *Runtime) AfterDeleteAccount() RuntimeAfterDeleteAccountFunction {
return r.afterReqFunctions.afterDeleteAccountFunction
}

func (r *Runtime) BeforeSessionRefresh() RuntimeBeforeSessionRefreshFunction {
return r.beforeReqFunctions.beforeSessionRefreshFunction
}
Expand Down
Loading

0 comments on commit c7200ba

Please sign in to comment.