2 Commits

Author SHA1 Message Date
GotPPay
daf2d31952 fixed sql query error 2018-05-04 16:38:56 +02:00
Senad Uka
9da9f7eb78 Upstream sync 2018-05-03 07:57:08 +02:00
27 changed files with 38 additions and 498 deletions

View File

@@ -149,23 +149,3 @@ func (s *userService) GetContactType() (retVal []viewmodel.ContactType, err erro
return s.mapEntity.User.ToContactTypeModelSlice(entity), nil
}
func (s *userService) SaveContact(contact viewmodel.Contact) (retVal viewmodel.Contact, err error) {
entity := s.mapEntity.User.ToContactEntity(contact)
entity, err = s.svc.Users.SaveContact(entity)
if err != nil {
return retVal, errors.Wrap(err)
}
return s.mapEntity.User.ToContactModel(entity), err
}
func (s *userService) RemoveContact(contact viewmodel.Contact) (retVal viewmodel.Contact, err error) {
entity := s.mapEntity.User.ToContactEntity(contact)
entity, err = s.svc.Users.RemoveContact(entity)
if err != nil {
return retVal, errors.Wrap(err)
}
return s.mapEntity.User.ToContactModel(entity), err
}

View File

@@ -158,11 +158,8 @@ func (mapping *userMapping) ToContactTypeModelSlice(list []entity.ContactType) (
// ToContactModel maps a Contact entity to Contact view model
func (mapping *userMapping) ToContactModel(item entity.ContactInfo) viewmodel.Contact {
return viewmodel.Contact{
ID: item.UUID,
User: mapping.ToUserModel(item.User),
Author: mapping.ToUserModel(item.Author),
Type: mapping.ToContactTypeModel(item.Type),
Value: item.Value,
Type: mapping.ToContactTypeModel(item.Type),
Value: item.Value,
}
}
@@ -180,11 +177,8 @@ func (mapping *userMapping) ToContactModelSlice(list []entity.ContactInfo) (retV
// ToContactEntity maps a Contact entity to Contact view model
func (mapping *userMapping) ToContactEntity(item viewmodel.Contact) entity.ContactInfo {
return entity.ContactInfo{
UUID: item.ID,
User: mapping.ToUserEntity(item.User),
Author: mapping.ToUserEntity(item.Author),
Type: mapping.ToContactTypeEntity(item.Type),
Value: item.Value,
Type: mapping.ToContactTypeEntity(item.Type),
Value: item.Value,
}
}

View File

@@ -15,7 +15,6 @@ type WebhookResponse struct {
//RideRequest has the data to dispatch a ride
type RideRequest struct {
UserUUID string `json:"user_uuid,omitempty"`
UserConsent bool `json:"user_consent,omitempty"`
Status string `json:"status,omitempty"`
RideID string `json:"ride_id,omitempty"`
RideType string `json:"ride_type,omitempty"`
@@ -159,4 +158,4 @@ type RideRoute struct {
Duration int64 `json:"duration,omitempty"`
ETA int64 `json:"eta,omitempty"`
Bearing int64 `json:"bearing,omitempty"`
}
}

View File

@@ -26,11 +26,8 @@ type User struct {
}
type Contact struct {
ID string `json:"id,omitempty"`
User User `json:"-"`
Type ContactType `json:"type,omitempty"`
Value string `json:"contact,omitempty"`
Author User `json:"-"`
Type ContactType `json:"type,omitempty"`
Value string `json:"contact,omitempty"`
}
type ContactType struct {

View File

@@ -79,23 +79,18 @@ p, *, *, *, *, *, *, /v1/nemt/organization/type, GET
p, AD, *, *, *, *, *, /v1/nemt/organization/*, GET
p, AD, *, *, *, *, *, /v1/nemt/organization/*, POST
p, AD, *, *, *, *, *, /v1/nemt/organization/*, PUT
p, AD, *, *, *, *, *, /v1/nemt/organization/*, DELETE
p, SCHDAD, *, *, *, [equal*], *, /v1/nemt/organization/*, GET
p, SCHDAD, *, *, *, [equal*], *, /v1/nemt/organization/*, POST
p, SCHDAD, *, *, *, [equal*], *, /v1/nemt/organization/*, PUT
p, SCHDAD, *, *, *, [equal*], *, /v1/nemt/organization/*, DELETE
p, PLANAD, *, *, *, [equal*], *, /v1/nemt/organization/*, GET
p, PLANAD, *, *, *, [equal*], *, /v1/nemt/organization/*, POST
p, PLANAD, *, *, *, [equal*], *, /v1/nemt/organization/*, PUT
p, PLANAD, *, *, *, [equal*], *, /v1/nemt/organization/*, DELETE
p, BDCAD, *, *, *, *, *, /v1/nemt/organization/*, GET
p, BDCAD, *, *, *, *, *, /v1/nemt/organization/*, POST
p, BDCAD, *, *, *, *, *, /v1/nemt/organization/*, PUT
p, BDCAD, *, *, *, *, *, /v1/nemt/organization/*, DELETE
p, BCBSIAD, *, *, *, *, *, /v1/nemt/organization/*, GET
p, BCBSIAD, *, *, *, *, *, /v1/nemt/organization/*, POST
p, BCBSIAD, *, *, *, *, *, /v1/nemt/organization/*, PUT
p, BCBSIAD, *, *, *, *, *, /v1/nemt/organization/*, DELETE
p, SPT, *, programsupport, *, *, *, /v1/nemt/organization/*, GET
p, SP, *, provider, *, *, *, /v1/nemt/organization, GET
p, SP, *, plan, *, *, *, /v1/nemt/organization, GET
@@ -113,3 +108,4 @@ p, BCBSIAD, *, bcbsi, *, *, *, /v1/nemt/eligibility, POST
p, BDCAD, *, techsupport, *, *, *, /v1/nemt/eligibility, POST
p, PLANAD, *, plan, *, *, *, /v1/nemt/eligibility, POST
p, AD, *, *, *, *, *, /v1/nemt/eligibility, POST
1 p AD * * * * * * *
79 p AD * * * * * /v1/nemt/organization/* GET
80 p AD * * * * * /v1/nemt/organization/* POST
81 p AD * * * * * /v1/nemt/organization/* PUT
p AD * * * * * /v1/nemt/organization/* DELETE
82 p SCHDAD * * * [equal*] * /v1/nemt/organization/* GET
83 p SCHDAD * * * [equal*] * /v1/nemt/organization/* POST
84 p SCHDAD * * * [equal*] * /v1/nemt/organization/* PUT
p SCHDAD * * * [equal*] * /v1/nemt/organization/* DELETE
85 p PLANAD * * * [equal*] * /v1/nemt/organization/* GET
86 p PLANAD * * * [equal*] * /v1/nemt/organization/* POST
87 p PLANAD * * * [equal*] * /v1/nemt/organization/* PUT
p PLANAD * * * [equal*] * /v1/nemt/organization/* DELETE
88 p BDCAD * * * * * /v1/nemt/organization/* GET
89 p BDCAD * * * * * /v1/nemt/organization/* POST
90 p BDCAD * * * * * /v1/nemt/organization/* PUT
p BDCAD * * * * * /v1/nemt/organization/* DELETE
91 p BCBSIAD * * * * * /v1/nemt/organization/* GET
92 p BCBSIAD * * * * * /v1/nemt/organization/* POST
93 p BCBSIAD * * * * * /v1/nemt/organization/* PUT
p BCBSIAD * * * * * /v1/nemt/organization/* DELETE
94 p SPT * programsupport * * * /v1/nemt/organization/* GET
95 p SP * provider * * * /v1/nemt/organization GET
96 p SP * plan * * * /v1/nemt/organization GET
108 p BDCAD * techsupport * * * /v1/nemt/eligibility POST
109 p PLANAD * plan * * * /v1/nemt/eligibility POST
110 p AD * * * * * /v1/nemt/eligibility POST
111

View File

@@ -37,7 +37,6 @@ db = 0
pass = "3rdaP3KL2x%V"
prefix = "nemt-portal-api-dev"
default-expiration = "5m"
master-name = "devmaster01"
[log]
log-to-file = false

View File

@@ -37,7 +37,6 @@ db = 0
pass = "3rdaP3KL2x%V"
prefix = "portal-api-prod"
default-expiration = "5m"
master-name = "master01"
[log]
log-to-file = false

View File

@@ -37,7 +37,6 @@ db = 0
pass = "3rdaP3KL2x%V"
prefix = "portal-api-test"
default-expiration = "5m"
master-name = "devmaster01"
[log]
log-to-file = false

View File

@@ -80,9 +80,7 @@ func (c *notificationRepo) getQuery() string {
INNER JOIN tab_login e
ON c.user_id = e.user_id
INNER JOIN tab_login f
ON d.user_id = f.user_id
INNER JOIN tab_ride g
ON g.ride_id = a.ride_id `
ON d.user_id = f.user_id`
}
func (c *notificationRepo) GetLastNotificationFromPhoneNumber(notificationType string, phoneNumber string, status string) (entity.Notification, error) {

View File

@@ -294,7 +294,7 @@ func (c *organizationRepo) GetAllTypes() ([]entity.OrganizationType, error) {
}
func (c *organizationRepo) GetTypeByKey(key string) (entity.OrganizationType, error) {
return c.parseTypeEntity(c.conn.QueryRow(c.getTypeQuery()+" WHERE organization_type_key=? ", key))
return c.parseTypeEntity(c.conn.QueryRow(c.getTypeQuery()+" WHERE b.organization_type_key=?", key))
}
func (c *organizationRepo) GetByType(organizationTypeKey string, user entity.User) ([]entity.Organization, error) {

View File

@@ -63,8 +63,7 @@ func (c *userRepo) GetContacts(userID int64) ([]entity.ContactInfo, error) {
a.user_id,
b.contact_type_id,
b.key contact_type_key,
b.name contact_type_name,
a.contact_uuid
b.name contact_type_name
FROM tab_contact a
INNER JOIN tab_contact_type b
ON a.contact_type_id = b.contact_type_id
@@ -80,7 +79,7 @@ func (c *userRepo) GetContacts(userID int64) ([]entity.ContactInfo, error) {
retVal := make([]entity.ContactInfo, 0)
for rows.Next() {
contact := entity.ContactInfo{}
err = rows.Scan(&contact.ID, &contact.Value, &contact.User.ID, &contact.Type.ID, &contact.Type.Key, &contact.Type.Value, &contact.UUID)
err = rows.Scan(&contact.ID, &contact.Value, &contact.UserID, &contact.Type.ID, &contact.Type.Key, &contact.Type.Value)
if err != nil {
return nil, err
}
@@ -355,11 +354,9 @@ func (c *userRepo) Create(user entity.User) (retVal entity.User, err error) {
if retVal.Email != "" {
contact := entity.ContactInfo{
Type: entity.ContactType{Key: "email"},
Value: retVal.Email,
User: entity.User{
ID: retVal.ID,
},
Type: entity.ContactType{Key: "email"},
Value: retVal.Email,
UserID: retVal.ID,
}
contact, err = c.addContactInfo(contact)
@@ -370,11 +367,9 @@ func (c *userRepo) Create(user entity.User) (retVal entity.User, err error) {
if retVal.PhoneNumber != "" {
contact := entity.ContactInfo{
Type: entity.ContactType{Key: "phone"},
Value: retVal.PhoneNumber,
User: entity.User{
ID: retVal.ID,
},
Type: entity.ContactType{Key: "phone"},
Value: retVal.PhoneNumber,
UserID: retVal.ID,
}
contact, err = c.addContactInfo(contact)
@@ -392,10 +387,19 @@ func (c *userRepo) SaveContact(contact entity.ContactInfo) (entity.ContactInfo,
func (c *userRepo) RemoveContact(contact entity.ContactInfo) (entity.ContactInfo, error) {
const (
query = `DELETE FROM tab_contact WHERE contact_uuid = ?;`
query = `INSERT INTO tab_contact(contact_type_id, user_id, contact)
SELECT a.contact_type_id, ? user_id, ? contact
FROM
tab_contact_type a
LEFT JOIN tab_contact b
ON a.contact_type_id = b.contact_type_id
AND b.user_id = ?
AND b.contact = ?
WHERE a.key = ?
AND b.contact_id IS NULL;`
)
result, err := c.conn.Exec(query, contact.UUID)
result, err := c.conn.Exec(query, contact.UserID, contact.Value, contact.UserID, contact.Value, contact.Type.Key)
if err != nil {
return contact, err
}
@@ -411,8 +415,8 @@ func (c *userRepo) RemoveContact(contact entity.ContactInfo) (entity.ContactInfo
func (c *userRepo) addContactInfo(contact entity.ContactInfo) (entity.ContactInfo, error) {
const (
query = `INSERT INTO tab_contact(contact_type_id, user_id, contact, contact_uuid)
SELECT a.contact_type_id, ? user_id, ? contact, ? contact_uuid
query = `INSERT INTO tab_contact(contact_type_id, user_id, contact)
SELECT a.contact_type_id, ? user_id, ? contact
FROM
tab_contact_type a
LEFT JOIN tab_contact b
@@ -423,13 +427,7 @@ func (c *userRepo) addContactInfo(contact entity.ContactInfo) (entity.ContactInf
AND b.contact_id IS NULL;`
)
sUUID, err := uuid.NewV4()
if err != nil {
return contact, err
}
contact.UUID = sUUID.String()
result, err := c.conn.Exec(query, contact.User.ID, contact.Value, contact.UUID, contact.User.ID, contact.Value, contact.Type.Key)
result, err := c.conn.Exec(query, contact.UserID, contact.Value, contact.UserID, contact.Value, contact.Type.Key)
if err != nil {
return contact, err
}
@@ -786,7 +784,7 @@ func (c *userRepo) getAddressSecondaryData(address entity.Address) (entity.Addre
// GetAll returns a list of all active cards
func (c *userRepo) GetAll() (list []entity.User, err error) {
return c.parseSet(c.conn.Query(c.getQuery() + " WHERE a.active = 1 "))
return c.parseSet(c.conn.Query(c.getQuery() + " AND a.active = 1 "))
}
// GetByID returns a single card data by its ID

View File

@@ -27,8 +27,6 @@ type UserRepo interface {
GetAddressByUUID(addressUUID string) (entity.Address, error)
GetContactType() (retVal []entity.ContactType, err error)
RemoveAddress(addressUUID string) error
SaveContact(contact entity.ContactInfo) (entity.ContactInfo, error)
RemoveContact(contact entity.ContactInfo) (entity.ContactInfo, error)
}
// RideRepo defines the data set for Rides

View File

@@ -34,10 +34,8 @@ type User struct {
type ContactInfo struct {
ID int64 `db:"contact_id" json:"contact_id"`
UUID string `db:"contact_uuid" json:"contact_uuid"`
Type ContactType `db:"contact_type" json:"contact_type"`
User User `db:"user" json:"-"`
Author User `db:"author" json:"-"`
UserID int64 `db:"user_id" json:"-"`
Value string `db:"value" json:"value"`
}

View File

@@ -82,26 +82,6 @@ func (s *userService) SaveAddress(address entity.Address) (entity.Address, error
return s.svc.db.Users().SaveAddress(address)
}
func (s *userService) SaveContact(contact entity.ContactInfo) (entity.ContactInfo, error) {
user, err := s.svc.db.Users().GetByUUID(contact.User.UUID, "")
if err != nil {
return entity.ContactInfo{}, nil
}
contact.User = user
return s.svc.db.Users().SaveContact(contact)
}
func (s *userService) RemoveContact(contact entity.ContactInfo) (entity.ContactInfo, error) {
user, err := s.svc.db.Users().GetByUUID(contact.User.UUID, "")
if err != nil {
return entity.ContactInfo{}, nil
}
contact.User = user
return s.svc.db.Users().RemoveContact(contact)
}
// GetAddressByUUID returns a list of users by profile
func (s *userService) GetAddressByUUID(addressUUID string) (entity.Address, error) {
return s.svc.db.Users().GetAddressByUUID(addressUUID)

View File

@@ -31,11 +31,10 @@ type RedisCache struct {
func Instance(cfg *config.Config) contract.CacheManager {
once.Do(func() {
client := redis.NewFailoverClient(&redis.FailoverOptions{
MasterName: cfg.Cache.Master,
MasterName: "master01",
SentinelAddrs: []string{fmt.Sprintf("%s:%v", cfg.Cache.Server, cfg.Cache.Port)},
Password: cfg.Cache.Pass,
DB: cfg.Cache.DB,
MaxRetries: 10,
})
instance = &RedisCache{cfg, client}

View File

@@ -119,7 +119,6 @@ type CacheConfig struct {
Pass string
Prefix string
DefaultExpiration time.Duration
Master string
}
// CacheConfig represents the configuration values about the documentation config.
@@ -195,7 +194,6 @@ func Read() (*Config, error) {
Pass: viper.GetString("cache.pass"),
Prefix: viper.GetString("cache.prefix"),
DefaultExpiration: viper.GetDuration("cache.default-expiration"),
Master: viper.GetString("cache.master-name"),
},
Lyft: LyftConfig{
Client: viper.GetString("lyft.key"),

View File

@@ -1,15 +0,0 @@
package authorization
import (
"bitbucket.org/nemt/nemt-portal-api/application/viewmodel"
)
func CanCreateAddress(user viewmodel.User, organization viewmodel.Organization) bool {
//rules are the same for address creation and for organization creation
return CanCreateOrganization(user, organization)
}
func CanUpdateAddress(user viewmodel.User, organization viewmodel.Organization) bool {
return CanCreateAddress(user, organization)
}

View File

@@ -1,15 +0,0 @@
package authorization
import (
"bitbucket.org/nemt/nemt-portal-api/application/viewmodel"
)
func CanCreateContact(user viewmodel.User, organization viewmodel.Organization) bool {
//rules are the same for contact creation and for organization creation
return CanCreateOrganization(user, organization)
}
func CanUpdateContact(user viewmodel.User, organization viewmodel.Organization) bool {
return CanCreateAddress(user, organization)
}

View File

@@ -20,57 +20,9 @@ func isSameOrganization(organizationA viewmodel.Organization, organizationB view
}
func grabOrgFromUser(user viewmodel.User) (viewmodel.Organization, error) {
if len(user.Profiles) < 1 {
return viewmodel.Organization{}, fmt.Errorf("User has no organizations %v", user)
}
return user.Profiles[0].Organization, nil
}
func grabOrgFromUserDirectly(user viewmodel.User) (viewmodel.Organization, error) {
if len(user.Organizations) < 1 {
return viewmodel.Organization{}, fmt.Errorf("User has no organizations %v", user)
}
return user.Organizations[0], nil
}
func CanCreateOrganization(user viewmodel.User, organization viewmodel.Organization ) bool {
userRole, err := grabProfileFromUser(user)
if err != nil {
return false
}
/*
Admin BCBSI
Admin Technical Support
Super Admin Technical Support
Manage all Organizations*/
if userRole.Key == bcbsiAdmin || userRole.Key == brighterDevAdmin || userRole.Key == superAdmin{
return true
}
userOrg, err := grabOrgFromUser(user)
if err != nil{
return false
}
/*
Admin Provider
Admin Plan
Manage the authenticated Authorized User's Organization and child Organizations */
if userRole.Key == providerAdmin || userRole.Key == planAdmin{
if isSameOrganization(userOrg, organization) || isAChildOrganization(userOrg, organization) {
return true
}
return false
}
return false
}
func CanUpdateOrganization(user viewmodel.User, organization viewmodel.Organization) bool{
return CanCreateOrganization(user, organization)
}

View File

@@ -21,7 +21,7 @@ func CanCreateUser(currentUser viewmodel.User, updatingUser viewmodel.User) bool
return false
}
updatingUserOrganization, err := grabOrgFromUserDirectly(updatingUser)
updatingUserOrganization, err := grabOrgFromUser(updatingUser)
if err != nil {
return false
}

View File

@@ -10,7 +10,6 @@ import (
"bitbucket.org/nemt/nemt-portal-api/infra/cache"
"bitbucket.org/nemt/nemt-portal-api/infra/config"
"bitbucket.org/nemt/nemt-portal-api/server/router/routeutils"
"bitbucket.org/nemt/nemt-portal-api/server/authorization"
"github.com/labstack/echo"
)
@@ -65,11 +64,6 @@ func (c *controller) handleAddOrganization(ctx echo.Context) error {
if err != nil {
return routeutils.HandleAPIError(ctx, err)
}
if !authorization.CanCreateOrganization(authUser, org) {
return routeutils.ResponseAPIAuthorizationError(ctx)
}
org.Author.ID = authUser.ID
org.LastEditor.ID = authUser.ID
@@ -133,15 +127,6 @@ func (c *controller) handleParent(ctx echo.Context) error {
return routeutils.HandleAPIError(ctx, err)
}
organization, err := c.svc.Organization.GetByUUID(orgUUID, authUser)
if err != nil {
return routeutils.HandleAPIError(ctx, err)
}
if !authorization.CanUpdateOrganization(authUser, organization){
return routeutils.ResponseAPIAuthorizationError(ctx)
}
resp, err := c.svc.Organization.SetParentOrganization(orgUUID, parent.UUID, authUser)
if err != nil {
return routeutils.HandleAPIError(ctx, err)
@@ -167,15 +152,6 @@ func (c *controller) handleChild(ctx echo.Context) error {
return routeutils.HandleAPIError(ctx, err)
}
organization, err := c.svc.Organization.GetByUUID(orgUUID, authUser)
if err != nil {
return routeutils.HandleAPIError(ctx, err)
}
if !authorization.CanUpdateOrganization(authUser, organization){
return routeutils.ResponseAPIAuthorizationError(ctx)
}
_, err = c.svc.Organization.SetParentOrganization(child.UUID, orgUUID, authUser)
if err != nil {
return routeutils.HandleAPIError(ctx, err)
@@ -270,18 +246,6 @@ func (c *controller) handleAddAddress(ctx echo.Context) error {
if err != nil {
return routeutils.HandleAPIError(ctx, err)
}
organization, err := c.svc.Organization.GetByUUID(orgUUID, authUser)
if err != nil {
return routeutils.HandleAPIError(ctx, err)
}
if !authorization.CanCreateAddress(authUser, organization) {
return routeutils.ResponseAPIAuthorizationError(ctx)
}
return routeutils.ResponseAPIAuthorizationError(ctx)
address.CreatedUser.ID = authUser.ID
address.UpdatedUser.ID = authUser.ID
@@ -314,7 +278,6 @@ func (c *controller) handleRemoveContact(ctx echo.Context) error {
if err != nil {
return routeutils.HandleAPIError(ctx, err)
}
contact.UpdatedUser.ID = authUser.ID
err = c.svc.Organization.InactivateOrganizationContact(orgUUID, contact, authUser)
@@ -346,16 +309,6 @@ func (c *controller) handleAddContact(ctx echo.Context) error {
if err != nil {
return routeutils.HandleAPIError(ctx, err)
}
organization, err := c.svc.Organization.GetByUUID(orgUUID, authUser)
if err != nil {
return routeutils.HandleAPIError(ctx, err)
}
if !authorization.CanCreateContact(authUser, organization) {
return routeutils.ResponseAPIAuthorizationError(ctx)
}
contact.CreatedUser.ID = authUser.ID
contact.UpdatedUser.ID = authUser.ID

View File

@@ -33,18 +33,6 @@ func ResponseAPIOK(c echo.Context, data interface{}) error {
return c.JSON(http.StatusOK, data)
}
// ResponseAPIErrorWithData returns a standard API error with additional data to the response
func ResponseAPIErrorWithData(c echo.Context, status int, message string, redirect bool, data interface{}) error {
returnValue := resultWrapper{
Error: true,
Message: message,
Redirect: redirect,
Data: data,
}
return c.JSON(status, returnValue)
}
// ResponseAPIError returns a standard API error to the response
func ResponseAPIError(c echo.Context, status int, message string, redirect bool) error {
returnValue := resultWrapper{
@@ -76,11 +64,6 @@ func ResponseAPIValidationError(c echo.Context, message string) error {
return ResponseAPIError(c, http.StatusUnprocessableEntity, message, false)
}
// ResponseAPICustomValidationError returns a standard API validation error with custom data to the response
func ResponseAPICustomValidationError(c echo.Context, message string, data interface{}) error {
return ResponseAPIErrorWithData(c, http.StatusUnprocessableEntity, message, false, data)
}
// ResponseAPIFieldValidationError returns a standard API field validation error to the response
func ResponseAPIFieldValidationError(c echo.Context, field string, message string) error {
err := errors.NewValidationError(field, message)

View File

@@ -15,7 +15,6 @@ import (
"bitbucket.org/nemt/nemt-portal-api/infra/auth"
"bitbucket.org/nemt/nemt-portal-api/infra/config"
"bitbucket.org/nemt/nemt-portal-api/server/router/routeutils"
"bitbucket.org/nemt/nemt-portal-api/server/validation"
"github.com/labstack/echo"
uuid "github.com/satori/go.uuid"
"google.golang.org/api/googleapi/transport"
@@ -232,11 +231,6 @@ func (c *controller) handle(ctx echo.Context) error {
return routeutils.ResponseAPIValidationError(ctx, "User not found")
}
//Validate ride request
if validationErrors := validation.ValidateRide(&requestRide, &user) ; len(validationErrors) > 0 {
return routeutils.ResponseAPICustomValidationError(ctx, "ride validation failed", validationErrors)
}
createdUser, err := auth.GetUserDetail(ctx, c.cfg)
if err != nil {
return routeutils.HandleAPIError(ctx, err)
@@ -875,4 +869,4 @@ func (c *controller) handleReady(ctx echo.Context) error {
}()
return routeutils.ResponseAPIOK(ctx, nextRide)
}
}

View File

@@ -128,62 +128,6 @@ func (c *controller) handleRemoveAddress(ctx echo.Context) error {
return routeutils.ResponseNoContent(ctx, addressID)
}
func (c *controller) handlePortalContact(ctx echo.Context) error {
userID, err := routeutils.GetAndValidateStringParam(ctx, "user_uuid", "mandatory field")
if err != nil {
return routeutils.HandleAPIError(ctx, err)
}
item, err := c.svc.Users.GetByUUID(userID, "")
if err != nil {
return routeutils.HandleAPIError(ctx, err)
}
createdUser, err := auth.GetUserDetail(ctx, c.cfg)
if err != nil {
return routeutils.HandleAPIError(ctx, err)
}
if item.ID == "" {
return routeutils.ResponseAPIValidationError(ctx, "User not found")
} else {
var Contact viewmodel.Contact
if err := ctx.Bind(&Contact); err != nil {
return routeutils.HandleAPIError(ctx, err)
}
Contact.User = item
Contact.Author = createdUser
Contact, err = c.svc.Users.SaveContact(Contact)
if err != nil {
return routeutils.HandleAPIError(ctx, err)
}
// Contact.User, err = c.svc.Users.GetByUUID(userID, "")
// if err != nil {
// return routeutils.HandleAPIError(ctx, err)
// }
return routeutils.ResponseAPIOK(ctx, Contact)
}
}
func (c *controller) handleRemoveContact(ctx echo.Context) error {
contactUUID, err := routeutils.GetAndValidateStringParam(ctx, "contact_uuid", "mandatory field")
if err != nil {
return routeutils.HandleAPIError(ctx, err)
}
contact := viewmodel.Contact{
ID: contactUUID,
}
contact, err = c.svc.Users.RemoveContact(contact)
if err != nil {
return routeutils.HandleAPIError(ctx, err)
}
return routeutils.ResponseNoContent(ctx, contact)
}
func (c *controller) handleMemberAddress(ctx echo.Context) error {
userID, err := routeutils.GetAndValidateStringParam(ctx, "user_uuid", "mandatory field")
if err != nil {

View File

@@ -17,8 +17,6 @@ const (
userDetailRoute = "/portal/:user_uuid"
userAddressRoute = "/portal/:user_uuid/address"
userRemoveAddressRoute = "/portal/:user_uuid/address/:address_uuid"
userContactRoute = "/portal/:user_uuid/contact"
userRemoveContactRoute = "/portal/:user_uuid/contact/:contact_uuid"
portalRoute = "/portal"
portalBulkRoute = "/portal/bulk"
contacttypeRoute = "/contacttype"
@@ -43,9 +41,6 @@ func Register(r *echo.Group, cfg *config.Config, svc *applicationservice.Service
r.POST(userAddressRoute, ctrl.handlePortalAddress)
r.PUT(userRemoveAddressRoute, ctrl.handleRemoveAddress)
r.POST(userContactRoute, ctrl.handlePortalContact)
r.PUT(userRemoveContactRoute, ctrl.handleRemoveContact)
//Can be cached
r.GET(contacttypeRoute, ctrl.handleContactType)

View File

@@ -18,7 +18,7 @@ func SetMiddlewares(server *echo.Echo, cfg *config.Config, log *logger.Logger, s
setCORSMiddleware(server, cfg)
setBodyLimitMiddleware(server)
setRateLimitMiddleware(server)
//setAuthorizationMiddleware(server, log, cfg, appsvc)
setAuthorizationMiddleware(server, log, cfg, appsvc)
err := setJWTMiddleware(server, cfg)
if err != nil {

View File

@@ -1,183 +0,0 @@
package validation
import (
"time"
"fmt"
"strconv"
"bitbucket.org/nemt/nemt-portal-api/application/viewmodel"
"bitbucket.org/nemt/nemt-portal-api/infra/errors"
)
const (
tripTypeFromVisit = "From Visit"
tripTypeToVisit = "To Visit"
tripTypeFromVisitWillCall = "From Visit / Will Call"
tripTypeRoundTrip = "Round Trip"
tripTypeRountTripWillCall = "Round Trip / Will Call"
)
const (
loadingTime = 30 //in minutes
minimumLoadTime = 30 //in minutes
minimumPickupTime = 10 //in minutes
)
const (
hoursInDay = 24
hoursIn180Days = 24*180
time8Hours = 8
time10Minutes = 10
)
func ValidateRide(requestRide *viewmodel.RideRequest, user *viewmodel.User) []errors.ValidationError {
var result []errors.ValidationError
//Step #1 validation
if userID, err := strconv.Atoi(user.ID) ; err != nil || userID <= 0 {
result = append(result, errors.ValidationError{Field : "user_uuid", Message : "Step #1 - Choose a Member" })
}
if originID, err := strconv.Atoi(requestRide.Origin.ID) ; err != nil || originID <= 0 {
result = append (result, errors.ValidationError{Field : "origin.id", Message : "Step #1 - Choose a Pickup Address"})
}
if !requestRide.UserConsent {
result = append (result, errors.ValidationError{Field : "user_consent", Message : "Step #1 - Member must consent to Terms of Use"})
}
//Step #2 validation
if destinationID, err := strconv.Atoi(requestRide.Destination.ID) ; err!= nil || destinationID <= 0 {
result = append (result, errors.ValidationError{Field : "destination.id", Message : "Step #2 - Choose a Provider"})
}
//Step #3 validation
isVisitDayToday := requestRide.VisitDate.Day() == time.Now().Day() && requestRide.VisitDate.Month() == time.Now().Month() && requestRide.VisitDate.Year() == time.Now().Year()
before8Hours := time.Now().Add(-time.Hour*time8Hours)
if requestRide.VisitDate == nil {
result = append (result, errors.ValidationError{Field : "visit_date", Message : "Step #3 - Choose a Date for the Visit"})
}else{
dayBeforeToday := time.Now().Add(-time.Hour*hoursInDay)
if requestRide.VisitDate.Before(dayBeforeToday) {
result = append (result, errors.ValidationError{Field : "visit_date", Message : "Step #3 - Visit cannot occur more than one day before today"})
}
dayAfter180Days := time.Now().Add(time.Hour*hoursIn180Days)
if requestRide.VisitDate.After(dayAfter180Days) {
result = append (result, errors.ValidationError{Field : "visit_date", Message : "Step #3 - Visit cannot occur more than 180 days after today"})
}
if requestRide.VisitTime == nil {
result = append (result, errors.ValidationError{Field : "visit_time", Message : "Step #3 - Choose a Time for the Visit"})
}else{
if isVisitDayToday && requestRide.VisitTime.Before(before8Hours) {
result = append (result, errors.ValidationError{Field : "visit_time", Message : "Step #3 - Visit is more than 8 hours in the past"})
}
}
}
//Step #4 validation
if requestRide.TripType.Value == "" {
result = append (result, errors.ValidationError{Field : "trip_type.value", Message : "Step #4 - Choose a Trip Type"})
}
timeWithDurationAndLoadingTime := requestRide.VisitTime.Add(-time.Duration(requestRide.Duration)*time.Second).Add(-loadingTime*time.Minute)
after10Minutes := time.Now().Add(time.Minute*time10Minutes)
switch requestRide.TripType.Value {
case tripTypeToVisit:
if requestRide.PickupTime == nil {
result = append (result, errors.ValidationError{Field : "pickup_time", Message : "Step #4 - Choose a Pickup Time"})
}else{
if requestRide.PickupTime.After(*requestRide.VisitTime) {
result = append (result, errors.ValidationError{Field : "pickup_time", Message : "Step #4 - Pickup Time must occur before Visit Time"})
}
if requestRide.PickupTime.After(timeWithDurationAndLoadingTime) {
result = append (result, errors.ValidationError{Field : "pickup_time", Message : "Step #4 - Pickup Time less than required time before Visit Time"})
}
if isVisitDayToday && requestRide.PickupTime.Before(before8Hours) {
result = append (result, errors.ValidationError{Field : "pickup_time", Message : "Step #4 - Visit cannot occour in the past"})
}
}
case tripTypeFromVisit :
if requestRide.PickupTime == nil {
result = append (result, errors.ValidationError{Field : "pickup_time", Message : "Step #4 - Choose a Pickup Time"})
}else{
timeWithMinimumPickupTime := time.Now().Add(minimumPickupTime*time.Minute)
if isVisitDayToday && requestRide.PickupTime.Before(timeWithMinimumPickupTime) {
result = append (result, errors.ValidationError{Field : "pickup_time", Message : fmt.Sprint("Step #4 - Time must be more than %d minutes from now",minimumPickupTime)})
}
if requestRide.PickupTime.Before(*requestRide.VisitTime) {
result = append (result, errors.ValidationError{Field : "pickup_time", Message : "Step #4 - Pickup Time less than required time after Visit Time"})
}
timeWithMinimumLoadTime := time.Now().Add(minimumLoadTime*time.Minute)
if requestRide.PickupTime.Before(timeWithMinimumLoadTime) {
result = append (result, errors.ValidationError{Field : "pickup_time", Message : "Step #4 - Pickup Time less than Minimum Load Time before Visit Time"})
}
}
case tripTypeFromVisitWillCall:
//no special validation for this case
case tripTypeRoundTrip:
if requestRide.PickupTime == nil {
result = append (result, errors.ValidationError{Field : "pickup_time", Message : "Step #4 - Choose a Pickup Time"})
}else{
if requestRide.PickupTime.After(*requestRide.VisitTime) {
result = append (result, errors.ValidationError{Field : "pickup_time", Message : "Step #4 - Pickup Time must occur before Visit Time"})
}
if requestRide.PickupTime.After(timeWithDurationAndLoadingTime) {
result = append (result, errors.ValidationError{Field : "pickup_time", Message : "Step #4 - Pickup Time less than required time before Visit Time"})
}
if isVisitDayToday && requestRide.PickupTime.Before(after10Minutes) {
result = append (result, errors.ValidationError{Field : "pickup_time", Message : "Step #4 - Pickup Time must be at least 10 minutes from now"})
}
}
if requestRide.ReturnTime == nil {
result = append (result, errors.ValidationError{Field : "return_time", Message : "Step #4 - Choose a Pickup Time"})
}else{
if isVisitDayToday {
if requestRide.ReturnTime.Before(before8Hours) {
result = append (result, errors.ValidationError{Field : "return_time", Message : "Step #4 - Return Time is more than 8 hours after Visit Time"})
}
if requestRide.ReturnTime.Before(after10Minutes) {
result = append (result, errors.ValidationError{Field : "return_time", Message : "Step #4 - Return Time must be at least 10 minutes from now"})
}
}
}
case tripTypeRountTripWillCall:
if requestRide.PickupTime == nil {
result = append (result, errors.ValidationError{Field : "pickup_time", Message : "Step #4 - Choose a Pickup Time"})
}else{
if requestRide.PickupTime.After(*requestRide.VisitTime) {
result = append (result, errors.ValidationError{Field : "pickup_time", Message : "Step #4 - Pickup Time must occur before Visit Time"})
}
if requestRide.PickupTime.After(timeWithDurationAndLoadingTime) {
result = append (result, errors.ValidationError{Field : "pickup_time", Message : "Step #4 - Pickup Time less than required time after Visit Time"})
}
if isVisitDayToday && requestRide.PickupTime.Before(before8Hours) {
result = append (result, errors.ValidationError{Field : "pickup_time", Message : "Step #4 - Visit cannot occur in the past "})
}
}
}
return result
}