Skip to content

Commit

Permalink
Use Timestampz. Merged heroiclabs#175
Browse files Browse the repository at this point in the history
  • Loading branch information
mofirouz authored and zyro committed Apr 22, 2018
1 parent 093cf4a commit b9caa72
Show file tree
Hide file tree
Showing 15 changed files with 174 additions and 191 deletions.
2 changes: 1 addition & 1 deletion data/modules/match_init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,4 @@
limitations under the License.
--]]

require("nakama").match_create("match", {debug = true})
--require("nakama").match_create("match", {debug = true})
4 changes: 2 additions & 2 deletions migrate/migrate-packr.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,5 @@ import "github.com/gobuffalo/packr"
// Go binary. You can use the "packr clean" command to clean up this,
// and any other packr generated files.
func init() {
packr.PackJSONBytes("./sql", "20180103142001_initial_schema.sql", "\"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\"")
}
packr.PackJSONBytes("./sql", "20180103142001_initial_schema.sql", "\"H4sIAAAAAAAA/7RXXXPiyhF951d0+SFINzKw7N3KrXWSKhnEWlksHCTurvNCDVIjTSzNKDMjMEnlv6dGH4Awxs4mVw8uoznd09N9+kyr/1MHfoIRz3eCxomC4eDDLxAkCB55IhkBu1AJF7IDJW5KQ2QSIyhYhAJUgmDnJEywWbHgVxSScgbD3gAMDbiql67MG+1ixwvIyA4YV1BIBJVQCWuaIuBziLkCyiDkWZ5SwkKELVVJuU/tpad9PNY++EoRyoBAyPMd8PUxEIiqg06Uyj/3+9vttkfKYHtcxP20gsn+1B05nu9cD3uD2mDBUpQSBP6joAIjWO2A5HlKQ7JKEVKyBS6AxAIxAsV1wFtBFWWxBZKv1ZYI1G4iKpWgq0K18tWER2ULwBkQBle2D65/Bbe27/qWdvLNDe5miwC+2fO57QWu48NsDqOZN3YDd+b5MJuA7T3CV9cbW4BUJSgAn3OhT8AFUJ1JjMq0+YitENa8CknmGNI1DSElLC5IjBDzDQpGWQw5ioxKXVEJhEXaTUozqogqX704l96o3+lcX8PvMxoLohAWeWc0d+zAgcC+nTrgTsCbBeB8d/3A1xwQEowOAMDD3L2354/w1XkEg0am1Slf0wiOnsXCHR9+aU/eYjq1SqR2xkiG1dqv9nx0Z8+ND8NfTNA584O57XpBteeyAS+fcAcLz/3rwjlxF1GZp2S3rFw27oafPpnVOtkQRcSyEOnxdof16+uSfPJzv684T2WPolqX7EtUlvZXYf7zH0qgTvxSkfgkbh02jJ2JvZgG0EXWrdymPCzT30aX2+otsRf34MonDCaCsJDKkFswsq9KW0Uz/CdneNH2gVR8CGiGYCx8+B2MCCMRMSsnGSoSEUUqJ3/xZ97tviD7cP/17+5JOrckTVE1wHebYUZougcehwx12SpcTqTcclGT5fYxcOy91ejOGX0FI0UWq8RokCb8ET4OB4NBXa81CXHF+dOyZFybPsc7xZzHKS5rXl7AkQxDZAqFxr6OkwpJ1ri7gAsLqXj29r4YxbgMecHKZGvGw4tED5qcHIH//CcYmCfZDwUShUvNGwAI3HvHD+z7h+BvR74Y3xqndkUe/ZDdBgVd7y7bjWw/MAZg+8frp44iKrVe155+yFHHvCmlzEdV5ODvpMKsFI9ex/V8Zx7o3M4aCaORtRcgs1NVaLpwfDC6g/q5PvOneboWdLuV3czTajWZuqNAyyCMZzqkO9f7ctN5S0uXEW5oiK8qqn47mc0d94tXvS2N9C5zZ+LMHW/k+IcTmTqWsTN1Akcna2SPnTOi3GbiOVFuONsWb2hn+q2TaaaeO5fkhQh1O1ogFVFoQc4l1Qp57rx7tFmF8O5jv/AUoVSUlVL8Awncx3HmWmsnsDlNvXjrfjm09B6p1XuhRzN9q0suFHCh72bOQPCt7J1pynZTXGrK9kkvxVoW4FBf/96eTptoD9LTinotKLLIGJgWULahCo0P+38jY2hasEp5+ISR8dG0IMIU9fufTQuICBO6wcj4ZFY5rW/xY0acFOktojGu9NVX3a9Gc4tP3O/3zmcIefgkOAmTrh6GSLqTKPQgp2fZMMWNHr0YL+IEtgmylnQmRMLY8UeQ8Qh1UfTMRFmEz72XhK47xmp5sP2RBb9ZC5825tG0dJySJY1eH5fe0+g1S4rV3zFULfGoLvRTZMiZwuoeO5kYLs4Moc7yOQ6etoyHMVF0g7AhaYESiECQldALlCg25eysQ0Y96lbHu3y446K1r53XmuwtUkrFBTmvfSFPUwx1aSwQSCILnnBnNaX4P5LlsNFbeq/50Tz/+81QTwW6OvXKf0GDTf0xehzKx6H5kgZZ9Em3aKI/Iqu9eMnQqvY6sa+xqdn9QzNPleBzk5T+SMT3eqnAbw1k76PXy4HsvXYtUT2mWotkmr41e11v7Hw/Ye/Bbqlzs6zNtI4safSsGbcn+Es677XwCXf1OLb/shzzLeuM57OHQ9e0O+bm/Oqxor0C2Q8cl9arUesCQt50/hMAAP//lEWCx2ERAAA=\"")
}
59 changes: 30 additions & 29 deletions migrate/sql/20180103142001_initial_schema.sql
Original file line number Diff line number Diff line change
Expand Up @@ -36,34 +36,35 @@ CREATE TABLE IF NOT EXISTS users (
steam_id VARCHAR(128) UNIQUE,
custom_id VARCHAR(128) UNIQUE,
edge_count INT DEFAULT 0 CHECK (edge_count >= 0) NOT NULL,
create_time BIGINT CHECK (create_time > 0) NOT NULL,
update_time BIGINT CHECK (update_time > 0) NOT NULL,
verify_time BIGINT DEFAULT 0 CHECK (verify_time >= 0) NOT NULL,
disable_time BIGINT DEFAULT 0 CHECK (disable_time >= 0) NOT NULL
create_time TIMESTAMPTZ DEFAULT now() NOT NULL,
update_time TIMESTAMPTZ DEFAULT now() NOT NULL,
verify_time TIMESTAMPTZ DEFAULT CAST(0 AS TIMESTAMPTZ) NOT NULL,
disable_time TIMESTAMPTZ DEFAULT CAST(0 AS TIMESTAMPTZ) NOT NULL
);

