diff --git a/clientapi/routing/pushrules.go b/clientapi/routing/pushrules.go new file mode 100644 index 000000000..e05a0aae4 --- /dev/null +++ b/clientapi/routing/pushrules.go @@ -0,0 +1,175 @@ +package routing + +import ( + "encoding/json" + "github.com/matrix-org/dendrite/clientapi/auth/authtypes" + "github.com/matrix-org/dendrite/clientapi/auth/storage/accounts" + "github.com/matrix-org/dendrite/clientapi/jsonerror" + "github.com/matrix-org/gomatrixserverlib" + "github.com/matrix-org/util" + "net/http" +) + +type PushCondition struct { + Kind string `json:"kind"` + Key string `json:"key"` + Pattern string `json:"pattern"` + Is string `json:"is"` +} + +type PushRule struct { + Actions interface{} `json:"actions"` + Default bool `json:"default"` + Enabled bool `json:"enabled"` + RuleId string `json:"rule_id"` + Conditions []PushCondition `json:"conditions"` + Pattern string `json:"pattern"` +} +type Global struct { + Content []PushRule `json:"content"` + Override []PushRule `json:"override"` + Room []PushRule `json:"room"` + Sender []PushRule `json:"sender"` + Underride []PushRule `json:"underride"` +} +type RuleSet struct { + Global Global `json:"global"` +} + +func GetPushRuleSet( + req *http.Request, + dev *authtypes.Device, + accountDB accounts.Database, +) util.JSONResponse { + localpart, _, err := gomatrixserverlib.SplitID('@', dev.UserID) + if err != nil { + util.GetLogger(req.Context()).WithError(err).Error("gomatrixserverlib.SplitID failed") + return jsonerror.InternalServerError() + } + data, err := accountDB.GetAccountDataByType(req.Context(), localpart, "", "m.push_rules") + if err != nil { + util.GetLogger(req.Context()).WithError(err).Error("m.push_rules data not found") + return jsonerror.InternalServerError() + } + pushRuleSet := RuleSet{Global{ + Content: []PushRule{}, + Override: []PushRule{}, + Room: []PushRule{}, + Sender: []PushRule{}, + Underride: []PushRule{}, + }} + + err = json.Unmarshal(data.Content, &pushRuleSet) + if err != nil { + util.GetLogger(req.Context()).WithError(err).Error("Could not unmarshal pushrules data") + return jsonerror.InternalServerError() + } + + return util.JSONResponse{ + Code: http.StatusOK, + JSON: pushRuleSet, + } +} + +func GetPushRule( + req *http.Request, dev *authtypes.Device, accountDB accounts.Database, + kind string, ruleID string, +) util.JSONResponse { + localpart, _, err := gomatrixserverlib.SplitID('@', dev.UserID) + if err != nil { + util.GetLogger(req.Context()).WithError(err).Error("gomatrixserverlib.SplitID failed") + return jsonerror.InternalServerError() + } + data, err := accountDB.GetAccountDataByType(req.Context(), localpart, "", "m.push_rules") + if err != nil { + util.GetLogger(req.Context()).WithError(err).Error("m.push_rules data not found") + return jsonerror.InternalServerError() + } + pushRuleSet := RuleSet{Global{ + Content: []PushRule{}, + Override: []PushRule{}, + Room: []PushRule{}, + Sender: []PushRule{}, + Underride: []PushRule{}, + }} + + err = json.Unmarshal(data.Content, &pushRuleSet) + if err != nil { + util.GetLogger(req.Context()).WithError(err).Error("Could not unmarshal pushrules data") + return jsonerror.InternalServerError() + } + + switch kind { + case "override": + for _, pushRule := range pushRuleSet.Global.Override { + if pushRule.RuleId == ruleID { + return util.JSONResponse{ + Code: http.StatusOK, + JSON: pushRule, + } + } + } + return util.JSONResponse{ + Code: http.StatusNotFound, + JSON: jsonerror.NotFound("Not found"), + } + case "underride": + for _, pushRule := range pushRuleSet.Global.Underride { + if pushRule.RuleId == ruleID { + return util.JSONResponse{ + Code: http.StatusOK, + JSON: pushRule, + } + } + } + return util.JSONResponse{ + Code: http.StatusNotFound, + JSON: jsonerror.NotFound("Not found"), + } + case "sender": + for _, pushRule := range pushRuleSet.Global.Sender { + if pushRule.RuleId == ruleID { + return util.JSONResponse{ + Code: http.StatusOK, + JSON: pushRule, + } + } + } + return util.JSONResponse{ + Code: http.StatusNotFound, + JSON: jsonerror.NotFound("Not found"), + } + case "room": + for _, pushRule := range pushRuleSet.Global.Room { + if pushRule.RuleId == ruleID { + return util.JSONResponse{ + Code: http.StatusOK, + JSON: pushRule, + } + } + } + return util.JSONResponse{ + Code: http.StatusNotFound, + JSON: jsonerror.NotFound("Not found"), + } + case "content": + for _, pushRule := range pushRuleSet.Global.Content { + if pushRule.RuleId == ruleID { + return util.JSONResponse{ + Code: http.StatusOK, + JSON: pushRule, + } + } + } + return util.JSONResponse{ + Code: http.StatusNotFound, + JSON: jsonerror.NotFound("Not found"), + } + default: + return util.JSONResponse{ + Code: http.StatusBadRequest, + JSON: jsonerror.NotFound("Unrecognised request"), + } + + } +} diff --git a/clientapi/routing/routing.go b/clientapi/routing/routing.go index f0841b796..d38c478f6 100644 --- a/clientapi/routing/routing.go +++ b/clientapi/routing/routing.go @@ -15,7 +15,6 @@ package routing import ( - "encoding/json" "net/http" "strings" @@ -255,21 +254,19 @@ func Setup( ).Methods(http.MethodGet, http.MethodPost, http.MethodOptions) r0mux.Handle("/pushrules/", - common.MakeExternalAPI("push_rules", func(req *http.Request) util.JSONResponse { - // TODO: Implement push rules API - res := json.RawMessage(`{ - "global": { - "content": [], - "override": [], - "room": [], - "sender": [], - "underride": [] - } - }`) - return util.JSONResponse{ - Code: http.StatusOK, - JSON: &res, + common.MakeAuthAPI("push_rules", authData, func(req *http.Request, device *authtypes.Device) util.JSONResponse { + + return GetPushRuleSet(req, device, accountDB) + }), + ).Methods(http.MethodGet, http.MethodOptions) + + r0mux.Handle("/pushrules/global/{kind}/{ruleId}", + common.MakeAuthAPI("push_rules", authData, func(req *http.Request, device *authtypes.Device) util.JSONResponse { + vars, err := common.URLDecodeMapValues(mux.Vars(req)) + if err != nil { + return util.ErrorResponse(err) } + return GetPushRule(req, device, accountDB, vars["kind"], vars["ruleId"]) }), ).Methods(http.MethodGet, http.MethodOptions)