updated createuser api (#687)
This commit is contained in:
parent
f72832ee69
commit
c829835dc1
@ -24,6 +24,16 @@ type Companies interface {
|
|||||||
Update(ctx context.Context, company *Company) error
|
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
|
// Company is a database object that describes Company entity
|
||||||
type Company struct {
|
type Company struct {
|
||||||
ID uuid.UUID
|
ID uuid.UUID
|
||||||
|
@ -55,11 +55,12 @@ func (gw *gateway) grapqlHandler(w http.ResponseWriter, req *http.Request) {
|
|||||||
|
|
||||||
err = json.NewEncoder(w).Encode(result)
|
err = json.NewEncoder(w).Encode(result)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
gw.logger.Error(err)
|
gw.log.Error(err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
gw.logger.Debug(result)
|
sugar := gw.log.Sugar()
|
||||||
|
sugar.Debug(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
// getToken retrieves token from request
|
// getToken retrieves token from request
|
||||||
|
@ -28,7 +28,7 @@ type Config struct {
|
|||||||
|
|
||||||
// Run implements Responsibility interface
|
// Run implements Responsibility interface
|
||||||
func (c Config) Run(ctx context.Context, server *provider.Provider) error {
|
func (c Config) Run(ctx context.Context, server *provider.Provider) error {
|
||||||
sugar := zap.NewExample().Sugar()
|
log := zap.NewExample()
|
||||||
|
|
||||||
// Create satellite DB
|
// Create satellite DB
|
||||||
dbURL, err := utils.ParseURL(c.DatabaseURL)
|
dbURL, err := utils.ParseURL(c.DatabaseURL)
|
||||||
@ -42,9 +42,12 @@ func (c Config) Run(ctx context.Context, server *provider.Provider) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
err = db.CreateTables()
|
err = db.CreateTables()
|
||||||
sugar.Error(err)
|
if err != nil {
|
||||||
|
log.Error(err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
service, err := satellite.NewService(
|
service, err := satellite.NewService(
|
||||||
|
log,
|
||||||
&satelliteauth.Hmac{Secret: []byte("my-suppa-secret-key")},
|
&satelliteauth.Hmac{Secret: []byte("my-suppa-secret-key")},
|
||||||
db,
|
db,
|
||||||
)
|
)
|
||||||
@ -71,7 +74,7 @@ func (c Config) Run(ctx context.Context, server *provider.Provider) error {
|
|||||||
go (&gateway{
|
go (&gateway{
|
||||||
schema: schema,
|
schema: schema,
|
||||||
config: c.GatewayConfig,
|
config: c.GatewayConfig,
|
||||||
logger: sugar,
|
log: log,
|
||||||
}).run()
|
}).run()
|
||||||
|
|
||||||
return server.Run(ctx)
|
return server.Run(ctx)
|
||||||
|
@ -21,7 +21,7 @@ type GatewayConfig struct {
|
|||||||
type gateway struct {
|
type gateway struct {
|
||||||
schema graphql.Schema
|
schema graphql.Schema
|
||||||
config GatewayConfig
|
config GatewayConfig
|
||||||
logger *zap.SugaredLogger
|
log *zap.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gw *gateway) run() {
|
func (gw *gateway) run() {
|
||||||
@ -36,7 +36,7 @@ func (gw *gateway) run() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
err := http.ListenAndServe(gw.config.Address, mux)
|
err := http.ListenAndServe(gw.config.Address, mux)
|
||||||
gw.logger.Errorf("unexpected exit of satellite gateway server: ", err)
|
gw.log.Error("unexpected exit of satellite gateway server: ", zap.Error(err))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gw *gateway) appHandler(w http.ResponseWriter, req *http.Request) {
|
func (gw *gateway) appHandler(w http.ResponseWriter, req *http.Request) {
|
||||||
|
95
pkg/satellite/satelliteweb/satelliteql/company.go
Normal file
95
pkg/satellite/satelliteweb/satelliteql/company.go
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
// 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{
|
||||||
|
fieldID: &graphql.Field{
|
||||||
|
Type: graphql.String,
|
||||||
|
},
|
||||||
|
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
|
||||||
|
}
|
@ -13,7 +13,9 @@ const (
|
|||||||
// Mutation is graphql request that modifies data
|
// Mutation is graphql request that modifies data
|
||||||
Mutation = "mutation"
|
Mutation = "mutation"
|
||||||
|
|
||||||
registerMutation = "register"
|
createUserMutation = "createUser"
|
||||||
|
|
||||||
|
input = "input"
|
||||||
)
|
)
|
||||||
|
|
||||||
// rootMutation creates mutation for graphql populated by AccountsClient
|
// rootMutation creates mutation for graphql populated by AccountsClient
|
||||||
@ -21,43 +23,28 @@ func rootMutation(service *satellite.Service, types Types) *graphql.Object {
|
|||||||
return graphql.NewObject(graphql.ObjectConfig{
|
return graphql.NewObject(graphql.ObjectConfig{
|
||||||
Name: Mutation,
|
Name: Mutation,
|
||||||
Fields: graphql.Fields{
|
Fields: graphql.Fields{
|
||||||
registerMutation: &graphql.Field{
|
createUserMutation: &graphql.Field{
|
||||||
Type: types.UserType(),
|
Type: graphql.String,
|
||||||
Args: graphql.FieldConfigArgument{
|
Args: graphql.FieldConfigArgument{
|
||||||
fieldEmail: &graphql.ArgumentConfig{
|
input: &graphql.ArgumentConfig{
|
||||||
Type: graphql.NewNonNull(graphql.String),
|
Type: graphql.NewNonNull(types.UserInput()),
|
||||||
},
|
|
||||||
fieldPassword: &graphql.ArgumentConfig{
|
|
||||||
Type: graphql.NewNonNull(graphql.String),
|
|
||||||
},
|
|
||||||
fieldFirstName: &graphql.ArgumentConfig{
|
|
||||||
Type: graphql.NewNonNull(graphql.String),
|
|
||||||
},
|
|
||||||
fieldLastName: &graphql.ArgumentConfig{
|
|
||||||
Type: graphql.NewNonNull(graphql.String),
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
// creates user and company from input params and returns userID if succeed
|
||||||
Resolve: func(p graphql.ResolveParams) (interface{}, error) {
|
Resolve: func(p graphql.ResolveParams) (interface{}, error) {
|
||||||
email, _ := p.Args[fieldEmail].(string)
|
var userInput = fromMapUserInfo(p.Args[input].(map[string]interface{}))
|
||||||
password, _ := p.Args[fieldPassword].(string)
|
|
||||||
firstName, _ := p.Args[fieldFirstName].(string)
|
|
||||||
lastName, _ := p.Args[fieldLastName].(string)
|
|
||||||
|
|
||||||
user, err := service.Register(
|
user, err := service.CreateUser(
|
||||||
p.Context,
|
p.Context,
|
||||||
&satellite.User{
|
userInput.User,
|
||||||
Email: email,
|
userInput.Company,
|
||||||
FirstName: firstName,
|
|
||||||
LastName: lastName,
|
|
||||||
PasswordHash: []byte(password),
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
return user, nil
|
return user.ID.String(), nil
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -24,7 +24,7 @@ func rootQuery(service *satellite.Service, types Types) *graphql.Object {
|
|||||||
Name: Query,
|
Name: Query,
|
||||||
Fields: graphql.Fields{
|
Fields: graphql.Fields{
|
||||||
userQuery: &graphql.Field{
|
userQuery: &graphql.Field{
|
||||||
Type: types.UserType(),
|
Type: types.User(),
|
||||||
Args: graphql.FieldConfigArgument{
|
Args: graphql.FieldConfigArgument{
|
||||||
fieldID: &graphql.ArgumentConfig{
|
fieldID: &graphql.ArgumentConfig{
|
||||||
Type: graphql.NewNonNull(graphql.String),
|
Type: graphql.NewNonNull(graphql.String),
|
||||||
@ -60,7 +60,7 @@ func rootQuery(service *satellite.Service, types Types) *graphql.Object {
|
|||||||
email, _ := p.Args[fieldEmail].(string)
|
email, _ := p.Args[fieldEmail].(string)
|
||||||
pass, _ := p.Args[fieldPassword].(string)
|
pass, _ := p.Args[fieldPassword].(string)
|
||||||
|
|
||||||
token, err := service.Login(p.Context, email, pass)
|
token, err := service.Token(p.Context, email, pass)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ package satelliteql
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/graphql-go/graphql"
|
"github.com/graphql-go/graphql"
|
||||||
|
|
||||||
"storj.io/storj/pkg/satellite"
|
"storj.io/storj/pkg/satellite"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -13,7 +14,11 @@ type Types interface {
|
|||||||
RootQuery() *graphql.Object
|
RootQuery() *graphql.Object
|
||||||
RootMutation() *graphql.Object
|
RootMutation() *graphql.Object
|
||||||
|
|
||||||
UserType() *graphql.Object
|
User() *graphql.Object
|
||||||
|
Company() *graphql.Object
|
||||||
|
|
||||||
|
UserInput() *graphql.InputObject
|
||||||
|
CompanyInput() *graphql.InputObject
|
||||||
}
|
}
|
||||||
|
|
||||||
// TypeCreator handles graphql type creation and error checking
|
// TypeCreator handles graphql type creation and error checking
|
||||||
@ -21,7 +26,11 @@ type TypeCreator struct {
|
|||||||
query *graphql.Object
|
query *graphql.Object
|
||||||
mutation *graphql.Object
|
mutation *graphql.Object
|
||||||
|
|
||||||
user *graphql.Object
|
user *graphql.Object
|
||||||
|
company *graphql.Object
|
||||||
|
|
||||||
|
userInput *graphql.InputObject
|
||||||
|
companyInput *graphql.InputObject
|
||||||
}
|
}
|
||||||
|
|
||||||
// RootQuery returns instance of query *graphql.Object
|
// RootQuery returns instance of query *graphql.Object
|
||||||
@ -36,11 +45,26 @@ func (c *TypeCreator) RootMutation() *graphql.Object {
|
|||||||
|
|
||||||
// Create create types and check for error
|
// Create create types and check for error
|
||||||
func (c *TypeCreator) Create(service *satellite.Service) error {
|
func (c *TypeCreator) Create(service *satellite.Service) error {
|
||||||
c.user = graphqlUser()
|
c.company = graphqlCompany()
|
||||||
|
if err := c.company.Error(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
c.companyInput = graphqlCompanyInput()
|
||||||
|
if err := c.companyInput.Error(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
c.user = graphqlUser(service, c)
|
||||||
if err := c.user.Error(); err != nil {
|
if err := c.user.Error(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
c.userInput = graphqlUserInput(c)
|
||||||
|
if err := c.userInput.Error(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
c.query = rootQuery(service, c)
|
c.query = rootQuery(service, c)
|
||||||
if err := c.query.Error(); err != nil {
|
if err := c.query.Error(); err != nil {
|
||||||
return err
|
return err
|
||||||
@ -54,7 +78,22 @@ func (c *TypeCreator) Create(service *satellite.Service) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// UserType returns instance of user *graphql.Object
|
// User returns instance of satellite.User *graphql.Object
|
||||||
func (c *TypeCreator) UserType() *graphql.Object {
|
func (c *TypeCreator) User() *graphql.Object {
|
||||||
return c.user
|
return c.user
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Company returns instance of satellite.Company *graphql.Object
|
||||||
|
func (c *TypeCreator) Company() *graphql.Object {
|
||||||
|
return c.company
|
||||||
|
}
|
||||||
|
|
||||||
|
// UserInput returns instance of UserInput *graphql.Object
|
||||||
|
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
|
||||||
|
}
|
||||||
|
@ -5,10 +5,13 @@ package satelliteql
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/graphql-go/graphql"
|
"github.com/graphql-go/graphql"
|
||||||
|
|
||||||
|
"storj.io/storj/pkg/satellite"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
userType = "user"
|
userType = "user"
|
||||||
|
userInputType = "userInput"
|
||||||
|
|
||||||
fieldID = "id"
|
fieldID = "id"
|
||||||
fieldEmail = "email"
|
fieldEmail = "email"
|
||||||
@ -18,8 +21,8 @@ const (
|
|||||||
fieldCreatedAt = "createdAt"
|
fieldCreatedAt = "createdAt"
|
||||||
)
|
)
|
||||||
|
|
||||||
// graphqlUser creates instance of user *graphql.Object
|
// graphqlUser creates *graphql.Object type representation of satellite.User
|
||||||
func graphqlUser() *graphql.Object {
|
func graphqlUser(service *satellite.Service, types Types) *graphql.Object {
|
||||||
return graphql.NewObject(graphql.ObjectConfig{
|
return graphql.NewObject(graphql.ObjectConfig{
|
||||||
Name: userType,
|
Name: userType,
|
||||||
Fields: graphql.Fields{
|
Fields: graphql.Fields{
|
||||||
@ -38,6 +41,59 @@ func graphqlUser() *graphql.Object {
|
|||||||
fieldCreatedAt: &graphql.Field{
|
fieldCreatedAt: &graphql.Field{
|
||||||
Type: graphql.DateTime,
|
Type: graphql.DateTime,
|
||||||
},
|
},
|
||||||
|
companyType: &graphql.Field{
|
||||||
|
Type: types.Company(),
|
||||||
|
Resolve: func(p graphql.ResolveParams) (interface{}, error) {
|
||||||
|
user, _ := p.Source.(satellite.User)
|
||||||
|
return service.GetCompany(p.Context, user.ID)
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// graphqlUserInput creates graphql.InputObject type needed to register/update satellite.User
|
||||||
|
func graphqlUserInput(types Types) *graphql.InputObject {
|
||||||
|
return graphql.NewInputObject(graphql.InputObjectConfig{
|
||||||
|
Name: userInputType,
|
||||||
|
Fields: graphql.InputObjectConfigFieldMap{
|
||||||
|
fieldEmail: &graphql.InputObjectFieldConfig{
|
||||||
|
Type: graphql.String,
|
||||||
|
},
|
||||||
|
fieldFirstName: &graphql.InputObjectFieldConfig{
|
||||||
|
Type: graphql.String,
|
||||||
|
},
|
||||||
|
fieldLastName: &graphql.InputObjectFieldConfig{
|
||||||
|
Type: graphql.String,
|
||||||
|
},
|
||||||
|
fieldPassword: &graphql.InputObjectFieldConfig{
|
||||||
|
Type: graphql.String,
|
||||||
|
},
|
||||||
|
companyType: &graphql.InputObjectFieldConfig{
|
||||||
|
Type: types.CompanyInput(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// UserInput encapsulates satellite.UserInfo and satellite.CompanyInfo which is used in user related queries
|
||||||
|
type UserInput struct {
|
||||||
|
User satellite.UserInfo
|
||||||
|
Company satellite.CompanyInfo
|
||||||
|
}
|
||||||
|
|
||||||
|
// fromMapUserInfo creates UserInput from input args
|
||||||
|
func fromMapUserInfo(args map[string]interface{}) (input UserInput) {
|
||||||
|
input.User.Email, _ = args[fieldEmail].(string)
|
||||||
|
input.User.FirstName, _ = args[fieldFirstName].(string)
|
||||||
|
input.User.LastName, _ = args[fieldLastName].(string)
|
||||||
|
input.User.Password, _ = args[fieldPassword].(string)
|
||||||
|
|
||||||
|
companyArgs, ok := args[companyType].(map[string]interface{})
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
input.Company = fromMapCompanyInfo(companyArgs)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
@ -9,6 +9,8 @@ import (
|
|||||||
"crypto/subtle"
|
"crypto/subtle"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"go.uber.org/zap"
|
||||||
|
|
||||||
"github.com/skyrings/skyring-common/tools/uuid"
|
"github.com/skyrings/skyring-common/tools/uuid"
|
||||||
"github.com/zeebo/errs"
|
"github.com/zeebo/errs"
|
||||||
|
|
||||||
@ -21,10 +23,11 @@ type Service struct {
|
|||||||
Signer
|
Signer
|
||||||
|
|
||||||
store DB
|
store DB
|
||||||
|
log *zap.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewService returns new instance of Service
|
// NewService returns new instance of Service
|
||||||
func NewService(signer Signer, store DB) (*Service, error) {
|
func NewService(log *zap.Logger, signer Signer, store DB) (*Service, error) {
|
||||||
if signer == nil {
|
if signer == nil {
|
||||||
return nil, errs.New("signer can't be nil")
|
return nil, errs.New("signer can't be nil")
|
||||||
}
|
}
|
||||||
@ -33,24 +36,65 @@ func NewService(signer Signer, store DB) (*Service, error) {
|
|||||||
return nil, errs.New("store can't be nil")
|
return nil, errs.New("store can't be nil")
|
||||||
}
|
}
|
||||||
|
|
||||||
return &Service{Signer: signer, store: store}, nil
|
if log == nil {
|
||||||
|
return nil, errs.New("log can't be nil")
|
||||||
|
}
|
||||||
|
|
||||||
|
return &Service{Signer: signer, store: store, log: log}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Register gets password hash value and creates new user
|
// CreateUser gets password hash value and creates new user
|
||||||
func (s *Service) Register(ctx context.Context, user *User) (*User, error) {
|
func (s *Service) CreateUser(ctx context.Context, userInfo UserInfo, companyInfo CompanyInfo) (*User, error) {
|
||||||
passwordHash := sha256.Sum256(user.PasswordHash)
|
passwordHash := sha256.Sum256([]byte(userInfo.Password))
|
||||||
user.PasswordHash = passwordHash[:]
|
|
||||||
|
user, err := s.store.Users().Insert(ctx, &User{
|
||||||
|
Email: userInfo.Email,
|
||||||
|
FirstName: userInfo.FirstName,
|
||||||
|
LastName: userInfo.LastName,
|
||||||
|
PasswordHash: passwordHash[:],
|
||||||
|
})
|
||||||
|
|
||||||
newUser, err := s.store.Users().Insert(ctx, user)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return newUser, nil
|
_, err = s.store.Companies().Insert(ctx, &Company{
|
||||||
|
UserID: user.ID,
|
||||||
|
Name: companyInfo.Name,
|
||||||
|
Address: companyInfo.Address,
|
||||||
|
Country: companyInfo.Country,
|
||||||
|
City: companyInfo.City,
|
||||||
|
State: companyInfo.State,
|
||||||
|
PostalCode: companyInfo.PostalCode,
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
s.log.Error(err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
return user, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Login authenticates user by credentials and returns auth token
|
// CreateCompany creates Company for authorized User
|
||||||
func (s *Service) Login(ctx context.Context, email, password string) (string, error) {
|
func (s *Service) CreateCompany(ctx context.Context, info CompanyInfo) (*Company, error) {
|
||||||
|
user, err := s.Authorize(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return s.store.Companies().Insert(ctx, &Company{
|
||||||
|
UserID: user.ID,
|
||||||
|
Name: info.Name,
|
||||||
|
Address: info.Address,
|
||||||
|
Country: info.Country,
|
||||||
|
City: info.City,
|
||||||
|
State: info.State,
|
||||||
|
PostalCode: info.PostalCode,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Token authenticates user by credentials and returns auth token
|
||||||
|
func (s *Service) Token(ctx context.Context, email, password string) (string, error) {
|
||||||
passwordHash := sha256.Sum256([]byte(password))
|
passwordHash := sha256.Sum256([]byte(password))
|
||||||
|
|
||||||
user, err := s.store.Users().GetByCredentials(ctx, passwordHash[:], email)
|
user, err := s.store.Users().GetByCredentials(ctx, passwordHash[:], email)
|
||||||
@ -74,27 +118,22 @@ func (s *Service) Login(ctx context.Context, email, password string) (string, er
|
|||||||
|
|
||||||
// GetUser returns user by id
|
// GetUser returns user by id
|
||||||
func (s *Service) GetUser(ctx context.Context, id uuid.UUID) (*User, error) {
|
func (s *Service) GetUser(ctx context.Context, id uuid.UUID) (*User, error) {
|
||||||
token, ok := auth.GetAPIKey(ctx)
|
_, err := s.Authorize(ctx)
|
||||||
if !ok {
|
|
||||||
return nil, errs.New("no api key was provided")
|
|
||||||
}
|
|
||||||
|
|
||||||
claims, err := s.authenticate(string(token))
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = s.authorize(ctx, claims)
|
return s.store.Users().Get(ctx, id)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetCompany returns company by userID
|
||||||
|
func (s *Service) GetCompany(ctx context.Context, userID uuid.UUID) (*Company, error) {
|
||||||
|
_, err := s.Authorize(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
user, err := s.store.Users().Get(ctx, id)
|
return s.store.Companies().GetByUserID(ctx, userID)
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return user, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) createToken(claims *satelliteauth.Claims) (string, error) {
|
func (s *Service) createToken(claims *satelliteauth.Claims) (string, error) {
|
||||||
@ -112,6 +151,22 @@ func (s *Service) createToken(claims *satelliteauth.Claims) (string, error) {
|
|||||||
return token.String(), nil
|
return token.String(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Authorize validates token from context and returns authenticated and authorized User
|
||||||
|
func (s *Service) Authorize(ctx context.Context) (*User, error) {
|
||||||
|
token, ok := auth.GetAPIKey(ctx)
|
||||||
|
if !ok {
|
||||||
|
return nil, errs.New("no api key was provided")
|
||||||
|
}
|
||||||
|
|
||||||
|
claims, err := s.authenticate(string(token))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return s.authorize(ctx, claims)
|
||||||
|
}
|
||||||
|
|
||||||
|
// authenticate validates toke signature and returns authenticated *satelliteauth.Claims
|
||||||
func (s *Service) authenticate(tokenS string) (*satelliteauth.Claims, error) {
|
func (s *Service) authenticate(tokenS string) (*satelliteauth.Claims, error) {
|
||||||
token, err := satelliteauth.FromBase64URLString(tokenS)
|
token, err := satelliteauth.FromBase64URLString(tokenS)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -137,15 +192,16 @@ func (s *Service) authenticate(tokenS string) (*satelliteauth.Claims, error) {
|
|||||||
return claims, nil
|
return claims, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) authorize(ctx context.Context, claims *satelliteauth.Claims) error {
|
// authorize checks claims and returns authorized User
|
||||||
|
func (s *Service) authorize(ctx context.Context, claims *satelliteauth.Claims) (*User, error) {
|
||||||
if !claims.Expiration.IsZero() && claims.Expiration.Before(time.Now()) {
|
if !claims.Expiration.IsZero() && claims.Expiration.Before(time.Now()) {
|
||||||
return errs.New("token is outdated")
|
return nil, errs.New("token is outdated")
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err := s.store.Users().Get(ctx, claims.ID)
|
user, err := s.store.Users().Get(ctx, claims.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errs.New("authorization failed. no user with id: %s", claims.ID.String())
|
return nil, errs.New("authorization failed. no user with id: %s", claims.ID.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return user, nil
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,14 @@ type Users interface {
|
|||||||
Update(ctx context.Context, user *User) error
|
Update(ctx context.Context, user *User) error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UserInfo holds data needed to create/update User
|
||||||
|
type UserInfo struct {
|
||||||
|
FirstName string `json:"firstName"`
|
||||||
|
LastName string `json:"lastName"`
|
||||||
|
Email string `json:"email"`
|
||||||
|
Password string `json:"password"`
|
||||||
|
}
|
||||||
|
|
||||||
// User is a database object that describes User entity
|
// User is a database object that describes User entity
|
||||||
type User struct {
|
type User struct {
|
||||||
ID uuid.UUID `json:"id"`
|
ID uuid.UUID `json:"id"`
|
||||||
|
Loading…
Reference in New Issue
Block a user