V3-663 Extend database with Project entity (#622)

* V3-663 Extend database with Project entity

* fixing linter
This commit is contained in:
Yehor Butko 2018-11-13 10:27:42 +02:00 committed by GitHub
parent 6576d31b29
commit 75213fa633
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 970 additions and 11 deletions

View File

@ -9,6 +9,8 @@ type DB interface {
Users() Users
// Companies is getter for Companies repository
Companies() Companies
// Projects is getter for Projects repository
Projects() Projects
// CreateTables is a method for creating all tables for satellitedb
CreateTables() error

42
pkg/satellite/projects.go Normal file
View File

@ -0,0 +1,42 @@
// Copyright (C) 2018 Storj Labs, Inc.
// See LICENSE for copying information.
package satellite
import (
"context"
"time"
"github.com/skyrings/skyring-common/tools/uuid"
)
// Projects exposes methods to manage Project table in database.
type Projects interface {
// GetAll is a method for querying all projects from the database.
GetAll(ctx context.Context) ([]Project, error)
// GetByUserID is a method for querying project from the database by userID.
GetByUserID(ctx context.Context, userID uuid.UUID) (*Project, error)
// Get is a method for querying project from the database by id.
Get(ctx context.Context, id uuid.UUID) (*Project, error)
// Insert is a method for inserting project into the database.
Insert(ctx context.Context, user *Project) (*Project, error)
// Delete is a method for deleting project by Id from the database.
Delete(ctx context.Context, id uuid.UUID) error
// Update is a method for updating project entity.
Update(ctx context.Context, user *Project) error
}
// Project is a database object that describes Project entity
type Project struct {
ID uuid.UUID
// FK on Users table. ID of project creator.
// TODO: Should it be named OwnerID?
UserID uuid.UUID
Name string
Description string
// Indicates if user accepted terms and conditions during project creation.
IsAgreedWithTerms bool
CreatedAt time.Time
}

View File

@ -199,9 +199,9 @@ func TestCompanyRepository(t *testing.T) {
func TestCompanyFromDbx(t *testing.T) {
t.Run("can't create dbo from nil dbx model", func(t *testing.T) {
user, err := companyFromDBX(nil)
company, err := companyFromDBX(nil)
assert.Nil(t, user)
assert.Nil(t, company)
assert.NotNil(t, err)
assert.Error(t, err)
})
@ -211,9 +211,9 @@ func TestCompanyFromDbx(t *testing.T) {
Id: []byte("qweqwe"),
}
user, err := companyFromDBX(&dbxCompany)
company, err := companyFromDBX(&dbxCompany)
assert.Nil(t, user)
assert.Nil(t, company)
assert.NotNil(t, err)
assert.Error(t, err)
})
@ -229,9 +229,9 @@ func TestCompanyFromDbx(t *testing.T) {
UserId: []byte("qweqwe"),
}
user, err := companyFromDBX(&dbxCompany)
company, err := companyFromDBX(&dbxCompany)
assert.Nil(t, user)
assert.Nil(t, company)
assert.NotNil(t, err)
assert.Error(t, err)
})

View File