INSERT INTO users (id, username, create_time, update_time)
VALUES ('00000000-0000-0000-0000-000000000000', '', 1, 1)
-- Setup System user.
INSERT INTO users (id, username)
VALUES ('00000000-0000-0000-0000-000000000000', '')
ON CONFLICT(id) DO NOTHING;

CREATE TABLE IF NOT EXISTS user_device (
PRIMARY KEY (id),
FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE CASCADE,

id VARCHAR(128) NOT NULL,
user_id UUID NOT NULL
id VARCHAR(128) NOT NULL,
user_id UUID NOT NULL
);

CREATE TABLE IF NOT EXISTS user_edge (
PRIMARY KEY (source_id, state, position),
FOREIGN KEY (source_id) REFERENCES users (id) ON DELETE CASCADE,
FOREIGN KEY (destination_id) REFERENCES users (id) ON DELETE CASCADE,

source_id UUID NOT NULL,
position BIGINT NOT NULL, -- Used for sort order on rows.
update_time BIGINT CHECK (update_time > 0) NOT NULL,
destination_id UUID NOT NULL,
state SMALLINT DEFAULT 0 NOT NULL, -- friend(0), invite(1), invited(2), blocked(3), deleted(4), archived(5)
source_id UUID NOT NULL,
position BIGINT NOT NULL, -- Used for sort order on rows.
update_time TIMESTAMPTZ DEFAULT now() NOT NULL,
destination_id UUID NOT NULL,
state SMALLINT DEFAULT 0 NOT NULL, -- friend(0), invite(1), invited(2), blocked(3), deleted(4), archived(5)

UNIQUE (source_id, destination_id)
);
Expand All @@ -73,28 +74,28 @@ CREATE TABLE IF NOT EXISTS notification (
PRIMARY KEY (user_id, create_time ASC, id),
FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE CASCADE,

id UUID CONSTRAINT notification_id_key UNIQUE NOT NULL,
user_id UUID NOT NULL,
subject VARCHAR(255) NOT NULL,
content JSONB DEFAULT '{}' NOT NULL,
code SMALLINT NOT NULL, -- Negative values are system reserved.
sender_id UUID, -- NULL for system messages.
create_time BIGINT CHECK (create_time > 0) NOT NULL
id UUID CONSTRAINT notification_id_key UNIQUE NOT NULL,
user_id UUID NOT NULL,
subject VARCHAR(255) NOT NULL,
content JSONB DEFAULT '{}' NOT NULL,
code SMALLINT NOT NULL, -- Negative values are system reserved.
sender_id UUID NOT NULL,
create_time TIMESTAMPTZ DEFAULT now() NOT NULL
);

