Validate /createRoom JSON

This commit is contained in:
Kegan Dougal 2017-03-07 16:55:02 +00:00
parent 66ba84f8e6
commit 5a2eb5bbb8
2 changed files with 60 additions and 12 deletions

View file

@ -2,19 +2,48 @@ package common
import (
"encoding/json"
"fmt"
"github.com/matrix-org/dendrite/clientapi/jsonerror"
"github.com/matrix-org/util"
"net/http"
"strings"
)
// UserID represents a parsed User ID string
type UserID struct {
Domain string
Localpart string
}
// UserIDFromString creates a UserID from an input string. Returns an error if
// the string is not a valid user ID.
func UserIDFromString(id string) (uid UserID, err error) {
// https://github.com/matrix-org/synapse/blob/v0.19.2/synapse/types.py#L92
if len(id) == 0 || id[0] != '@' {
err = fmt.Errorf("user id must start with '@'")
return
}
parts := strings.SplitN(id[1:], ":", 2)
if len(parts) != 2 {
err = fmt.Errorf("user id must be in the form @localpart:domain")
return
}
uid.Localpart = parts[0]
uid.Domain = parts[1]
return
}
// UnmarshalJSONRequest into the given interface pointer. Returns an error JSON response if
// there was a problem unmarshalling. Calling this function consumes the request body.
func UnmarshalJSONRequest(req *http.Request, iface interface{}) *util.JSONResponse {
defer req.Body.Close()
if err := json.NewDecoder(req.Body).Decode(iface); err != nil {
// TODO: We may want to suppress the Error() return in production? It's useful when
// debugging because an error will be produced for both invalid/malformed JSON AND
// valid JSON with incorrect types for values.
return &util.JSONResponse{
Code: 400,
JSON: jsonerror.NotJSON("The request body was not JSON"),
JSON: jsonerror.BadJSON("The request body could not be decoded into valid JSON. " + err.Error()),
}
}
return nil

View file

@ -4,10 +4,12 @@ import (
"encoding/json"
"fmt"
"net/http"
"strings"
log "github.com/Sirupsen/logrus"
"github.com/matrix-org/dendrite/clientapi/auth"
"github.com/matrix-org/dendrite/clientapi/common"
"github.com/matrix-org/dendrite/clientapi/jsonerror"
"github.com/matrix-org/util"
)
@ -23,6 +25,26 @@ type createRoomRequest struct {
RoomAliasName string `json:"room_alias_name"`
}
func (r createRoomRequest) Validate() *util.JSONResponse {
whitespace := "\t\n\x0b\x0c\r " // https://docs.python.org/2/library/string.html#string.whitespace
// https://github.com/matrix-org/synapse/blob/v0.19.2/synapse/handlers/room.py#L81
if strings.ContainsAny(r.RoomAliasName, whitespace) {
return &util.JSONResponse{
Code: 400,
JSON: jsonerror.BadJSON("room_alias_name cannot contain whitespace"),
}
}
for _, userID := range r.Invite {
if _, err := common.UserIDFromString(userID); err != nil {
return &util.JSONResponse{
Code: 400,
JSON: jsonerror.BadJSON("Entries in 'invite' must be valid user IDs"),
}
}
}
return nil
}
// https://matrix.org/docs/spec/client_server/r0.2.0.html#post-matrix-client-r0-createroom
type createRoomResponse struct {
RoomID string `json:"room_id"`
@ -42,26 +64,23 @@ func CreateRoom(req *http.Request) util.JSONResponse {
return *resErr
}
// TODO: apply rate-limit
// TODO: parse room_alias_name
// TODO: parse invite list (all valid user ids)
// TODO: invite 3pid list (all valid 3pids)
// TODO: visibility
if resErr = r.Validate(); resErr != nil {
return *resErr
}
// TODO: visibility/presets/raw initial state/creation content
hostname := "localhost"
roomID := fmt.Sprintf("!%s:%s", util.RandomString(16), hostname)
// TODO: Check room ID doesn't clash with an existing one
// TODO: Create room alias association
logger.WithFields(log.Fields{
"userID": userID,
"roomID": roomID,
}).Info("Creating room")
// TODO: Check room ID doesn't clash with an existing one
// TODO: Create room alias association
// TODO: handle preset
// TODO: handle raw initial state
// TODO: handle creation content
// send events into the room in order of:
// 1- m.room.create
// 2- room creator join member