Skip to content

Commit

Permalink
v2: add backwards-compatible login API
Browse files Browse the repository at this point in the history
  • Loading branch information
tulir committed Jun 26, 2024
1 parent 86135c5 commit baf113f
Show file tree
Hide file tree
Showing 5 changed files with 153 additions and 9 deletions.
153 changes: 148 additions & 5 deletions cmd/mautrix-signal-v2/legacyprovision.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,27 +17,170 @@
package main

import (
"encoding/json"
"fmt"
"net/http"
"strconv"
"sync"
"sync/atomic"

"github.com/gorilla/mux"
"github.com/rs/zerolog"

"go.mau.fi/mautrix-signal/legacyprovision"
"maunium.net/go/mautrix"
"maunium.net/go/mautrix/bridgev2"

"go.mau.fi/mautrix-signal/legacyprovision"
)

var legacyProvisionHandleID atomic.Uint32
var loginSessions = make(map[uint32]*legacyLoginProcess)
var loginSessionsLock sync.Mutex

type legacyLoginProcess struct {
ID uint32
Login bridgev2.LoginProcess
User *bridgev2.User
Done *bridgev2.UserLogin
}

func (llp *legacyLoginProcess) Delete() {
loginSessionsLock.Lock()
delete(loginSessions, llp.ID)
loginSessionsLock.Unlock()
}

func legacyProvLinkNew(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusNotImplemented)
handleID := legacyProvisionHandleID.Add(1)
user := m.Matrix.Provisioning.GetUser(r)
defLogin := user.GetDefaultLogin()
if defLogin != nil && defLogin.Client != nil && defLogin.Client.IsLoggedIn() {
legacyprovision.JSONResponse(w, http.StatusConflict, &legacyprovision.Error{
Error: "Already logged in",
ErrCode: "FI.MAU.ALREADY_LOGGED_IN",
})
return
}
log := zerolog.Ctx(r.Context())
login, err := m.Connector.CreateLogin(r.Context(), user, "qr")
if err != nil {
log.Err(err).Msg("Failed to create login")
legacyprovision.JSONResponse(w, http.StatusInternalServerError, &legacyprovision.Error{
Error: "Internal error starting login",
ErrCode: "M_UNKNOWN",
})
return
}
firstStep, err := login.Start(r.Context())
if err != nil {
log.Err(err).Msg("Failed to start login")
legacyprovision.JSONResponse(w, http.StatusInternalServerError, &legacyprovision.Error{
Error: "Internal error starting login",
ErrCode: "M_UNKNOWN",
})
return
} else if firstStep.Type != bridgev2.LoginStepTypeDisplayAndWait || firstStep.DisplayAndWaitParams.Type != bridgev2.LoginDisplayTypeQR {
log.Error().Any("first_step", firstStep).Msg("Unexpected first step")
legacyprovision.JSONResponse(w, http.StatusInternalServerError, &legacyprovision.Error{
Error: "Unexpected first login step",
ErrCode: "M_UNKNOWN",
})
return
}
loginSessionsLock.Lock()
loginSessions[handleID] = &legacyLoginProcess{
ID: handleID,
Login: login,
User: user,
}
loginSessionsLock.Unlock()
legacyprovision.JSONResponse(w, http.StatusOK, legacyprovision.Response{
Success: true,
Status: "provisioning_url_received",
SessionID: strconv.Itoa(int(handleID)),
URI: firstStep.DisplayAndWaitParams.Data,
})
}

func getLoginProcess(w http.ResponseWriter, r *http.Request) *legacyLoginProcess {
var body legacyprovision.LinkWaitForAccountRequest
err := json.NewDecoder(r.Body).Decode(&body)
if err != nil {
legacyprovision.JSONResponse(w, http.StatusBadRequest, legacyprovision.Error{
Success: false,
Error: "Error decoding JSON body",
ErrCode: mautrix.MBadJSON.ErrCode,
})
return nil
}
sessionID, err := strconv.Atoi(body.SessionID)
if err != nil {
legacyprovision.JSONResponse(w, http.StatusBadRequest, legacyprovision.Error{
Success: false,
Error: "Error decoding session ID in JSON body",
ErrCode: mautrix.MBadJSON.ErrCode,
})
return nil
}
process, ok := loginSessions[uint32(sessionID)]
user := m.Matrix.Provisioning.GetUser(r)
if !ok || process.User != user {
legacyprovision.JSONResponse(w, http.StatusNotFound, legacyprovision.Error{
Success: false,
Error: "No session found",
ErrCode: mautrix.MNotFound.ErrCode,
})
return nil
}
return process
}

