Stabilize SAM repositroy.

- aligned repository code, db schema and spec.json
 - add (not -short) tests for SAM repository
This commit is contained in:
Denis Arh
2018-07-26 23:59:29 +02:00
parent 52dbc4c0c3
commit 3d6f2165bd
28 changed files with 939 additions and 158 deletions
+44 -26
View File
@@ -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
View File
@@ -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 }
]
}
],
+14 -2
View File
@@ -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"
}
],
+44 -6
View File
@@ -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"
}
],
+19 -2
View File
@@ -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"
}
],
+13 -9
View File
@@ -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"
}
],
+14 -2
View File
@@ -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"
}
],
+17 -7
View File
@@ -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
}
+52
View File
@@ -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))
}
+16 -7
View File
@@ -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
}
+56
View File
@@ -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))
}
+7 -13
View File
@@ -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
}
+31
View File
@@ -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)
}
}
+11 -6
View File
@@ -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
}
+54
View File
@@ -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))
}
+10 -5
View File
@@ -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
}
+56
View File
@@ -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))
}
+8 -7
View File
@@ -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
}
+38
View File
@@ -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
View File
@@ -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
}
+56
View File
@@ -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
View File
@@ -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
}
+54
View File
@@ -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
View File
@@ -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
View File
@@ -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
+43 -2
View File
@@ -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
View File
@@ -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
View File
@@ -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