Make it possible to point Riot at Dendrite
ADD
src/github.com/matrix-org/dendrite/clientapi/readers/login.go
+package readers
+
+import (
+ "fmt"
+ "github.com/matrix-org/dendrite/clientapi/config"
+ "github.com/matrix-org/dendrite/clientapi/httputil"
+ "github.com/matrix-org/dendrite/clientapi/jsonerror"
+ "github.com/matrix-org/util"
+ "net/http"
+)
+
+type loginFlows struct {
+ Flows []flow `json:"flows"`
+}
+
+type flow struct {
+ Type string `json:"type"`
+ Stages []string `json:"stages"`
+}
+
+type passwordRequest struct {
+ User string `json:"user"`
+ Password string `json:"password"`
+}
+
+type loginResponse struct {
+ UserID string `json:"user_id"`
+ AccessToken string `json:"access_token"`
+ HomeServer string `json:"home_server"`
+}
+
+func passwordLogin() loginFlows {
+ f := loginFlows{}
+ s := flow{"m.login.password", []string{"m.login.password"}}
+ f.Flows = append(f.Flows, s)
+ return f
+}
+
+// Login implements GET and POST /login
+func Login(req *http.Request, cfg config.ClientAPI) util.JSONResponse {
+ if req.Method == "GET" { // TODO: support other forms of login other than password, depending on config options
+ return util.JSONResponse{
+ Code: 200,
+ JSON: passwordLogin(),
+ }
+ } else if req.Method == "POST" {
+ var r passwordRequest
+ resErr := httputil.UnmarshalJSONRequest(req, &r)
+ if resErr != nil {
+ return *resErr
+ }
+ if r.User == "" {
+ return util.JSONResponse{
+ Code: 400,
+ JSON: jsonerror.BadJSON("'user' must be supplied."),
+ }
+ }
+ // TODO: Check username and password properly
+ return util.JSONResponse{
+ Code: 200,
+ JSON: loginResponse{
+ UserID: makeUserID(r.User, cfg.ServerName),
+ AccessToken: makeUserID(r.User, cfg.ServerName), // FIXME: token is the user ID for now
+ HomeServer: cfg.ServerName,
+ },
+ }
+ }
+ return util.JSONResponse{
+ Code: 405,
+ JSON: jsonerror.NotFound("Bad method"),
+ }
+}
+
+func makeUserID(localpart, domain string) string {
+ return fmt.Sprintf("@%s:%s", localpart, domain)
+}

MODIFY
src/github.com/matrix-org/dendrite/clientapi/routing/routing.go
src/github.com/matrix-org/dendrite/clientapi/routing/routing.go
package routing
import (
+ "encoding/json"
"net/http"
"github.com/gorilla/mux"
"github.com/matrix-org/dendrite/clientapi/config"
"github.com/matrix-org/dendrite/clientapi/producers"
+ "github.com/matrix-org/dendrite/clientapi/readers"
"github.com/matrix-org/dendrite/clientapi/writers"
"github.com/matrix-org/dendrite/roomserver/api"
"github.com/matrix-org/util"
@@ -43,6 +45,87 @@ func Setup(servMux *http.ServeMux, httpClient *http.Client, cfg config.ClientAPI
})),
)
+ // Stub endpoints required by Riot
+
+ r0mux.Handle("/login",
+ make("login", util.NewJSONRequestHandler(func(req *http.Request) util.JSONResponse {
+ return readers.Login(req, cfg)
+ })),
+ )
+
+ r0mux.Handle("/pushrules/",
+ make("push_rules", util.NewJSONRequestHandler(func(req *http.Request) util.JSONResponse {
+ // TODO: Implement push rules API
+ res := json.RawMessage(`{
+ "global": {
+ "content": [],
+ "override": [],
+ "room": [],
+ "sender": [],
+ "underride": []
+ }
+ }`)
+ return util.JSONResponse{
+ Code: 200,
+ JSON: &res,
+ }
+ })),
+ )
+
+ r0mux.Handle("/user/{userID}/filter",
+ make("make_filter", util.NewJSONRequestHandler(func(req *http.Request) util.JSONResponse {
+ // TODO: Persist filter and return filter ID
+ return util.JSONResponse{
+ Code: 200,
+ JSON: struct{}{},
+ }
+ })),
+ )
+
+ r0mux.Handle("/user/{userID}/filter/{filterID}",
+ make("filter", util.NewJSONRequestHandler(func(req *http.Request) util.JSONResponse {
+ // TODO: Retrieve filter based on ID
+ return util.JSONResponse{
+ Code: 200,
+ JSON: struct{}{},
+ }
+ })),
+ )
+
+ // Riot user settings
+
+ r0mux.Handle("/profile/{userID}",
+ make("profile", util.NewJSONRequestHandler(func(req *http.Request) util.JSONResponse {
+ // TODO: Get profile data for user ID
+ return util.JSONResponse{
+ Code: 200,
+ JSON: struct{}{},
+ }
+ })),
+ )
+
+ r0mux.Handle("/account/3pid",
+ make("account_3pid", util.NewJSONRequestHandler(func(req *http.Request) util.JSONResponse {
+ // TODO: Get 3pid data for user ID
+ res := json.RawMessage(`{"threepids":[]}`)
+ return util.JSONResponse{
+ Code: 200,
+ JSON: &res,
+ }
+ })),
+ )
+
+ // Riot logs get flooded unless this is handled
+ r0mux.Handle("/presence/{userID}/status",
+ make("presence", util.NewJSONRequestHandler(func(req *http.Request) util.JSONResponse {
+ // TODO: Set presence (probably the responsibility of a presence server not clientapi)
+ return util.JSONResponse{
+ Code: 200,
+ JSON: struct{}{},
+ }
+ })),
+ )
+
servMux.Handle("/metrics", prometheus.Handler())
servMux.Handle("/api/", http.StripPrefix("/api", apiMux))
}

MODIFY
vendor/manifest
vendor/manifest
{
"importpath": "github.com/matrix-org/util",
"repository": "https://github.com/matrix-org/util",
- "revision": "ec8896cd7d9ba6de6143c5f123d1e45413657e7d",
+ "revision": "bc9d5e2d2f68a2ca279fce0fa2f28a91ecf301ed",
"branch": "master"
},
{

MODIFY
vendor/src/github.com/matrix-org/util/json.go
vendor/src/github.com/matrix-org/util/json.go
@@ -111,6 +111,11 @@ func MakeJSONAPI(handler JSONRequestHandler) http.HandlerFunc {
logger := GetLogger(req.Context())
logger.Print("Incoming request")
+ if req.Method == "OPTIONS" {
+ SetCORSHeaders(w)
+ w.WriteHeader(200)
+ return
+ }
res := handler.OnIncomingRequest(req)
// Set common headers returned regardless of the outcome of the request

Make it possible to point Riot at Dendrite (#74)