Skip to content

Commit

Permalink
v2: add extra wait step to login
Browse files Browse the repository at this point in the history
  • Loading branch information
tulir committed Jun 26, 2024
1 parent 4352712 commit 72e9cc6
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 29 deletions.
35 changes: 22 additions & 13 deletions cmd/mautrix-signal-v2/legacyprovision.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import (
"maunium.net/go/mautrix/bridgev2"

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

var legacyProvisionHandleID atomic.Uint32
Expand All @@ -40,7 +41,6 @@ type legacyLoginProcess struct {
ID uint32
Login bridgev2.LoginProcess
User *bridgev2.User
Done *bridgev2.UserLogin
}

func (llp *legacyLoginProcess) Delete() {
Expand Down Expand Up @@ -78,7 +78,7 @@ func legacyProvLinkNew(w http.ResponseWriter, r *http.Request) {
ErrCode: "M_UNKNOWN",
})
return
} else if firstStep.Type != bridgev2.LoginStepTypeDisplayAndWait || firstStep.DisplayAndWaitParams.Type != bridgev2.LoginDisplayTypeQR {
} else if firstStep.StepID != connector.LoginStepQR || 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",
Expand Down Expand Up @@ -141,21 +141,22 @@ func legacyProvLinkWaitScan(w http.ResponseWriter, r *http.Request) {
}
res, err := login.Login.(bridgev2.LoginProcessDisplayAndWait).Wait(r.Context())
if err != nil {
zerolog.Ctx(r.Context()).Err(err).Msg("Failed to log in")
legacyprovision.JSONResponse(w, http.StatusInternalServerError, legacyprovision.Error{
Error: "Failed to log in",
ErrCode: "M_UNKNOWN",
})
login.Delete()
return
} else if res.Type != bridgev2.LoginStepTypeComplete {
} else if res.StepID != connector.LoginStepProcess {
zerolog.Ctx(r.Context()).Error().Any("first_step", res).Msg("Unexpected login step")
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",
Expand All @@ -167,20 +168,28 @@ func legacyProvLinkWaitAccount(w http.ResponseWriter, r *http.Request) {
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,
res, err := login.Login.(bridgev2.LoginProcessDisplayAndWait).Wait(r.Context())
if err != nil {
zerolog.Ctx(r.Context()).Err(err).Msg("Failed to log in")
legacyprovision.JSONResponse(w, http.StatusInternalServerError, legacyprovision.Error{
Error: "Failed to log in",
ErrCode: "M_UNKNOWN",
})
login.Delete()
} else {
} else if res.StepID != connector.LoginStepComplete || res.Type != bridgev2.LoginStepTypeComplete {
zerolog.Ctx(r.Context()).Error().Any("first_step", res).Msg("Unexpected login step")
legacyprovision.JSONResponse(w, http.StatusInternalServerError, legacyprovision.Error{
Error: "Login not completed",
Error: "Unexpected login step",
ErrCode: "M_UNKNOWN",
})
} else {
legacyprovision.JSONResponse(w, http.StatusOK, legacyprovision.Response{
Success: true,
Status: "prekeys_registered",
UUID: string(res.CompleteParams.UserLogin.ID),
Number: res.CompleteParams.UserLogin.Metadata.RemoteName,
})
}
login.Delete()
}

func legacyProvLogout(w http.ResponseWriter, r *http.Request) {
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.20240626114248-5dbfd7093e58
maunium.net/go/mautrix v0.19.0-beta.1.0.20240626170142-1a18d9ee55f1
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.20240626114248-5dbfd7093e58 h1:N2Mll8zmQPEFhLgJdH/QPw9Wu4nnLD1LIrAyk0vohHo=
maunium.net/go/mautrix v0.19.0-beta.1.0.20240626114248-5dbfd7093e58/go.mod h1:pFbqAannSyJnohVycF4NW3IngBLWUt/f9KYfJcwyQec=
maunium.net/go/mautrix v0.19.0-beta.1.0.20240626170142-1a18d9ee55f1 h1:iE/MzeUGHAs2pbtq/hVnJp7pFQhgjRnZZFfnFDwZdq0=
maunium.net/go/mautrix v0.19.0-beta.1.0.20240626170142-1a18d9ee55f1/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=
55 changes: 42 additions & 13 deletions pkg/connector/login.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import (
"maunium.net/go/mautrix/bridgev2/database"

"go.mau.fi/mautrix-signal/pkg/signalmeow"
"go.mau.fi/mautrix-signal/pkg/signalmeow/store"
)

func (s *SignalConnector) GetLoginFlows() []bridgev2.LoginFlow {
Expand All @@ -48,6 +49,8 @@ type QRLogin struct {
Main *SignalConnector
cancelChan context.CancelFunc
ProvChan chan signalmeow.ProvisioningResponse

ProvData *store.DeviceData
}

var _ bridgev2.LoginProcessDisplayAndWait = (*QRLogin)(nil)
Expand All @@ -60,6 +63,12 @@ func (qr *QRLogin) Cancel() {
}()
}

const (
LoginStepQR = "fi.mau.signal.login.qr"
LoginStepProcess = "fi.mau.signal.login.processing"
LoginStepComplete = "fi.mau.signal.login.complete"
)

func (qr *QRLogin) Start(ctx context.Context) (*bridgev2.LoginStep, error) {
log := qr.Main.Bridge.Log.With().
Str("action", "login").
Expand All @@ -84,7 +93,7 @@ func (qr *QRLogin) Start(ctx context.Context) (*bridgev2.LoginStep, error) {
}
return &bridgev2.LoginStep{
Type: bridgev2.LoginStepTypeDisplayAndWait,
StepID: "fi.mau.signal.login.qr",
StepID: LoginStepQR,
Instructions: "Scan the QR code on your Signal app to log in",
DisplayAndWaitParams: &bridgev2.LoginDisplayAndWaitParams{
Type: bridgev2.LoginDisplayTypeQR,
Expand All @@ -97,25 +106,45 @@ func (qr *QRLogin) Wait(ctx context.Context) (*bridgev2.LoginStep, error) {
if qr.ProvChan == nil {
return nil, fmt.Errorf("login not started")
}
defer qr.cancelChan()

var signalID uuid.UUID
var signalPhone string
if qr.ProvData == nil {
return qr.qrWait(ctx)
} else {
return qr.processingWait(ctx)
}
}

func (qr *QRLogin) qrWait(ctx context.Context) (*bridgev2.LoginStep, error) {
select {
case resp := <-qr.ProvChan:
if resp.Err != nil || resp.State == signalmeow.StateProvisioningError {
qr.cancelChan()
return nil, resp.Err
} else if resp.State != signalmeow.StateProvisioningDataReceived {
qr.cancelChan()
return nil, fmt.Errorf("unexpected state %v", resp.State)
} else if resp.ProvisioningData.ACI == uuid.Nil {
qr.cancelChan()
return nil, fmt.Errorf("no signal account ID received")
}
signalID = resp.ProvisioningData.ACI
signalPhone = resp.ProvisioningData.Number
qr.ProvData = resp.ProvisioningData
return &bridgev2.LoginStep{
Type: bridgev2.LoginStepTypeDisplayAndWait,
StepID: LoginStepProcess,
Instructions: fmt.Sprintf("Processing login as %s...", resp.ProvisioningData.Number),
DisplayAndWaitParams: &bridgev2.LoginDisplayAndWaitParams{
Type: bridgev2.LoginDisplayTypeNothing,
},
}, nil
case <-ctx.Done():
qr.cancelChan()
return nil, ctx.Err()
}
newLoginID := makeUserLoginID(signalID)
}

func (qr *QRLogin) processingWait(ctx context.Context) (*bridgev2.LoginStep, error) {
defer qr.cancelChan()
newLoginID := makeUserLoginID(qr.ProvData.ACI)

select {
case resp := <-qr.ProvChan:
Expand All @@ -141,19 +170,19 @@ func (qr *QRLogin) Wait(ctx context.Context) (*bridgev2.LoginStep, error) {
ID: newLoginID,
Metadata: database.UserLoginMetadata{
StandardUserLoginMetadata: database.StandardUserLoginMetadata{
RemoteName: signalPhone,
RemoteName: qr.ProvData.Number,
},
Extra: map[string]any{
"phone": signalPhone,
"phone": qr.ProvData.Number,
},
},
}, nil)
if err != nil {
return nil, fmt.Errorf("failed to save new login: %w", err)
}
} else {
ul.Metadata.Extra["phone"] = signalPhone
ul.Metadata.RemoteName = signalPhone
ul.Metadata.Extra["phone"] = qr.ProvData.Number
ul.Metadata.RemoteName = qr.ProvData.Number
err = ul.Save(ctx)
if err != nil {
return nil, fmt.Errorf("failed to update existing login: %w", err)
Expand All @@ -170,8 +199,8 @@ func (qr *QRLogin) Wait(ctx context.Context) (*bridgev2.LoginStep, error) {
}
return &bridgev2.LoginStep{
Type: bridgev2.LoginStepTypeComplete,
StepID: "fi.mau.signal.login.complete",
Instructions: fmt.Sprintf("Successfully logged in as %s / %s", signalPhone, signalID),
StepID: LoginStepComplete,
Instructions: fmt.Sprintf("Successfully logged in as %s / %s", qr.ProvData.Number, qr.ProvData.ACI),
CompleteParams: &bridgev2.LoginCompleteParams{
UserLoginID: ul.ID,
UserLogin: ul,
Expand Down

0 comments on commit 72e9cc6

Please sign in to comment.