Commit 4c25d50c authored by Lee Brown's avatar Lee Brown

fix where, auth use request arg

parent 0471af92
......@@ -55,7 +55,7 @@ func (p *Project) Find(ctx context.Context, w http.ResponseWriter, r *http.Reque
if err != nil {
return web.RespondJsonError(ctx, w, weberror.NewError(ctx, err, http.StatusBadRequest))
}
req.Where = &where
req.Where = where
req.Args = args
}
......
......@@ -42,6 +42,10 @@ func (c *Signup) Signup(ctx context.Context, w http.ResponseWriter, r *http.Requ
// Claims are optional as authentication is not required ATM for this method.
claims, _ := auth.ClaimsFromContext(ctx)
// Hack to allow custom validation to be handled by business logic package.
ctx = context.WithValue(ctx, signup.KeyTagUniqueEmail, true)
ctx = context.WithValue(ctx, signup.KeyTagUniqueName, true)
var req signup.SignupRequest
if err := web.Decode(ctx, r, &req); err != nil {
if _, ok := errors.Cause(err).(*weberror.Error); !ok {
......
......@@ -60,7 +60,7 @@ func (u *User) Find(ctx context.Context, w http.ResponseWriter, r *http.Request,
if err != nil {
return web.RespondJsonError(ctx, w, weberror.NewError(ctx, err, http.StatusBadRequest))
}
req.Where = &where
req.Where = where
req.Args = args
}
......@@ -442,7 +442,9 @@ func (u *User) SwitchAccount(ctx context.Context, w http.ResponseWriter, r *http
return err
}
tkn, err := user_auth.SwitchAccount(ctx, u.MasterDB, u.TokenGenerator, claims, params["account_id"], sessionTtl, v.Now)
tkn, err := user_auth.SwitchAccount(ctx, u.MasterDB, u.TokenGenerator, claims, user_auth.SwitchAccountRequest{
AccountID: params["account_id"],
}, sessionTtl, v.Now)
if err != nil {
cause := errors.Cause(err)
switch cause {
......@@ -486,10 +488,16 @@ func (u *User) Token(ctx context.Context, w http.ResponseWriter, r *http.Request
return web.RespondJsonError(ctx, w, weberror.NewError(ctx, err, http.StatusUnauthorized))
}
accountID := r.URL.Query().Get("account_id")
// Optional to include scope.
scope := r.URL.Query().Get("scope")
tkn, err := user_auth.Authenticate(ctx, u.MasterDB, u.TokenGenerator, email, pass, sessionTtl, v.Now, scope)
tkn, err := user_auth.Authenticate(ctx, u.MasterDB, u.TokenGenerator, user_auth.AuthenticateRequest{
Email: email,
Password: pass,
AccountID: accountID,
}, sessionTtl, v.Now, scope)
if err != nil {
cause := errors.Cause(err)
switch cause {
......@@ -505,30 +513,5 @@ func (u *User) Token(ctx context.Context, w http.ResponseWriter, r *http.Request
}
}
accountID := r.URL.Query().Get("account_id")
if accountID != "" && accountID != tkn.AccountID {
claims, err := u.TokenGenerator.ParseClaims(tkn.AccessToken)
if err != nil {
return err
}
tkn, err = user_auth.SwitchAccount(ctx, u.MasterDB, u.TokenGenerator, claims, accountID, sessionTtl, v.Now)
if err != nil {
cause := errors.Cause(err)
switch cause {
case user_auth.ErrAuthenticationFailure:
return web.RespondJsonError(ctx, w, weberror.NewError(ctx, err, http.StatusUnauthorized))
default:
_, ok := cause.(validator.ValidationErrors)
if ok {
return web.RespondJsonError(ctx, w, weberror.NewError(ctx, err, http.StatusBadRequest))
}
return errors.Wrap(err, "switch account")
}
}
}
return web.RespondJson(ctx, w, tkn, http.StatusOK)
}
......@@ -55,7 +55,7 @@ func (u *UserAccount) Find(ctx context.Context, w http.ResponseWriter, r *http.R
if err != nil {
return web.RespondJsonError(ctx, w, weberror.NewError(ctx, err, http.StatusBadRequest))
}
req.Where = &where
req.Where = where
req.Args = args
}
......
......@@ -102,9 +102,13 @@ func TestAccountCRUDAdmin(t *testing.T) {
"address1": tr.Account.Address1,
"city": tr.Account.City,
"status": map[string]interface{}{
"value": "active",
"title": "Active",
"options": []map[string]interface{}{{"selected": false, "title": "[Active Pending Disabled]", "value": "[active pending disabled]"}},
"value": "active",
"title": "Active",
"options": []map[string]interface{}{
{"selected": true, "title": "Active", "value": "active"},
{"selected": false, "title": "Pending", "value": "pending"},
{"selected": false, "title": "Disabled", "value": "disabled"},
},
},
"signup_user_id": &tr.Account.SignupUserID.String,
}
......@@ -322,9 +326,13 @@ func TestAccountCRUDUser(t *testing.T) {
"address1": tr.Account.Address1,
"city": tr.Account.City,
"status": map[string]interface{}{
"value": "active",
"title": "Active",
"options": []map[string]interface{}{{"selected": false, "title": "[Active Pending Disabled]", "value": "[active pending disabled]"}},
"value": "active",
"title": "Active",
"options": []map[string]interface{}{
{"selected": true, "title": "Active", "value": "active"},
{"selected": false, "title": "Pending", "value": "pending"},
{"selected": false, "title": "Disabled", "value": "disabled"},
},
},
"signup_user_id": &tr.Account.SignupUserID.String,
}
......
......@@ -79,7 +79,7 @@ func TestProjectCRUDAdmin(t *testing.T) {
"updated_at": web.NewTimeResponse(ctx, actual.UpdatedAt.Value),
"id": actual.ID,
"account_id": req.AccountID,
"status": web.NewEnumResponse(ctx, "active", project.ProjectStatus_Values),
"status": web.NewEnumResponse(ctx, "active", project.ProjectStatus_ValuesInterface()...),
"created_at": web.NewTimeResponse(ctx, actual.CreatedAt.Value),
"name": req.Name,
}
......
......@@ -56,7 +56,10 @@ func newMockSignup() mockSignup {
}
expires := time.Now().UTC().Sub(s.User.CreatedAt) + time.Hour
tkn, err := user_auth.Authenticate(tests.Context(), test.MasterDB, authenticator, req.User.Email, req.User.Password, expires, now)
tkn, err := user_auth.Authenticate(tests.Context(), test.MasterDB, authenticator, user_auth.AuthenticateRequest{
Email: req.User.Email,
Password: req.User.Password,
}, expires, now)
if err != nil {
panic(err)
}
......@@ -139,9 +142,13 @@ func TestSignup(t *testing.T) {
"address1": req.Account.Address1,
"city": req.Account.City,
"status": map[string]interface{}{
"value": "active",
"title": "Active",
"options": []map[string]interface{}{{"selected": false, "title": "[Active Pending Disabled]", "value": "[active pending disabled]"}},
"value": "active",
"title": "Active",
"options": []map[string]interface{}{
{"selected": true, "title": "Active", "value": "active"},
{"selected": false, "title": "Pending", "value": "pending"},
{"selected": false, "title": "Disabled", "value": "disabled"},
},
},
"signup_user_id": &actual.Account.SignupUserID,
},
......
......@@ -95,7 +95,10 @@ func testMain(m *testing.M) int {
}
expires := time.Now().UTC().Sub(signup1.User.CreatedAt) + time.Hour
adminTkn, err := user_auth.Authenticate(tests.Context(), test.MasterDB, authenticator, signupReq1.User.Email, signupReq1.User.Password, expires, now)
adminTkn, err := user_auth.Authenticate(tests.Context(), test.MasterDB, authenticator, user_auth.AuthenticateRequest{
Email: signupReq1.User.Email,
Password: signupReq1.User.Password,
}, expires, now)
if err != nil {
panic(err)
}
......@@ -146,7 +149,10 @@ func testMain(m *testing.M) int {
panic(err)
}
userTkn, err := user_auth.Authenticate(tests.Context(), test.MasterDB, authenticator, usr.Email, userReq.Password, expires, now)
userTkn, err := user_auth.Authenticate(tests.Context(), test.MasterDB, authenticator, user_auth.AuthenticateRequest{
Email: usr.Email,
Password: userReq.Password,
}, expires, now)
if err != nil {
panic(err)
}
......
......@@ -89,13 +89,18 @@ func TestUserAccountCRUDAdmin(t *testing.T) {
}
created = actual
var roles []interface{}
for _, r := range req.Roles {
roles = append(roles, r)
}
expectedMap := map[string]interface{}{
"updated_at": web.NewTimeResponse(ctx, actual.UpdatedAt.Value),
//"id": actual.ID,
"account_id": req.AccountID,
"user_id": req.UserID,
"status": web.NewEnumResponse(ctx, "active", user_account.UserAccountStatus_Values),
"roles": req.Roles,
"status": web.NewEnumResponse(ctx, "active", user_account.UserAccountStatus_ValuesInterface()...),
"roles": web.NewEnumMultiResponse(ctx, roles, user_account.UserAccountRole_ValuesInterface()...),
"created_at": web.NewTimeResponse(ctx, actual.CreatedAt.Value),
}
......
......@@ -1419,7 +1419,7 @@ func TestUserToken(t *testing.T) {
// Test user token with invalid email.
{
expectedStatus := http.StatusUnauthorized
expectedStatus := http.StatusBadRequest
rt := requestTest{
fmt.Sprintf("Token %d using invalid email", expectedStatus),
......@@ -1434,7 +1434,9 @@ func TestUserToken(t *testing.T) {
t.Logf("\tTest: %s - %s %s", rt.name, rt.method, rt.url)
r := httptest.NewRequest(rt.method, rt.url, nil)
r.SetBasicAuth("invalid email.com", "some random password")
invalidEmail := "invalid email.com"
r.SetBasicAuth(invalidEmail, "some random password")
w := httptest.NewRecorder()
r.Header.Set("Content-Type", web.MIMEApplicationJSONCharsetUTF8)
......@@ -1456,8 +1458,17 @@ func TestUserToken(t *testing.T) {
expected := weberror.ErrorResponse{
StatusCode: expectedStatus,
Error: http.StatusText(expectedStatus),
Details: user_auth.ErrAuthenticationFailure.Error(),
Error: "Field validation error",
Fields: []weberror.FieldError{
{
Field: "email",
Value: invalidEmail,
Tag: "email",
Error: "email must be a valid email address",
Display: "email must be a valid email address",
},
},
Details: actual.Details,
StackTrace: actual.StackTrace,
}
......
......@@ -110,9 +110,8 @@ func (h *Projects) Index(ctx context.Context, w http.ResponseWriter, r *http.Req
}
loadFunc := func(ctx context.Context, sorting string, fields []datatable.DisplayField) (resp [][]datatable.ColumnValue, err error) {
whereFilter := "account_id = ?"
res, err := project.Find(ctx, claims, h.MasterDB, project.ProjectFindRequest{
Where: &whereFilter,
Where: "account_id = ?",
Args: []interface{}{claims.Audience},
Order: strings.Split(sorting, ","),
})
......
......@@ -209,6 +209,8 @@ func (h *User) ResetPassword(ctx context.Context, w http.ResponseWriter, r *http
// ResetConfirm handles changing a users password after they have clicked on the link emailed.
func (h *User) ResetConfirm(ctx context.Context, w http.ResponseWriter, r *http.Request, params map[string]string) error {
resetHash := params["hash"]
ctxValues, err := webcontext.ContextValues(ctx)
if err != nil {
return err
......@@ -217,31 +219,36 @@ func (h *User) ResetConfirm(ctx context.Context, w http.ResponseWriter, r *http.
//
req := new(user.UserResetConfirmRequest)
data := make(map[string]interface{})
f := func() error {
f := func() (bool, error) {
if r.Method == http.MethodPost {
err := r.ParseForm()
if err != nil {
return err
return false, err
}
decoder := schema.NewDecoder()
if err := decoder.Decode(req, r.PostForm); err != nil {
return err
return false, err
}
// Append the query param value to the request.
req.ResetHash = params["hash"]
req.ResetHash = resetHash
u, err := user.ResetConfirm(ctx, h.MasterDB, *req, h.SecretKey, ctxValues.Now)
if err != nil {
switch errors.Cause(err) {
case user.ErrResetExpired:
webcontext.SessionFlashError(ctx,
"Reset Expired",
"The reset has expired.")
return false, nil
default:
if verr, ok := weberror.NewValidationError(ctx, err); ok {
data["validationErrors"] = verr.(*weberror.Error)
return nil
return false, nil
} else {
return err
return false, err
}
}
}
......@@ -249,34 +256,51 @@ func (h *User) ResetConfirm(ctx context.Context, w http.ResponseWriter, r *http.
// Authenticated the user. Probably should use the default session TTL from UserLogin.
token, err := user_auth.Authenticate(ctx, h.MasterDB, h.Authenticator, u.Email, req.Password, time.Hour, ctxValues.Now)
if err != nil {
switch errors.Cause(err) {
case account.ErrForbidden:
return web.RespondError(ctx, w, weberror.NewError(ctx, err, http.StatusForbidden))
default:
if verr, ok := weberror.NewValidationError(ctx, err); ok {
data["validationErrors"] = verr.(*weberror.Error)
return nil
} else {
return err
}
if verr, ok := weberror.NewValidationError(ctx, err); ok {
data["validationErrors"] = verr.(*weberror.Error)
return false, nil
} else {
return false, err
}
}
// Add the token to the users session.
err = handleSessionToken(ctx, h.MasterDB, w, r, token)
if err != nil {
return err
return false, err
}
// Redirect the user to the dashboard.
http.Redirect(w, r, "/", http.StatusFound)
return true, nil
}
return nil
_, err = user.ParseResetHash(ctx, h.SecretKey, resetHash, ctxValues.Now)
if err != nil {
switch errors.Cause(err) {
case user.ErrResetExpired:
webcontext.SessionFlashError(ctx,
"Reset Expired",
"The reset has expired.")
return false, nil
default:
if verr, ok := weberror.NewValidationError(ctx, err); ok {
data["validationErrors"] = verr.(*weberror.Error)
return false, nil
} else {
return false, err
}
}
}
return false, nil
}
if err := f(); err != nil {
end, err := f()
if err != nil {
return web.RenderError(ctx, w, r, err, h.Renderer, TmplLayoutBase, TmplContentErrorGeneric, web.MIMETextHTMLCharsetUTF8)
} else if end {
return nil
}
data["form"] = req
......@@ -572,9 +596,8 @@ func (h *User) VirtualLogin(ctx context.Context, w http.ResponseWriter, r *http.
return nil
}
usrAccFilter := "account_id = ?"
usrAccs, err := user_account.Find(ctx, claims, h.MasterDB, user_account.UserAccountFindRequest{
Where: &usrAccFilter,
Where: "account_id = ?",
Args: []interface{}{claims.Audience},
})
if err != nil {
......@@ -597,10 +620,10 @@ func (h *User) VirtualLogin(ctx context.Context, w http.ResponseWriter, r *http.
userPhs = append(userPhs, "?")
}
usrFilter := fmt.Sprintf("id IN (%s)", strings.Join(userPhs, ", "))
users, err := user.Find(ctx, claims, h.MasterDB, user.UserFindRequest{
Where: &usrFilter,
Args: userIDs,
Where: fmt.Sprintf("id IN (%s)",
strings.Join(userPhs, ", ")),
Args: userIDs,
})
if err != nil {
return err
......
......@@ -52,12 +52,18 @@ func urlUsersUpdate(userID string) string {
return fmt.Sprintf("/users/%s/update", userID)
}
// UserLoginRequest extends the AuthenicateRequest with the RememberMe flag.
// UserCreateRequest extends the UserCreateRequest with a list of roles.
type UserCreateRequest struct {
user.UserCreateRequest
Roles user_account.UserAccountRoles `json:"roles" validate:"required,dive,oneof=admin user" enums:"admin,user" swaggertype:"array,string" example:"admin"`
}
// UserUpdateRequest extends the UserUpdateRequest with a list of roles.
type UserUpdateRequest struct {
user.UserUpdateRequest
Roles user_account.UserAccountRoles `json:"roles" validate:"required,dive,oneof=admin user" enums:"admin,user" swaggertype:"array,string" example:"admin"`
}
// Index handles listing all the users for the current account.
func (h *Users) Index(ctx context.Context, w http.ResponseWriter, r *http.Request, params map[string]string) error {
......@@ -198,8 +204,6 @@ func (h *Users) Create(ctx context.Context, w http.ResponseWriter, r *http.Reque
}
decoder := schema.NewDecoder()
decoder.IgnoreUnknownKeys(true)
if err := decoder.Decode(req, r.PostForm); err != nil {
return false, err
}
......@@ -279,11 +283,11 @@ func (h *Users) Create(ctx context.Context, w http.ResponseWriter, r *http.Reque
return err
}
var roleValues []interface{}
for _, v := range user_account.UserAccountRole_Values {
roleValues = append(roleValues, string(v))
var selectedRoles []interface{}
for _, r := range req.Roles {
selectedRoles = append(selectedRoles, r.String())
}
data["roles"] = web.NewEnumResponse(ctx, nil, roleValues...)
data["roles"] = web.NewEnumMultiResponse(ctx, selectedRoles, user_account.UserAccountRole_ValuesInterface()...)
data["form"] = req
......@@ -389,7 +393,7 @@ func (h *Users) Update(ctx context.Context, w http.ResponseWriter, r *http.Reque
}
//
req := new(user.UserUpdateRequest)
req := new(UserUpdateRequest)
data := make(map[string]interface{})
f := func() (bool, error) {
if r.Method == http.MethodPost {
......@@ -400,13 +404,27 @@ func (h *Users) Update(ctx context.Context, w http.ResponseWriter, r *http.Reque
decoder := schema.NewDecoder()
decoder.IgnoreUnknownKeys(true)
if err := decoder.Decode(req, r.PostForm); err != nil {
return false, err
}
req.ID = userID
err = user.Update(ctx, claims, h.MasterDB, *req, ctxValues.Now)
// Bypass the uniq check on email here for the moment, it will be caught before the user_account is
// created by user.Create.
ctx = context.WithValue(ctx, webcontext.KeyTagUnique, true)
// Validate the request.
err = webcontext.Validator().StructCtx(ctx, req)
if err != nil {
if verr, ok := weberror.NewValidationError(ctx, err); ok {
data["validationErrors"] = verr.(*weberror.Error)
return false, nil
} else {
return false, err
}
}
err = user.Update(ctx, claims, h.MasterDB, req.UserUpdateRequest, ctxValues.Now)
if err != nil {
switch errors.Cause(err) {
default:
......@@ -419,6 +437,25 @@ func (h *Users) Update(ctx context.Context, w http.ResponseWriter, r *http.Reque
}
}
if req.Roles != nil {
err = user_account.Update(ctx, claims, h.MasterDB, user_account.UserAccountUpdateRequest{
UserID: userID,
AccountID: claims.Audience,
Roles: &req.Roles,
}, ctxValues.Now)
if err != nil {
switch errors.Cause(err) {
default:
if verr, ok := weberror.NewValidationError(ctx, err); ok {
data["validationErrors"] = verr.(*weberror.Error)
return false, nil
} else {
return false, err
}
}
}
}
if r.PostForm.Get("Password") != "" {
pwdReq := new(user.UserUpdatePasswordRequest)
......@@ -469,11 +506,20 @@ func (h *Users) Update(ctx context.Context, w http.ResponseWriter, r *http.Reque
return err
}
usrAcc, err := user_account.Read(ctx, claims, h.MasterDB, user_account.UserAccountReadRequest{
UserID: userID,
AccountID: claims.Audience,
})
if err != nil {
return err
}
if req.ID == "" {
req.FirstName = &usr.FirstName
req.LastName = &usr.LastName
req.Email = &usr.Email
req.Timezone = usr.Timezone
req.Roles = usrAcc.Roles
}
data["user"] = usr.Response(ctx)
......@@ -483,9 +529,15 @@ func (h *Users) Update(ctx context.Context, w http.ResponseWriter, r *http.Reque
return err
}
var selectedRoles []interface{}
for _, r := range req.Roles {
selectedRoles = append(selectedRoles, r.String())
}
data["roles"] = web.NewEnumMultiResponse(ctx, selectedRoles, user_account.UserAccountRole_ValuesInterface()...)
data["form"] = req
if verr, ok := weberror.NewValidationError(ctx, webcontext.Validator().Struct(user.UserUpdateRequest{})); ok {
if verr, ok := weberror.NewValidationError(ctx, webcontext.Validator().Struct(UserUpdateRequest{})); ok {
data["userValidationDefaults"] = verr.(*weberror.Error)
}
......
......@@ -28,7 +28,6 @@
{{ template "validation-error" . }}
<form class="user" method="post" novalidate>
<input type="hidden" name="ResetHash" value="{{ $.form.ResetHash }}" />
<div class="form-group row">
<div class="col-sm-6 mb-3 mb-sm-0">
<input type="password" class="form-control form-control-user {{ ValidationFieldClass $.validationErrors "Password" }}" name="Password" value="{{ $.form.Password }}" placeholder="Password" required>
......
......@@ -63,13 +63,13 @@
<small>Role</small><br/>
{{ if .userAccount }}
<b>
{{ range $r := .userAccount.Roles }}
{{ if eq $r "admin" }}
<span class="text-pink"><i class="far fa-kiss-wink-heart mr-1"></i>{{ $r }}</span>
{{ range $r := .userAccount.Roles }}{{ if $r.Selected }}
{{ if eq $r.Value "admin" }}
<span class="text-pink"><i class="far fa-kiss-wink-heart mr-1"></i>{{ $r.Title }}</span>
{{else}}
<span class="text-purple"><i class="far fa-user-circle mr-1"></i>{{ $r }}</span>
<span class="text-purple"><i class="far fa-user-circle mr-1"></i>{{ $r.Title }}</span>
{{end}}
{{ end }}
{{ end }}{{ end }}
</b>
{{ end }}
</p>
......
......@@ -153,8 +153,8 @@ func selectQuery() *sqlbuilder.SelectBuilder {
func Find(ctx context.Context, claims auth.Claims, dbConn *sqlx.DB, req AccountFindRequest) (Accounts, error) {
query := selectQuery()
if req.Where != nil {
query.Where(query.And(*req.Where))
if req.Where != "" {
query.Where(query.And(req.Where))
}
if len(req.Order) > 0 {
query.OrderBy(req.Order...)
......
......@@ -65,8 +65,8 @@ func applyClaimsSelect(ctx context.Context, claims auth.Claims, query *sqlbuilde
// TODO: Need to figure out why can't parse the args when appending the where to the query.
func Find(ctx context.Context, claims auth.Claims, dbConn *sqlx.DB, req AccountPreferenceFindRequest) ([]*AccountPreference, error) {
query := sqlbuilder.NewSelectBuilder()
if req.Where != nil {
query.Where(query.And(*req.Where))
if req.Where != "" {
query.Where(query.And(req.Where))
}
if len(req.Order) > 0 {
query.OrderBy(req.Order...)
......
......@@ -397,7 +397,7 @@ func TestFind(t *testing.T) {
// Test sort accounts.
prefTests = append(prefTests, accountTest{"Find all order by created_at asc",
AccountPreferenceFindRequest{
Where: &createdFilter,
Where: createdFilter,
Args: []interface{}{startTime, endTime},
Order: []string{"created_at"},
},
......@@ -412,7 +412,7 @@ func TestFind(t *testing.T) {
}
prefTests = append(prefTests, accountTest{"Find all order by created_at desc",
AccountPreferenceFindRequest{
Where: &createdFilter,
Where: createdFilter,
Args: []interface{}{startTime, endTime},
Order: []string{"created_at desc"},
},
......@@ -424,7 +424,7 @@ func TestFind(t *testing.T) {
var limit uint = 2
prefTests = append(prefTests, accountTest{"Find limit",
AccountPreferenceFindRequest{
Where: &createdFilter,
Where: createdFilter,
Args: []interface{}{startTime, endTime},
Order: []string{"created_at"},
Limit: &limit,
......@@ -437,7 +437,7 @@ func TestFind(t *testing.T) {
var offset uint = 1
prefTests = append(prefTests, accountTest{"Find limit, offset",
AccountPreferenceFindRequest{
Where: &createdFilter,
Where: createdFilter,
Args: []interface{}{startTime, endTime},
Order: []string{"created_at"},
Limit: &limit,
......@@ -462,10 +462,9 @@ func TestFind(t *testing.T) {
expected = append(expected, &u)
}
where := createdFilter + " AND (" + strings.Join(whereParts, " OR ") + ")"
prefTests = append(prefTests, accountTest{"Find where",
AccountPreferenceFindRequest{
Where: &where,
Where: createdFilter + " AND (" + strings.Join(whereParts, " OR ") + ")",
Args: whereArgs,
Order: []string{"created_at"},
},
......
......@@ -84,7 +84,7 @@ type AccountPreferenceDeleteRequest struct {
// AccountPreferenceFindRequest defines the possible options to search for accounts. By default
// archived accounts will be excluded from response.
type AccountPreferenceFindRequest struct {
Where *string `json:"where" example:"name = ?"`
Where string `json:"where" example:"name = ?"`
Args []interface{} `json:"args" swaggertype:"array,string" example:"Company Name,active"`
Order []string `json:"order" example:"created_at desc"`
Limit *uint `json:"limit" example:"10"`
......
<
......@@ -842,7 +842,7 @@ func TestFind(t *testing.T) {
type accountTest struct {
name string
req AccountFindRequest
expected []*Account
expected Accounts
error error
}
......@@ -853,7 +853,7 @@ func TestFind(t *testing.T) {
// Test sort accounts.
accountTests = append(accountTests, accountTest{"Find all order by created_at asc",
AccountFindRequest{
Where: &createdFilter,
Where: createdFilter,
Args: []interface{}{startTime, endTime},
Order: []string{"created_at"},
},
......@@ -868,7 +868,7 @@ func TestFind(t *testing.T) {
}
accountTests = append(accountTests, accountTest{"Find all order by created_at desc",
AccountFindRequest{
Where: &createdFilter,