Removing company and project ownership (#917)

This commit is contained in:
Yehor Butko 2018-12-20 18:18:08 +02:00 committed by GitHub
parent 1c119c6215
commit ac860c1984
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
36 changed files with 459 additions and 2239 deletions

View File

@ -1,48 +0,0 @@
// Copyright (C) 2018 Storj Labs, Inc.
// See LICENSE for copying information.
package satellite
import (
"context"
"time"
"github.com/skyrings/skyring-common/tools/uuid"
)
// Companies exposes methods to manage Company table in database.
type Companies interface {
// GetByUserID is a method for querying company from the database by userID
GetByUserID(ctx context.Context, userID uuid.UUID) (*Company, error)
// Insert is a method for inserting company into the database
Insert(ctx context.Context, company *Company) (*Company, error)
// Delete is a method for deleting company by userID from the database.
Delete(ctx context.Context, userID uuid.UUID) error
// Update is a method for updating company entity
Update(ctx context.Context, company *Company) error
}
// CompanyInfo holds data needed to create/update Company
type CompanyInfo struct {
Name string
Address string
Country string
City string
State string
PostalCode string
}
// Company is a database object that describes Company entity
type Company struct {
//PK and FK on users table
UserID uuid.UUID
Name string
Address string
Country string
City string
State string
PostalCode string
CreatedAt time.Time
}

View File

@ -9,8 +9,6 @@ import "context"
type DB interface {
// Users is a getter for Users repository
Users() Users
// Companies is a getter for Companies repository
Companies() Companies
// Projects is a getter for Projects repository
Projects() Projects
// ProjectMembers is a getter for ProjectMembers repository

View File

@ -14,8 +14,6 @@ import (
type Projects interface {
// GetAll is a method for querying all projects from the database.
GetAll(ctx context.Context) ([]Project, error)
// GetByOwnerID is a method for querying projects from the database by ownerID.
GetByOwnerID(ctx context.Context, ownerID uuid.UUID) ([]Project, error)
// GetByUserID is a method for querying all projects 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.
@ -31,11 +29,8 @@ type Projects interface {
// Project is a database object that describes Project entity
type Project struct {
ID uuid.UUID `json:"id"`
// FK on Users table. ID of project creator.
OwnerID *uuid.UUID `json:"ownerId"`
Name string `json:"name"`
CompanyName string `json:"companyName"`
Description string `json:"description"`
// stores last accepted version of terms of use.
TermsAccepted int `json:"termsAccepted"`
@ -46,7 +41,6 @@ type Project struct {
// ProjectInfo holds data needed to create/update Project
type ProjectInfo struct {
Name string `json:"name"`
CompanyName string `json:"companyName"`
Description string `json:"description"`
// Indicates if user accepted Terms & Conditions during project creation on UI
IsTermsAccepted bool `json:"isTermsAccepted"`

View File

@ -1,100 +0,0 @@
// 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"
)
// implementation of Companies interface repository using spacemonkeygo/dbx orm
type companies struct {
db dbx.Methods
}
// Get is a method for querying company from the database by user id
func (companies *companies) GetByUserID(ctx context.Context, userID uuid.UUID) (*satellite.Company, error) {
company, err := companies.db.Get_Company_By_UserId(ctx, dbx.Company_UserId(userID[:]))
if err != nil {
return nil, err
}
return companyFromDBX(company)
}
// Insert is a method for inserting company into the database
func (companies *companies) Insert(ctx context.Context, company *satellite.Company) (*satellite.Company, error) {
createdCompany, err := companies.db.Create_Company(
ctx,
dbx.Company_UserId(company.UserID[:]),
dbx.Company_Name(company.Name),
dbx.Company_Address(company.Address),
dbx.Company_Country(company.Country),
dbx.Company_City(company.City),
dbx.Company_State(company.State),
dbx.Company_PostalCode(company.PostalCode))
if err != nil {
return nil, err
}
return companyFromDBX(createdCompany)
}
// Delete is a method for deleting company by Id from the database.
func (companies *companies) Delete(ctx context.Context, userID uuid.UUID) error {
_, err := companies.db.Delete_Company_By_UserId(ctx, dbx.Company_UserId(userID[:]))
return err
}
// Update is a method for updating company entity
func (companies *companies) Update(ctx context.Context, company *satellite.Company) error {
_, err := companies.db.Update_Company_By_UserId(
ctx,
dbx.Company_UserId(company.UserID[:]),
getCompanyUpdateFields(company))
return err
}
// companyFromDBX is used for creating Company entity from autogenerated dbx.Company struct
func companyFromDBX(company *dbx.Company) (*satellite.Company, error) {
if company == nil {
return nil, errs.New("company parameter is nil")
}
userID, err := bytesToUUID(company.UserId)
if err != nil {
return nil, err
}
return &satellite.Company{
UserID: userID,
Name: company.Name,
Address: company.Address,
Country: company.Country,
City: company.City,
State: company.State,
PostalCode: company.PostalCode,
CreatedAt: company.CreatedAt,
}, nil
}
// getCompanyUpdateFields is used to generate company update fields
func getCompanyUpdateFields(company *satellite.Company) dbx.Company_Update_Fields {
return dbx.Company_Update_Fields{
Name: dbx.Company_Name(company.Name),
Address: dbx.Company_Address(company.Address),
Country: dbx.Company_Country(company.Country),
City: dbx.Company_City(company.City),
State: dbx.Company_State(company.State),
PostalCode: dbx.Company_PostalCode(company.PostalCode),
}
}

View File

@ -1,213 +0,0 @@
// Copyright (C) 2018 Storj Labs, Inc.
// See LICENSE for copying information.
package satellitedb
import (
"testing"
"github.com/stretchr/testify/assert"
"storj.io/storj/internal/testcontext"
"storj.io/storj/pkg/satellite"
"storj.io/storj/pkg/satellite/satellitedb/dbx"
)
func TestCompanyRepository(t *testing.T) {
//testing constants
const (
// for user
lastName = "lastName"
email = "email@ukr.net"
pass = "123456"
userName = "name"
// for company
companyName = "Storj"
address = "somewhere"
country = "USA"
city = "Atlanta"
state = "Georgia"
postalCode = "02183"
// updated company values
newCompanyName = "Storage"
newAddress = "where"
newCountry = "Usa"
newCity = "Otlanta"
newState = "Jeorgia"
newPostalCode = "02184"
)
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 {
t.Fatal(err)
}
defer ctx.Check(db.Close)
// creating tables
err = db.CreateTables()
if err != nil {
t.Fatal(err)
}
// repositories
users := db.Users()
companies := db.Companies()
var user *satellite.User
t.Run("Can't insert company without user", func(t *testing.T) {
company := &satellite.Company{
Name: companyName,
Address: address,
Country: country,
City: city,
State: state,
PostalCode: postalCode,
}
createdCompany, err := companies.Insert(ctx, company)
assert.Nil(t, createdCompany)
assert.NotNil(t, err)
assert.Error(t, err)
})
t.Run("Insert company 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)
company := &satellite.Company{
UserID: user.ID,
Name: companyName,
Address: address,
Country: country,
City: city,
State: state,
PostalCode: postalCode,
}
createdCompany, err := companies.Insert(ctx, company)
assert.NotNil(t, createdCompany)
assert.Nil(t, err)
assert.NoError(t, err)
})
t.Run("Get company success", func(t *testing.T) {
companyByUserID, err := companies.GetByUserID(ctx, user.ID)
assert.Nil(t, err)
assert.NoError(t, err)
assert.Equal(t, companyByUserID.UserID, user.ID)
assert.Equal(t, companyByUserID.Name, companyName)
assert.Equal(t, companyByUserID.Address, address)
assert.Equal(t, companyByUserID.Country, country)
assert.Equal(t, companyByUserID.City, city)
assert.Equal(t, companyByUserID.State, state)
assert.Equal(t, companyByUserID.PostalCode, postalCode)
companyByID, err := companies.GetByUserID(ctx, companyByUserID.UserID)
assert.Nil(t, err)
assert.NoError(t, err)
assert.Equal(t, companyByID.UserID, user.ID)
assert.Equal(t, companyByID.Name, companyName)
assert.Equal(t, companyByID.Address, address)
assert.Equal(t, companyByID.Country, country)
assert.Equal(t, companyByID.City, city)
assert.Equal(t, companyByID.State, state)
assert.Equal(t, companyByID.PostalCode, postalCode)
})
t.Run("Update company success", func(t *testing.T) {
oldCompany, err := companies.GetByUserID(ctx, user.ID)
assert.NoError(t, err)
assert.NotNil(t, oldCompany)
// creating new company with updated values
newCompany := &satellite.Company{
UserID: user.ID,
Name: newCompanyName,
Address: newAddress,
Country: newCountry,
City: newCity,
State: newState,
PostalCode: newPostalCode,
}
err = companies.Update(ctx, newCompany)
assert.Nil(t, err)
assert.NoError(t, err)
// fetching updated company from db
newCompany, err = companies.GetByUserID(ctx, oldCompany.UserID)
assert.NoError(t, err)
assert.Equal(t, newCompany.UserID, user.ID)
assert.Equal(t, newCompany.Name, newCompanyName)
assert.Equal(t, newCompany.Address, newAddress)
assert.Equal(t, newCompany.Country, newCountry)
assert.Equal(t, newCompany.City, newCity)
assert.Equal(t, newCompany.State, newState)
assert.Equal(t, newCompany.PostalCode, newPostalCode)
})
t.Run("Delete company success", func(t *testing.T) {
oldCompany, err := companies.GetByUserID(ctx, user.ID)
assert.NoError(t, err)
assert.NotNil(t, oldCompany)
err = companies.Delete(ctx, oldCompany.UserID)
assert.Nil(t, err)
assert.NoError(t, err)
_, err = companies.GetByUserID(ctx, oldCompany.UserID)
assert.NotNil(t, err)
assert.Error(t, err)
})
}
func TestCompanyFromDbx(t *testing.T) {
t.Run("can't create dbo from nil dbx model", func(t *testing.T) {
company, err := companyFromDBX(nil)
assert.Nil(t, company)
assert.NotNil(t, err)
assert.Error(t, err)
})
t.Run("can't create dbo from dbx model with invalid UserID", func(t *testing.T) {
dbxCompany := dbx.Company{
UserId: []byte("qweqwe"),
}
company, err := companyFromDBX(&dbxCompany)
assert.Nil(t, company)
assert.NotNil(t, err)
assert.Error(t, err)
})
}

View File

@ -47,11 +47,6 @@ func (db *Database) Users() satellite.Users {
return &users{db.methods}
}
// Companies is a getter for Companies repository
func (db *Database) Companies() satellite.Companies {
return &companies{db.methods}
}
// Projects is a getter for Projects repository
func (db *Database) Projects() satellite.Projects {
return &projects{db.methods}

View File

@ -25,37 +25,12 @@ update user ( where user.id = ? )
delete user ( where user.id = ? )
model company (
key user_id
field user_id user.id cascade
field name text ( updatable )
field address text ( updatable )
field country text ( updatable )
field city text ( updatable )
field state text ( updatable )
field postal_code text ( updatable )
field created_at timestamp ( autoinsert )
)
read one (
select company
where company.user_id = ?
)
create company ( )
update company ( where company.user_id = ? )
delete company ( where company.user_id = ? )
model project (
key id
field id blob
field owner_id user.id setnull ( nullable, updatable )
field name text
field company_name text
field description text ( updatable )
// stores last accepted version of terms of use
field terms_accepted int ( updatable )
@ -67,10 +42,6 @@ read one (
select project
where project.id = ?
)
read all (
select project
where project.owner_id = ?
)
read all (
select project
join project.id = project_member.project_id

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,13 @@
-- AUTOGENERATED BY gopkg.in/spacemonkeygo/dbx.v1
-- DO NOT EDIT
CREATE TABLE projects (
id BLOB NOT NULL,
name TEXT NOT NULL,
description TEXT NOT NULL,
terms_accepted INTEGER NOT NULL,
created_at TIMESTAMP NOT NULL,
PRIMARY KEY ( id )
);
CREATE TABLE users (
id BLOB NOT NULL,
first_name TEXT NOT NULL,
@ -10,27 +18,6 @@ CREATE TABLE users (
PRIMARY KEY ( id ),
UNIQUE ( email )
);
CREATE TABLE companies (
user_id BLOB NOT NULL REFERENCES users( id ) ON DELETE CASCADE,
name TEXT NOT NULL,
address TEXT NOT NULL,
country TEXT NOT NULL,
city TEXT NOT NULL,
state TEXT NOT NULL,
postal_code TEXT NOT NULL,
created_at TIMESTAMP NOT NULL,
PRIMARY KEY ( user_id )
);
CREATE TABLE projects (
id BLOB NOT NULL,
owner_id BLOB REFERENCES users( id ) ON DELETE SET NULL,
name TEXT NOT NULL,
company_name TEXT NOT NULL,
description TEXT NOT NULL,
terms_accepted INTEGER NOT NULL,
created_at TIMESTAMP NOT NULL,
PRIMARY KEY ( id )
);
CREATE TABLE project_members (
member_id BLOB NOT NULL REFERENCES users( id ) ON DELETE CASCADE,
project_id BLOB NOT NULL REFERENCES projects( id ) ON DELETE CASCADE,

View File

@ -146,13 +146,11 @@ func prepareUsersAndProjects(ctx context.Context, t *testing.T, users satellite.
Name: "projName1",
TermsAccepted: 1,
Description: "Test project 1",
OwnerID: &usersList[0].ID,
},
{
Name: "projName2",
TermsAccepted: 1,
Description: "Test project 1",
OwnerID: &usersList[1].ID,
},
}

View File

@ -29,16 +29,6 @@ func (projects *projects) GetAll(ctx context.Context) ([]satellite.Project, erro
return projectsFromDbxSlice(projectsDbx)
}
// GetByOwnerID is a method for querying projects from the database by ownerID.
func (projects *projects) GetByOwnerID(ctx context.Context, ownerID uuid.UUID) ([]satellite.Project, error) {
projectsDbx, err := projects.db.All_Project_By_OwnerId(ctx, dbx.Project_OwnerId(ownerID[:]))
if err != nil {
return nil, err
}
return projectsFromDbxSlice(projectsDbx)
}
// GetByUserID is a method for querying all projects from the database by userID.
func (projects *projects) GetByUserID(ctx context.Context, userID uuid.UUID) ([]satellite.Project, error) {
projectsDbx, err := projects.db.All_Project_By_ProjectMember_MemberId(ctx, dbx.ProjectMember_MemberId(userID[:]))
@ -66,23 +56,11 @@ func (projects *projects) Insert(ctx context.Context, project *satellite.Project
return nil, err
}
var ownerID dbx.Project_OwnerId_Field
if project.OwnerID != nil {
ownerID = dbx.Project_OwnerId(project.OwnerID[:])
} else {
ownerID = dbx.Project_OwnerId(nil)
}
createdProject, err := projects.db.Create_Project(ctx,
dbx.Project_Id(projectID[:]),
dbx.Project_Name(project.Name),
dbx.Project_CompanyName(project.CompanyName),
dbx.Project_Description(project.Description),
dbx.Project_TermsAccepted(project.TermsAccepted),
dbx.Project_Create_Fields{
OwnerId: ownerID,
})
dbx.Project_TermsAccepted(project.TermsAccepted))
if err != nil {
return nil, err
@ -105,10 +83,6 @@ func (projects *projects) Update(ctx context.Context, project *satellite.Project
TermsAccepted: dbx.Project_TermsAccepted(project.TermsAccepted),
}
if project.OwnerID != nil {
updateFields.OwnerId = dbx.Project_OwnerId(project.OwnerID[:])
}
_, err := projects.db.Update_Project_By_Id(ctx,
dbx.Project_Id(project.ID[:]),
updateFields)
@ -130,23 +104,11 @@ func projectFromDBX(project *dbx.Project) (*satellite.Project, error) {
u := &satellite.Project{
ID: id,
Name: project.Name,
CompanyName: project.CompanyName,
Description: project.Description,
TermsAccepted: project.TermsAccepted,
CreatedAt: project.CreatedAt,
}
if project.OwnerId == nil {
u.OwnerID = nil
} else {
ownerID, err := bytesToUUID(project.OwnerId)
if err != nil {
return nil, err
}
u.OwnerID = &ownerID
}
return u, nil
}

View File

@ -6,7 +6,6 @@ package satellitedb
import (
"testing"
"github.com/skyrings/skyring-common/tools/uuid"
"github.com/stretchr/testify/assert"
"storj.io/storj/internal/testcontext"
@ -25,7 +24,6 @@ func TestProjectsRepository(t *testing.T) {
// for project
name = "Project"
companyName = "Comp Name"
description = "some description"
// updated project values
@ -52,25 +50,9 @@ func TestProjectsRepository(t *testing.T) {
// repositories
users := db.Users()
projects := db.Projects()
var project *satellite.Project
var owner *satellite.User
t.Run("Can insert project without owner", func(t *testing.T) {
project := &satellite.Project{
OwnerID: nil,
Name: name,
CompanyName: companyName,
Description: description,
TermsAccepted: 1,
}
createdProject, err := projects.Insert(ctx, project)
assert.NotNil(t, createdProject)
assert.Nil(t, err)
assert.NoError(t, err)
})
t.Run("Insert project successfully", func(t *testing.T) {
owner, err = users.Insert(ctx, &satellite.User{
FirstName: userName,
@ -82,59 +64,41 @@ func TestProjectsRepository(t *testing.T) {
assert.NoError(t, err)
assert.NotNil(t, owner)
project := &satellite.Project{
OwnerID: &owner.ID,
project = &satellite.Project{
Name: name,
CompanyName: companyName,
Description: description,
TermsAccepted: 1,
}
createdProject, err := projects.Insert(ctx, project)
project, err = projects.Insert(ctx, project)
assert.NotNil(t, createdProject)
assert.NotNil(t, project)
assert.Nil(t, err)
assert.NoError(t, err)
})
t.Run("Get project success", func(t *testing.T) {
projectsByOwnerID, err := projects.GetByOwnerID(ctx, owner.ID)
assert.Nil(t, err)
assert.NoError(t, err)
assert.Equal(t, len(projectsByOwnerID), 1)
assert.Equal(t, projectsByOwnerID[0].OwnerID, &owner.ID)
assert.Equal(t, projectsByOwnerID[0].Name, name)
assert.Equal(t, projectsByOwnerID[0].CompanyName, companyName)
assert.Equal(t, projectsByOwnerID[0].Description, description)
assert.Equal(t, projectsByOwnerID[0].TermsAccepted, 1)
projectByID, err := projects.Get(ctx, projectsByOwnerID[0].ID)
projectByID, err := projects.Get(ctx, project.ID)
assert.Nil(t, err)
assert.NoError(t, err)
assert.Equal(t, projectByID.ID, projectsByOwnerID[0].ID)
assert.Equal(t, projectByID.OwnerID, &owner.ID)
assert.Equal(t, projectByID.ID, project.ID)
assert.Equal(t, projectByID.Name, name)
assert.Equal(t, projectByID.CompanyName, companyName)
assert.Equal(t, projectByID.Description, description)
assert.Equal(t, projectByID.TermsAccepted, 1)
})
t.Run("Update project success", func(t *testing.T) {
oldProjects, err := projects.GetByOwnerID(ctx, owner.ID)
oldProject, err := projects.Get(ctx, project.ID)
assert.NoError(t, err)
assert.NotNil(t, oldProjects)
assert.Equal(t, len(oldProjects), 1)
assert.NotNil(t, oldProject)
// creating new project with updated values
newProject := &satellite.Project{
ID: oldProjects[0].ID,
OwnerID: &owner.ID,
ID: oldProject.ID,
Description: newDescription,
TermsAccepted: 2,
}
@ -145,28 +109,27 @@ func TestProjectsRepository(t *testing.T) {
assert.NoError(t, err)
// fetching updated project from db
newProject, err = projects.Get(ctx, oldProjects[0].ID)
newProject, err = projects.Get(ctx, oldProject.ID)
assert.NoError(t, err)
assert.Equal(t, newProject.ID, oldProjects[0].ID)
assert.Equal(t, newProject.OwnerID, &owner.ID)
assert.Equal(t, newProject.ID, oldProject.ID)
assert.Equal(t, newProject.Description, newDescription)
assert.Equal(t, newProject.TermsAccepted, 2)
})
t.Run("Delete project success", func(t *testing.T) {
oldProjects, err := projects.GetByOwnerID(ctx, owner.ID)
oldProject, err := projects.Get(ctx, project.ID)
assert.NoError(t, err)
assert.NotNil(t, oldProjects)
assert.NotNil(t, oldProject)
err = projects.Delete(ctx, oldProjects[0].ID)
err = projects.Delete(ctx, oldProject.ID)
assert.Nil(t, err)
assert.NoError(t, err)
_, err = projects.Get(ctx, oldProjects[0].ID)
_, err = projects.Get(ctx, oldProject.ID)
assert.NotNil(t, err)
assert.Error(t, err)
@ -177,10 +140,9 @@ func TestProjectsRepository(t *testing.T) {
assert.Nil(t, err)
assert.NoError(t, err)
assert.Equal(t, len(allProjects), 1)
assert.Equal(t, len(allProjects), 0)
newProject := &satellite.Project{
OwnerID: &owner.ID,
Description: description,
Name: name,
TermsAccepted: 1,
@ -195,10 +157,9 @@ func TestProjectsRepository(t *testing.T) {
assert.Nil(t, err)
assert.NoError(t, err)
assert.Equal(t, len(allProjects), 2)
assert.Equal(t, len(allProjects), 1)
newProject2 := &satellite.Project{
OwnerID: &owner.ID,
Description: description,
Name: name,
TermsAccepted: 1,
@ -213,7 +174,7 @@ func TestProjectsRepository(t *testing.T) {
assert.Nil(t, err)
assert.NoError(t, err)
assert.Equal(t, len(allProjects), 3)
assert.Equal(t, len(allProjects), 2)
})
}
@ -237,21 +198,4 @@ func TestProjectFromDbx(t *testing.T) {
assert.NotNil(t, err)
assert.Error(t, err)
})
t.Run("can't create dbo from dbx model with invalid OwnerID", func(t *testing.T) {
projectID, err := uuid.New()
assert.NoError(t, err)
assert.Nil(t, err)
dbxProject := dbx.Project{
Id: projectID[:],
OwnerId: []byte("qweqwe"),
}
project, err := projectFromDBX(&dbxProject)
assert.Nil(t, project)
assert.NotNil(t, err)
assert.Error(t, err)
})
}

View File

@ -1,134 +0,0 @@
// Copyright (C) 2018 Storj Labs, Inc.
// See LICENSE for copying information.
package satelliteql
import (
"github.com/graphql-go/graphql"
"storj.io/storj/pkg/satellite"
)
const (
companyType = "company"
companyInputType = "companyInput"
fieldUserID = "userID"
fieldName = "name"
fieldAddress = "address"
fieldCountry = "country"
fieldCity = "city"
fieldState = "state"
fieldPostalCode = "postalCode"
)
// graphqlCompany creates *graphql.Object type representation of satellite.Company
func graphqlCompany() *graphql.Object {
return graphql.NewObject(graphql.ObjectConfig{
Name: companyType,
Fields: graphql.Fields{
fieldUserID: &graphql.Field{
Type: graphql.String,
},
fieldName: &graphql.Field{
Type: graphql.String,
},
fieldAddress: &graphql.Field{
Type: graphql.String,
},
fieldCountry: &graphql.Field{
Type: graphql.String,
},
fieldCity: &graphql.Field{
Type: graphql.String,
},
fieldState: &graphql.Field{
Type: graphql.String,
},
fieldPostalCode: &graphql.Field{
Type: graphql.String,
},
},
})
}
// graphqlCompanyInput creates graphql.InputObject type needed to register/update satellite.Company
func graphqlCompanyInput() *graphql.InputObject {
return graphql.NewInputObject(graphql.InputObjectConfig{
Name: companyInputType,
Fields: graphql.InputObjectConfigFieldMap{
fieldName: &graphql.InputObjectFieldConfig{
Type: graphql.String,
},
fieldAddress: &graphql.InputObjectFieldConfig{
Type: graphql.String,
},
fieldCountry: &graphql.InputObjectFieldConfig{
Type: graphql.String,
},
fieldCity: &graphql.InputObjectFieldConfig{
Type: graphql.String,
},
fieldState: &graphql.InputObjectFieldConfig{
Type: graphql.String,
},
fieldPostalCode: &graphql.InputObjectFieldConfig{
Type: graphql.String,
},
},
})
}
// fromMapCompanyInfo creates satellite.CompanyInfo from input args
func fromMapCompanyInfo(args map[string]interface{}) (company satellite.CompanyInfo) {
company.Name, _ = args[fieldName].(string)
company.Address, _ = args[fieldAddress].(string)
company.Country, _ = args[fieldCountry].(string)
company.City, _ = args[fieldCity].(string)
company.State, _ = args[fieldState].(string)
company.PostalCode, _ = args[fieldPostalCode].(string)
return
}
// fillCompanyInfo fills satellite.CompanyInfo from satellite.Company and input args
func fillCompanyInfo(company *satellite.Company, args map[string]interface{}) satellite.CompanyInfo {
info := satellite.CompanyInfo{
Name: company.Name,
Address: company.Address,
Country: company.Country,
City: company.City,
State: company.State,
PostalCode: company.PostalCode,
}
for fName, fValue := range args {
val, ok := fValue.(string)
if !ok {
continue
}
switch fName {
case fieldName:
info.Name = val
company.Name = val
case fieldAddress:
info.Address = val
company.Address = val
case fieldCountry:
info.Country = val
company.Country = val
case fieldCity:
info.City = val
company.City = val
case fieldState:
info.State = val
company.State = val
case fieldPostalCode:
info.PostalCode = val
company.PostalCode = val
}
}
return info
}

View File

@ -21,9 +21,6 @@ const (
deleteUserMutation = "deleteUser"
changeUserPasswordMutation = "changeUserPassword"
createCompanyMutation = "createCompany"
updateCompanyMutation = "updateCompany"
createProjectMutation = "createProject"
deleteProjectMutation = "deleteProject"
updateProjectDescriptionMutation = "updateProjectDescription"
@ -151,62 +148,6 @@ func rootMutation(service *satellite.Service, types Types) *graphql.Object {
return user, err
},
},
createCompanyMutation: &graphql.Field{
Type: types.Company(),
Args: graphql.FieldConfigArgument{
fieldUserID: &graphql.ArgumentConfig{
Type: graphql.String,
},
input: &graphql.ArgumentConfig{
Type: graphql.NewNonNull(types.CompanyInput()),
},
},
Resolve: func(p graphql.ResolveParams) (interface{}, error) {
id, err := uuidIDAuthFallback(p, fieldUserID)
if err != nil {
return nil, err
}
input, _ := p.Args[input].(map[string]interface{})
info := fromMapCompanyInfo(input)
return service.CreateCompany(p.Context, *id, info)
},
},
updateCompanyMutation: &graphql.Field{
Type: types.Company(),
Args: graphql.FieldConfigArgument{
fieldUserID: &graphql.ArgumentConfig{
Type: graphql.String,
},
input: &graphql.ArgumentConfig{
Type: graphql.NewNonNull(types.CompanyInput()),
},
},
Resolve: func(p graphql.ResolveParams) (interface{}, error) {
id, err := uuidIDAuthFallback(p, fieldUserID)
if err != nil {
return nil, err
}
input, _ := p.Args[input].(map[string]interface{})
company, err := service.GetCompany(p.Context, *id)
if err != nil {
return nil, err
}
updatedCompany := *company
info := fillCompanyInfo(&updatedCompany, input)
err = service.UpdateCompany(p.Context, *id, info)
if err != nil {
return company, err
}
return &updatedCompany, nil
},
},
// creates project from input params
createProjectMutation: &graphql.Field{
Type: types.Project(),

View File

@ -11,9 +11,8 @@ import (
const (
projectType = "project"
projectInputType = "projectInput"
fieldName = "name"
fieldOwnerName = "ownerName"
fieldCompanyName = "companyName"
fieldDescription = "description"
// Indicates if user accepted Terms & Conditions during project creation
// Used in input model
@ -35,9 +34,6 @@ func graphqlProject(service *satellite.Service, types Types) *graphql.Object {
fieldName: &graphql.Field{
Type: graphql.String,
},
fieldCompanyName: &graphql.Field{
Type: graphql.String,
},
fieldDescription: &graphql.Field{
Type: graphql.String,
},
@ -47,23 +43,6 @@ func graphqlProject(service *satellite.Service, types Types) *graphql.Object {
fieldCreatedAt: &graphql.Field{
Type: graphql.DateTime,
},
fieldOwnerName: &graphql.Field{
Type: graphql.String,
Resolve: func(p graphql.ResolveParams) (interface{}, error) {
// TODO: return owner (user) instead of ownerName
project, _ := p.Source.(satellite.Project)
if project.OwnerID == nil {
return "", nil
}
user, err := service.GetUser(p.Context, *project.OwnerID)
if err != nil {
return "", nil
}
return user.FirstName + " " + user.LastName, nil
},
},
fieldMembers: &graphql.Field{
Type: graphql.NewList(types.ProjectMember()),
Args: graphql.FieldConfigArgument{
@ -113,9 +92,6 @@ func graphqlProjectInput() *graphql.InputObject {
fieldName: &graphql.InputObjectFieldConfig{
Type: graphql.String,
},
fieldCompanyName: &graphql.InputObjectFieldConfig{
Type: graphql.String,
},
fieldDescription: &graphql.InputObjectFieldConfig{
Type: graphql.String,
},
@ -131,7 +107,6 @@ func fromMapProjectInfo(args map[string]interface{}) (project satellite.ProjectI
project.Name, _ = args[fieldName].(string)
project.Description, _ = args[fieldDescription].(string)
project.IsTermsAccepted, _ = args[fieldIsTermsAccepted].(bool)
project.CompanyName, _ = args[fieldCompanyName].(string)
return
}

View File

@ -17,12 +17,10 @@ type Types interface {
Token() *graphql.Object
User() *graphql.Object
Company() *graphql.Object
Project() *graphql.Object
ProjectMember() *graphql.Object
UserInput() *graphql.InputObject
CompanyInput() *graphql.InputObject
ProjectInput() *graphql.InputObject
}
@ -34,23 +32,16 @@ type TypeCreator struct {
token *graphql.Object
user *graphql.Object
company *graphql.Object
project *graphql.Object
projectMember *graphql.Object
userInput *graphql.InputObject
companyInput *graphql.InputObject
projectInput *graphql.InputObject
}
// Create create types and check for error
func (c *TypeCreator) Create(service *satellite.Service) error {
// inputs
c.companyInput = graphqlCompanyInput()
if err := c.companyInput.Error(); err != nil {
return err
}
c.userInput = graphqlUserInput(c)
if err := c.userInput.Error(); err != nil {
return err
@ -62,12 +53,7 @@ func (c *TypeCreator) Create(service *satellite.Service) error {
}
// entities
c.company = graphqlCompany()
if err := c.company.Error(); err != nil {
return err
}
c.user = graphqlUser(service, c)
c.user = graphqlUser()
if err := c.user.Error(); err != nil {
return err
}
@ -121,11 +107,6 @@ func (c *TypeCreator) User() *graphql.Object {
return c.user
}
// Company returns instance of satellite.Company *graphql.Object
func (c *TypeCreator) Company() *graphql.Object {
return c.company
}
// Project returns instance of satellite.Project *graphql.Object
func (c *TypeCreator) Project() *graphql.Object {
return c.project
@ -141,11 +122,6 @@ func (c *TypeCreator) UserInput() *graphql.InputObject {
return c.userInput
}
// CompanyInput returns instance of CompanyInfo *graphql.Object
func (c *TypeCreator) CompanyInput() *graphql.InputObject {
return c.companyInput
}
// ProjectInput returns instance of ProjectInfo *graphql.Object
func (c *TypeCreator) ProjectInput() *graphql.InputObject {
return c.projectInput

View File

@ -4,8 +4,6 @@
package satelliteql
import (
"context"
"github.com/graphql-go/graphql"
"storj.io/storj/pkg/satellite"
@ -15,6 +13,7 @@ const (
userType = "user"
userInputType = "userInput"
fieldUserID = "userID"
fieldID = "id"
fieldEmail = "email"
fieldPassword = "password"
@ -48,28 +47,9 @@ func baseUserConfig() graphql.ObjectConfig {
}
// graphqlUser creates *graphql.Object type representation of satellite.User
func graphqlUser(service *satellite.Service, types Types) *graphql.Object {
config := baseUserConfig()
config.Fields.(graphql.Fields)[companyType] = &graphql.Field{
Type: types.Company(),
Resolve: func(p graphql.ResolveParams) (interface{}, error) {
user, _ := p.Source.(*satellite.User)
// if root value contains context used instead one from params
// as RootValue seems like the only way to pass additional from parent resolver
rootValue := p.Info.RootValue.(map[string]interface{})
ctx := rootValue["context"]
if ctx != nil {
return service.GetCompany(ctx.(context.Context), user.ID)
}
return service.GetCompany(p.Context, user.ID)
},
}
return graphql.NewObject(config)
// TODO: simplify
func graphqlUser() *graphql.Object {
return graphql.NewObject(baseUserConfig())
}
// graphqlUserInput creates graphql.InputObject type needed to register/update satellite.User

View File

@ -169,64 +169,9 @@ func (s *Service) DeleteUser(ctx context.Context, id uuid.UUID, password string)
return ErrUnauthorized.New("origin password is incorrect")
}
projects, err := s.store.Projects().GetByOwnerID(ctx, auth.User.ID)
if err != nil {
return errs.Wrap(err)
}
if len(projects) > 0 {
return errs.New("can't delete account with project ownership")
}
return s.store.Users().Delete(ctx, id)
}
// CreateCompany creates Company for User with given id
func (s *Service) CreateCompany(ctx context.Context, userID uuid.UUID, info CompanyInfo) (*Company, error) {
_, err := GetAuth(ctx)
if err != nil {
return nil, err
}
return s.store.Companies().Insert(ctx, &Company{
UserID: userID,
Name: info.Name,
Address: info.Address,
Country: info.Country,
City: info.City,
State: info.State,
PostalCode: info.PostalCode,
})
}
// GetCompany returns Company by userID
func (s *Service) GetCompany(ctx context.Context, userID uuid.UUID) (*Company, error) {
_, err := GetAuth(ctx)
if err != nil {
return nil, err
}
return s.store.Companies().GetByUserID(ctx, userID)
}
// UpdateCompany updates Company with given userID
func (s *Service) UpdateCompany(ctx context.Context, userID uuid.UUID, info CompanyInfo) error {
_, err := GetAuth(ctx)
if err != nil {
return err
}
return s.store.Companies().Update(ctx, &Company{
UserID: userID,
Name: info.Name,
Address: info.Address,
Country: info.Country,
City: info.City,
State: info.State,
PostalCode: info.PostalCode,
})
}
// GetProject is a method for querying project by id
func (s *Service) GetProject(ctx context.Context, projectID uuid.UUID) (*Project, error) {
_, err := GetAuth(ctx)
@ -259,9 +204,7 @@ func (s *Service) CreateProject(ctx context.Context, projectInfo ProjectInfo) (*
}
project := &Project{
OwnerID: &auth.User.ID,
Description: projectInfo.Description,
CompanyName: projectInfo.CompanyName,
Name: projectInfo.Name,
TermsAccepted: 1, //TODO: get lat version of Term of Use
}
@ -286,20 +229,12 @@ func (s *Service) CreateProject(ctx context.Context, projectInfo ProjectInfo) (*
// DeleteProject is a method for deleting project by id
func (s *Service) DeleteProject(ctx context.Context, projectID uuid.UUID) error {
auth, err := GetAuth(ctx)
_, err := GetAuth(ctx)
if err != nil {
return err
}
project, err := s.store.Projects().Get(ctx, projectID)
if err != nil {
return err
}
if !uuid.Equal(auth.User.ID, *project.OwnerID) {
return ErrUnauthorized.New("only owner can delete the project")
}
// TODO: before deletion we should check if user is a project member
return s.store.Projects().Delete(ctx, projectID)
}

View File

@ -58,7 +58,7 @@ export async function deleteProjectMember(userID: string, projectID: string): Pr
// Performs graqhQL request.
// Throws an exception if error occurs
export async function fetchProjectMembers(projectID: string): Promise<any> {
export async function fetchProjectMembers(projectID: string, limit: string, offset: string): Promise<any> {
let response: any = null;
try {
response = await apollo.query(
@ -68,15 +68,12 @@ export async function fetchProjectMembers(projectID: string): Promise<any> {
project(
id: "${projectID}",
) {
members {
members(limit: ${limit}, offset: ${offset}) {
user {
id,
firstName,
lastName,
email,
company {
name
}
},
joinedAt
}

View File

@ -7,112 +7,106 @@ import gql from 'graphql-tag';
// Performs graqhQL request.
// Throws an exception if error occurs
export async function createProject(project: Project): Promise<any> {
let response = await apollo.mutate(
{
mutation: gql(`
mutation {
createProject(
input: {
name: "${project.name}",
description: "${project.description}",
companyName: "${project.companyName}",
isTermsAccepted: ${project.isTermsAccepted},
}
) {id}
}`
),
fetchPolicy: 'no-cache',
}
);
let response: any = null;
if (!response) {
// TODO: replace with popup in future
console.error('cannot create project');
try {
response = await apollo.mutate(
{
mutation: gql(`
mutation {
createProject(
input: {
name: "${project.name}",
description: "${project.description}",
isTermsAccepted: ${project.isTermsAccepted},
}
) {id}
}`
),
fetchPolicy: 'no-cache',
}
);
} catch (e) {
console.error(e);
}
return null;
}
return response;
return response;
}
// Performs graqhQL request for fetching all projects of current user.
export async function fetchProjects(): Promise<any> {
let response = await apollo.query(
{
query: gql(`
query {
myProjects{
name
id
description
createdAt
ownerName
companyName
isTermsAccepted
}
}`
),
fetchPolicy: 'no-cache',
}
);
let response: any = null;
if (!response) {
// TODO: replace with popup in future
console.error('cannot fetch projects');
try {
response = await apollo.query(
{
query: gql(`
query {
myProjects{
name
id
description
createdAt
isTermsAccepted
}
}`
),
fetchPolicy: 'no-cache',
}
);
return null;
} catch (e) {
console.error(e);
}
return response;
return response;
}
// Performs graqhQL request for updating selected project description
export async function updateProject(projectID: string, description: string): Promise<any> {
let response = await apollo.mutate(
{
mutation: gql(`
mutation {
updateProjectDescription(
id: "${projectID}",
description: "${description}"
)
}`
),
fetchPolicy: 'no-cache',
}
);
let response: any = null;
if (!response) {
// TODO: replace with popup in future
console.error('cannot update project');
try {
response = await apollo.mutate(
{
mutation: gql(`
mutation {
updateProjectDescription(
id: "${projectID}",
description: "${description}"
)
}`
),
fetchPolicy: 'no-cache',
}
);
} catch (e) {
console.error(e);
}
return null;
}
return response;
return response;
}
// Performs graqhQL request for deleting selected project
export async function deleteProject(projectID: string): Promise<any> {
let response = await apollo.mutate(
{
mutation: gql(`
mutation {
deleteProject(
id: "${projectID}"
)
}`
),
fetchPolicy: 'no-cache',
}
);
let response: any = null;
if (!response) {
// TODO: replace with popup in future
console.error('cannot delete project');
try {
response = await apollo.mutate(
{
mutation: gql(`
mutation {
deleteProject(
id: "${projectID}"
)
}`
),
fetchPolicy: 'no-cache',
}
);
} catch (e) {
console.error(e);
}
return null;
}
return response;
return response;
}

View File

@ -7,68 +7,33 @@ import gql from 'graphql-tag';
// Performs update user info graphQL mutation request.
// Returns User object if succeed, null otherwise
export async function updateBasicUserInfoRequest(user: User) {
let response = await apolloManager.mutate(
{
mutation: gql(`
mutation {
updateUser (
id: "${user.id}",
input: {
email: "${user.email}",
firstName: "${user.firstName}",
lastName: "${user.lastName}"
let response: any = null;
try {
response = await apolloManager.mutate(
{
mutation: gql(`
mutation {
updateUser (
id: "${user.id}",
input: {
email: "${user.email}",
firstName: "${user.firstName}",
lastName: "${user.lastName}"
}
) {
email,
firstName,
lastName
}
) {
email,
firstName,
lastName
}
}
`),
fetchPolicy: 'no-cache',
}
);
if (!response) {
return null;
}
return response;
}
// Performs update company info graphQL mutation request.
// Returns Company object if succeed, null otherwise
export async function updateCompanyInfoRequest(userId: string, company: Company) {
let response = await apolloManager.mutate(
{
mutation: gql(`
mutation {
updateCompany(
userID:"${userId}",
input:{
name:"${company.name}",
address:"${company.address}",
country:"${company.country}",
city:"${company.city}",
state:"${company.state}",
postalCode:"${company.postalCode}"
}
){
name,
address,
country,
city,
state,
postalCode
}
}
`)
}
);
if (!response) {
return null;
}
}`
),
fetchPolicy: 'no-cache',
}
);
} catch (e) {
console.error(e);
}
return response;
}
@ -76,29 +41,31 @@ export async function updateCompanyInfoRequest(userId: string, company: Company)
// Performs change password graphQL mutation
// Returns base user fields
export async function updatePasswordRequest(userId: string, password: string) {
let response = await apolloManager.mutate(
{
mutation: gql(`
mutation {
updateUser (
id: "${userId}",
input: {
password: "${password}"
}
) {
email,
firstName,
lastName
}
}
`),
fetchPolicy: 'no-cache',
}
);
let response: any = null;
if (!response) {
return null;
}
try {
response = await apolloManager.mutate(
{
mutation: gql(`
mutation {
updateUser (
id: "${userId}",
input: {
password: "${password}"
}
) {
email,
firstName,
lastName
}
}`
),
fetchPolicy: 'no-cache',
}
);
} catch (e) {
console.error(e);
}
return response;
}
@ -107,98 +74,110 @@ export async function updatePasswordRequest(userId: string, password: string) {
// Throws an exception if error occurs
// Returns object with newly created user
export async function createUserRequest(user: User, password: string): Promise<any> {
let response = await apolloManager.mutate(
{
mutation: gql(`
mutation {
createUser(
input:{
email: "${user.email}",
password: "${password}",
firstName: "${user.firstName}",
lastName: "${user.lastName}",
company: {
name: "${user.company.name}",
address: "${user.company.address}",
country: "${user.company.country}",
city: "${user.company.city}",
state: "${user.company.state}",
postalCode: "${user.company.postalCode}"
}
}
)
}
`),
fetchPolicy: 'no-cache',
}
);
let response: any = null;
if (!response) {
return null;
}
try {
response = await apolloManager.mutate(
{
mutation: gql(`
mutation {
createUser(
input:{
email: "${user.email}",
password: "${password}",
firstName: "${user.firstName}",
lastName: "${user.lastName}",
}
)
}`
),
fetchPolicy: 'no-cache',
}
);
} catch (e) {
console.error(e);
}
return response;
}
// Performs graqhQL request.
// Returns Token, User objects.
// Throws an exception if error occurs
export async function getTokenRequest(email: string, password: string): Promise<any> {
let response = await apolloManager.query(
{
query: gql(`
query {
token(email: "${email}",
password: "${password}") {
token,
user{
id,
firstName,
lastName,
email,
company{
name,
address,
country,
city,
state,
postalCode
}
}
}
}`),
fetchPolicy: 'no-cache',
}
);
let response: any = null;
if (!response) {
return null;
}
try {
response = await apolloManager.query(
{
query: gql(`
query {
token(email: "${email}",
password: "${password}") {
token
}
}`
),
fetchPolicy: 'no-cache',
}
);
} catch (e) {
console.error(e);
}
return response;
return response;
}
// Performs graqhQL request.
// Returns Token, User objects.
// Throws an exception if error occurs
export async function getUserRequest(): Promise<any> {
let response: any = null;
try {
response = await apolloManager.query(
{
query: gql(`
query {
user {
firstName,
lastName,
email,
}
}`
),
fetchPolicy: 'no-cache',
}
);
} catch (e) {
console.error(e);
}
return response;
}
// Performs graqhQL request.
// User object.
// Throws an exception if error occurs
export async function deleteUserAccountRequest(userId: string): Promise<any> {
let response = await apolloManager.mutate(
{
mutation: gql(`
mutation {
deleteUser(id: "${userId}") {
id
}
}
`),
fetchPolicy: 'no-cache'
}
);
export async function deleteUserAccountRequest(password: string): Promise<any> {
let response: any = null;
if (!response) {
return null;
}
try {
response = await apolloManager.mutate(
{
mutation: gql(`
mutation {
deleteUser(password: "${password}") {
id
}
}`
),
fetchPolicy: 'no-cache'
}
);
} catch (e) {
console.error(e);
}
return response;
}

View File

@ -55,75 +55,6 @@
</div>
</div>
<!--end of Account settings area -->
<!--start of Company area -->
<div class="account-area-company-container">
<h1>Company</h1>
<h2>Optional</h2>
<div class="account-area-row-container">
<HeaderedInput
class="full-input"
label="Company Name"
placeholder ="Enter Company Name"
width="100%"
ref="companyNameInput"
:initValue="originalCompanyName"
@setData="setCompanyName" />
</div>
<div class="account-area-row-container">
<HeaderedInput
class="full-input"
label="Company Address"
placeholder ="Enter Company Address"
width="100%"
ref="companyAddressInput"
:initValue="originalCompanyAddress"
@setData="setCompanyAddress" />
</div>
<div class="account-area-row-container">
<HeaderedInput
label="Country"
placeholder ="Enter Country"
width="100%"
ref="companyCountryInput"
:initValue="originalCompanyCountry"
@setData="setCompanyCountry" />
<HeaderedInput
label="City"
placeholder ="Enter City"
width="100%"
ref="companyCityInput"
:initValue="originalCompanyCity"
@setData="setCompanyCity" />
</div>
<div class="account-area-row-container">
<HeaderedInput
label="State"
placeholder ="Enter State"
width="100%"
ref="companyStateInput"
:initValue="originalCompanyState"
@setData="setCompanyState" />
<HeaderedInput
label="Postal Code"
placeholder ="Enter Postal Code"
width="100%"
ref="companyPostalCodeInput"
:initValue="originalCompanyPostalCode"
@setData="setCompanyPostalCode" />
</div>
<div v-if="isCompanyEditing" class="account-area-save-button-area" >
<div class="account-area-save-button-area__btn">
<Button class="account-area-save-button-area__cancel-button" label="Cancel" width="140px" height="50px" :onPress="onCancelCompanyButtonClick" isWhite/>
<Button label="Save" width="140px" height="50px" :onPress="onSaveCompanySettingsButtonClick"/>
</div>
</div>
<div v-if="!isCompanyEditing" class="account-area-save-button-area" >
<div class="account-area-save-button-area__btn">
<Button label="Save" width="140px" height="50px" :onPress="onSaveCompanySettingsButtonClick" isWhite isDisabled/>
</div>
</div>
</div>
<!--end of Company area -->
<!--start of Password area -->
<div class="account-area-password-container">
<h1>Change Password</h1>
@ -206,22 +137,6 @@ import ROUTES from '@/utils/constants/routerConstants';
newEmail: '',
isAccountSettingsEditing: false,
originalCompanyName: this.$store.getters.user.company.name,
originalCompanyAddress: this.$store.getters.user.company.address,
originalCompanyCountry: this.$store.getters.user.company.country,
originalCompanyCity: this.$store.getters.user.company.city,
originalCompanyState: this.$store.getters.user.company.state,
originalCompanyPostalCode: this.$store.getters.user.company.postalCode,
companyName: this.$store.getters.user.company.name,
companyAddress: this.$store.getters.user.company.address,
companyCountry: this.$store.getters.user.company.country,
companyCity: this.$store.getters.user.company.city,
companyState: this.$store.getters.user.company.state,
companyPostalCode: this.$store.getters.user.company.postalCode,
isCompanyEditing: false,
oldPassword: '',
newPassword: '',
confirmationPassword: '',
@ -309,70 +224,6 @@ import ROUTES from '@/utils/constants/routerConstants';
this.$data.isAccountSettingsEditing = false;
},
setCompanyName: function (value: string) {
this.$data.companyName = value;
this.$data.isCompanyEditing = true;
},
setCompanyAddress: function (value: string) {
this.$data.companyAddress = value;
this.$data.isCompanyEditing = true;
},
setCompanyCountry: function (value: string) {
this.$data.companyCountry = value;
this.$data.isCompanyEditing = true;
},
setCompanyCity: function (value: string) {
this.$data.companyCity = value;
this.$data.isCompanyEditing = true;
},
setCompanyState: function (value: string) {
this.$data.companyState = value;
this.$data.isCompanyEditing = true;
},
setCompanyPostalCode: function (value: string) {
this.$data.companyPostalCode = value;
this.$data.isCompanyEditing = true;
},
onCancelCompanyButtonClick: function () {
this.$data.companyName = this.$data.originalCompanyName;
this.$data.companyAddress = this.$data.originalCompanyAddress;
this.$data.companyCountry = this.$data.originalCompanyCountry;
this.$data.companyCity = this.$data.originalCompanyCity;
this.$data.companyState = this.$data.originalCompanyState;
this.$data.companyPostalCode = this.$data.originalCompanyPostalCode;
(this.$refs['companyNameInput'] as HeaderedInput).setValue(this.$data.originalCompanyName);
(this.$refs['companyAddressInput'] as HeaderedInput).setValue(this.$data.originalCompanyAddress);
(this.$refs['companyCountryInput'] as HeaderedInput).setValue(this.$data.originalCompanyCountry);
(this.$refs['companyCityInput'] as HeaderedInput).setValue(this.$data.originalCompanyCity);
(this.$refs['companyStateInput'] as HeaderedInput).setValue(this.$data.originalCompanyState);
(this.$refs['companyPostalCodeInput'] as HeaderedInput).setValue(this.$data.originalCompanyPostalCode);
this.$data.isCompanyEditing = false;
},
onSaveCompanySettingsButtonClick: async function () {
let user = {
id: this.$store.getters.user.id,
company: {
name: this.$data.companyName,
address: this.$data.companyAddress,
country: this.$data.companyCountry,
city: this.$data.companyCity,
state: this.$data.companyState,
postalCode: this.$data.companyPostalCode
}
};
let isSuccess = await this.$store.dispatch('updateCompanyInfo', user);
if (!isSuccess) {
// TODO Change to popup
console.error('error while changing company info');
return;
}
this.$data.isCompanyEditing = false;
},
setOldPassword: function (value: string) {
this.$data.oldPassword = value;
this.$data.oldPasswordError = '';
@ -573,10 +424,6 @@ export default class AccountArea extends Vue {
}
}
.input-container.full-input {
width: 100%;
}
@media screen and (max-width: 1020px) {
.account-area-save-button-area {
flex-direction: column;

View File

@ -18,13 +18,6 @@
:error="nameError"
@setData="setProjectName">
</HeaderedInput>
<HeaderedInput
label="Company Name"
placeholder="Enter Company Name"
class="full-input"
width="100%"
@setData="setCompanyName">
</HeaderedInput>
<HeaderedInput
label="Description"
placeholder="Enter Project Description"
@ -73,7 +66,6 @@ import Button from '@/components/common/Button.vue';
data: function () {
return {
name: '',
companyName: '',
description: '',
isTermsAccepted: false,
termsAcceptedError: false,
@ -85,9 +77,6 @@ import Button from '@/components/common/Button.vue';
this.$data.name = value;
this.$data.nameError = '';
},
setCompanyName: function (value: string): void {
this.$data.companyName = value;
},
setProjectDescription: function (value: string): void {
this.$data.description = value;
},
@ -119,7 +108,6 @@ import Button from '@/components/common/Button.vue';
let isSuccess = this.$store.dispatch('createProject', {
name: this.$data.name,
description: this.$data.description,
companyName: this.$data.companyName,
isTermsAccepted: this.$data.isTermsAccepted,
});

View File

@ -37,7 +37,7 @@ import ProjectSelectionDropdown from './ProjectSelectionDropdown.vue';
return;
}
if (this.$store.getters.selectedProject.id) {
const isFetchProjectMemberSuccess = await this.$store.dispatch('fetchProjectMembers');
const isFetchProjectMemberSuccess = await this.$store.dispatch('fetchProjectMembers', {limit: 20, offset: 0});
if (!isFetchProjectMemberSuccess) {
// TODO: Replace with popup

View File

@ -10,10 +10,6 @@
<h2>Project Name</h2>
<h3>{{name}}</h3>
</div>
<div class="project-details-info-container__name-container">
<h2>Company / Organization</h2>
<h3>{{companyName}}</h3>
</div>
</div>
<div class="project-details-info-container">
<div class="project-details-info-container__description-container" v-if="!isEditing">
@ -55,10 +51,6 @@
</div>
</div>
</div>
<div class="project-details__terms-area">
<img src="static/images/projectDetails/checked.svg" alt="">
<h2>{{projectApproval}}</h2>
</div>
<div class="project-details__button-area">
<!-- TODO: change vw to px -->
<Button label="Delete project" width="10vw" height="5vh" :onPress="onDeleteButtonClick" isWhite/>
@ -133,14 +125,6 @@ import { EMPTY_STATE_IMAGES } from '@/utils/constants/emptyStatesImages';
description: function (): string {
return this.$store.getters.selectedProject.description;
},
companyName: function (): string {
return this.$store.getters.selectedProject.companyName;
},
projectApproval: function (): string {
let date = new Date(this.$store.getters.selectedProject.createdAt);
return `Project Approval ${date.toLocaleDateString()} by ${this.$store.getters.selectedProject.ownerName}`;
},
// this computed is used to indicate if project is selected.
// if false - we should change UI
isProjectSelected: function (): boolean {
@ -309,4 +293,4 @@ export default class ProjectDetailsArea extends Vue {
}
}
}
</style>
</style>

View File

@ -81,9 +81,9 @@ export const projectMembersModule = {
clearProjectMemberSelection: function ({commit}: any) {
commit(PROJECT_MEMBER_MUTATIONS.CLEAR_SELECTION);
},
fetchProjectMembers: async function ({commit, rootGetters}: any): Promise<boolean> {
fetchProjectMembers: async function ({commit, rootGetters}: any, limitoffset: any): Promise<boolean> {
const projectId = rootGetters.selectedProject.id;
const response = await fetchProjectMembers(projectId);
const response = await fetchProjectMembers(projectId, limitoffset.limit, limitoffset.offset);
if (!response || !response.data) {
return false;

View File

@ -10,7 +10,6 @@ export const projectsModule = {
selectedProject: {
name: 'Choose Project',
id: '',
ownerName: '',
companyName: '',
description: '',
isTermsAccepted: false,

View File

@ -5,8 +5,8 @@ import { USER_MUTATIONS, } from '../mutationConstants';
import {
deleteUserAccountRequest,
updateBasicUserInfoRequest,
updateCompanyInfoRequest,
updatePasswordRequest
updatePasswordRequest,
getUserRequest
} from '@/api/users';
export const usersModule = {
@ -16,14 +16,6 @@ export const usersModule = {
lastName: '',
email: '',
id: '',
company: {
name: '',
address: '',
country: '',
city: '',
state: '',
postalCode: '',
}
}
},
@ -33,12 +25,6 @@ export const usersModule = {
state.user.lastName = user.lastName;
state.user.email = user.email;
state.user.id = user.id;
state.user.company.name = user.company.name;
state.user.company.address = user.company.address;
state.user.company.country = user.company.country;
state.user.company.city = user.company.city;
state.user.company.state = user.company.state;
state.user.company.postalCode = user.company.postalCode;
},
[USER_MUTATIONS.REVERT_TO_DEFAULT_USER_INFO](state: any): void {
@ -46,12 +32,6 @@ export const usersModule = {
state.user.lastName = '';
state.user.email = '';
state.user.id = '';
state.user.company.name = '';
state.user.company.address = '';
state.user.company.country = '';
state.user.company.city = '';
state.user.company.state = '';
state.user.company.postalCode = '';
},
[USER_MUTATIONS.UPDATE_USER_INFO](state: any, user: User): void {
@ -59,19 +39,9 @@ export const usersModule = {
state.user.lastName = user.lastName;
state.user.email = user.email;
},
[USER_MUTATIONS.UPDATE_COMPANY_INFO](state: any, company: Company): void {
state.user.company.name = company.name;
state.user.company.address = company.address;
state.user.company.country = company.country;
state.user.company.city = company.city;
state.user.company.state = company.state;
state.user.company.postalCode = company.postalCode;
},
},
actions: {
setUserInfo: setUserInfo,
updateBasicUserInfo: async function ({commit}: any, userInfo: User): Promise<boolean> {
let response = await updateBasicUserInfoRequest(userInfo);
@ -83,37 +53,25 @@ export const usersModule = {
return true;
},
updateCompanyInfo: async function ({commit}: any, userInfo: User): Promise<boolean> {
let response = await updateCompanyInfoRequest(userInfo.id, userInfo.company);
if (!response || !response.data) {
return false;
}
commit(USER_MUTATIONS.UPDATE_COMPANY_INFO, response.data.updateCompany);
return true;
},
updatePassword: async function ({state}: any, password: string): Promise<boolean> {
let response = await updatePasswordRequest(state.user.id, password);
if (!response) {
console.error('error during password change');
return false;
}
return true;
return response !== null;
},
deleteUserAccount: async function ({commit, state}: any): Promise<boolean> {
let response = await deleteUserAccountRequest(state.user.id);
deleteUserAccount: async function ({commit, state}: any, password: string): Promise<boolean> {
let response = await deleteUserAccountRequest(password);
return response !== null;
},
getUser: async function ({commit}: any): Promise<boolean> {
let response = await getUserRequest();
if (!response) {
console.error('error during account delete');
return false;
}
commit(USER_MUTATIONS.SET_USER_INFO, response.data.user);
return true;
}
},
@ -125,7 +83,3 @@ export const usersModule = {
userName: (state: any) => `${state.user.firstName} ${state.user.lastName}`
},
};
function setUserInfo({commit}: any, userInfo: User): void {
commit(USER_MUTATIONS.SET_USER_INFO, userInfo);
}

View File

@ -5,7 +5,6 @@ export const USER_MUTATIONS = {
SET_USER_INFO: 'SET_USER_INFO',
REVERT_TO_DEFAULT_USER_INFO: 'REVERT_TO_DEFAULT_USER_INFO',
UPDATE_USER_INFO: 'UPDATE_USER_INFO',
UPDATE_COMPANY_INFO: 'UPDATE_COMPANY_INFO',
};
export const PROJECTS_MUTATIONS = {

View File

@ -4,11 +4,9 @@
// Project is a type, used for creating new project in backend
declare type Project = {
id: string,
ownerName: string,
name: string,
description: string,
companyName: string,
isTermsAccepted: boolean,
createdAt: string,
@ -28,9 +26,6 @@ declare type TeamMemberModel = {
email: string,
firstName: string,
lastName: string,
company: {
companyName: string,
}
}
joinedAt: string,
}

View File

@ -12,13 +12,6 @@ declare type RegisterData = {
passwordError: string,
repeatedPassword: string,
repeatedPasswordError: string,
companyName: string,
companyAddress: string,
country: string,
city: string,
state: string,
postalCode: string,
isTermsAccepted: boolean,
isTermsAcceptedError: boolean,
optionalAreaShown: boolean
}

View File

@ -6,14 +6,4 @@ declare type User = {
lastName: string,
email: string,
id: string,
company: Company
}
declare type Company = {
name: string,
address: string,
country: string,
city: string,
state: string,
postalCode: string
}
}

View File

@ -3,14 +3,34 @@
const tokenKey: string = 'tokenKey';
export function getToken(): string | null {
return sessionStorage.getItem(tokenKey);
export function getToken(): string {
return getCookie(tokenKey);
}
export function setToken(tokenValue: string): void {
sessionStorage.setItem(tokenKey, tokenValue);
document.cookie = tokenKey + '=' + tokenValue + '; path=/';
}
export function removeToken(): void {
sessionStorage.removeItem(tokenKey);
document.cookie = tokenKey + '=; path=/';
}
function getCookie(cname: string): string {
let name: string = cname + '=';
let decodedCookie: string = decodeURIComponent(document.cookie);
let ca: string[] = decodedCookie.split(';');
for (let i = 0; i < ca.length; i++) {
let c = ca[i];
while (c.charAt(0) === ' ') {
c = c.substring(1);
}
if (c.indexOf(name) === 0) {
return c.substring(name.length, c.length);
}
}
return '';
}

View File

@ -19,6 +19,10 @@ import DashboardHeader from '@/components/dashboard/DashboardHeader.vue';
import NavigationArea from '@/components/navigation/NavigationArea.vue';
@Component({
beforeMount: async function() {
// TODO: check error and show notification
this.$store.dispatch('getUser');
},
components: {
NavigationArea,
DashboardHeader

View File

@ -64,19 +64,15 @@ import { getTokenRequest } from '@/api/users';
this.$data.password = value;
},
onLogin: async function () {
try {
let loginData = await getTokenRequest(this.$data.email, this.$data.password);
let loginData = await getTokenRequest(this.$data.email, this.$data.password);
setToken(loginData.data.token.token);
this.$store.dispatch('setUserInfo', loginData.data.token.user)
.then(() => {
this.$router.push(ROUTES.DASHBOARD.path);
}).catch((error) => {
console.error(error);
});
} catch (error) {
console.error(error);
if (!loginData) {
// TODO: show popup here
return;
}
setToken(loginData.data.token.token);
this.$router.push(ROUTES.DASHBOARD.path);
}
},

View File

@ -54,72 +54,6 @@
@setData="setRepeatedPassword"
isPassword>
</HeaderedInput>
<div class="register-area__scrollable__form-area__company-area">
<h2>Company</h2>
<div class="register-area__scrollable__form-area__company-area__details-area"
v-on:click="showOptional">
<h2 v-if="!optionalAreaShown"
class="register-area__scrollable__form-area__company-area__details-area__text">
Details</h2>
<h2 v-if="optionalAreaShown"
class="register-area__scrollable__form-area__company-area__details-area__text">Hide
Details</h2>
<div class="register-area__scrollable__form-area__company-area__details-area__expander-area">
<img v-if="!optionalAreaShown" src="../../static/images/register/BlueExpand.svg"/>
<img v-if="optionalAreaShown" src="../../static/images/register/BlueHide.svg"/>
</div>
</div>
</div>
<HeaderedInput
class="full-input"
label="Company Name"
placeholder="Enter Company Name"
@setData="setCompanyName"
isOptional>
</HeaderedInput>
<!-- start of optional area -->
<transition name="fade">
<div id="optional-area"
v-bind:class="[optionalAreaShown ? 'optional-area--active' : 'optional-area']">
<HeaderedInput
class="full-input"
label="Company Address"
placeholder="Enter Company Address"
isOptional
isMultiline
@setData="setCompanyAddress"
height="100px">
</HeaderedInput>
<HeaderedInput
class="full-input"
label="Country"
placeholder="Enter Country"
@setData="setCountry"
isOptional>
</HeaderedInput>
<HeaderedInput
class="full-input"
label="City"
placeholder="Enter City"
@setData="setCity"
isOptional>
</HeaderedInput>
<HeaderedInput
class="full-input"
label="State"
placeholder="Enter State"
@setData="setState"
isOptional>
</HeaderedInput>
<HeaderedInput
class="full-input"
label="Postal Code"
placeholder="Enter Postal Code"
@setData="setPostalCode"
isOptional>
</HeaderedInput>
</div>
</transition>
<!-- end of optional area -->
<div class="register-area__scrollable__form-area__terms-area">
<Checkbox
@ -171,41 +105,10 @@ import { createUserRequest } from '@/api/users';
this.$data.repeatedPassword = value;
this.$data.repeatedPasswordError = '';
},
setCompanyName: function (value: string) {
this.$data.companyName = value;
},
setCompanyAddress: function (value: string) {
this.$data.companyAddress = value;
},
setCountry: function (value: string) {
this.$data.country = value;
},
setCity: function (value: string) {
this.$data.city = value;
},
setState: function (value: string) {
this.$data.state = value;
},
setPostalCode: function (value: string) {
this.$data.postalCode = value;
},
setTermsAccepted: function (value: boolean) {
this.$data.isTermsAccepted = value;
this.$data.isTermsAcceptedError = false;
},
showOptional: function () {
let scrollableDiv = document.querySelector('.register-area__scrollable');
if (this.$data.optionalAreaShown == false) {
setTimeout(() => {
if (scrollableDiv) {
scrollableDiv.scroll(0, window.innerHeight - 200);
}
}, 10);
}
this.$data.optionalAreaShown = !this.$data.optionalAreaShown;
},
onCreateClick: async function () {
let hasError = false;
@ -246,21 +149,15 @@ import { createUserRequest } from '@/api/users';
email: this.$data.email,
firstName: this.$data.firstName,
lastName: this.$data.lastName,
company: {
name: this.$data.companyName,
address: this.$data.companyAddress,
city: this.$data.companyCity,
country: this.$data.companyCountry,
postalCode: this.$data.companyPostalCode,
state: this.$data.companyState
}
};
try {
await createUserRequest(user, this.$data.password);
this.$router.push(ROUTES.LOGIN.path);
} catch (error) {
console.error(error);
let response = await createUserRequest(user, this.$data.password);
if (!response) {
// TODO: show popup here
return;
}
this.$router.push(ROUTES.LOGIN.path);
}
},
data: function (): RegisterData {
@ -276,15 +173,8 @@ import { createUserRequest } from '@/api/users';
passwordError: '',
repeatedPassword: '',
repeatedPasswordError: '',
companyName: '',
companyAddress: '',
country: '',
city: '',
state: '',
postalCode: '',
isTermsAccepted: false,
isTermsAcceptedError: false,
optionalAreaShown: false
};
},
computed: {},