Filter unmarshal & validation before storing

Signed-off-by: Thibaut CHARLES cromfr@gmail.com
This commit is contained in:
Crom (Thibaut CHARLES) 2017-12-23 15:09:29 +01:00
parent fa362ecef2
commit 9af5e73fdf
No known key found for this signature in database
GPG key ID: 45A3D5F880B9E6D0
4 changed files with 36 additions and 17 deletions

View file

@ -17,8 +17,9 @@ package accounts
import ( import (
"context" "context"
"database/sql" "database/sql"
"encoding/json"
"github.com/matrix-org/gomatrixserverlib" "github.com/matrix-org/gomatrix"
) )
const filterSchema = ` const filterSchema = `
@ -71,20 +72,29 @@ func (s *filterStatements) prepare(db *sql.DB) (err error) {
func (s *filterStatements) selectFilter( func (s *filterStatements) selectFilter(
ctx context.Context, localpart string, filterID string, ctx context.Context, localpart string, filterID string,
) (filter []byte, err error) { ) (*gomatrix.Filter, error) {
err = s.selectFilterStmt.QueryRowContext(ctx, localpart, filterID).Scan(&filter) var filterData []byte
return err := s.selectFilterStmt.QueryRowContext(ctx, localpart, filterID).Scan(&filterData)
if err != nil {
return nil, err
}
var filter gomatrix.Filter
if err = json.Unmarshal(filterData, &filter); err != nil {
return nil, err
}
return &filter, err
} }
func (s *filterStatements) insertFilter( func (s *filterStatements) insertFilter(
ctx context.Context, filter []byte, localpart string, ctx context.Context, filter *gomatrix.Filter, localpart string,
) (filterID string, err error) { ) (filterID string, err error) {
var existingFilterID string var existingFilterID string
// This can result in a race condition when two clients try to insert the // This can result in a race condition when two clients try to insert the
// same filter and localpart at the same time, however this is not a // same filter and localpart at the same time, however this is not a
// problem as both calls will result in the same filterID // problem as both calls will result in the same filterID
filterJSON, err := gomatrixserverlib.CanonicalJSON(filter) filterJSON, err := json.Marshal(filter)
if err != nil { if err != nil {
return "", err return "", err
} }

View file

@ -21,6 +21,7 @@ import (
"github.com/matrix-org/dendrite/clientapi/auth/authtypes" "github.com/matrix-org/dendrite/clientapi/auth/authtypes"
"github.com/matrix-org/dendrite/common" "github.com/matrix-org/dendrite/common"
"github.com/matrix-org/gomatrix"
"github.com/matrix-org/gomatrixserverlib" "github.com/matrix-org/gomatrixserverlib"
"golang.org/x/crypto/bcrypt" "golang.org/x/crypto/bcrypt"
// Import the postgres database driver. // Import the postgres database driver.
@ -329,7 +330,7 @@ func (d *Database) GetThreePIDsForLocalpart(
// no such filter exists or if there was an error talking to the database. // no such filter exists or if there was an error talking to the database.
func (d *Database) GetFilter( func (d *Database) GetFilter(
ctx context.Context, localpart string, filterID string, ctx context.Context, localpart string, filterID string,
) ([]byte, error) { ) (*gomatrix.Filter, error) {
return d.filter.selectFilter(ctx, localpart, filterID) return d.filter.selectFilter(ctx, localpart, filterID)
} }
@ -337,7 +338,7 @@ func (d *Database) GetFilter(
// Returns the filterID as a string. Otherwise returns an error if something // Returns the filterID as a string. Otherwise returns an error if something
// goes wrong. // goes wrong.
func (d *Database) PutFilter( func (d *Database) PutFilter(
ctx context.Context, localpart string, filter []byte, ctx context.Context, localpart string, filter *gomatrix.Filter,
) (string, error) { ) (string, error) {
return d.filter.insertFilter(ctx, filter, localpart) return d.filter.insertFilter(ctx, filter, localpart)
} }

View file

@ -49,7 +49,7 @@ func GetFilter(
return httputil.LogThenError(req, err) return httputil.LogThenError(req, err)
} }
res, err := accountDB.GetFilter(req.Context(), localpart, filterID) filter, err := accountDB.GetFilter(req.Context(), localpart, filterID)
if err != nil { if err != nil {
//TODO better error handling. This error message is *probably* right, //TODO better error handling. This error message is *probably* right,
// but if there are obscure db errors, this will also be returned, // but if there are obscure db errors, this will also be returned,
@ -59,15 +59,15 @@ func GetFilter(
JSON: jsonerror.NotFound("No such filter"), JSON: jsonerror.NotFound("No such filter"),
} }
} }
filter := gomatrix.Filter{}
err = json.Unmarshal(res, &filter) filterJSON, err := json.Marshal(filter)
if err != nil { if err != nil {
httputil.LogThenError(req, err) return httputil.LogThenError(req, err)
} }
return util.JSONResponse{ return util.JSONResponse{
Code: 200, Code: 200,
JSON: filter, JSON: filterJSON,
} }
} }
@ -103,15 +103,14 @@ func PutFilter(
return *reqErr return *reqErr
} }
filterArray, err := json.Marshal(filter) if err = filter.Validate(); err != nil {
if err != nil {
return util.JSONResponse{ return util.JSONResponse{
Code: 400, Code: 400,
JSON: jsonerror.BadJSON("Filter is malformed"), JSON: jsonerror.BadJSON("Invalid filter: " + err.Error()),
} }
} }
filterID, err := accountDB.PutFilter(req.Context(), localpart, filterArray) filterID, err := accountDB.PutFilter(req.Context(), localpart, &filter)
if err != nil { if err != nil {
return httputil.LogThenError(req, err) return httputil.LogThenError(req, err)
} }

View file

@ -14,6 +14,8 @@
package gomatrix package gomatrix
import "errors"
//Filter is used by clients to specify how the server should filter responses to e.g. sync requests //Filter is used by clients to specify how the server should filter responses to e.g. sync requests
//Specified by: https://matrix.org/docs/spec/client_server/r0.2.0.html#filtering //Specified by: https://matrix.org/docs/spec/client_server/r0.2.0.html#filtering
type Filter struct { type Filter struct {
@ -41,3 +43,10 @@ type FilterPart struct {
Senders []string `json:"senders,omitempty"` Senders []string `json:"senders,omitempty"`
Types []string `json:"types,omitempty"` Types []string `json:"types,omitempty"`
} }
func (filter *Filter) Validate() error {
if filter.EventFormat != "client" && filter.EventFormat != "federation" {
return errors.New("Bad event_format value. Must be any of [\"client\", \"federation\"]")
}
return nil
}