func legacyProvLinkWaitScan(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusNotImplemented)
login := getLoginProcess(w, r)
if login == nil {
return
}
res, err := login.Login.(bridgev2.LoginProcessDisplayAndWait).Wait(r.Context())
if err != nil {
legacyprovision.JSONResponse(w, http.StatusInternalServerError, legacyprovision.Error{
Error: "Failed to log in",
ErrCode: "M_UNKNOWN",
})
login.Delete()
return
} else if res.Type != bridgev2.LoginStepTypeComplete {
legacyprovision.JSONResponse(w, http.StatusInternalServerError, legacyprovision.Error{
Error: "Unexpected login step",
ErrCode: "M_UNKNOWN",
})
login.Delete()
return
}
login.Done = res.CompleteParams.UserLogin
legacyprovision.JSONResponse(w, http.StatusOK, legacyprovision.Response{
Success: true,
Status: "provisioning_data_received",
})
}

func legacyProvLinkWaitAccount(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusNotImplemented)
login := getLoginProcess(w, r)
if login == nil {
return
}
if login.Done != nil {
legacyprovision.JSONResponse(w, http.StatusOK, legacyprovision.Response{
Success: true,
Status: "prekeys_registered",
UUID: string(login.Done.ID),
Number: login.Done.Metadata.RemoteName,
})
login.Delete()
} else {
legacyprovision.JSONResponse(w, http.StatusInternalServerError, legacyprovision.Error{
Error: "Login not completed",
ErrCode: "M_UNKNOWN",
})
}
}

func legacyProvLogout(w http.ResponseWriter, r *http.Request) {
Expand Down
2 changes: 1 addition & 1 deletion cmd/mautrix-signal-v2/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ func main() {
20,
"v0.5.1",
"v0.7.0",
m.LegacyMigrateSimple(legacyMigrateRenameTables, legacyMigrateCopyData),
m.LegacyMigrateSimple(legacyMigrateRenameTables, legacyMigrateCopyData, 2),
true,
)
}
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ require (
golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8
golang.org/x/net v0.26.0
google.golang.org/protobuf v1.34.2
maunium.net/go/mautrix v0.19.0-beta.1.0.20240625184543-3f8bb2fd54b1
maunium.net/go/mautrix v0.19.0-beta.1.0.20240626114248-5dbfd7093e58
nhooyr.io/websocket v1.8.11
)

Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
maunium.net/go/mauflag v1.0.0 h1:YiaRc0tEI3toYtJMRIfjP+jklH45uDHtT80nUamyD4M=
maunium.net/go/mauflag v1.0.0/go.mod h1:nLivPOpTpHnpzEh8jEdSL9UqO9+/KBJFmNRlwKfkPeA=
maunium.net/go/mautrix v0.19.0-beta.1.0.20240625184543-3f8bb2fd54b1 h1:V+PMBFKZwUA0Jy5DrLh1TtDZhnagQMFN9/2/m3T+SLc=
maunium.net/go/mautrix v0.19.0-beta.1.0.20240625184543-3f8bb2fd54b1/go.mod h1:pFbqAannSyJnohVycF4NW3IngBLWUt/f9KYfJcwyQec=
maunium.net/go/mautrix v0.19.0-beta.1.0.20240626114248-5dbfd7093e58 h1:N2Mll8zmQPEFhLgJdH/QPw9Wu4nnLD1LIrAyk0vohHo=
maunium.net/go/mautrix v0.19.0-beta.1.0.20240626114248-5dbfd7093e58/go.mod h1:pFbqAannSyJnohVycF4NW3IngBLWUt/f9KYfJcwyQec=
nhooyr.io/websocket v1.8.11 h1:f/qXNc2/3DpoSZkHt1DQu6rj4zGC8JmkkLkWss0MgN0=
nhooyr.io/websocket v1.8.11/go.mod h1:rN9OFWIUwuxg4fR5tELlYC04bXYowCP9GX47ivo2l+c=
1 change: 1 addition & 0 deletions pkg/connector/login.go
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ func (qr *QRLogin) Wait(ctx context.Context) (*bridgev2.LoginStep, error) {
Instructions: fmt.Sprintf("Successfully logged in as %s / %s", signalPhone, signalID),
CompleteParams: &bridgev2.LoginCompleteParams{
UserLoginID: ul.ID,
UserLogin: ul,
},
}, nil
}

0 comments on commit baf113f

Please sign in to comment.