mirror of
https://github.com/hoernschen/dendrite.git
synced 2024-12-26 15:08:28 +00:00
Implement fully read markers (#1475)
See #653 Signed-off-by: Loïck Bonniot <git@lesterpig.com> Co-authored-by: Kegsay <kegan@matrix.org>
This commit is contained in:
parent
009401ad4d
commit
f3e8ae01ef
3 changed files with 83 additions and 4 deletions
|
@ -20,8 +20,10 @@ import (
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/matrix-org/dendrite/clientapi/httputil"
|
||||||
"github.com/matrix-org/dendrite/clientapi/jsonerror"
|
"github.com/matrix-org/dendrite/clientapi/jsonerror"
|
||||||
"github.com/matrix-org/dendrite/clientapi/producers"
|
"github.com/matrix-org/dendrite/clientapi/producers"
|
||||||
|
roomserverAPI "github.com/matrix-org/dendrite/roomserver/api"
|
||||||
"github.com/matrix-org/dendrite/userapi/api"
|
"github.com/matrix-org/dendrite/userapi/api"
|
||||||
|
|
||||||
"github.com/matrix-org/util"
|
"github.com/matrix-org/util"
|
||||||
|
@ -91,6 +93,13 @@ func SaveAccountData(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if dataType == "m.fully_read" {
|
||||||
|
return util.JSONResponse{
|
||||||
|
Code: http.StatusForbidden,
|
||||||
|
JSON: jsonerror.Forbidden("Unable to set read marker"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
body, err := ioutil.ReadAll(req.Body)
|
body, err := ioutil.ReadAll(req.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
util.GetLogger(req.Context()).WithError(err).Error("ioutil.ReadAll failed")
|
util.GetLogger(req.Context()).WithError(err).Error("ioutil.ReadAll failed")
|
||||||
|
@ -112,7 +121,7 @@ func SaveAccountData(
|
||||||
}
|
}
|
||||||
dataRes := api.InputAccountDataResponse{}
|
dataRes := api.InputAccountDataResponse{}
|
||||||
if err := userAPI.InputAccountData(req.Context(), &dataReq, &dataRes); err != nil {
|
if err := userAPI.InputAccountData(req.Context(), &dataReq, &dataRes); err != nil {
|
||||||
util.GetLogger(req.Context()).WithError(err).Error("userAPI.QueryAccountData failed")
|
util.GetLogger(req.Context()).WithError(err).Error("userAPI.InputAccountData failed")
|
||||||
return util.ErrorResponse(err)
|
return util.ErrorResponse(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,3 +136,67 @@ func SaveAccountData(
|
||||||
JSON: struct{}{},
|
JSON: struct{}{},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type readMarkerJSON struct {
|
||||||
|
FullyRead string `json:"m.fully_read"`
|
||||||
|
Read string `json:"m.read"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type fullyReadEvent struct {
|
||||||
|
EventID string `json:"event_id"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// SaveReadMarker implements POST /rooms/{roomId}/read_markers
|
||||||
|
func SaveReadMarker(
|
||||||
|
req *http.Request, userAPI api.UserInternalAPI, rsAPI roomserverAPI.RoomserverInternalAPI,
|
||||||
|
syncProducer *producers.SyncAPIProducer, device *api.Device, roomID string,
|
||||||
|
) util.JSONResponse {
|
||||||
|
// Verify that the user is a member of this room
|
||||||
|
resErr := checkMemberInRoom(req.Context(), rsAPI, device.UserID, roomID)
|
||||||
|
if resErr != nil {
|
||||||
|
return *resErr
|
||||||
|
}
|
||||||
|
|
||||||
|
var r readMarkerJSON
|
||||||
|
resErr = httputil.UnmarshalJSONRequest(req, &r)
|
||||||
|
if resErr != nil {
|
||||||
|
return *resErr
|
||||||
|
}
|
||||||
|
|
||||||
|
if r.FullyRead == "" {
|
||||||
|
return util.JSONResponse{
|
||||||
|
Code: http.StatusBadRequest,
|
||||||
|
JSON: jsonerror.BadJSON("Missing m.fully_read mandatory field"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
data, err := json.Marshal(fullyReadEvent{EventID: r.FullyRead})
|
||||||
|
if err != nil {
|
||||||
|
return jsonerror.InternalServerError()
|
||||||
|
}
|
||||||
|
|
||||||
|
dataReq := api.InputAccountDataRequest{
|
||||||
|
UserID: device.UserID,
|
||||||
|
DataType: "m.fully_read",
|
||||||
|
RoomID: roomID,
|
||||||
|
AccountData: data,
|
||||||
|
}
|
||||||
|
dataRes := api.InputAccountDataResponse{}
|
||||||
|
if err := userAPI.InputAccountData(req.Context(), &dataReq, &dataRes); err != nil {
|
||||||
|
util.GetLogger(req.Context()).WithError(err).Error("userAPI.InputAccountData failed")
|
||||||
|
return util.ErrorResponse(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := syncProducer.SendData(device.UserID, roomID, "m.fully_read"); err != nil {
|
||||||
|
util.GetLogger(req.Context()).WithError(err).Error("syncProducer.SendData failed")
|
||||||
|
return jsonerror.InternalServerError()
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO handle the read receipt that may be included in the read marker
|
||||||
|
// See https://matrix.org/docs/spec/client_server/r0.6.0#post-matrix-client-r0-rooms-roomid-read-markers
|
||||||
|
|
||||||
|
return util.JSONResponse{
|
||||||
|
Code: http.StatusOK,
|
||||||
|
JSON: struct{}{},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -695,12 +695,15 @@ func Setup(
|
||||||
).Methods(http.MethodGet, http.MethodOptions)
|
).Methods(http.MethodGet, http.MethodOptions)
|
||||||
|
|
||||||
r0mux.Handle("/rooms/{roomID}/read_markers",
|
r0mux.Handle("/rooms/{roomID}/read_markers",
|
||||||
httputil.MakeExternalAPI("rooms_read_markers", func(req *http.Request) util.JSONResponse {
|
httputil.MakeAuthAPI("rooms_read_markers", userAPI, func(req *http.Request, device *userapi.Device) util.JSONResponse {
|
||||||
if r := rateLimits.rateLimit(req); r != nil {
|
if r := rateLimits.rateLimit(req); r != nil {
|
||||||
return *r
|
return *r
|
||||||
}
|
}
|
||||||
// TODO: return the read_markers.
|
vars, err := httputil.URLDecodeMapValues(mux.Vars(req))
|
||||||
return util.JSONResponse{Code: http.StatusOK, JSON: struct{}{}}
|
if err != nil {
|
||||||
|
return util.ErrorResponse(err)
|
||||||
|
}
|
||||||
|
return SaveReadMarker(req, userAPI, rsAPI, syncProducer, device, vars["roomID"])
|
||||||
}),
|
}),
|
||||||
).Methods(http.MethodPost, http.MethodOptions)
|
).Methods(http.MethodPost, http.MethodOptions)
|
||||||
|
|
||||||
|
|
|
@ -456,6 +456,9 @@ After changing password, can log in with new password
|
||||||
After changing password, existing session still works
|
After changing password, existing session still works
|
||||||
After changing password, different sessions can optionally be kept
|
After changing password, different sessions can optionally be kept
|
||||||
After changing password, a different session no longer works by default
|
After changing password, a different session no longer works by default
|
||||||
|
Read markers appear in incremental v2 /sync
|
||||||
|
Read markers appear in initial v2 /sync
|
||||||
|
Read markers can be updated
|
||||||
Local users can peek into world_readable rooms by room ID
|
Local users can peek into world_readable rooms by room ID
|
||||||
We can't peek into rooms with shared history_visibility
|
We can't peek into rooms with shared history_visibility
|
||||||
We can't peek into rooms with invited history_visibility
|
We can't peek into rooms with invited history_visibility
|
||||||
|
|
Loading…
Reference in a new issue