1
0
mirror of https://github.com/raseels-repos/golang-saas-starter-kit.git synced 2025-06-17 00:17:59 +02:00

Complated web-api crud endpoints and unittests. unittest for find

endpoints still need to be implemented.
This commit is contained in:
Lee Brown
2019-06-27 04:48:18 -08:00
parent 48ae19bd6a
commit 24dd0dff42
27 changed files with 4062 additions and 1529 deletions

View File

@ -72,8 +72,8 @@ func SwitchAccount(ctx context.Context, dbConn *sqlx.DB, tknGen TokenGenerator,
// Defines struct to apply validation for the supplied claims and account ID.
req := struct {
UserID string `validate:"required,uuid"`
AccountID string `validate:"required,uuid"`
UserID string `json:"user_id" validate:"required,uuid"`
AccountID string `json:"account_id" validate:"required,uuid"`
}{
UserID: claims.Subject,
AccountID: accountID,

View File

@ -90,35 +90,52 @@ func CanReadUser(ctx context.Context, claims auth.Claims, dbConn *sqlx.DB, userI
// CanModifyUser determines if claims has the authority to modify the specified user ID.
func CanModifyUser(ctx context.Context, claims auth.Claims, dbConn *sqlx.DB, userID string) error {
// If the request has claims from a specific account, ensure that the user
// has the correct access to the account.
// If the request has claims from a specific user, ensure that the user
// has the correct role for creating a new user.
if claims.Subject != "" && claims.Subject != userID {
// When the claims Audience - AccountID - does not match the requested account, the
// claims Audience - AccountID - should have a record with an admin role.
// select id from users_accounts where account_id = [claims.Audience] and user_id = [userID] and any (roles) = 'admin'
query := sqlbuilder.NewSelectBuilder().Select("id").From(userAccountTableName)
query.Where(query.And(
query.Equal("account_id", claims.Audience),
query.Equal("user_id", userID),
"'"+auth.RoleAdmin+"' = ANY (roles)",
))
queryStr, args := query.Build()
queryStr = dbConn.Rebind(queryStr)
var userAccountId string
err := dbConn.QueryRowContext(ctx, queryStr, args...).Scan(&userAccountId)
if err != nil && err != sql.ErrNoRows {
err = errors.Wrapf(err, "query - %s", query.String())
// Users with the role of admin are ony allows to create users.
if !claims.HasRole(auth.RoleAdmin) {
err := errors.WithStack(ErrForbidden)
return err
}
// When there is no userAccount ID returned, then the current user does not have access
// to the specified account.
if userAccountId == "" {
return errors.WithStack(ErrForbidden)
}
}
if err := CanReadUser(ctx, claims, dbConn, userID); err != nil {
return err
}
// TODO: Review, this doesn't seem correct, replaced with above.
/*
// If the request has claims from a specific account, ensure that the user
// has the correct access to the account.
if claims.Subject != "" && claims.Subject != userID {
// When the claims Audience - AccountID - does not match the requested account, the
// claims Audience - AccountID - should have a record with an admin role.
// select id from users_accounts where account_id = [claims.Audience] and user_id = [userID] and any (roles) = 'admin'
query := sqlbuilder.NewSelectBuilder().Select("id").From(userAccountTableName)
query.Where(query.And(
query.Equal("account_id", claims.Audience),
query.Equal("user_id", userID),
"'"+auth.RoleAdmin+"' = ANY (roles)",
))
queryStr, args := query.Build()
queryStr = dbConn.Rebind(queryStr)
var userAccountId string
err := dbConn.QueryRowContext(ctx, queryStr, args...).Scan(&userAccountId)
if err != nil && err != sql.ErrNoRows {
err = errors.Wrapf(err, "query - %s", query.String())
return err
}
// When there is no userAccount ID returned, then the current user does not have access
// to the specified account.
if userAccountId == "" {
return errors.WithStack(ErrForbidden)
}
}
*/
return nil
}
@ -598,7 +615,7 @@ func Delete(ctx context.Context, claims auth.Claims, dbConn *sqlx.DB, userID str
// Defines the struct to apply validation
req := struct {
ID string `validate:"required,uuid"`
ID string `json:"id" validate:"required,uuid"`
}{
ID: userID,
}

View File

@ -1,7 +1,6 @@
package user
import (
"github.com/lib/pq"
"math/rand"
"os"
"strings"
@ -13,6 +12,7 @@ import (
"github.com/dgrijalva/jwt-go"
"github.com/google/go-cmp/cmp"
"github.com/huandu/go-sqlbuilder"
"github.com/lib/pq"
"github.com/pborman/uuid"
"github.com/pkg/errors"
)
@ -149,9 +149,9 @@ func TestCreateValidation(t *testing.T) {
func(req UserCreateRequest, res *User) *User {
return nil
},
errors.New("Key: 'UserCreateRequest.Name' Error:Field validation for 'Name' failed on the 'required' tag\n" +
"Key: 'UserCreateRequest.Email' Error:Field validation for 'Email' failed on the 'required' tag\n" +
"Key: 'UserCreateRequest.Password' Error:Field validation for 'Password' failed on the 'required' tag"),
errors.New("Key: 'UserCreateRequest.name' Error:Field validation for 'name' failed on the 'required' tag\n" +
"Key: 'UserCreateRequest.email' Error:Field validation for 'email' failed on the 'required' tag\n" +
"Key: 'UserCreateRequest.password' Error:Field validation for 'password' failed on the 'required' tag"),
},
{"Valid Email",
UserCreateRequest{
@ -163,7 +163,7 @@ func TestCreateValidation(t *testing.T) {
func(req UserCreateRequest, res *User) *User {
return nil
},
errors.New("Key: 'UserCreateRequest.Email' Error:Field validation for 'Email' failed on the 'email' tag"),
errors.New("Key: 'UserCreateRequest.email' Error:Field validation for 'email' failed on the 'email' tag"),
},
{"Passwords Match",
UserCreateRequest{
@ -175,7 +175,7 @@ func TestCreateValidation(t *testing.T) {
func(req UserCreateRequest, res *User) *User {
return nil
},
errors.New("Key: 'UserCreateRequest.PasswordConfirm' Error:Field validation for 'PasswordConfirm' failed on the 'eqfield' tag"),
errors.New("Key: 'UserCreateRequest.password_confirm' Error:Field validation for 'password_confirm' failed on the 'eqfield' tag"),
},
{"Default Timezone",
UserCreateRequest{
@ -276,7 +276,7 @@ func TestCreateValidationEmailUnique(t *testing.T) {
Password: "W0rkL1fe#",
PasswordConfirm: "W0rkL1fe#",
}
expectedErr := errors.New("Key: 'UserCreateRequest.Email' Error:Field validation for 'Email' failed on the 'unique' tag")
expectedErr := errors.New("Key: 'UserCreateRequest.email' Error:Field validation for 'email' failed on the 'unique' tag")
_, err = Create(ctx, auth.Claims{}, test.MasterDB, req2, now)
if err == nil {
t.Logf("\t\tWant: %+v", expectedErr)
@ -384,7 +384,7 @@ func TestUpdateValidation(t *testing.T) {
var userTests = []userTest{
{"Required Fields",
UserUpdateRequest{},
errors.New("Key: 'UserUpdateRequest.ID' Error:Field validation for 'ID' failed on the 'required' tag"),
errors.New("Key: 'UserUpdateRequest.id' Error:Field validation for 'id' failed on the 'required' tag"),
},
}
@ -394,7 +394,7 @@ func TestUpdateValidation(t *testing.T) {
ID: uuid.NewRandom().String(),
Email: &invalidEmail,
},
errors.New("Key: 'UserUpdateRequest.Email' Error:Field validation for 'Email' failed on the 'email' tag"),
errors.New("Key: 'UserUpdateRequest.email' Error:Field validation for 'email' failed on the 'email' tag"),
})
now := time.Date(2018, time.October, 1, 0, 0, 0, 0, time.UTC)
@ -469,7 +469,7 @@ func TestUpdateValidationEmailUnique(t *testing.T) {
ID: user2.ID,
Email: &user1.Email,
}
expectedErr := errors.New("Key: 'UserUpdateRequest.Email' Error:Field validation for 'Email' failed on the 'unique' tag")
expectedErr := errors.New("Key: 'UserUpdateRequest.email' Error:Field validation for 'email' failed on the 'unique' tag")
err = Update(ctx, auth.Claims{}, test.MasterDB, updateReq, now)
if err == nil {
t.Logf("\t\tWant: %+v", expectedErr)
@ -533,8 +533,8 @@ func TestUpdatePassword(t *testing.T) {
}
// Ensure validation is working by trying UpdatePassword with an empty request.
expectedErr := errors.New("Key: 'UserUpdatePasswordRequest.ID' Error:Field validation for 'ID' failed on the 'required' tag\n" +
"Key: 'UserUpdatePasswordRequest.Password' Error:Field validation for 'Password' failed on the 'required' tag")
expectedErr := errors.New("Key: 'UserUpdatePasswordRequest.id' Error:Field validation for 'id' failed on the 'required' tag\n" +
"Key: 'UserUpdatePasswordRequest.password' Error:Field validation for 'password' failed on the 'required' tag")
err = UpdatePassword(ctx, auth.Claims{}, test.MasterDB, UserUpdatePasswordRequest{}, now)
if err == nil {
t.Logf("\t\tWant: %+v", expectedErr)