Stabilize SAM repositroy.
- aligned repository code, db schema and spec.json - add (not -short) tests for SAM repository
This commit is contained in:
@@ -2,8 +2,10 @@
|
||||
CREATE TABLE organisations (
|
||||
id BIGINT UNSIGNED NOT NULL,
|
||||
fqn TEXT NOT NULL, -- fully qualified name of the organisation
|
||||
label TEXT NOT NULL, -- display name of the organisation
|
||||
name TEXT NOT NULL, -- display name of the organisation
|
||||
|
||||
created_at DATETIME NOT NULL DEFAULT NOW(),
|
||||
updated_at DATETIME NULL,
|
||||
archived_at DATETIME NULL,
|
||||
deleted_at DATETIME NULL, -- organisation soft delete
|
||||
|
||||
@@ -13,9 +15,11 @@ CREATE TABLE organisations (
|
||||
-- Keeps all known teams
|
||||
CREATE TABLE teams (
|
||||
id BIGINT UNSIGNED NOT NULL,
|
||||
label TEXT NOT NULL, -- display name of the team
|
||||
name TEXT NOT NULL, -- display name of the team
|
||||
handle TEXT NOT NULL, -- team handle string
|
||||
|
||||
created_at DATETIME NOT NULL DEFAULT NOW(),
|
||||
updated_at DATETIME NULL,
|
||||
archived_at DATETIME NULL,
|
||||
deleted_at DATETIME NULL, -- team soft delete
|
||||
|
||||
@@ -28,6 +32,8 @@ CREATE TABLE channels (
|
||||
name TEXT NOT NULL, -- display name of the channel
|
||||
meta JSON NOT NULL,
|
||||
|
||||
created_at DATETIME NOT NULL DEFAULT NOW(),
|
||||
updated_at DATETIME NULL,
|
||||
archived_at DATETIME NULL,
|
||||
deleted_at DATETIME NULL, -- channel soft delete
|
||||
|
||||
@@ -46,6 +52,8 @@ CREATE TABLE users (
|
||||
|
||||
rel_organisation BIGINT UNSIGNED NOT NULL REFERENCES organisation(id),
|
||||
|
||||
created_at DATETIME NOT NULL DEFAULT NOW(),
|
||||
updated_at DATETIME NULL,
|
||||
suspended_at DATETIME NULL,
|
||||
deleted_at DATETIME NULL, -- user soft delete
|
||||
|
||||
@@ -69,6 +77,8 @@ CREATE TABLE channel_members (
|
||||
messages_since DATETIME NULL,
|
||||
messages_until DATETIME NULL,
|
||||
|
||||
created_at DATETIME NOT NULL DEFAULT NOW(),
|
||||
|
||||
PRIMARY KEY (rel_channel, rel_user)
|
||||
);
|
||||
|
||||
@@ -87,49 +97,57 @@ CREATE TABLE channel_views (
|
||||
|
||||
CREATE TABLE channel_pins (
|
||||
rel_channel BIGINT UNSIGNED NOT NULL REFERENCES channels(id),
|
||||
rel_message BIGINT UNSIGNED NULL REFERENCES messages(id),
|
||||
rel_message BIGINT UNSIGNED NOT NULL REFERENCES messages(id),
|
||||
rel_user BIGINT UNSIGNED NOT NULL REFERENCES users(id),
|
||||
|
||||
created_at DATETIME NOT NULL DEFAULT NOW(),
|
||||
|
||||
PRIMARY KEY (rel_channel, rel_message)
|
||||
);
|
||||
|
||||
CREATE TABLE messages (
|
||||
id BIGINT UNSIGNED NOT NULL,
|
||||
id BIGINT UNSIGNED NOT NULL,
|
||||
type TEXT,
|
||||
message TEXT NOT NULL,
|
||||
message TEXT NOT NULL,
|
||||
meta JSON,
|
||||
rel_user BIGINT UNSIGNED NOT NULL REFERENCES users(id),
|
||||
rel_channel BIGINT UNSIGNED NOT NULL REFERENCES channels(id),
|
||||
reply_to BIGINT UNSIGNED NULL REFERENCES messages(id),
|
||||
rel_user BIGINT UNSIGNED NOT NULL REFERENCES users(id),
|
||||
rel_channel BIGINT UNSIGNED NOT NULL REFERENCES channels(id),
|
||||
reply_to BIGINT UNSIGNED NULL REFERENCES messages(id),
|
||||
|
||||
updated_at DATETIME NULL,
|
||||
deleted_at DATETIME NULL,
|
||||
created_at DATETIME NOT NULL DEFAULT NOW(),
|
||||
updated_at DATETIME NULL,
|
||||
deleted_at DATETIME NULL,
|
||||
|
||||
PRIMARY KEY (id)
|
||||
);
|
||||
|
||||
CREATE TABLE reactions (
|
||||
id BIGINT UNSIGNED NOT NULL,
|
||||
rel_user BIGINT UNSIGNED NOT NULL REFERENCES users(id),
|
||||
rel_message BIGINT UNSIGNED NOT NULL REFERENCES messages(id),
|
||||
rel_channel BIGINT UNSIGNED NOT NULL REFERENCES channels(id),
|
||||
reaction TEXT NOT NULL,
|
||||
id BIGINT UNSIGNED NOT NULL,
|
||||
rel_user BIGINT UNSIGNED NOT NULL REFERENCES users(id),
|
||||
rel_message BIGINT UNSIGNED NOT NULL REFERENCES messages(id),
|
||||
rel_channel BIGINT UNSIGNED NOT NULL REFERENCES channels(id),
|
||||
reaction TEXT NOT NULL,
|
||||
|
||||
created_at DATETIME NOT NULL DEFAULT NOW(),
|
||||
|
||||
PRIMARY KEY (id)
|
||||
);
|
||||
|
||||
CREATE TABLE attachments (
|
||||
id BIGINT UNSIGNED NOT NULL,
|
||||
rel_user BIGINT UNSIGNED NOT NULL REFERENCES users(id),
|
||||
rel_message BIGINT UNSIGNED NOT NULL REFERENCES messages(id),
|
||||
rel_channel BIGINT UNSIGNED NOT NULL REFERENCES channels(id),
|
||||
url TEXT NOT NULL,
|
||||
preview_url TEXT NOT NULL,
|
||||
size INT UNSIGNED NOT NULL,
|
||||
mimetype TEXT NOT NULL,
|
||||
name TEXT NOT NULL,
|
||||
attachment JSON NOT NULL,
|
||||
deleted_at DATETIME NULL,
|
||||
id BIGINT UNSIGNED NOT NULL,
|
||||
rel_user BIGINT UNSIGNED NOT NULL REFERENCES users(id),
|
||||
rel_message BIGINT UNSIGNED NOT NULL REFERENCES messages(id),
|
||||
rel_channel BIGINT UNSIGNED NOT NULL REFERENCES channels(id),
|
||||
url TEXT,
|
||||
preview_url TEXT,
|
||||
size INT UNSIGNED,
|
||||
mimetype TEXT,
|
||||
name TEXT,
|
||||
attachment JSON NOT NULL,
|
||||
|
||||
created_at DATETIME NOT NULL DEFAULT NOW(),
|
||||
updated_at DATETIME NULL,
|
||||
deleted_at DATETIME NULL,
|
||||
|
||||
PRIMARY KEY (id)
|
||||
);
|
||||
|
||||
+38
-15
@@ -11,10 +11,14 @@
|
||||
"name": "Organisation",
|
||||
"imports": ["time"],
|
||||
"fields": [
|
||||
{ "name": "ID", "type": "uint64" },
|
||||
{ "name": "ID", "type": "uint64" },
|
||||
{ "name": "FQN", "type": "string", "dbname": "fqn" },
|
||||
{ "name": "Name", "type": "string" },
|
||||
{ "type": "*time.Time", "name": "ArchivedAt", "tag": "json:\",omitempty\"", "complex": true },
|
||||
{ "type": "*time.Time", "name": "DeletedAt", "tag": "json:\",omitempty\"", "complex": true }
|
||||
|
||||
{ "name": "CreatedAt", "type": "time.Time", "tag": "json:\"created_at,omitempty\"", "complex": true },
|
||||
{ "name": "UpdatedAt", "type": "*time.Time", "tag": "json:\"updated_at,omitempty\"", "complex": true },
|
||||
{ "name": "ArchivedAt", "type": "*time.Time", "tag": "json:\"archived_at,omitempty\"", "complex": true },
|
||||
{ "name": "DeletedAt", "type": "*time.Time", "tag": "json:\"deleted_at,omitempty\"", "complex": true }
|
||||
]
|
||||
}
|
||||
],
|
||||
@@ -104,10 +108,12 @@
|
||||
"fields": [
|
||||
{ "type": "uint64", "name": "ID" },
|
||||
{ "type": "string", "name": "Name" },
|
||||
{ "type": "[]uint64", "name": "MemberIDs", "tag": "json:\"-\"", "complex": true },
|
||||
{ "type": "[]User", "name": "Members", "tag": "json:\",omitempty\"", "complex": true },
|
||||
{ "type": "*time.Time", "name": "ArchivedAt", "tag": "json:\",omitempty\"", "complex": true },
|
||||
{ "type": "*time.Time", "name": "DeletedAt", "tag": "json:\",omitempty\"", "complex": true }
|
||||
{ "type": "string", "name": "Handle" },
|
||||
|
||||
{ "name": "CreatedAt", "type": "time.Time", "tag": "json:\"created_at,omitempty\"", "complex": true },
|
||||
{ "name": "UpdatedAt", "type": "*time.Time", "tag": "json:\"updated_at,omitempty\"", "complex": true },
|
||||
{ "name": "ArchivedAt", "type": "*time.Time", "tag": "json:\"archived_at,omitempty\"", "complex": true },
|
||||
{ "name": "DeletedAt", "type": "*time.Time", "tag": "json:\"deleted_at,omitempty\"", "complex": true }
|
||||
]
|
||||
}
|
||||
],
|
||||
@@ -233,8 +239,11 @@
|
||||
{ "type": "string", "name": "Topic", "dbname": "-" },
|
||||
{ "type": "json.RawMessage", "name": "Meta", "complex": true},
|
||||
{ "type": "uint64", "name": "LastMessageID", "tag": "json:\",omitempty\"", "dbname": "rel_last_message" },
|
||||
{ "type": "*time.Time", "name": "ArchivedAt", "tag": "json:\",omitempty\"", "complex": true },
|
||||
{ "type": "*time.Time", "name": "DeletedAt", "tag": "json:\",omitempty\"", "complex": true }
|
||||
|
||||
{ "name": "CreatedAt", "type": "time.Time", "tag": "json:\"created_at,omitempty\"", "complex": true },
|
||||
{ "name": "UpdatedAt", "type": "*time.Time", "tag": "json:\"updated_at,omitempty\"", "complex": true },
|
||||
{ "name": "ArchivedAt", "type": "*time.Time", "tag": "json:\"archived_at,omitempty\"", "complex": true },
|
||||
{ "name": "DeletedAt", "type": "*time.Time", "tag": "json:\"deleted_at,omitempty\"", "complex": true }
|
||||
]
|
||||
}
|
||||
],
|
||||
@@ -325,9 +334,10 @@
|
||||
{ "name": "UserID", "type": "uint64", "dbname": "rel_user" },
|
||||
{ "name": "ChannelID", "type": "uint64", "dbname": "rel_channel"},
|
||||
{ "name": "ReplyTo", "type": "uint64", "dbname": "reply_to" },
|
||||
{ "name": "UpdatedAt", "type": "*time.Time", "tag": "json:\",omitempty\"", "complex": true },
|
||||
{ "name": "DeletedAt", "type": "*time.Time", "tag": "json:\",omitempty\"", "complex": true }
|
||||
|
||||
{ "name": "CreatedAt", "type": "time.Time", "tag": "json:\"created_at,omitempty\"", "complex": true },
|
||||
{ "name": "UpdatedAt", "type": "*time.Time", "tag": "json:\"updated_at,omitempty\"", "complex": true },
|
||||
{ "name": "DeletedAt", "type": "*time.Time", "tag": "json:\"deleted_at,omitempty\"", "complex": true }
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -339,7 +349,8 @@
|
||||
{ "name": "MessageID", "type": "uint64", "dbname": "rel_message"},
|
||||
{ "name": "ChannelID", "type": "uint64", "dbname": "rel_channel"},
|
||||
{ "name": "Reaction", "type": "string" },
|
||||
{ "name": "DeletedAt", "type": "*time.Time", "tag": "json:\",omitempty\"", "complex": true }
|
||||
|
||||
{ "name": "CreatedAt", "type": "time.Time", "tag": "json:\"created_at,omitempty\"", "complex": true }
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -351,7 +362,16 @@
|
||||
{ "name": "MessageID", "type": "uint64", "dbname": "rel_message"},
|
||||
{ "name": "ChannelID", "type": "uint64", "dbname": "rel_channel"},
|
||||
{ "name": "Attachment", "type": "json.RawMessage" , "complex": true},
|
||||
{ "name": "DeletedAt", "type": "*time.Time", "tag": "json:\",omitempty\"", "complex": true }
|
||||
|
||||
{ "name": "Url", "type": "string" },
|
||||
{ "name": "PreviewUrl", "type": "string" },
|
||||
{ "name": "Size", "type": "uint" },
|
||||
{ "name": "Mimetype", "type": "string" },
|
||||
{ "name": "Name", "type": "string" },
|
||||
|
||||
{ "name": "CreatedAt", "type": "time.Time", "tag": "json:\"created_at,omitempty\"", "complex": true },
|
||||
{ "name": "UpdatedAt", "type": "*time.Time", "tag": "json:\"updated_at,omitempty\"", "complex": true },
|
||||
{ "name": "DeletedAt", "type": "*time.Time", "tag": "json:\"deleted_at,omitempty\"", "complex": true }
|
||||
]
|
||||
}
|
||||
],
|
||||
@@ -521,8 +541,11 @@
|
||||
{ "type": "interface{}", "name": "Meta", "tag": "json:\"-\"" },
|
||||
{ "type": "uint64", "name": "OrganisationID", "dbname": "rel_organisation" },
|
||||
{ "type": "[]byte", "name": "Password", "tag": "json:\"-\"", "complex": true },
|
||||
{ "type": "*time.Time", "name": "SuspendedAt", "tag": "json:\",omitempty\"", "complex": true },
|
||||
{ "type": "*time.Time", "name": "DeletedAt", "tag": "json:\",omitempty\"", "complex": true }
|
||||
|
||||
{ "name": "CreatedAt", "type": "time.Time", "tag": "json:\"created_at,omitempty\"", "complex": true },
|
||||
{ "name": "UpdatedAt", "type": "*time.Time", "tag": "json:\"updated_at,omitempty\"", "complex": true },
|
||||
{ "name": "SuspendedAt","type": "*time.Time", "tag": "json:\"suspended_at,omitempty\"","complex": true },
|
||||
{ "name": "DeletedAt", "type": "*time.Time", "tag": "json:\"deleted_at,omitempty\"", "complex": true }
|
||||
]
|
||||
}
|
||||
],
|
||||
|
||||
@@ -30,16 +30,28 @@
|
||||
"tag": "json:\",omitempty\"",
|
||||
"type": "uint64"
|
||||
},
|
||||
{
|
||||
"complex": true,
|
||||
"name": "CreatedAt",
|
||||
"tag": "json:\"created_at,omitempty\"",
|
||||
"type": "time.Time"
|
||||
},
|
||||
{
|
||||
"complex": true,
|
||||
"name": "UpdatedAt",
|
||||
"tag": "json:\"updated_at,omitempty\"",
|
||||
"type": "*time.Time"
|
||||
},
|
||||
{
|
||||
"complex": true,
|
||||
"name": "ArchivedAt",
|
||||
"tag": "json:\",omitempty\"",
|
||||
"tag": "json:\"archived_at,omitempty\"",
|
||||
"type": "*time.Time"
|
||||
},
|
||||
{
|
||||
"complex": true,
|
||||
"name": "DeletedAt",
|
||||
"tag": "json:\",omitempty\"",
|
||||
"tag": "json:\"deleted_at,omitempty\"",
|
||||
"type": "*time.Time"
|
||||
}
|
||||
],
|
||||
|
||||
@@ -32,16 +32,22 @@
|
||||
"name": "ReplyTo",
|
||||
"type": "uint64"
|
||||
},
|
||||
{
|
||||
"complex": true,
|
||||
"name": "CreatedAt",
|
||||
"tag": "json:\"created_at,omitempty\"",
|
||||
"type": "time.Time"
|
||||
},
|
||||
{
|
||||
"complex": true,
|
||||
"name": "UpdatedAt",
|
||||
"tag": "json:\",omitempty\"",
|
||||
"tag": "json:\"updated_at,omitempty\"",
|
||||
"type": "*time.Time"
|
||||
},
|
||||
{
|
||||
"complex": true,
|
||||
"name": "DeletedAt",
|
||||
"tag": "json:\",omitempty\"",
|
||||
"tag": "json:\"deleted_at,omitempty\"",
|
||||
"type": "*time.Time"
|
||||
}
|
||||
],
|
||||
@@ -77,9 +83,9 @@
|
||||
},
|
||||
{
|
||||
"complex": true,
|
||||
"name": "DeletedAt",
|
||||
"tag": "json:\",omitempty\"",
|
||||
"type": "*time.Time"
|
||||
"name": "CreatedAt",
|
||||
"tag": "json:\"created_at,omitempty\"",
|
||||
"type": "time.Time"
|
||||
}
|
||||
],
|
||||
"imports": [
|
||||
@@ -113,10 +119,42 @@
|
||||
"name": "Attachment",
|
||||
"type": "json.RawMessage"
|
||||
},
|
||||
{
|
||||
"name": "Url",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "PreviewUrl",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "Size",
|
||||
"type": "uint"
|
||||
},
|
||||
{
|
||||
"name": "Mimetype",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "Name",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"complex": true,
|
||||
"name": "CreatedAt",
|
||||
"tag": "json:\"created_at,omitempty\"",
|
||||
"type": "time.Time"
|
||||
},
|
||||
{
|
||||
"complex": true,
|
||||
"name": "UpdatedAt",
|
||||
"tag": "json:\"updated_at,omitempty\"",
|
||||
"type": "*time.Time"
|
||||
},
|
||||
{
|
||||
"complex": true,
|
||||
"name": "DeletedAt",
|
||||
"tag": "json:\",omitempty\"",
|
||||
"tag": "json:\"deleted_at,omitempty\"",
|
||||
"type": "*time.Time"
|
||||
}
|
||||
],
|
||||
|
||||
@@ -10,20 +10,37 @@
|
||||
"name": "ID",
|
||||
"type": "uint64"
|
||||
},
|
||||
{
|
||||
"dbname": "fqn",
|
||||
"name": "FQN",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "Name",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"complex": true,
|
||||
"name": "CreatedAt",
|
||||
"tag": "json:\"created_at,omitempty\"",
|
||||
"type": "time.Time"
|
||||
},
|
||||
{
|
||||
"complex": true,
|
||||
"name": "UpdatedAt",
|
||||
"tag": "json:\"updated_at,omitempty\"",
|
||||
"type": "*time.Time"
|
||||
},
|
||||
{
|
||||
"complex": true,
|
||||
"name": "ArchivedAt",
|
||||
"tag": "json:\",omitempty\"",
|
||||
"tag": "json:\"archived_at,omitempty\"",
|
||||
"type": "*time.Time"
|
||||
},
|
||||
{
|
||||
"complex": true,
|
||||
"name": "DeletedAt",
|
||||
"tag": "json:\",omitempty\"",
|
||||
"tag": "json:\"deleted_at,omitempty\"",
|
||||
"type": "*time.Time"
|
||||
}
|
||||
],
|
||||
|
||||
@@ -15,27 +15,31 @@
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"complex": true,
|
||||
"name": "MemberIDs",
|
||||
"tag": "json:\"-\"",
|
||||
"type": "[]uint64"
|
||||
"name": "Handle",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"complex": true,
|
||||
"name": "Members",
|
||||
"tag": "json:\",omitempty\"",
|
||||
"type": "[]User"
|
||||
"name": "CreatedAt",
|
||||
"tag": "json:\"created_at,omitempty\"",
|
||||
"type": "time.Time"
|
||||
},
|
||||
{
|
||||
"complex": true,
|
||||
"name": "UpdatedAt",
|
||||
"tag": "json:\"updated_at,omitempty\"",
|
||||
"type": "*time.Time"
|
||||
},
|
||||
{
|
||||
"complex": true,
|
||||
"name": "ArchivedAt",
|
||||
"tag": "json:\",omitempty\"",
|
||||
"tag": "json:\"archived_at,omitempty\"",
|
||||
"type": "*time.Time"
|
||||
},
|
||||
{
|
||||
"complex": true,
|
||||
"name": "DeletedAt",
|
||||
"tag": "json:\",omitempty\"",
|
||||
"tag": "json:\"deleted_at,omitempty\"",
|
||||
"type": "*time.Time"
|
||||
}
|
||||
],
|
||||
|
||||
@@ -29,16 +29,28 @@
|
||||
"tag": "json:\"-\"",
|
||||
"type": "[]byte"
|
||||
},
|
||||
{
|
||||
"complex": true,
|
||||
"name": "CreatedAt",
|
||||
"tag": "json:\"created_at,omitempty\"",
|
||||
"type": "time.Time"
|
||||
},
|
||||
{
|
||||
"complex": true,
|
||||
"name": "UpdatedAt",
|
||||
"tag": "json:\"updated_at,omitempty\"",
|
||||
"type": "*time.Time"
|
||||
},
|
||||
{
|
||||
"complex": true,
|
||||
"name": "SuspendedAt",
|
||||
"tag": "json:\",omitempty\"",
|
||||
"tag": "json:\"suspended_at,omitempty\"",
|
||||
"type": "*time.Time"
|
||||
},
|
||||
{
|
||||
"complex": true,
|
||||
"name": "DeletedAt",
|
||||
"tag": "json:\",omitempty\"",
|
||||
"tag": "json:\"deleted_at,omitempty\"",
|
||||
"type": "*time.Time"
|
||||
}
|
||||
],
|
||||
|
||||
@@ -4,10 +4,11 @@ import (
|
||||
"context"
|
||||
"github.com/crusttech/crust/sam/types"
|
||||
"github.com/titpetric/factory"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
sqlAttachmentScope = "deleted_at IS NULL AND archived_at IS NULL"
|
||||
sqlAttachmentScope = "deleted_at IS NULL"
|
||||
|
||||
ErrAttachmentNotFound = repositoryError("AttachmentNotFound")
|
||||
)
|
||||
@@ -25,7 +26,7 @@ func (r attachment) FindByID(ctx context.Context, id uint64) (*types.Attachment,
|
||||
|
||||
mod := &types.Attachment{}
|
||||
if err := db.GetContext(ctx, mod, "SELECT * FROM attachments WHERE id = ? AND "+sqlAttachmentScope, id); err != nil {
|
||||
return nil, ErrDatabaseError
|
||||
return nil, err
|
||||
} else if mod.ID == 0 {
|
||||
return nil, ErrAttachmentNotFound
|
||||
} else {
|
||||
@@ -39,13 +40,13 @@ func (r attachment) FindByRange(ctx context.Context, channelID, fromAttachmentID
|
||||
sql := `
|
||||
SELECT *
|
||||
FROM attachments
|
||||
WHERE rel_attachment BETWEEN ? AND ?
|
||||
WHERE id BETWEEN ? AND ?
|
||||
AND rel_channel = ?
|
||||
AND deleted_at IS NULL`
|
||||
|
||||
rval := make([]*types.Attachment, 0)
|
||||
if err := db.Select(&rval, sql, fromAttachmentID, toAttachmentID, channelID); err != nil {
|
||||
return nil, ErrDatabaseError
|
||||
if err := db.SelectContext(ctx, &rval, sql, fromAttachmentID, toAttachmentID, channelID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return rval, nil
|
||||
@@ -55,8 +56,14 @@ func (r attachment) Create(ctx context.Context, mod *types.Attachment) (*types.A
|
||||
db := factory.Database.MustGet()
|
||||
|
||||
mod.SetID(factory.Sonyflake.NextID())
|
||||
mod.SetCreatedAt(time.Now())
|
||||
|
||||
if mod.Attachment == nil {
|
||||
mod.SetAttachment([]byte("{}"))
|
||||
}
|
||||
|
||||
if err := db.Insert("attachments", mod); err != nil {
|
||||
return nil, ErrDatabaseError
|
||||
return nil, err
|
||||
} else {
|
||||
return mod, nil
|
||||
}
|
||||
@@ -65,8 +72,11 @@ func (r attachment) Create(ctx context.Context, mod *types.Attachment) (*types.A
|
||||
func (r attachment) Update(ctx context.Context, mod *types.Attachment) (*types.Attachment, error) {
|
||||
db := factory.Database.MustGet()
|
||||
|
||||
now := time.Now()
|
||||
mod.SetUpdatedAt(&now)
|
||||
|
||||
if err := db.Replace("attachments", mod); err != nil {
|
||||
return nil, ErrDatabaseError
|
||||
return nil, err
|
||||
} else {
|
||||
return mod, nil
|
||||
}
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
package repository
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/crusttech/crust/sam/types"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestAttachment(t *testing.T) {
|
||||
var err error
|
||||
|
||||
if testing.Short() {
|
||||
t.Skip("skipping test in short mode.")
|
||||
return
|
||||
}
|
||||
|
||||
rpo := Attachment()
|
||||
ctx := context.Background()
|
||||
att := types.Attachment{}.New()
|
||||
|
||||
var aa []*types.Attachment
|
||||
|
||||
att.SetChannelID(1)
|
||||
|
||||
att, err = rpo.Create(ctx, att)
|
||||
must(t, err)
|
||||
if att.ChannelID != 1 {
|
||||
t.Fatal("Changes were not stored")
|
||||
}
|
||||
|
||||
att.SetChannelID(2)
|
||||
|
||||
att, err = rpo.Update(ctx, att)
|
||||
must(t, err)
|
||||
if att.ChannelID != 2 {
|
||||
t.Fatal("Changes were not stored")
|
||||
}
|
||||
|
||||
att, err = rpo.FindByID(ctx, att.ID)
|
||||
must(t, err)
|
||||
if att.ChannelID != 2 {
|
||||
t.Fatal("Changes were not stored")
|
||||
}
|
||||
|
||||
aa, err = rpo.FindByRange(ctx, 2, 0, att.ID)
|
||||
must(t, err)
|
||||
if len(aa) == 0 {
|
||||
t.Fatal("No results found")
|
||||
}
|
||||
|
||||
must(t, rpo.Delete(ctx, att.ID))
|
||||
}
|
||||
@@ -25,8 +25,8 @@ func (r channel) FindByID(ctx context.Context, id uint64) (*types.Channel, error
|
||||
db := factory.Database.MustGet()
|
||||
|
||||
mod := &types.Channel{}
|
||||
if err := db.Get(mod, "SELECT * FROM channels WHERE id = ? AND "+sqlChannelScope, id); err != nil {
|
||||
return nil, ErrDatabaseError
|
||||
if err := db.GetContext(ctx, mod, "SELECT * FROM channels WHERE id = ? AND "+sqlChannelScope, id); err != nil {
|
||||
return nil, err
|
||||
} else if mod.ID == 0 {
|
||||
return nil, ErrChannelNotFound
|
||||
} else {
|
||||
@@ -42,7 +42,7 @@ func (r channel) Find(ctx context.Context, filter *types.ChannelFilter) ([]*type
|
||||
|
||||
if filter != nil {
|
||||
if filter.Query != "" {
|
||||
sql += "AND name LIKE ?"
|
||||
sql += " AND name LIKE ?"
|
||||
params = append(params, filter.Query+"%")
|
||||
}
|
||||
}
|
||||
@@ -50,8 +50,8 @@ func (r channel) Find(ctx context.Context, filter *types.ChannelFilter) ([]*type
|
||||
sql += " ORDER BY name ASC"
|
||||
|
||||
rval := make([]*types.Channel, 0)
|
||||
if err := db.Select(&rval, sql, params...); err != nil {
|
||||
return nil, ErrDatabaseError
|
||||
if err := db.SelectContext(ctx, &rval, sql, params...); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
return rval, nil
|
||||
}
|
||||
@@ -61,8 +61,14 @@ func (r channel) Create(ctx context.Context, mod *types.Channel) (*types.Channel
|
||||
db := factory.Database.MustGet()
|
||||
|
||||
mod.SetID(factory.Sonyflake.NextID())
|
||||
mod.SetCreatedAt(time.Now())
|
||||
|
||||
if mod.Meta == nil {
|
||||
mod.SetMeta([]byte("{}"))
|
||||
}
|
||||
|
||||
if err := db.Insert("channels", mod); err != nil {
|
||||
return nil, ErrDatabaseError
|
||||
return nil, err
|
||||
} else {
|
||||
return mod, nil
|
||||
}
|
||||
@@ -71,8 +77,11 @@ func (r channel) Create(ctx context.Context, mod *types.Channel) (*types.Channel
|
||||
func (r channel) Update(ctx context.Context, mod *types.Channel) (*types.Channel, error) {
|
||||
db := factory.Database.MustGet()
|
||||
|
||||
now := time.Now()
|
||||
mod.SetUpdatedAt(&now)
|
||||
|
||||
if err := db.Replace("channels", mod); err != nil {
|
||||
return nil, ErrDatabaseError
|
||||
return nil, err
|
||||
} else {
|
||||
return mod, nil
|
||||
}
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
package repository
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/crusttech/crust/sam/types"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestChannel(t *testing.T) {
|
||||
var err error
|
||||
|
||||
if testing.Short() {
|
||||
t.Skip("skipping test in short mode.")
|
||||
return
|
||||
}
|
||||
|
||||
rpo := Channel()
|
||||
ctx := context.Background()
|
||||
att := types.Channel{}.New()
|
||||
|
||||
var name1, name2 = "Test channel v1", "Test channel v2"
|
||||
|
||||
var aa []*types.Channel
|
||||
|
||||
att.SetName(name1)
|
||||
|
||||
att, err = rpo.Create(ctx, att)
|
||||
must(t, err)
|
||||
if att.Name != name1 {
|
||||
t.Fatal("Changes were not stored")
|
||||
}
|
||||
|
||||
att.SetName(name2)
|
||||
|
||||
att, err = rpo.Update(ctx, att)
|
||||
must(t, err)
|
||||
if att.Name != name2 {
|
||||
t.Fatal("Changes were not stored")
|
||||
}
|
||||
|
||||
att, err = rpo.FindByID(ctx, att.ID)
|
||||
must(t, err)
|
||||
if att.Name != name2 {
|
||||
t.Fatal("Changes were not stored")
|
||||
}
|
||||
|
||||
aa, err = rpo.Find(ctx, &types.ChannelFilter{Query: name2})
|
||||
must(t, err)
|
||||
if len(aa) == 0 {
|
||||
t.Fatal("No results found")
|
||||
}
|
||||
|
||||
must(t, rpo.Archive(ctx, att.ID))
|
||||
must(t, rpo.Unarchive(ctx, att.ID))
|
||||
must(t, rpo.Delete(ctx, att.ID))
|
||||
}
|
||||
@@ -6,26 +6,20 @@ import (
|
||||
"github.com/titpetric/factory"
|
||||
)
|
||||
|
||||
func simpleUpdate(ctx context.Context, tableName, columnName string, value interface{}, id uint64) error {
|
||||
func simpleUpdate(ctx context.Context, tableName, columnName string, value interface{}, id uint64) (err error) {
|
||||
db := factory.Database.MustGet()
|
||||
|
||||
sql := fmt.Sprintf("UPDATE %s SET %s = ? WHERE id = ?", tableName, columnName)
|
||||
|
||||
if _, err := db.ExecContext(ctx, sql, value, id); err != nil {
|
||||
return ErrDatabaseError
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
_, err = db.ExecContext(ctx, sql, value, id)
|
||||
return err
|
||||
}
|
||||
|
||||
func simpleDelete(ctx context.Context, tableName string, id uint64) error {
|
||||
func simpleDelete(ctx context.Context, tableName string, id uint64) (err error) {
|
||||
db := factory.Database.MustGet()
|
||||
|
||||
sql := fmt.Sprintf("DELETE %s WHERE id = ?", tableName)
|
||||
sql := fmt.Sprintf("DELETE FROM %s WHERE id = ?", tableName)
|
||||
|
||||
if _, err := db.ExecContext(ctx, sql, id); err != nil {
|
||||
return ErrDatabaseError
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
_, err = db.ExecContext(ctx, sql, id)
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
package repository
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"github.com/joho/godotenv"
|
||||
_ "github.com/joho/godotenv"
|
||||
"github.com/titpetric/factory"
|
||||
"os"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
flag.Parse()
|
||||
|
||||
if testing.Short() {
|
||||
return
|
||||
}
|
||||
|
||||
// @todo this is a very optimistic initialization, make it more robust
|
||||
godotenv.Load("../../.env")
|
||||
factory.Database.Add("default", os.Getenv("SAM_DB_DSN"))
|
||||
factory.Database.MustGet().Profiler = &factory.Database.ProfilerStdout
|
||||
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
|
||||
func must(t *testing.T, err error) {
|
||||
if err != nil {
|
||||
t.Fatalf("Error: %v", err)
|
||||
}
|
||||
}
|
||||
@@ -3,8 +3,8 @@ package repository
|
||||
import (
|
||||
"context"
|
||||
"github.com/crusttech/crust/sam/types"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/titpetric/factory"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -28,7 +28,7 @@ func (r message) FindByID(ctx context.Context, id uint64) (*types.Message, error
|
||||
|
||||
mod := &types.Message{}
|
||||
if err := db.GetContext(ctx, mod, sql, id); err != nil {
|
||||
return nil, errors.Wrap(err, ErrDatabaseError.String())
|
||||
return nil, err
|
||||
} else if mod.ID == 0 {
|
||||
return nil, ErrMessageNotFound
|
||||
} else {
|
||||
@@ -44,7 +44,7 @@ func (r message) Find(ctx context.Context, filter *types.MessageFilter) ([]*type
|
||||
|
||||
if filter != nil {
|
||||
if filter.Query != "" {
|
||||
sql += "AND name LIKE ?"
|
||||
sql += " AND message LIKE ?"
|
||||
params = append(params, filter.Query+"%")
|
||||
}
|
||||
}
|
||||
@@ -74,7 +74,7 @@ func (r message) Find(ctx context.Context, filter *types.MessageFilter) ([]*type
|
||||
|
||||
rval := make([]*types.Message, 0)
|
||||
if err := db.SelectContext(ctx, &rval, sql, params...); err != nil {
|
||||
return nil, errors.Wrap(err, ErrDatabaseError.String())
|
||||
return nil, err
|
||||
} else {
|
||||
return rval, nil
|
||||
}
|
||||
@@ -84,8 +84,10 @@ func (r message) Create(ctx context.Context, mod *types.Message) (*types.Message
|
||||
db := factory.Database.MustGet()
|
||||
|
||||
mod.SetID(factory.Sonyflake.NextID())
|
||||
mod.SetCreatedAt(time.Now())
|
||||
|
||||
if err := db.Insert("messages", mod); err != nil {
|
||||
return nil, ErrDatabaseError
|
||||
return nil, err
|
||||
} else {
|
||||
return mod, nil
|
||||
}
|
||||
@@ -94,8 +96,11 @@ func (r message) Create(ctx context.Context, mod *types.Message) (*types.Message
|
||||
func (r message) Update(ctx context.Context, mod *types.Message) (*types.Message, error) {
|
||||
db := factory.Database.MustGet()
|
||||
|
||||
now := time.Now()
|
||||
mod.SetUpdatedAt(&now)
|
||||
|
||||
if err := db.Replace("messages", mod); err != nil {
|
||||
return nil, ErrDatabaseError
|
||||
return nil, err
|
||||
} else {
|
||||
return mod, nil
|
||||
}
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
package repository
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/crusttech/crust/sam/types"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestMessage(t *testing.T) {
|
||||
var err error
|
||||
|
||||
if testing.Short() {
|
||||
t.Skip("skipping test in short mode.")
|
||||
return
|
||||
}
|
||||
|
||||
rpo := Message()
|
||||
ctx := context.Background()
|
||||
att := types.Message{}.New()
|
||||
|
||||
var msg1, msg2 = "Test message v1", "Test message v2"
|
||||
|
||||
var aa []*types.Message
|
||||
|
||||
att.SetMessage(msg1)
|
||||
|
||||
att, err = rpo.Create(ctx, att)
|
||||
must(t, err)
|
||||
if att.Message != msg1 {
|
||||
t.Fatal("Changes were not stored")
|
||||
}
|
||||
|
||||
att.SetMessage(msg2)
|
||||
|
||||
att, err = rpo.Update(ctx, att)
|
||||
must(t, err)
|
||||
if att.Message != msg2 {
|
||||
t.Fatal("Changes were not stored")
|
||||
}
|
||||
|
||||
att, err = rpo.FindByID(ctx, att.ID)
|
||||
must(t, err)
|
||||
if att.Message != msg2 {
|
||||
t.Fatal("Changes were not stored")
|
||||
}
|
||||
|
||||
aa, err = rpo.Find(ctx, &types.MessageFilter{Query: msg2})
|
||||
must(t, err)
|
||||
if len(aa) == 0 {
|
||||
t.Fatal("No results found")
|
||||
}
|
||||
|
||||
must(t, rpo.Delete(ctx, att.ID))
|
||||
}
|
||||
@@ -26,7 +26,7 @@ func (r organisation) FindByID(ctx context.Context, id uint64) (*types.Organisat
|
||||
|
||||
mod := &types.Organisation{}
|
||||
if err := db.Get(mod, "SELECT * FROM organisations WHERE id = ? AND "+sqlOrganisationScope, id); err != nil {
|
||||
return nil, ErrDatabaseError
|
||||
return nil, err
|
||||
} else if mod.ID == 0 {
|
||||
return nil, ErrOrganisationNotFound
|
||||
} else {
|
||||
@@ -42,7 +42,7 @@ func (r organisation) Find(ctx context.Context, filter *types.OrganisationFilter
|
||||
|
||||
if filter != nil {
|
||||
if filter.Query != "" {
|
||||
sql += "AND ame LIKE ?"
|
||||
sql += " AND name LIKE ?"
|
||||
params = append(params, filter.Query+"%")
|
||||
}
|
||||
}
|
||||
@@ -51,7 +51,7 @@ func (r organisation) Find(ctx context.Context, filter *types.OrganisationFilter
|
||||
|
||||
rval := make([]*types.Organisation, 0)
|
||||
if err := db.Select(&rval, sql, params...); err != nil {
|
||||
return nil, ErrDatabaseError
|
||||
return nil, err
|
||||
} else {
|
||||
return rval, nil
|
||||
}
|
||||
@@ -61,8 +61,10 @@ func (r organisation) Create(ctx context.Context, mod *types.Organisation) (*typ
|
||||
db := factory.Database.MustGet()
|
||||
|
||||
mod.SetID(factory.Sonyflake.NextID())
|
||||
mod.SetCreatedAt(time.Now())
|
||||
|
||||
if err := db.Insert("organisations", mod); err != nil {
|
||||
return nil, ErrDatabaseError
|
||||
return nil, err
|
||||
} else {
|
||||
return mod, nil
|
||||
}
|
||||
@@ -71,8 +73,11 @@ func (r organisation) Create(ctx context.Context, mod *types.Organisation) (*typ
|
||||
func (r organisation) Update(ctx context.Context, mod *types.Organisation) (*types.Organisation, error) {
|
||||
db := factory.Database.MustGet()
|
||||
|
||||
now := time.Now()
|
||||
mod.SetUpdatedAt(&now)
|
||||
|
||||
if err := db.Replace("organisations", mod); err != nil {
|
||||
return nil, ErrDatabaseError
|
||||
return nil, err
|
||||
} else {
|
||||
return mod, nil
|
||||
}
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
package repository
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/crusttech/crust/sam/types"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestOrganisation(t *testing.T) {
|
||||
var err error
|
||||
|
||||
if testing.Short() {
|
||||
t.Skip("skipping test in short mode.")
|
||||
return
|
||||
}
|
||||
|
||||
rpo := Organisation()
|
||||
ctx := context.Background()
|
||||
att := types.Organisation{}.New()
|
||||
|
||||
var name1, name2 = "Test organisation v1", "Test organisation v2"
|
||||
|
||||
var aa []*types.Organisation
|
||||
|
||||
att.SetName(name1)
|
||||
|
||||
att, err = rpo.Create(ctx, att)
|
||||
must(t, err)
|
||||
if att.Name != name1 {
|
||||
t.Fatal("Changes were not stored")
|
||||
}
|
||||
|
||||
att.SetName(name2)
|
||||
|
||||
att, err = rpo.Update(ctx, att)
|
||||
must(t, err)
|
||||
if att.Name != name2 {
|
||||
t.Fatal("Changes were not stored")
|
||||
}
|
||||
|
||||
att, err = rpo.FindByID(ctx, att.ID)
|
||||
must(t, err)
|
||||
if att.Name != name2 {
|
||||
t.Fatal("Changes were not stored")
|
||||
}
|
||||
|
||||
aa, err = rpo.Find(ctx, &types.OrganisationFilter{Query: name2})
|
||||
must(t, err)
|
||||
if len(aa) == 0 {
|
||||
t.Fatal("No results found")
|
||||
}
|
||||
|
||||
must(t, rpo.Archive(ctx, att.ID))
|
||||
must(t, rpo.Unarchive(ctx, att.ID))
|
||||
must(t, rpo.Delete(ctx, att.ID))
|
||||
}
|
||||
@@ -4,11 +4,10 @@ import (
|
||||
"context"
|
||||
"github.com/crusttech/crust/sam/types"
|
||||
"github.com/titpetric/factory"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
sqlReactionScope = "deleted_at IS NULL AND archived_at IS NULL"
|
||||
|
||||
ErrReactionNotFound = repositoryError("ReactionNotFound")
|
||||
)
|
||||
|
||||
@@ -24,8 +23,8 @@ func (r reaction) FindByID(ctx context.Context, id uint64) (*types.Reaction, err
|
||||
db := factory.Database.MustGet()
|
||||
|
||||
mod := &types.Reaction{}
|
||||
if err := db.GetContext(ctx, mod, "SELECT * FROM reactions WHERE id = ? AND "+sqlReactionScope, id); err != nil {
|
||||
return nil, ErrDatabaseError
|
||||
if err := db.GetContext(ctx, mod, "SELECT * FROM reactions WHERE id = ?", id); err != nil {
|
||||
return nil, err
|
||||
} else if mod.ID == 0 {
|
||||
return nil, ErrReactionNotFound
|
||||
} else {
|
||||
@@ -44,7 +43,7 @@ func (r reaction) FindByRange(ctx context.Context, channelID, fromReactionID, to
|
||||
|
||||
rval := make([]*types.Reaction, 0)
|
||||
if err := db.Select(&rval, sql, fromReactionID, toReactionID, channelID); err != nil {
|
||||
return nil, ErrDatabaseError
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return rval, nil
|
||||
@@ -54,8 +53,10 @@ func (r reaction) Create(ctx context.Context, mod *types.Reaction) (*types.React
|
||||
db := factory.Database.MustGet()
|
||||
|
||||
mod.SetID(factory.Sonyflake.NextID())
|
||||
mod.SetCreatedAt(time.Now())
|
||||
|
||||
if err := db.Insert("reactions", mod); err != nil {
|
||||
return nil, ErrDatabaseError
|
||||
return nil, err
|
||||
} else {
|
||||
return mod, nil
|
||||
}
|
||||
@@ -65,7 +66,7 @@ func (r reaction) Delete(ctx context.Context, id uint64) error {
|
||||
db := factory.Database.MustGet()
|
||||
|
||||
if _, err := db.ExecContext(ctx, "DELETE FROM reactions WHERE id = ?", id); err != nil {
|
||||
return ErrDatabaseError
|
||||
return err
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
package repository
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/crusttech/crust/sam/types"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestReaction(t *testing.T) {
|
||||
var err error
|
||||
|
||||
if testing.Short() {
|
||||
t.Skip("skipping test in short mode.")
|
||||
return
|
||||
}
|
||||
|
||||
rpo := Reaction()
|
||||
ctx := context.Background()
|
||||
att := types.Reaction{}.New()
|
||||
|
||||
var reaction = ":laugh:"
|
||||
|
||||
att.SetReaction(reaction)
|
||||
|
||||
att, err = rpo.Create(ctx, att)
|
||||
must(t, err)
|
||||
if att.Reaction != reaction {
|
||||
t.Fatal("Changes were not stored")
|
||||
}
|
||||
|
||||
att, err = rpo.FindByID(ctx, att.ID)
|
||||
must(t, err)
|
||||
if att.Reaction != reaction {
|
||||
t.Fatal("Changes were not stored")
|
||||
}
|
||||
|
||||
must(t, rpo.Delete(ctx, att.ID))
|
||||
}
|
||||
+10
-5
@@ -26,7 +26,7 @@ func (r team) FindByID(ctx context.Context, id uint64) (*types.Team, error) {
|
||||
|
||||
mod := &types.Team{}
|
||||
if err := db.Get(mod, "SELECT * FROM teams WHERE id = ? AND "+sqlTeamScope, id); err != nil {
|
||||
return nil, ErrDatabaseError
|
||||
return nil, err
|
||||
} else if mod.ID == 0 {
|
||||
return nil, ErrTeamNotFound
|
||||
} else {
|
||||
@@ -42,7 +42,7 @@ func (r team) Find(ctx context.Context, filter *types.TeamFilter) ([]*types.Team
|
||||
|
||||
if filter != nil {
|
||||
if filter.Query != "" {
|
||||
sql += "AND name LIKE ?"
|
||||
sql += " AND name LIKE ?"
|
||||
params = append(params, filter.Query+"%")
|
||||
}
|
||||
}
|
||||
@@ -51,7 +51,7 @@ func (r team) Find(ctx context.Context, filter *types.TeamFilter) ([]*types.Team
|
||||
|
||||
rval := make([]*types.Team, 0)
|
||||
if err := db.Select(&rval, sql, params...); err != nil {
|
||||
return nil, ErrDatabaseError
|
||||
return nil, err
|
||||
} else {
|
||||
return rval, nil
|
||||
}
|
||||
@@ -61,8 +61,10 @@ func (r team) Create(ctx context.Context, mod *types.Team) (*types.Team, error)
|
||||
db := factory.Database.MustGet()
|
||||
|
||||
mod.SetID(factory.Sonyflake.NextID())
|
||||
mod.SetCreatedAt(time.Now())
|
||||
|
||||
if err := db.Insert("teams", mod); err != nil {
|
||||
return nil, ErrDatabaseError
|
||||
return nil, err
|
||||
} else {
|
||||
return mod, nil
|
||||
}
|
||||
@@ -71,8 +73,11 @@ func (r team) Create(ctx context.Context, mod *types.Team) (*types.Team, error)
|
||||
func (r team) Update(ctx context.Context, mod *types.Team) (*types.Team, error) {
|
||||
db := factory.Database.MustGet()
|
||||
|
||||
now := time.Now()
|
||||
mod.SetUpdatedAt(&now)
|
||||
|
||||
if err := db.Replace("teams", mod); err != nil {
|
||||
return nil, ErrDatabaseError
|
||||
return nil, err
|
||||
} else {
|
||||
return mod, nil
|
||||
}
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
package repository
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/crusttech/crust/sam/types"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestTeam(t *testing.T) {
|
||||
var err error
|
||||
|
||||
if testing.Short() {
|
||||
t.Skip("skipping test in short mode.")
|
||||
return
|
||||
}
|
||||
|
||||
rpo := Team()
|
||||
ctx := context.Background()
|
||||
att := types.Team{}.New()
|
||||
|
||||
var name1, name2 = "Test team v1", "Test team v2"
|
||||
|
||||
var aa []*types.Team
|
||||
|
||||
att.SetName(name1)
|
||||
|
||||
att, err = rpo.Create(ctx, att)
|
||||
must(t, err)
|
||||
if att.Name != name1 {
|
||||
t.Fatal("Changes were not stored")
|
||||
}
|
||||
|
||||
att.SetName(name2)
|
||||
|
||||
att, err = rpo.Update(ctx, att)
|
||||
must(t, err)
|
||||
if att.Name != name2 {
|
||||
t.Fatal("Changes were not stored")
|
||||
}
|
||||
|
||||
att, err = rpo.FindByID(ctx, att.ID)
|
||||
must(t, err)
|
||||
if att.Name != name2 {
|
||||
t.Fatal("Changes were not stored")
|
||||
}
|
||||
|
||||
aa, err = rpo.Find(ctx, &types.TeamFilter{Query: name2})
|
||||
must(t, err)
|
||||
if len(aa) == 0 {
|
||||
t.Fatal("No results found")
|
||||
}
|
||||
|
||||
must(t, rpo.Archive(ctx, att.ID))
|
||||
must(t, rpo.Unarchive(ctx, att.ID))
|
||||
must(t, rpo.Delete(ctx, att.ID))
|
||||
}
|
||||
+15
-6
@@ -27,7 +27,7 @@ func (r user) FindByUsername(ctx context.Context, username string) (*types.User,
|
||||
|
||||
mod := &types.User{}
|
||||
if err := db.Get(mod, "SELECT * FROM users WHERE username = ? AND "+sqlUserScope, username); err != nil {
|
||||
return nil, ErrDatabaseError
|
||||
return nil, err
|
||||
} else if mod.ID == 0 {
|
||||
return nil, ErrUserNotFound
|
||||
} else {
|
||||
@@ -40,7 +40,7 @@ func (r user) FindByID(ctx context.Context, id uint64) (*types.User, error) {
|
||||
|
||||
mod := &types.User{}
|
||||
if err := db.Get(mod, "SELECT * FROM users WHERE id = ? AND "+sqlUserScope, id); err != nil {
|
||||
return nil, ErrDatabaseError
|
||||
return nil, err
|
||||
} else if mod.ID == 0 {
|
||||
return nil, ErrUserNotFound
|
||||
} else {
|
||||
@@ -56,7 +56,7 @@ func (r user) Find(ctx context.Context, filter *types.UserFilter) ([]*types.User
|
||||
|
||||
if filter != nil {
|
||||
if filter.Query != "" {
|
||||
sql += "AND username LIKE ?"
|
||||
sql += " AND username LIKE ?"
|
||||
params = append(params, filter.Query+"%")
|
||||
}
|
||||
}
|
||||
@@ -65,7 +65,7 @@ func (r user) Find(ctx context.Context, filter *types.UserFilter) ([]*types.User
|
||||
|
||||
rval := make([]*types.User, 0)
|
||||
if err := db.Select(&rval, sql, params...); err != nil {
|
||||
return nil, ErrDatabaseError
|
||||
return nil, err
|
||||
} else {
|
||||
return rval, nil
|
||||
}
|
||||
@@ -75,8 +75,14 @@ func (r user) Create(ctx context.Context, mod *types.User) (*types.User, error)
|
||||
db := factory.Database.MustGet()
|
||||
|
||||
mod.SetID(factory.Sonyflake.NextID())
|
||||
mod.SetCreatedAt(time.Now())
|
||||
|
||||
if mod.Meta == nil {
|
||||
mod.SetMeta([]byte("{}"))
|
||||
}
|
||||
|
||||
if err := db.Insert("users", mod); err != nil {
|
||||
return nil, ErrDatabaseError
|
||||
return nil, err
|
||||
} else {
|
||||
return mod, nil
|
||||
}
|
||||
@@ -85,8 +91,11 @@ func (r user) Create(ctx context.Context, mod *types.User) (*types.User, error)
|
||||
func (r user) Update(ctx context.Context, mod *types.User) (*types.User, error) {
|
||||
db := factory.Database.MustGet()
|
||||
|
||||
now := time.Now()
|
||||
mod.SetUpdatedAt(&now)
|
||||
|
||||
if err := db.Replace("users", mod); err != nil {
|
||||
return nil, ErrDatabaseError
|
||||
return nil, err
|
||||
} else {
|
||||
return mod, nil
|
||||
}
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
package repository
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/crusttech/crust/sam/types"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestUser(t *testing.T) {
|
||||
var err error
|
||||
|
||||
if testing.Short() {
|
||||
t.Skip("skipping test in short mode.")
|
||||
return
|
||||
}
|
||||
|
||||
rpo := User()
|
||||
ctx := context.Background()
|
||||
att := types.User{}.New()
|
||||
|
||||
var name1, name2 = "Test user v1", "Test user v2"
|
||||
|
||||
var aa []*types.User
|
||||
|
||||
att.SetUsername(name1)
|
||||
|
||||
att, err = rpo.Create(ctx, att)
|
||||
must(t, err)
|
||||
if att.Username != name1 {
|
||||
t.Fatal("Changes were not stored")
|
||||
}
|
||||
|
||||
att.SetUsername(name2)
|
||||
|
||||
att, err = rpo.Update(ctx, att)
|
||||
must(t, err)
|
||||
if att.Username != name2 {
|
||||
t.Fatal("Changes were not stored")
|
||||
}
|
||||
|
||||
att, err = rpo.FindByID(ctx, att.ID)
|
||||
must(t, err)
|
||||
if att.Username != name2 {
|
||||
t.Fatal("Changes were not stored")
|
||||
}
|
||||
|
||||
aa, err = rpo.Find(ctx, &types.UserFilter{Query: name2})
|
||||
must(t, err)
|
||||
if len(aa) == 0 {
|
||||
t.Fatal("No results found")
|
||||
}
|
||||
|
||||
must(t, rpo.Delete(ctx, att.ID))
|
||||
}
|
||||
+28
-2
@@ -28,8 +28,10 @@ type (
|
||||
Topic string `db:"-"`
|
||||
Meta json.RawMessage `db:"meta"`
|
||||
LastMessageID uint64 `json:",omitempty" db:"rel_last_message"`
|
||||
ArchivedAt *time.Time `json:",omitempty" db:"archived_at"`
|
||||
DeletedAt *time.Time `json:",omitempty" db:"deleted_at"`
|
||||
CreatedAt time.Time `json:"created_at,omitempty" db:"created_at"`
|
||||
UpdatedAt *time.Time `json:"updated_at,omitempty" db:"updated_at"`
|
||||
ArchivedAt *time.Time `json:"archived_at,omitempty" db:"archived_at"`
|
||||
DeletedAt *time.Time `json:"deleted_at,omitempty" db:"deleted_at"`
|
||||
|
||||
changed []string
|
||||
}
|
||||
@@ -108,6 +110,30 @@ func (c *Channel) SetLastMessageID(value uint64) *Channel {
|
||||
return c
|
||||
}
|
||||
|
||||
// Get the value of CreatedAt
|
||||
func (c *Channel) GetCreatedAt() time.Time {
|
||||
return c.CreatedAt
|
||||
}
|
||||
|
||||
// Set the value of CreatedAt
|
||||
func (c *Channel) SetCreatedAt(value time.Time) *Channel {
|
||||
c.changed = append(c.changed, "CreatedAt")
|
||||
c.CreatedAt = value
|
||||
return c
|
||||
}
|
||||
|
||||
// Get the value of UpdatedAt
|
||||
func (c *Channel) GetUpdatedAt() *time.Time {
|
||||
return c.UpdatedAt
|
||||
}
|
||||
|
||||
// Set the value of UpdatedAt
|
||||
func (c *Channel) SetUpdatedAt(value *time.Time) *Channel {
|
||||
c.changed = append(c.changed, "UpdatedAt")
|
||||
c.UpdatedAt = value
|
||||
return c
|
||||
}
|
||||
|
||||
// Get the value of ArchivedAt
|
||||
func (c *Channel) GetArchivedAt() *time.Time {
|
||||
return c.ArchivedAt
|
||||
|
||||
+130
-16
@@ -29,20 +29,21 @@ type (
|
||||
UserID uint64 `db:"rel_user"`
|
||||
ChannelID uint64 `db:"rel_channel"`
|
||||
ReplyTo uint64 `db:"reply_to"`
|
||||
UpdatedAt *time.Time `json:",omitempty" db:"updated_at"`
|
||||
DeletedAt *time.Time `json:",omitempty" db:"deleted_at"`
|
||||
CreatedAt time.Time `json:"created_at,omitempty" db:"created_at"`
|
||||
UpdatedAt *time.Time `json:"updated_at,omitempty" db:"updated_at"`
|
||||
DeletedAt *time.Time `json:"deleted_at,omitempty" db:"deleted_at"`
|
||||
|
||||
changed []string
|
||||
}
|
||||
|
||||
// Messages -
|
||||
Reaction struct {
|
||||
ID uint64 `db:"id"`
|
||||
UserID uint64 `db:"rel_user"`
|
||||
MessageID uint64 `db:"rel_message"`
|
||||
ChannelID uint64 `db:"rel_channel"`
|
||||
Reaction string `db:"reaction"`
|
||||
DeletedAt *time.Time `json:",omitempty" db:"deleted_at"`
|
||||
ID uint64 `db:"id"`
|
||||
UserID uint64 `db:"rel_user"`
|
||||
MessageID uint64 `db:"rel_message"`
|
||||
ChannelID uint64 `db:"rel_channel"`
|
||||
Reaction string `db:"reaction"`
|
||||
CreatedAt time.Time `json:"created_at,omitempty" db:"created_at"`
|
||||
|
||||
changed []string
|
||||
}
|
||||
@@ -54,7 +55,14 @@ type (
|
||||
MessageID uint64 `db:"rel_message"`
|
||||
ChannelID uint64 `db:"rel_channel"`
|
||||
Attachment json.RawMessage `db:"attachment"`
|
||||
DeletedAt *time.Time `json:",omitempty" db:"deleted_at"`
|
||||
Url string `db:"url"`
|
||||
PreviewUrl string `db:"preview_url"`
|
||||
Size uint `db:"size"`
|
||||
Mimetype string `db:"mimetype"`
|
||||
Name string `db:"name"`
|
||||
CreatedAt time.Time `json:"created_at,omitempty" db:"created_at"`
|
||||
UpdatedAt *time.Time `json:"updated_at,omitempty" db:"updated_at"`
|
||||
DeletedAt *time.Time `json:"deleted_at,omitempty" db:"deleted_at"`
|
||||
|
||||
changed []string
|
||||
}
|
||||
@@ -159,6 +167,18 @@ func (m *Message) SetReplyTo(value uint64) *Message {
|
||||
return m
|
||||
}
|
||||
|
||||
// Get the value of CreatedAt
|
||||
func (m *Message) GetCreatedAt() time.Time {
|
||||
return m.CreatedAt
|
||||
}
|
||||
|
||||
// Set the value of CreatedAt
|
||||
func (m *Message) SetCreatedAt(value time.Time) *Message {
|
||||
m.changed = append(m.changed, "CreatedAt")
|
||||
m.CreatedAt = value
|
||||
return m
|
||||
}
|
||||
|
||||
// Get the value of UpdatedAt
|
||||
func (m *Message) GetUpdatedAt() *time.Time {
|
||||
return m.UpdatedAt
|
||||
@@ -258,15 +278,15 @@ func (m *Reaction) SetReaction(value string) *Reaction {
|
||||
return m
|
||||
}
|
||||
|
||||
// Get the value of DeletedAt
|
||||
func (m *Reaction) GetDeletedAt() *time.Time {
|
||||
return m.DeletedAt
|
||||
// Get the value of CreatedAt
|
||||
func (m *Reaction) GetCreatedAt() time.Time {
|
||||
return m.CreatedAt
|
||||
}
|
||||
|
||||
// Set the value of DeletedAt
|
||||
func (m *Reaction) SetDeletedAt(value *time.Time) *Reaction {
|
||||
m.changed = append(m.changed, "DeletedAt")
|
||||
m.DeletedAt = value
|
||||
// Set the value of CreatedAt
|
||||
func (m *Reaction) SetCreatedAt(value time.Time) *Reaction {
|
||||
m.changed = append(m.changed, "CreatedAt")
|
||||
m.CreatedAt = value
|
||||
return m
|
||||
}
|
||||
|
||||
@@ -343,6 +363,100 @@ func (m *Attachment) SetAttachment(value json.RawMessage) *Attachment {
|
||||
return m
|
||||
}
|
||||
|
||||
// Get the value of Url
|
||||
func (m *Attachment) GetUrl() string {
|
||||
return m.Url
|
||||
}
|
||||
|
||||
// Set the value of Url
|
||||
func (m *Attachment) SetUrl(value string) *Attachment {
|
||||
if m.Url != value {
|
||||
m.changed = append(m.changed, "Url")
|
||||
m.Url = value
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
// Get the value of PreviewUrl
|
||||
func (m *Attachment) GetPreviewUrl() string {
|
||||
return m.PreviewUrl
|
||||
}
|
||||
|
||||
// Set the value of PreviewUrl
|
||||
func (m *Attachment) SetPreviewUrl(value string) *Attachment {
|
||||
if m.PreviewUrl != value {
|
||||
m.changed = append(m.changed, "PreviewUrl")
|
||||
m.PreviewUrl = value
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
// Get the value of Size
|
||||
func (m *Attachment) GetSize() uint {
|
||||
return m.Size
|
||||
}
|
||||
|
||||
// Set the value of Size
|
||||
func (m *Attachment) SetSize(value uint) *Attachment {
|
||||
if m.Size != value {
|
||||
m.changed = append(m.changed, "Size")
|
||||
m.Size = value
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
// Get the value of Mimetype
|
||||
func (m *Attachment) GetMimetype() string {
|
||||
return m.Mimetype
|
||||
}
|
||||
|
||||
// Set the value of Mimetype
|
||||
func (m *Attachment) SetMimetype(value string) *Attachment {
|
||||
if m.Mimetype != value {
|
||||
m.changed = append(m.changed, "Mimetype")
|
||||
m.Mimetype = value
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
// Get the value of Name
|
||||
func (m *Attachment) GetName() string {
|
||||
return m.Name
|
||||
}
|
||||
|
||||
// Set the value of Name
|
||||
func (m *Attachment) SetName(value string) *Attachment {
|
||||
if m.Name != value {
|
||||
m.changed = append(m.changed, "Name")
|
||||
m.Name = value
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
// Get the value of CreatedAt
|
||||
func (m *Attachment) GetCreatedAt() time.Time {
|
||||
return m.CreatedAt
|
||||
}
|
||||
|
||||
// Set the value of CreatedAt
|
||||
func (m *Attachment) SetCreatedAt(value time.Time) *Attachment {
|
||||
m.changed = append(m.changed, "CreatedAt")
|
||||
m.CreatedAt = value
|
||||
return m
|
||||
}
|
||||
|
||||
// Get the value of UpdatedAt
|
||||
func (m *Attachment) GetUpdatedAt() *time.Time {
|
||||
return m.UpdatedAt
|
||||
}
|
||||
|
||||
// Set the value of UpdatedAt
|
||||
func (m *Attachment) SetUpdatedAt(value *time.Time) *Attachment {
|
||||
m.changed = append(m.changed, "UpdatedAt")
|
||||
m.UpdatedAt = value
|
||||
return m
|
||||
}
|
||||
|
||||
// Get the value of DeletedAt
|
||||
func (m *Attachment) GetDeletedAt() *time.Time {
|
||||
return m.DeletedAt
|
||||
|
||||
@@ -23,9 +23,12 @@ type (
|
||||
// Organisations - Organisations represent a top-level grouping entity. There may be many organisations defined in a single deployment.
|
||||
Organisation struct {
|
||||
ID uint64 `db:"id"`
|
||||
FQN string `db:"fqn"`
|
||||
Name string `db:"name"`
|
||||
ArchivedAt *time.Time `json:",omitempty" db:"archived_at"`
|
||||
DeletedAt *time.Time `json:",omitempty" db:"deleted_at"`
|
||||
CreatedAt time.Time `json:"created_at,omitempty" db:"created_at"`
|
||||
UpdatedAt *time.Time `json:"updated_at,omitempty" db:"updated_at"`
|
||||
ArchivedAt *time.Time `json:"archived_at,omitempty" db:"archived_at"`
|
||||
DeletedAt *time.Time `json:"deleted_at,omitempty" db:"deleted_at"`
|
||||
|
||||
changed []string
|
||||
}
|
||||
@@ -50,6 +53,20 @@ func (o *Organisation) SetID(value uint64) *Organisation {
|
||||
return o
|
||||
}
|
||||
|
||||
// Get the value of FQN
|
||||
func (o *Organisation) GetFQN() string {
|
||||
return o.FQN
|
||||
}
|
||||
|
||||
// Set the value of FQN
|
||||
func (o *Organisation) SetFQN(value string) *Organisation {
|
||||
if o.FQN != value {
|
||||
o.changed = append(o.changed, "FQN")
|
||||
o.FQN = value
|
||||
}
|
||||
return o
|
||||
}
|
||||
|
||||
// Get the value of Name
|
||||
func (o *Organisation) GetName() string {
|
||||
return o.Name
|
||||
@@ -64,6 +81,30 @@ func (o *Organisation) SetName(value string) *Organisation {
|
||||
return o
|
||||
}
|
||||
|
||||
// Get the value of CreatedAt
|
||||
func (o *Organisation) GetCreatedAt() time.Time {
|
||||
return o.CreatedAt
|
||||
}
|
||||
|
||||
// Set the value of CreatedAt
|
||||
func (o *Organisation) SetCreatedAt(value time.Time) *Organisation {
|
||||
o.changed = append(o.changed, "CreatedAt")
|
||||
o.CreatedAt = value
|
||||
return o
|
||||
}
|
||||
|
||||
// Get the value of UpdatedAt
|
||||
func (o *Organisation) GetUpdatedAt() *time.Time {
|
||||
return o.UpdatedAt
|
||||
}
|
||||
|
||||
// Set the value of UpdatedAt
|
||||
func (o *Organisation) SetUpdatedAt(value *time.Time) *Organisation {
|
||||
o.changed = append(o.changed, "UpdatedAt")
|
||||
o.UpdatedAt = value
|
||||
return o
|
||||
}
|
||||
|
||||
// Get the value of ArchivedAt
|
||||
func (o *Organisation) GetArchivedAt() *time.Time {
|
||||
return o.ArchivedAt
|
||||
|
||||
+33
-18
@@ -24,10 +24,11 @@ type (
|
||||
Team struct {
|
||||
ID uint64 `db:"id"`
|
||||
Name string `db:"name"`
|
||||
MemberIDs []uint64 `json:"-" db:"member_i_ds"`
|
||||
Members []User `json:",omitempty" db:"members"`
|
||||
ArchivedAt *time.Time `json:",omitempty" db:"archived_at"`
|
||||
DeletedAt *time.Time `json:",omitempty" db:"deleted_at"`
|
||||
Handle string `db:"handle"`
|
||||
CreatedAt time.Time `json:"created_at,omitempty" db:"created_at"`
|
||||
UpdatedAt *time.Time `json:"updated_at,omitempty" db:"updated_at"`
|
||||
ArchivedAt *time.Time `json:"archived_at,omitempty" db:"archived_at"`
|
||||
DeletedAt *time.Time `json:"deleted_at,omitempty" db:"deleted_at"`
|
||||
|
||||
changed []string
|
||||
}
|
||||
@@ -66,27 +67,41 @@ func (t *Team) SetName(value string) *Team {
|
||||
return t
|
||||
}
|
||||
|
||||
// Get the value of MemberIDs
|
||||
func (t *Team) GetMemberIDs() []uint64 {
|
||||
return t.MemberIDs
|
||||
// Get the value of Handle
|
||||
func (t *Team) GetHandle() string {
|
||||
return t.Handle
|
||||
}
|
||||
|
||||
// Set the value of MemberIDs
|
||||
func (t *Team) SetMemberIDs(value []uint64) *Team {
|
||||
t.changed = append(t.changed, "MemberIDs")
|
||||
t.MemberIDs = value
|
||||
// Set the value of Handle
|
||||
func (t *Team) SetHandle(value string) *Team {
|
||||
if t.Handle != value {
|
||||
t.changed = append(t.changed, "Handle")
|
||||
t.Handle = value
|
||||
}
|
||||
return t
|
||||
}
|
||||
|
||||
// Get the value of Members
|
||||
func (t *Team) GetMembers() []User {
|
||||
return t.Members
|
||||
// Get the value of CreatedAt
|
||||
func (t *Team) GetCreatedAt() time.Time {
|
||||
return t.CreatedAt
|
||||
}
|
||||
|
||||
// Set the value of Members
|
||||
func (t *Team) SetMembers(value []User) *Team {
|
||||
t.changed = append(t.changed, "Members")
|
||||
t.Members = value
|
||||
// Set the value of CreatedAt
|
||||
func (t *Team) SetCreatedAt(value time.Time) *Team {
|
||||
t.changed = append(t.changed, "CreatedAt")
|
||||
t.CreatedAt = value
|
||||
return t
|
||||
}
|
||||
|
||||
// Get the value of UpdatedAt
|
||||
func (t *Team) GetUpdatedAt() *time.Time {
|
||||
return t.UpdatedAt
|
||||
}
|
||||
|
||||
// Set the value of UpdatedAt
|
||||
func (t *Team) SetUpdatedAt(value *time.Time) *Team {
|
||||
t.changed = append(t.changed, "UpdatedAt")
|
||||
t.UpdatedAt = value
|
||||
return t
|
||||
}
|
||||
|
||||
|
||||
+28
-2
@@ -27,8 +27,10 @@ type (
|
||||
Meta interface{} `json:"-" db:"meta"`
|
||||
OrganisationID uint64 `db:"rel_organisation"`
|
||||
Password []byte `json:"-" db:"password"`
|
||||
SuspendedAt *time.Time `json:",omitempty" db:"suspended_at"`
|
||||
DeletedAt *time.Time `json:",omitempty" db:"deleted_at"`
|
||||
CreatedAt time.Time `json:"created_at,omitempty" db:"created_at"`
|
||||
UpdatedAt *time.Time `json:"updated_at,omitempty" db:"updated_at"`
|
||||
SuspendedAt *time.Time `json:"suspended_at,omitempty" db:"suspended_at"`
|
||||
DeletedAt *time.Time `json:"deleted_at,omitempty" db:"deleted_at"`
|
||||
|
||||
changed []string
|
||||
}
|
||||
@@ -107,6 +109,30 @@ func (u *User) SetPassword(value []byte) *User {
|
||||
return u
|
||||
}
|
||||
|
||||
// Get the value of CreatedAt
|
||||
func (u *User) GetCreatedAt() time.Time {
|
||||
return u.CreatedAt
|
||||
}
|
||||
|
||||
// Set the value of CreatedAt
|
||||
func (u *User) SetCreatedAt(value time.Time) *User {
|
||||
u.changed = append(u.changed, "CreatedAt")
|
||||
u.CreatedAt = value
|
||||
return u
|
||||
}
|
||||
|
||||
// Get the value of UpdatedAt
|
||||
func (u *User) GetUpdatedAt() *time.Time {
|
||||
return u.UpdatedAt
|
||||
}
|
||||
|
||||
// Set the value of UpdatedAt
|
||||
func (u *User) SetUpdatedAt(value *time.Time) *User {
|
||||
u.changed = append(u.changed, "UpdatedAt")
|
||||
u.UpdatedAt = value
|
||||
return u
|
||||
}
|
||||
|
||||
// Get the value of SuspendedAt
|
||||
func (u *User) GetSuspendedAt() *time.Time {
|
||||
return u.SuspendedAt
|
||||
|
||||
Reference in New Issue
Block a user