CREATE TABLE IF NOT EXISTS storage (
PRIMARY KEY (collection, read, key, user_id),
FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE CASCADE,

collection VARCHAR(128) NOT NULL,
key VARCHAR(128) NOT NULL,
user_id UUID NOT NULL,
value JSONB DEFAULT '{}' NOT NULL,
version VARCHAR(32) NOT NULL, -- md5 hash of value object.
read SMALLINT DEFAULT 1 CHECK (read >= 0) NOT NULL,
write SMALLINT DEFAULT 1 CHECK (write >= 0) NOT NULL,
create_time TIMESTAMPTZ NOT NULL,
update_time TIMESTAMPTZ NOT NULL,
collection VARCHAR(128) NOT NULL,
key VARCHAR(128) NOT NULL,
user_id UUID NOT NULL,
value JSONB DEFAULT '{}' NOT NULL,
version VARCHAR(32) NOT NULL, -- md5 hash of value object.
read SMALLINT DEFAULT 1 CHECK (read >= 0) NOT NULL,
write SMALLINT DEFAULT 1 CHECK (write >= 0) NOT NULL,
create_time TIMESTAMPTZ DEFAULT now() NOT NULL,
update_time TIMESTAMPTZ DEFAULT now() NOT NULL,

UNIQUE (collection, key, user_id)
);
Expand Down
2 changes: 1 addition & 1 deletion server/api_authenticate.go
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ func (s *ApiServer) AuthenticateFacebook(ctx context.Context, in *api.Authentica

// Import friends if requested.
if in.Import == nil || in.Import.Value {
importFacebookFriends(s.logger, s.db, s.socialClient, uuid.FromStringOrNil(dbUserID), dbUsername, in.Account.Token, false)
importFacebookFriends(s.logger, s.db, s.router, s.socialClient, uuid.FromStringOrNil(dbUserID), dbUsername, in.Account.Token, false)
}

token := generateToken(s.config, dbUserID, dbUsername)
Expand Down
2 changes: 1 addition & 1 deletion server/api_friend.go
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ func (s *ApiServer) ImportFacebookFriends(ctx context.Context, in *api.ImportFac
return nil, status.Error(codes.InvalidArgument, "Facebook token is required.")
}

err := importFacebookFriends(s.logger, s.db, s.socialClient, ctx.Value(ctxUserIDKey{}).(uuid.UUID), ctx.Value(ctxUsernameKey{}).(string), in.Account.Token, in.Reset_ != nil && in.Reset_.Value)
err := importFacebookFriends(s.logger, s.db, s.router, s.socialClient, ctx.Value(ctxUserIDKey{}).(uuid.UUID), ctx.Value(ctxUsernameKey{}).(string), in.Account.Token, in.Reset_ != nil && in.Reset_.Value)
if err != nil {
// Already logged inside the core importFacebookFriends function.
return nil, err
Expand Down
42 changes: 14 additions & 28 deletions server/api_link.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ import (
"database/sql"
"strconv"
"strings"
"time"

"github.com/golang/protobuf/ptypes/empty"
"github.com/heroiclabs/nakama/api"
Expand All @@ -42,18 +41,16 @@ func (s *ApiServer) LinkCustom(ctx context.Context, in *api.AccountCustom) (*emp
}

userID := ctx.Value(ctxUserIDKey{})
ts := time.Now().UTC().Unix()
res, err := s.db.Exec(`
UPDATE users
SET custom_id = $2, update_time = $3
SET custom_id = $2, update_time = now()
WHERE (id = $1)
AND (NOT EXISTS
(SELECT id
FROM users
WHERE custom_id = $2 AND NOT id = $1))`,
userID,
customID,
ts)
customID)

if err != nil {
s.logger.Error("Could not link custom ID.", zap.Error(err), zap.Any("input", in))
Expand All @@ -77,7 +74,6 @@ func (s *ApiServer) LinkDevice(ctx context.Context, in *api.AccountDevice) (*emp

fnErr := Transact(s.logger, s.db, func(tx *sql.Tx) error {
userID := ctx.Value(ctxUserIDKey{})
ts := time.Now().UTC().Unix()

var dbDeviceIdLinkedUser int64
err := tx.QueryRow("SELECT COUNT(id) FROM user_device WHERE id = $1 AND user_id = $2 LIMIT 1", deviceID, userID).Scan(&dbDeviceIdLinkedUser)
Expand All @@ -97,7 +93,7 @@ func (s *ApiServer) LinkDevice(ctx context.Context, in *api.AccountDevice) (*emp
}
}

_, err = tx.Exec("UPDATE users SET update_time = $1 WHERE id = $2", ts, userID)
_, err = tx.Exec("UPDATE users SET update_time = now() WHERE id = $1", userID)
if err != nil {
s.logger.Error("Cannot update users table while linking.", zap.Error(err), zap.Any("input", in))
return status.Error(codes.Internal, "Error linking Device ID.")
Expand Down Expand Up @@ -129,19 +125,17 @@ func (s *ApiServer) LinkEmail(ctx context.Context, in *api.AccountEmail) (*empty
hashedPassword, _ := bcrypt.GenerateFromPassword([]byte(in.Password), bcrypt.DefaultCost)

userID := ctx.Value(ctxUserIDKey{})
ts := time.Now().UTC().Unix()
res, err := s.db.Exec(`
UPDATE users
SET email = $2, password = $3, update_time = $4
SET email = $2, password = $3, update_time = now()
WHERE (id = $1)
AND (NOT EXISTS
(SELECT id
FROM users
WHERE email = $2 AND NOT id = $1))`,
userID,
cleanEmail,
hashedPassword,
ts)
hashedPassword)

if err != nil {
s.logger.Error("Could not link email.", zap.Error(err), zap.Any("input", in))
Expand All @@ -165,18 +159,16 @@ func (s *ApiServer) LinkFacebook(ctx context.Context, in *api.LinkFacebookReques
}

userID := ctx.Value(ctxUserIDKey{})
ts := time.Now().UTC().Unix()
res, err := s.db.Exec(`
UPDATE users
SET facebook_id = $2, update_time = $3
SET facebook_id = $2, update_time = now()
WHERE (id = $1)
AND (NOT EXISTS
(SELECT id
FROM users
WHERE facebook_id = $2 AND NOT id = $1))`,
userID,
facebookProfile.ID,
ts)
facebookProfile.ID)

if err != nil {
s.logger.Error("Could not link Facebook ID.", zap.Error(err), zap.Any("input", in))
Expand All @@ -187,7 +179,7 @@ AND (NOT EXISTS

// Import friends if requested.
if in.Import == nil || in.Import.Value {
importFacebookFriends(s.logger, s.db, s.socialClient, userID.(uuid.UUID), ctx.Value(ctxUsernameKey{}).(string), in.Account.Token, false)
importFacebookFriends(s.logger, s.db, s.router, s.socialClient, userID.(uuid.UUID), ctx.Value(ctxUsernameKey{}).(string), in.Account.Token, false)
}

return &empty.Empty{}, nil
Expand Down Expand Up @@ -215,18 +207,16 @@ func (s *ApiServer) LinkGameCenter(ctx context.Context, in *api.AccountGameCente
}

userID := ctx.Value(ctxUserIDKey{})
ts := time.Now().UTC().Unix()
res, err := s.db.Exec(`
UPDATE users
SET gamecenter_id = $2, update_time = $3
SET gamecenter_id = $2, update_time = now()
WHERE (id = $1)
AND (NOT EXISTS
(SELECT id
FROM users
WHERE gamecenter_id = $2 AND NOT id = $1))`,
userID,
in.PlayerId,
ts)
in.PlayerId)

if err != nil {
s.logger.Error("Could not link GameCenter ID.", zap.Error(err), zap.Any("input", in))
Expand All @@ -250,18 +240,16 @@ func (s *ApiServer) LinkGoogle(ctx context.Context, in *api.AccountGoogle) (*emp
}

userID := ctx.Value(ctxUserIDKey{})
ts := time.Now().UTC().Unix()
res, err := s.db.Exec(`
UPDATE users
SET google_id = $2, update_time = $3
SET google_id = $2, update_time = now()
WHERE (id = $1)
AND (NOT EXISTS
(SELECT id
FROM users
WHERE google_id = $2 AND NOT id = $1))`,
userID,
googleProfile.Sub,
ts)
googleProfile.Sub)

if err != nil {
s.logger.Error("Could not link Google ID.", zap.Error(err), zap.Any("input", in))
Expand Down Expand Up @@ -289,18 +277,16 @@ func (s *ApiServer) LinkSteam(ctx context.Context, in *api.AccountSteam) (*empty
}

userID := ctx.Value(ctxUserIDKey{})
ts := time.Now().UTC().Unix()
res, err := s.db.Exec(`
UPDATE users
SET steam_id = $2, update_time = $3
SET steam_id = $2, update_time = now()
WHERE (id = $1)
AND (NOT EXISTS
(SELECT id
FROM users
WHERE steam_id = $2 AND NOT id = $1))`,
userID,
strconv.FormatUint(steamProfile.SteamID, 10),
ts)
strconv.FormatUint(steamProfile.SteamID, 10))

if err != nil {
s.logger.Error("Could not link Steam ID.", zap.Error(err), zap.Any("input", in))
Expand Down
Loading

0 comments on commit b9caa72

Please sign in to comment.