From 83f8effbed1e01ae452b365a0567dfd9480a9742 Mon Sep 17 00:00:00 2001 From: Brendan Abolivier Date: Wed, 16 Aug 2017 15:00:09 +0100 Subject: [PATCH] Implement public rooms directory --- .../publicroomsapi/directory/public_rooms.go | 108 ++++++++++++++++++ .../publicroomsapi/routing/routing.go | 5 + .../storage/public_rooms_table.go | 1 + 3 files changed, 114 insertions(+) create mode 100644 src/github.com/matrix-org/dendrite/publicroomsapi/directory/public_rooms.go diff --git a/src/github.com/matrix-org/dendrite/publicroomsapi/directory/public_rooms.go b/src/github.com/matrix-org/dendrite/publicroomsapi/directory/public_rooms.go new file mode 100644 index 000000000..93c9302c0 --- /dev/null +++ b/src/github.com/matrix-org/dendrite/publicroomsapi/directory/public_rooms.go @@ -0,0 +1,108 @@ +// Copyright 2017 Vector Creations Ltd +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package directory + +import ( + "net/http" + "strconv" + + "github.com/matrix-org/dendrite/clientapi/httputil" + "github.com/matrix-org/dendrite/clientapi/jsonerror" + "github.com/matrix-org/dendrite/publicroomsapi/storage" + "github.com/matrix-org/dendrite/publicroomsapi/types" + "github.com/matrix-org/util" +) + +type publicRoomReq struct { + Since string `json:"since,omitempty"` + Limit int16 `json:"limit,omitempty"` + Filter string `json:"filter,omitempty"` +} + +type publicRoomRes struct { + Chunk []types.PublicRoom `json:"chunk"` + NextBatch string `json:"next_batch,omitempty"` + PrevBatch string `json:"prev_batch,omitempty"` + Estimate int64 `json:"total_room_count_estimate,omitempty"` +} + +// GetPublicRooms implements GET /publicRooms +func GetPublicRooms( + req *http.Request, publicRoomDatabase *storage.PublicRoomsServerDatabase, +) util.JSONResponse { + var limit int16 + var offset int64 + var request publicRoomReq + var response publicRoomRes + + if fillErr := fillPublicRoomsReq(req, &request); fillErr != nil { + return *fillErr + } + + limit = request.Limit + offset, err := strconv.ParseInt(request.Since, 10, 64) + // ParseInt returns 0 and an error when trying to parse an empty string + // In that case, we want to assign 0 so we ignore the error + if err != nil && len(request.Since) > 0 { + return httputil.LogThenError(req, err) + } + + if response.Estimate, err = publicRoomDatabase.CountPublicRooms(); err != nil { + return httputil.LogThenError(req, err) + } + + if offset > 0 { + response.PrevBatch = strconv.Itoa(int(offset) - 1) + } + if response.Estimate > int64(limit) { + response.NextBatch = strconv.Itoa(int(offset) + int(limit)) + } + + if response.Chunk, err = publicRoomDatabase.GetPublicRooms(offset, limit); err != nil { + return httputil.LogThenError(req, err) + } + + return util.JSONResponse{ + Code: 200, + JSON: response, + } +} + +// fillPublicRoomsReq fills the Limit, Since and Filter attributes of a GET or POST request +// on /publicRooms by parsing the incoming HTTP request +func fillPublicRoomsReq(httpReq *http.Request, request *publicRoomReq) *util.JSONResponse { + if httpReq.Method == "GET" { + limit, err := strconv.Atoi(httpReq.FormValue("limit")) + // Atoi returns 0 and an error when trying to parse an empty string + // In that case, we want to assign 0 so we ignore the error + if err != nil && len(httpReq.FormValue("limit")) > 0 { + reqErr := httputil.LogThenError(httpReq, err) + return &reqErr + } + request.Limit = int16(limit) + request.Since = httpReq.FormValue("since") + return nil + } else if httpReq.Method == "POST" { + if reqErr := httputil.UnmarshalJSONRequest(httpReq, request); reqErr != nil { + return reqErr + } + return nil + } + + return &util.JSONResponse{ + Code: 405, + JSON: jsonerror.NotFound("Bad method"), + } +} diff --git a/src/github.com/matrix-org/dendrite/publicroomsapi/routing/routing.go b/src/github.com/matrix-org/dendrite/publicroomsapi/routing/routing.go index bcba06524..b5ba766bd 100644 --- a/src/github.com/matrix-org/dendrite/publicroomsapi/routing/routing.go +++ b/src/github.com/matrix-org/dendrite/publicroomsapi/routing/routing.go @@ -41,4 +41,9 @@ func Setup(apiMux *mux.Router, publicRoomsDB *storage.PublicRoomsServerDatabase) return directory.SetVisibility(req, publicRoomsDB, vars["roomID"]) }), ).Methods("PUT", "OPTIONS") + r0mux.Handle("/publicRooms", + common.MakeAPI("public_rooms", func(req *http.Request) util.JSONResponse { + return directory.GetPublicRooms(req, publicRoomsDB) + }), + ).Methods("GET", "POST", "OPTIONS") } diff --git a/src/github.com/matrix-org/dendrite/publicroomsapi/storage/public_rooms_table.go b/src/github.com/matrix-org/dendrite/publicroomsapi/storage/public_rooms_table.go index a5b275902..37b42b06d 100644 --- a/src/github.com/matrix-org/dendrite/publicroomsapi/storage/public_rooms_table.go +++ b/src/github.com/matrix-org/dendrite/publicroomsapi/storage/public_rooms_table.go @@ -31,6 +31,7 @@ var editableAttributes = []string{ "world_readable", "guest_can_join", "avatar_url", + "visibility", } const publicRoomsSchema = `