@ -4,7 +4,6 @@
package satellitedb
import (
"storj.io/storj/internal/migrate"
"storj.io/storj/pkg/satellite"
"storj.io/storj/pkg/satellite/satellitedb/dbx"
@ -40,9 +39,20 @@ func (db *Database) Companies() satellite.Companies {
return &companies{db.db}
}
// Projects is getter for Projects repository
func (db *Database) Projects() satellite.Projects {
return &projects{db.db}
}
// CreateTables is a method for creating all tables for satellitedb
func (db *Database) CreateTables() error {
return migrate.Create("satellitedb", db.db)
//TODO: this code will be returned in the new commit
//return migrate.Create("satellitedb", db.db)
//TODO: this code should be removed in the new commit
_, err := db.db.Exec(db.db.Schema())
return err
}
// Close is used to close db connection

View File

@ -53,4 +53,30 @@ read one (
)
create company ( )
update company ( where company.id = ? )
delete company ( where company.id = ? )
delete company ( where company.id = ? )
model project (
key id
field id blob
field user_id user.id cascade
field name text ( updatable )
field description text ( updatable )
field is_agreed_with_terms bool ( updatable )
field created_at timestamp ( autoinsert )
)
read all ( select project)
read one (
select project
where project.id = ?
)
read one (
select project
where project.user_id = ?
)
create project ( )
update project ( where project.id = ? )
delete project ( where project.id = ? )

View File

@ -287,6 +287,15 @@ CREATE TABLE companies (
postal_code TEXT NOT NULL,
created_at TIMESTAMP NOT NULL,
PRIMARY KEY ( id )
);
CREATE TABLE projects (
id BLOB NOT NULL,
user_id BLOB NOT NULL REFERENCES users( id ) ON DELETE CASCADE,
name TEXT NOT NULL,
description TEXT NOT NULL,
is_agreed_with_terms INTEGER NOT NULL,
created_at TIMESTAMP NOT NULL,
PRIMARY KEY ( id )
);`
}
@ -661,6 +670,131 @@ func (f Company_CreatedAt_Field) value() interface{} {
func (Company_CreatedAt_Field) _Column() string { return "created_at" }
type Project struct {
Id []byte
UserId []byte
Name string
Description string
IsAgreedWithTerms bool
CreatedAt time.Time
}
func (Project) _Table() string { return "projects" }
type Project_Update_Fields struct {
Name Project_Name_Field
Description Project_Description_Field
IsAgreedWithTerms Project_IsAgreedWithTerms_Field
}
type Project_Id_Field struct {
_set bool
_value []byte
}
func Project_Id(v []byte) Project_Id_Field {
return Project_Id_Field{_set: true, _value: v}
}
func (f Project_Id_Field) value() interface{} {
if !f._set {
return nil
}
return f._value
}
func (Project_Id_Field) _Column() string { return "id" }
type Project_UserId_Field struct {
_set bool
_value []byte
}
func Project_UserId(v []byte) Project_UserId_Field {
return Project_UserId_Field{_set: true, _value: v}
}
func (f Project_UserId_Field) value() interface{} {
if !f._set {
return nil
}
return f._value
}
func (Project_UserId_Field) _Column() string { return "user_id" }
type Project_Name_Field struct {
_set bool
_value string
}
func Project_Name(v string) Project_Name_Field {
return Project_Name_Field{_set: true, _value: v}
}
func (f Project_Name_Field) value() interface{} {
if !f._set {
return nil
}
return f._value
}
func (Project_Name_Field) _Column() string { return "name" }
type Project_Description_Field struct {
_set bool
_value string
}
func Project_Description(v string) Project_Description_Field {
return Project_Description_Field{_set: true, _value: v}
}
func (f Project_Description_Field) value() interface{} {
if !f._set {
return nil
}
return f._value
}
func (Project_Description_Field) _Column() string { return "description" }
type Project_IsAgreedWithTerms_Field struct {
_set bool
_value bool
}
func Project_IsAgreedWithTerms(v bool) Project_IsAgreedWithTerms_Field {
return Project_IsAgreedWithTerms_Field{_set: true, _value: v}
}
func (f Project_IsAgreedWithTerms_Field) value() interface{} {
if !f._set {
return nil
}
return f._value
}
func (Project_IsAgreedWithTerms_Field) _Column() string { return "is_agreed_with_terms" }
type Project_CreatedAt_Field struct {
_set bool
_value time.Time
}
func Project_CreatedAt(v time.Time) Project_CreatedAt_Field {
return Project_CreatedAt_Field{_set: true, _value: v}
}
func (f Project_CreatedAt_Field) value() interface{} {
if !f._set {
return nil
}
return f._value
}
func (Project_CreatedAt_Field) _Column() string { return "created_at" }
func toUTC(t time.Time) time.Time {
return t.UTC()
}
@ -901,6 +1035,39 @@ func (obj *sqlite3Impl) Create_Company(ctx context.Context,
}
func (obj *sqlite3Impl) Create_Project(ctx context.Context,
project_id Project_Id_Field,
project_user_id Project_UserId_Field,
project_name Project_Name_Field,
project_description Project_Description_Field,
project_is_agreed_with_terms Project_IsAgreedWithTerms_Field) (
project *Project, err error) {
__now := obj.db.Hooks.Now().UTC()
__id_val := project_id.value()
__user_id_val := project_user_id.value()
__name_val := project_name.value()
__description_val := project_description.value()
__is_agreed_with_terms_val := project_is_agreed_with_terms.value()
__created_at_val := __now
var __embed_stmt = __sqlbundle_Literal("INSERT INTO projects ( id, user_id, name, description, is_agreed_with_terms, created_at ) VALUES ( ?, ?, ?, ?, ?, ? )")
var __stmt = __sqlbundle_Render(obj.dialect, __embed_stmt)
obj.logStmt(__stmt, __id_val, __user_id_val, __name_val, __description_val, __is_agreed_with_terms_val, __created_at_val)
__res, err := obj.driver.Exec(__stmt, __id_val, __user_id_val, __name_val, __description_val, __is_agreed_with_terms_val, __created_at_val)
if err != nil {
return nil, obj.makeErr(err)
}
__pk, err := __res.LastInsertId()
if err != nil {
return nil, obj.makeErr(err)
}
return obj.getLastProject(ctx, __pk)
}
func (obj *sqlite3Impl) Get_User_By_Email_And_PasswordHash(ctx context.Context,
user_email User_Email_Field,
user_password_hash User_PasswordHash_Field) (
@ -1008,6 +1175,102 @@ func (obj *sqlite3Impl) Get_Company_By_Id(ctx context.Context,
}
func (obj *sqlite3Impl) All_Project(ctx context.Context) (
rows []*Project, err error) {
var __embed_stmt = __sqlbundle_Literal("SELECT projects.id, projects.user_id, projects.name, projects.description, projects.is_agreed_with_terms, projects.created_at FROM projects")
var __values []interface{}
__values = append(__values)
var __stmt = __sqlbundle_Render(obj.dialect, __embed_stmt)
obj.logStmt(__stmt, __values...)
__rows, err := obj.driver.Query(__stmt, __values...)
if err != nil {
return nil, obj.makeErr(err)
}
defer __rows.Close()
for __rows.Next() {
project := &Project{}
err = __rows.Scan(&project.Id, &project.UserId, &project.Name, &project.Description, &project.IsAgreedWithTerms, &project.CreatedAt)
if err != nil {
return nil, obj.makeErr(err)
}
rows = append(rows, project)
}
if err := __rows.Err(); err != nil {
return nil, obj.makeErr(err)
}
return rows, nil
}
func (obj *sqlite3Impl) Get_Project_By_Id(ctx context.Context,
project_id Project_Id_Field) (
project *Project, err error) {
var __embed_stmt = __sqlbundle_Literal("SELECT projects.id, projects.user_id, projects.name, projects.description, projects.is_agreed_with_terms, projects.created_at FROM projects WHERE projects.id = ?")
var __values []interface{}
__values = append(__values, project_id.value())
var __stmt = __sqlbundle_Render(obj.dialect, __embed_stmt)
obj.logStmt(__stmt, __values...)
project = &Project{}
err = obj.driver.QueryRow(__stmt, __values...).Scan(&project.Id, &project.UserId, &project.Name, &project.Description, &project.IsAgreedWithTerms, &project.CreatedAt)
if err != nil {
return nil, obj.makeErr(err)
}
return project, nil
}
func (obj *sqlite3Impl) Get_Project_By_UserId(ctx context.Context,
project_user_id Project_UserId_Field) (
project *Project, err error) {
var __embed_stmt = __sqlbundle_Literal("SELECT projects.id, projects.user_id, projects.name, projects.description, projects.is_agreed_with_terms, projects.created_at FROM projects WHERE projects.user_id = ? LIMIT 2")
var __values []interface{}
__values = append(__values, project_user_id.value())
var __stmt = __sqlbundle_Render(obj.dialect, __embed_stmt)
obj.logStmt(__stmt, __values...)
__rows, err := obj.driver.Query(__stmt, __values...)
if err != nil {
return nil, obj.makeErr(err)
}
defer __rows.Close()
if !__rows.Next() {
if err := __rows.Err(); err != nil {
return nil, obj.makeErr(err)
}
return nil, makeErr(sql.ErrNoRows)
}
project = &Project{}
err = __rows.Scan(&project.Id, &project.UserId, &project.Name, &project.Description, &project.IsAgreedWithTerms, &project.CreatedAt)
if err != nil {
return nil, obj.makeErr(err)
}
if __rows.Next() {
return nil, tooManyRows("Project_By_UserId")
}
if err := __rows.Err(); err != nil {
return nil, obj.makeErr(err)
}
return project, nil
}
func (obj *sqlite3Impl) Update_User_By_Id(ctx context.Context,
user_id User_Id_Field,
update User_Update_Fields) (
@ -1148,6 +1411,66 @@ func (obj *sqlite3Impl) Update_Company_By_Id(ctx context.Context,
return company, nil
}
func (obj *sqlite3Impl) Update_Project_By_Id(ctx context.Context,
project_id Project_Id_Field,
update Project_Update_Fields) (
project *Project, err error) {
var __sets = &__sqlbundle_Hole{}
var __embed_stmt = __sqlbundle_Literals{Join: "", SQLs: []__sqlbundle_SQL{__sqlbundle_Literal("UPDATE projects SET "), __sets, __sqlbundle_Literal(" WHERE projects.id = ?")}}
__sets_sql := __sqlbundle_Literals{Join: ", "}
var __values []interface{}
var __args []interface{}
if update.Name._set {
__values = append(__values, update.Name.value())
__sets_sql.SQLs = append(__sets_sql.SQLs, __sqlbundle_Literal("name = ?"))
}
if update.Description._set {
__values = append(__values, update.Description.value())
__sets_sql.SQLs = append(__sets_sql.SQLs, __sqlbundle_Literal("description = ?"))
}
if update.IsAgreedWithTerms._set {
__values = append(__values, update.IsAgreedWithTerms.value())
__sets_sql.SQLs = append(__sets_sql.SQLs, __sqlbundle_Literal("is_agreed_with_terms = ?"))
}
if len(__sets_sql.SQLs) == 0 {
return nil, emptyUpdate()
}
__args = append(__args, project_id.value())
__values = append(__values, __args...)
__sets.SQL = __sets_sql
var __stmt = __sqlbundle_Render(obj.dialect, __embed_stmt)
obj.logStmt(__stmt, __values...)
project = &Project{}
_, err = obj.driver.Exec(__stmt, __values...)
if err != nil {
return nil, obj.makeErr(err)
}
var __embed_stmt_get = __sqlbundle_Literal("SELECT projects.id, projects.user_id, projects.name, projects.description, projects.is_agreed_with_terms, projects.created_at FROM projects WHERE projects.id = ?")
var __stmt_get = __sqlbundle_Render(obj.dialect, __embed_stmt_get)
obj.logStmt("(IMPLIED) "+__stmt_get, __args...)
err = obj.driver.QueryRow(__stmt_get, __args...).Scan(&project.Id, &project.UserId, &project.Name, &project.Description, &project.IsAgreedWithTerms, &project.CreatedAt)
if err == sql.ErrNoRows {
return nil, nil
}
if err != nil {
return nil, obj.makeErr(err)
}
return project, nil
}
func (obj *sqlite3Impl) Delete_User_By_Id(ctx context.Context,
user_id User_Id_Field) (
deleted bool, err error) {
@ -1200,6 +1523,32 @@ func (obj *sqlite3Impl) Delete_Company_By_Id(ctx context.Context,
}
func (obj *sqlite3Impl) Delete_Project_By_Id(ctx context.Context,
project_id Project_Id_Field) (
deleted bool, err error) {
var __embed_stmt = __sqlbundle_Literal("DELETE FROM projects WHERE projects.id = ?")
var __values []interface{}
__values = append(__values, project_id.value())
var __stmt = __sqlbundle_Render(obj.dialect, __embed_stmt)
obj.logStmt(__stmt, __values...)
__res, err := obj.driver.Exec(__stmt, __values...)
if err != nil {
return false, obj.makeErr(err)
}
__count, err := __res.RowsAffected()
if err != nil {
return false, obj.makeErr(err)
}
return __count > 0, nil
}
func (obj *sqlite3Impl) getLastUser(ctx context.Context,
pk int64) (
user *User, err error) {
@ -1236,6 +1585,24 @@ func (obj *sqlite3Impl) getLastCompany(ctx context.Context,
}
func (obj *sqlite3Impl) getLastProject(ctx context.Context,
pk int64) (
project *Project, err error) {
var __embed_stmt = __sqlbundle_Literal("SELECT projects.id, projects.user_id, projects.name, projects.description, projects.is_agreed_with_terms, projects.created_at FROM projects WHERE _rowid_ = ?")
var __stmt = __sqlbundle_Render(obj.dialect, __embed_stmt)
obj.logStmt(__stmt, pk)
project = &Project{}
err = obj.driver.QueryRow(__stmt, pk).Scan(&project.Id, &project.UserId, &project.Name, &project.Description, &project.IsAgreedWithTerms, &project.CreatedAt)
if err != nil {
return nil, obj.makeErr(err)
}
return project, nil
}
func (impl sqlite3Impl) isConstraintError(err error) (
constraint string, ok bool) {
if e, ok := err.(sqlite3.Error); ok {
@ -1254,6 +1621,16 @@ func (impl sqlite3Impl) isConstraintError(err error) (
func (obj *sqlite3Impl) deleteAll(ctx context.Context) (count int64, err error) {
var __res sql.Result
var __count int64
__res, err = obj.driver.Exec("DELETE FROM projects;")
if err != nil {
return 0, obj.makeErr(err)
}
__count, err = __res.RowsAffected()
if err != nil {
return 0, obj.makeErr(err)
}
count += __count
__res, err = obj.driver.Exec("DELETE FROM companies;")
if err != nil {
return 0, obj.makeErr(err)
@ -1321,6 +1698,15 @@ func (rx *Rx) Rollback() (err error) {
return err
}
func (rx *Rx) All_Project(ctx context.Context) (
rows []*Project, err error) {
var tx *Tx
if tx, err = rx.getTx(ctx); err != nil {
return
}
return tx.All_Project(ctx)
}
func (rx *Rx) Create_Company(ctx context.Context,
company_id Company_Id_Field,
company_user_id Company_UserId_Field,
@ -1339,6 +1725,21 @@ func (rx *Rx) Create_Company(ctx context.Context,
}
func (rx *Rx) Create_Project(ctx context.Context,
project_id Project_Id_Field,
project_user_id Project_UserId_Field,
project_name Project_Name_Field,
project_description Project_Description_Field,
project_is_agreed_with_terms Project_IsAgreedWithTerms_Field) (
project *Project, err error) {
var tx *Tx
if tx, err = rx.getTx(ctx); err != nil {
return
}
return tx.Create_Project(ctx, project_id, project_user_id, project_name, project_description, project_is_agreed_with_terms)
}
func (rx *Rx) Create_User(ctx context.Context,
user_id User_Id_Field,
user_first_name User_FirstName_Field,
@ -1364,6 +1765,16 @@ func (rx *Rx) Delete_Company_By_Id(ctx context.Context,
return tx.Delete_Company_By_Id(ctx, company_id)
}
func (rx *Rx) Delete_Project_By_Id(ctx context.Context,
project_id Project_Id_Field) (
deleted bool, err error) {
var tx *Tx
if tx, err = rx.getTx(ctx); err != nil {
return
}
return tx.Delete_Project_By_Id(ctx, project_id)
}
func (rx *Rx) Delete_User_By_Id(ctx context.Context,
user_id User_Id_Field) (
deleted bool, err error) {
@ -1394,6 +1805,26 @@ func (rx *Rx) Get_Company_By_UserId(ctx context.Context,
return tx.Get_Company_By_UserId(ctx, company_user_id)
}
func (rx *Rx) Get_Project_By_Id(ctx context.Context,
project_id Project_Id_Field) (
project *Project, err error) {
var tx *Tx
if tx, err = rx.getTx(ctx); err != nil {
return
}
return tx.Get_Project_By_Id(ctx, project_id)
}
func (rx *Rx) Get_Project_By_UserId(ctx context.Context,
project_user_id Project_UserId_Field) (
project *Project, err error) {
var tx *Tx
if tx, err = rx.getTx(ctx); err != nil {
return
}
return tx.Get_Project_By_UserId(ctx, project_user_id)
}
func (rx *Rx) Get_User_By_Email_And_PasswordHash(ctx context.Context,
user_email User_Email_Field,
user_password_hash User_PasswordHash_Field) (
@ -1426,6 +1857,17 @@ func (rx *Rx) Update_Company_By_Id(ctx context.Context,
return tx.Update_Company_By_Id(ctx, company_id, update)
}
func (rx *Rx) Update_Project_By_Id(ctx context.Context,
project_id Project_Id_Field,
update Project_Update_Fields) (
project *Project, err error) {
var tx *Tx
if tx, err = rx.getTx(ctx); err != nil {
return
}
return tx.Update_Project_By_Id(ctx, project_id, update)
}
func (rx *Rx) Update_User_By_Id(ctx context.Context,
user_id User_Id_Field,
update User_Update_Fields) (
@ -1438,6 +1880,9 @@ func (rx *Rx) Update_User_By_Id(ctx context.Context,
}
type Methods interface {
All_Project(ctx context.Context) (
rows []*Project, err error)
Create_Company(ctx context.Context,
company_id Company_Id_Field,
company_user_id Company_UserId_Field,
@ -1449,6 +1894,14 @@ type Methods interface {
company_postal_code Company_PostalCode_Field) (
company *Company, err error)
Create_Project(ctx context.Context,
project_id Project_Id_Field,
project_user_id Project_UserId_Field,
project_name Project_Name_Field,
project_description Project_Description_Field,
project_is_agreed_with_terms Project_IsAgreedWithTerms_Field) (
project *Project, err error)
Create_User(ctx context.Context,
user_id User_Id_Field,
user_first_name User_FirstName_Field,
@ -1461,6 +1914,10 @@ type Methods interface {
company_id Company_Id_Field) (
deleted bool, err error)
Delete_Project_By_Id(ctx context.Context,
project_id Project_Id_Field) (
deleted bool, err error)
Delete_User_By_Id(ctx context.Context,
user_id User_Id_Field) (
deleted bool, err error)
@ -1473,6 +1930,14 @@ type Methods interface {
company_user_id Company_UserId_Field) (
company *Company, err error)
Get_Project_By_Id(ctx context.Context,
project_id Project_Id_Field) (
project *Project, err error)
Get_Project_By_UserId(ctx context.Context,
project_user_id Project_UserId_Field) (
project *Project, err error)
Get_User_By_Email_And_PasswordHash(ctx context.Context,
user_email User_Email_Field,
user_password_hash User_PasswordHash_Field) (
@ -1487,6 +1952,11 @@ type Methods interface {
update Company_Update_Fields) (
company *Company, err error)
Update_Project_By_Id(ctx context.Context,
project_id Project_Id_Field,
update Project_Update_Fields) (
project *Project, err error)
Update_User_By_Id(ctx context.Context,
user_id User_Id_Field,
update User_Update_Fields) (

View File

@ -22,3 +22,12 @@ CREATE TABLE companies (
created_at TIMESTAMP NOT NULL,
PRIMARY KEY ( id )
);
CREATE TABLE projects (
id BLOB NOT NULL,
user_id BLOB NOT NULL REFERENCES users( id ) ON DELETE CASCADE,
name TEXT NOT NULL,
description TEXT NOT NULL,
is_agreed_with_terms INTEGER NOT NULL,
created_at TIMESTAMP NOT NULL,
PRIMARY KEY ( id )
);

View File

@ -0,0 +1,138 @@
// Copyright (C) 2018 Storj Labs, Inc.
// See LICENSE for copying information.
package satellitedb
import (
"context"
"github.com/skyrings/skyring-common/tools/uuid"
"github.com/zeebo/errs"
"storj.io/storj/pkg/satellite"
"storj.io/storj/pkg/satellite/satellitedb/dbx"
"storj.io/storj/pkg/utils"
)
// implementation of Projects interface repository using spacemonkeygo/dbx orm
type projects struct {
db *dbx.DB
}
// GetAll is a method for querying all projects from the database.
func (projects *projects) GetAll(ctx context.Context) ([]satellite.Project, error) {
projectsDbxSlice, err := projects.db.All_Project(ctx)
if err != nil {
return nil, err
}
projectsCount := len(projectsDbxSlice)
var projectDboSlice []satellite.Project
var errors []error
// Generating []dbo from []dbx and collecting all errors
for i := 0; i < projectsCount; i++ {
projectDbo, err := projectFromDBX(projectsDbxSlice[i])
if err != nil {
errors = append(errors, err)
}
projectDboSlice = append(projectDboSlice, *projectDbo)
}
return projectDboSlice, utils.CombineErrors(errors...)
}
// GetByUserID is a method for querying project from the database by user id
func (projects *projects) GetByUserID(ctx context.Context, userID uuid.UUID) (*satellite.Project, error) {
project, err := projects.db.Get_Project_By_UserId(ctx, dbx.Project_UserId(userID[:]))
if err != nil {
return nil, err
}
return projectFromDBX(project)
}
// Get is a method for querying project from the database by id.
func (projects *projects) Get(ctx context.Context, id uuid.UUID) (*satellite.Project, error) {
project, err := projects.db.Get_Project_By_Id(ctx, dbx.Project_Id(id[:]))
if err != nil {
return nil, err
}
return projectFromDBX(project)
}
// Insert is a method for inserting project into the database.
func (projects *projects) Insert(ctx context.Context, project *satellite.Project) (*satellite.Project, error) {
projectID, err := uuid.New()
if err != nil {
return nil, err
}
createdProject, err := projects.db.Create_Project(ctx,
dbx.Project_Id(projectID[:]),
dbx.Project_UserId(project.UserID[:]),
dbx.Project_Name(project.Name),
dbx.Project_Description(project.Description),
dbx.Project_IsAgreedWithTerms(project.IsAgreedWithTerms))
if err != nil {
return nil, err
}
return projectFromDBX(createdProject)
}
// Delete is a method for deleting project by Id from the database.
func (projects *projects) Delete(ctx context.Context, id uuid.UUID) error {
_, err := projects.db.Delete_Project_By_Id(ctx, dbx.Project_Id(id[:]))
return err
}
// Update is a method for updating user entity
func (projects *projects) Update(ctx context.Context, project *satellite.Project) error {
_, err := projects.db.Update_Project_By_Id(ctx,
dbx.Project_Id(project.ID[:]),
dbx.Project_Update_Fields{
Name: dbx.Project_Name(project.Name),
Description: dbx.Project_Description(project.Description),
IsAgreedWithTerms: dbx.Project_IsAgreedWithTerms(project.IsAgreedWithTerms),
})
return err
}
// projectFromDBX is used for creating Project entity from autogenerated dbx.Project struct
func projectFromDBX(project *dbx.Project) (*satellite.Project, error) {
if project == nil {
return nil, errs.New("project parameter is nil")
}
id, err := bytesToUUID(project.Id)
if err != nil {
return nil, err
}
userID, err := bytesToUUID(project.UserId)
if err != nil {
return nil, err
}
u := &satellite.Project{
ID: id,
UserID: userID,
Name: project.Name,
Description: project.Description,
IsAgreedWithTerms: project.IsAgreedWithTerms,
CreatedAt: project.CreatedAt,
}
return u, nil
}

View File

@ -0,0 +1,257 @@
// Copyright (C) 2018 Storj Labs, Inc.
// See LICENSE for copying information.
package satellitedb
import (
"testing"
"github.com/skyrings/skyring-common/tools/uuid"
"storj.io/storj/pkg/satellite/satellitedb/dbx"
"github.com/stretchr/testify/assert"
"storj.io/storj/internal/testcontext"
"storj.io/storj/pkg/satellite"
)
func TestProjectsRepository(t *testing.T) {
//testing constants
const (
// for user
lastName = "lastName"
email = "email@ukr.net"
pass = "123456"
userName = "name"
// for project
name = "Storj"
description = "some description"
// updated project values
newName = "Dropbox"
newDescription = "some new description"
)
ctx := testcontext.New(t)
defer ctx.Cleanup()
// creating in-memory db and opening connection
// to test with real db3 file use this connection string - "../db/accountdb.db3"
db, err := New("sqlite3", "file::memory:?mode=memory&cache=shared")
if err != nil {
assert.NoError(t, err)
}
defer ctx.Check(db.Close)
// creating tables
err = db.CreateTables()
if err != nil {
assert.NoError(t, err)
}
// repositories
users := db.Users()
projects := db.Projects()
var user *satellite.User
t.Run("Can't insert project without user", func(t *testing.T) {
project := &satellite.Project{
Name: name,
Description: description,
IsAgreedWithTerms: false,
}
createdCompany, err := projects.Insert(ctx, project)
assert.Nil(t, createdCompany)
assert.NotNil(t, err)
assert.Error(t, err)
})
t.Run("Insert project successfully", func(t *testing.T) {
user, err = users.Insert(ctx, &satellite.User{
FirstName: userName,
LastName: lastName,
Email: email,
PasswordHash: []byte(pass),
})
assert.NoError(t, err)
assert.NotNil(t, user)
project := &satellite.Project{
UserID: user.ID,
Name: name,
Description: description,
IsAgreedWithTerms: false,
}
createdProject, err := projects.Insert(ctx, project)
assert.NotNil(t, createdProject)
assert.Nil(t, err)
assert.NoError(t, err)
})
t.Run("Get project success", func(t *testing.T) {
projectByUserID, err := projects.GetByUserID(ctx, user.ID)
assert.Nil(t, err)
assert.NoError(t, err)
assert.Equal(t, projectByUserID.UserID, user.ID)
assert.Equal(t, projectByUserID.Name, name)
assert.Equal(t, projectByUserID.Description, description)
assert.Equal(t, projectByUserID.IsAgreedWithTerms, false)
projectByID, err := projects.Get(ctx, projectByUserID.ID)
assert.Nil(t, err)
assert.NoError(t, err)
assert.Equal(t, projectByID.ID, projectByUserID.ID)
assert.Equal(t, projectByID.UserID, user.ID)
assert.Equal(t, projectByID.Name, name)
assert.Equal(t, projectByID.Description, description)
assert.Equal(t, projectByID.IsAgreedWithTerms, false)
})
t.Run("Update project success", func(t *testing.T) {
oldProject, err := projects.GetByUserID(ctx, user.ID)
assert.NoError(t, err)
assert.NotNil(t, oldProject)
// creating new company with updated values
newProject := &satellite.Project{
ID: oldProject.ID,
UserID: user.ID,
Name: newName,
Description: newDescription,
IsAgreedWithTerms: true,
}
err = projects.Update(ctx, newProject)
assert.Nil(t, err)
assert.NoError(t, err)
// fetching updated project from db
newProject, err = projects.Get(ctx, oldProject.ID)
assert.NoError(t, err)
assert.Equal(t, newProject.ID, oldProject.ID)
assert.Equal(t, newProject.UserID, user.ID)
assert.Equal(t, newProject.Name, newName)
assert.Equal(t, newProject.Description, newDescription)
assert.Equal(t, newProject.IsAgreedWithTerms, true)
})
t.Run("Delete project success", func(t *testing.T) {
oldProject, err := projects.GetByUserID(ctx, user.ID)
assert.NoError(t, err)
assert.NotNil(t, oldProject)
err = projects.Delete(ctx, oldProject.ID)
assert.Nil(t, err)
assert.NoError(t, err)
_, err = projects.Get(ctx, oldProject.ID)
assert.NotNil(t, err)
assert.Error(t, err)
})
t.Run("GetAll success", func(t *testing.T) {
allProjects, err := projects.GetAll(ctx)
assert.Nil(t, err)
assert.NoError(t, err)
assert.Equal(t, len(allProjects), 0)
newProject := &satellite.Project{
UserID: user.ID,
Description: description,
Name: name,
IsAgreedWithTerms: true,
}
_, err = projects.Insert(ctx, newProject)
assert.Nil(t, err)
assert.NoError(t, err)
allProjects, err = projects.GetAll(ctx)
assert.Nil(t, err)
assert.NoError(t, err)
assert.Equal(t, len(allProjects), 1)
newProject2 := &satellite.Project{
UserID: user.ID,
Description: description,
Name: name,
IsAgreedWithTerms: true,
}
_, err = projects.Insert(ctx, newProject2)
assert.Nil(t, err)
assert.NoError(t, err)
allProjects, err = projects.GetAll(ctx)
assert.Nil(t, err)
assert.NoError(t, err)
assert.Equal(t, len(allProjects), 2)
})
}
func TestProjectFromDbx(t *testing.T) {
t.Run("can't create dbo from nil dbx model", func(t *testing.T) {
user, err := projectFromDBX(nil)
assert.Nil(t, user)
assert.NotNil(t, err)
assert.Error(t, err)
})
t.Run("can't create dbo from dbx model with invalid ID", func(t *testing.T) {
dbxProject := dbx.Project{
Id: []byte("qweqwe"),
}
project, err := projectFromDBX(&dbxProject)
assert.Nil(t, project)
assert.NotNil(t, err)
assert.Error(t, err)
})
t.Run("can't create dbo from dbx model with invalid UserID", func(t *testing.T) {
projectID, err := uuid.New()
assert.NoError(t, err)
assert.Nil(t, err)
dbxProject := dbx.Project{
Id: projectID[:],
UserId: []byte("qweqwe"),
}
project, err := projectFromDBX(&dbxProject)
assert.Nil(t, project)
assert.NotNil(t, err)
assert.Error(t, err)
})
}

View File

@ -48,8 +48,13 @@ func (users *users) GetByCredentials(ctx context.Context, password []byte, email
// Insert is a method for inserting user into the database
func (users *users) Insert(ctx context.Context, user *satellite.User) (*satellite.User, error) {
userID, err := uuid.New()
if err != nil {
return nil, err
}
createdUser, err := users.db.Create_User(ctx,
dbx.User_Id(user.ID[:]),
dbx.User_Id(userID[:]),
dbx.User_FirstName(user.FirstName),
dbx.User_LastName(user.LastName),
dbx.User_Email(user.Email),

View File

@ -14,7 +14,7 @@ func bytesToUUID(data []byte) (uuid.UUID, error) {
copy(id[:], data)
if len(id) != len(data) {
return uuid.UUID{}, errs.New("Invalid bytes array")
return uuid.UUID{}, errs.New("Invalid uuid")
}
return id, nil