diff --git a/cmd/mautrix-signal-v2/legacyprovision.go b/cmd/mautrix-signal-v2/legacyprovision.go
new file mode 100644
index 00000000..5b8e2038
--- /dev/null
+++ b/cmd/mautrix-signal-v2/legacyprovision.go
@@ -0,0 +1,133 @@
+// mautrix-signal - A Matrix-Signal puppeting bridge.
+// Copyright (C) 2024 Tulir Asokan
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is istributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+
+package main
+
+import (
+ "fmt"
+ "net/http"
+
+ "github.com/gorilla/mux"
+ "github.com/rs/zerolog"
+
+ "go.mau.fi/mautrix-signal/legacyprovision"
+ "maunium.net/go/mautrix"
+ "maunium.net/go/mautrix/bridgev2"
+)
+
+func legacyProvLinkNew(w http.ResponseWriter, r *http.Request) {
+ w.WriteHeader(http.StatusNotImplemented)
+}
+
+func legacyProvLinkWaitScan(w http.ResponseWriter, r *http.Request) {
+ w.WriteHeader(http.StatusNotImplemented)
+}
+
+func legacyProvLinkWaitAccount(w http.ResponseWriter, r *http.Request) {
+ w.WriteHeader(http.StatusNotImplemented)
+}
+
+func legacyProvLogout(w http.ResponseWriter, r *http.Request) {
+ user := m.Matrix.Provisioning.GetUser(r)
+ for {
+ login := user.GetDefaultLogin()
+ if login == nil {
+ break
+ }
+ login.Logout(r.Context())
+ }
+ legacyprovision.JSONResponse(w, http.StatusOK, nil)
+}
+
+func legacyResolveIdentifierOrStartChat(w http.ResponseWriter, r *http.Request, create bool) {
+ login := m.Matrix.Provisioning.GetLoginForRequest(w, r)
+ if login == nil {
+ return
+ }
+ api := login.Client.(bridgev2.IdentifierResolvingNetworkAPI)
+ resp, err := api.ResolveIdentifier(r.Context(), mux.Vars(r)["phonenum"], create)
+ if err != nil {
+ zerolog.Ctx(r.Context()).Err(err).Msg("Failed to resolve identifier")
+ legacyprovision.JSONResponse(w, http.StatusInternalServerError, &legacyprovision.Error{
+ Error: fmt.Sprintf("Failed to resolve identifier: %v", err),
+ ErrCode: "M_UNKNOWN",
+ })
+ return
+ } else if resp == nil {
+ legacyprovision.JSONResponse(w, http.StatusNotFound, &legacyprovision.Error{
+ ErrCode: mautrix.MNotFound.ErrCode,
+ Error: "User not found on Signal",
+ })
+ return
+ }
+ status := http.StatusOK
+ apiResp := &legacyprovision.ResolveIdentifierResponse{
+ ChatID: legacyprovision.ResolveIdentifierResponseChatID{
+ UUID: string(resp.UserID),
+ Number: "",
+ },
+ }
+ if resp.Ghost != nil {
+ if resp.UserInfo != nil {
+ resp.Ghost.UpdateInfo(r.Context(), resp.UserInfo)
+ }
+ apiResp.OtherUser = &legacyprovision.ResolveIdentifierResponseOtherUser{
+ MXID: resp.Ghost.Intent.GetMXID(),
+ DisplayName: resp.Ghost.Name,
+ AvatarURL: resp.Ghost.AvatarMXC.ParseOrIgnore(),
+ }
+ }
+ if resp.Chat != nil {
+ if resp.Chat.Portal == nil {
+ resp.Chat.Portal, err = m.Bridge.GetPortalByID(r.Context(), resp.Chat.PortalID)
+ if err != nil {
+ zerolog.Ctx(r.Context()).Err(err).Msg("Failed to get portal")
+ legacyprovision.JSONResponse(w, http.StatusInternalServerError, &mautrix.RespError{
+ Err: "Failed to get portal",
+ ErrCode: "M_UNKNOWN",
+ })
+ return
+ }
+ }
+ if create && resp.Chat.Portal.MXID == "" {
+ apiResp.JustCreated = true
+ status = http.StatusCreated
+ err = resp.Chat.Portal.CreateMatrixRoom(r.Context(), login, resp.Chat.PortalInfo)
+ if err != nil {
+ zerolog.Ctx(r.Context()).Err(err).Msg("Failed to create portal room")
+ legacyprovision.JSONResponse(w, http.StatusInternalServerError, &mautrix.RespError{
+ Err: "Failed to create portal room",
+ ErrCode: "M_UNKNOWN",
+ })
+ return
+ }
+ }
+ apiResp.RoomID = resp.Chat.Portal.MXID
+ }
+ legacyprovision.JSONResponse(w, status, &legacyprovision.Response{
+ Success: true,
+ Status: "ok",
+ ResolveIdentifierResponse: apiResp,
+ })
+}
+
+func legacyProvResolveIdentifier(w http.ResponseWriter, r *http.Request) {
+ legacyResolveIdentifierOrStartChat(w, r, false)
+}
+
+func legacyProvPM(w http.ResponseWriter, r *http.Request) {
+ legacyResolveIdentifierOrStartChat(w, r, true)
+}
diff --git a/cmd/mautrix-signal-v2/main.go b/cmd/mautrix-signal-v2/main.go
index bc55d45b..7c0762c5 100644
--- a/cmd/mautrix-signal-v2/main.go
+++ b/cmd/mautrix-signal-v2/main.go
@@ -17,6 +17,8 @@
package main
import (
+ "net/http"
+
"maunium.net/go/mautrix/bridgev2/bridgeconfig"
"maunium.net/go/mautrix/bridgev2/matrix/mxmain"
@@ -53,6 +55,16 @@ func main() {
true,
)
}
+ m.PostStart = func() {
+ if m.Matrix.Provisioning != nil {
+ m.Matrix.Provisioning.Router.HandleFunc("/v2/link/new", legacyProvLinkNew).Methods(http.MethodPost)
+ m.Matrix.Provisioning.Router.HandleFunc("/v2/link/wait/scan", legacyProvLinkWaitScan).Methods(http.MethodPost)
+ m.Matrix.Provisioning.Router.HandleFunc("/v2/link/wait/account", legacyProvLinkWaitAccount).Methods(http.MethodPost)
+ m.Matrix.Provisioning.Router.HandleFunc("/v2/logout", legacyProvLogout).Methods(http.MethodPost)
+ m.Matrix.Provisioning.Router.HandleFunc("/v2/resolve_identifier/{phonenum}", legacyProvResolveIdentifier).Methods(http.MethodGet)
+ m.Matrix.Provisioning.Router.HandleFunc("/v2/pm/{phonenum}", legacyProvPM).Methods(http.MethodPost)
+ }
+ }
m.InitVersion(Tag, Commit, BuildTime)
m.Run()
}
diff --git a/go.mod b/go.mod
index 046efb63..0f99be49 100644
--- a/go.mod
+++ b/go.mod
@@ -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.20240625104456-54ff874fac72
+ maunium.net/go/mautrix v0.19.0-beta.1.0.20240625120422-13b2d6275302
nhooyr.io/websocket v1.8.11
)
diff --git a/go.sum b/go.sum
index 3ee63e21..c6356ce7 100644
--- a/go.sum
+++ b/go.sum
@@ -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.20240625104456-54ff874fac72 h1:66ojF6y1KlyOyPLj6/XVxoj+ex/LmxFoCiR6SzvEFBI=
-maunium.net/go/mautrix v0.19.0-beta.1.0.20240625104456-54ff874fac72/go.mod h1:pFbqAannSyJnohVycF4NW3IngBLWUt/f9KYfJcwyQec=
+maunium.net/go/mautrix v0.19.0-beta.1.0.20240625120422-13b2d6275302 h1:PbCdso3xltp5ztKXpAW4C4tC8LLgxeHkJ4mF/7HE3Z0=
+maunium.net/go/mautrix v0.19.0-beta.1.0.20240625120422-13b2d6275302/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=
diff --git a/legacyprovision/types.go b/legacyprovision/types.go
new file mode 100644
index 00000000..72f393a0
--- /dev/null
+++ b/legacyprovision/types.go
@@ -0,0 +1,92 @@
+// mautrix-signal - A Matrix-Signal puppeting bridge.
+// Copyright (C) 2024 Tulir Asokan
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is istributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+
+package legacyprovision
+
+import (
+ "encoding/json"
+ "net/http"
+
+ "maunium.net/go/mautrix/id"
+)
+
+func JSONResponse(w http.ResponseWriter, status int, response any) {
+ w.Header().Add("Content-Type", "application/json")
+ w.WriteHeader(status)
+ _ = json.NewEncoder(w).Encode(response)
+}
+
+type Error struct {
+ Success bool `json:"success"`
+ Error string `json:"error"`
+ ErrCode string `json:"errcode"`
+}
+
+type Response struct {
+ Success bool `json:"success"`
+ Status string `json:"status"`
+
+ // For response in LinkNew
+ SessionID string `json:"session_id,omitempty"`
+ URI string `json:"uri,omitempty"`
+
+ // For response in LinkWaitForAccount
+ UUID string `json:"uuid,omitempty"`
+ Number string `json:"number,omitempty"`
+
+ // For response in ResolveIdentifier
+ *ResolveIdentifierResponse
+}
+
+type WhoAmIResponse struct {
+ Permissions int `json:"permissions"`
+ MXID string `json:"mxid"`
+ Signal *WhoAmIResponseSignal `json:"signal,omitempty"`
+}
+
+type WhoAmIResponseSignal struct {
+ Number string `json:"number"`
+ UUID string `json:"uuid"`
+ Name string `json:"name"`
+ Ok bool `json:"ok"`
+}
+
+type ResolveIdentifierResponse struct {
+ RoomID id.RoomID `json:"room_id"`
+ ChatID ResolveIdentifierResponseChatID `json:"chat_id"`
+ JustCreated bool `json:"just_created"`
+ OtherUser *ResolveIdentifierResponseOtherUser `json:"other_user,omitempty"`
+}
+
+type ResolveIdentifierResponseChatID struct {
+ UUID string `json:"uuid"`
+ Number string `json:"number"`
+}
+
+type ResolveIdentifierResponseOtherUser struct {
+ MXID id.UserID `json:"mxid"`
+ DisplayName string `json:"displayname"`
+ AvatarURL id.ContentURI `json:"avatar_url"`
+}
+
+type LinkWaitForScanRequest struct {
+ SessionID string `json:"session_id"`
+}
+
+type LinkWaitForAccountRequest struct {
+ SessionID string `json:"session_id"`
+ DeviceName string `json:"device_name"` // TODO this seems to not be used anywhere
+}
diff --git a/pkg/connector/chatinfo.go b/pkg/connector/chatinfo.go
index 7c4c6466..f0f06f30 100644
--- a/pkg/connector/chatinfo.go
+++ b/pkg/connector/chatinfo.go
@@ -19,7 +19,6 @@ package connector
import (
"context"
"crypto/sha256"
- "errors"
"fmt"
"strconv"
"strings"
@@ -148,7 +147,7 @@ func (s *SignalClient) ResolveIdentifier(ctx context.Context, number string, cre
aci = resp[e164Number].ACI
pni = resp[e164Number].PNI
if aci == uuid.Nil && pni == uuid.Nil {
- return nil, errors.New("user not found on Signal")
+ return nil, nil
}
recipient, err = s.Client.Store.RecipientStore.UpdateRecipientE164(ctx, aci, pni, e164String)
if err != nil {
diff --git a/provisioning.go b/provisioning.go
index 3be384b7..46b52d1f 100644
--- a/provisioning.go
+++ b/provisioning.go
@@ -36,6 +36,7 @@ import (
"maunium.net/go/mautrix"
"maunium.net/go/mautrix/id"
+ "go.mau.fi/mautrix-signal/legacyprovision"
"go.mau.fi/mautrix-signal/pkg/libsignalgo"
"go.mau.fi/mautrix-signal/pkg/signalmeow"
"go.mau.fi/mautrix-signal/pkg/signalmeow/types"
@@ -86,18 +87,12 @@ func (prov *ProvisioningAPI) Init() {
}
}
-func jsonResponse(w http.ResponseWriter, status int, response any) {
- w.Header().Add("Content-Type", "application/json")
- w.WriteHeader(status)
- _ = json.NewEncoder(w).Encode(response)
-}
-
func (prov *ProvisioningAPI) AuthMiddleware(h http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
auth := strings.TrimPrefix(r.Header.Get("Authorization"), "Bearer ")
if auth != prov.bridge.Config.Bridge.Provisioning.SharedSecret {
zerolog.Ctx(r.Context()).Warn().Msg("Authentication token does not match shared secret")
- jsonResponse(w, http.StatusForbidden, &mautrix.RespError{
+ legacyprovision.JSONResponse(w, http.StatusForbidden, &mautrix.RespError{
Err: "Authentication token does not match shared secret",
ErrCode: mautrix.MForbidden.ErrCode,
})
@@ -109,60 +104,7 @@ func (prov *ProvisioningAPI) AuthMiddleware(h http.Handler) http.Handler {
})
}
-type Error struct {
- Success bool `json:"success"`
- Error string `json:"error"`
- ErrCode string `json:"errcode"`
-}
-
-type Response struct {
- Success bool `json:"success"`
- Status string `json:"status"`
-
- // For response in LinkNew
- SessionID string `json:"session_id,omitempty"`
- URI string `json:"uri,omitempty"`
-
- // For response in LinkWaitForAccount
- UUID string `json:"uuid,omitempty"`
- Number string `json:"number,omitempty"`
-
- // For response in ResolveIdentifier
- *ResolveIdentifierResponse
-}
-
-type WhoAmIResponse struct {
- Permissions int `json:"permissions"`
- MXID string `json:"mxid"`
- Signal *WhoAmIResponseSignal `json:"signal,omitempty"`
-}
-
-type WhoAmIResponseSignal struct {
- Number string `json:"number"`
- UUID string `json:"uuid"`
- Name string `json:"name"`
- Ok bool `json:"ok"`
-}
-
-type ResolveIdentifierResponse struct {
- RoomID id.RoomID `json:"room_id"`
- ChatID ResolveIdentifierResponseChatID `json:"chat_id"`
- JustCreated bool `json:"just_created"`
- OtherUser *ResolveIdentifierResponseOtherUser `json:"other_user,omitempty"`
-}
-
-type ResolveIdentifierResponseChatID struct {
- UUID string `json:"uuid"`
- Number string `json:"number"`
-}
-
-type ResolveIdentifierResponseOtherUser struct {
- MXID string `json:"mxid"`
- DisplayName string `json:"displayname"`
- AvatarURL string `json:"avatar_url"`
-}
-
-func (prov *ProvisioningAPI) resolveIdentifier(ctx context.Context, user *User, inputPhone string) (int, *ResolveIdentifierResponse, error) {
+func (prov *ProvisioningAPI) resolveIdentifier(ctx context.Context, user *User, inputPhone string) (int, *legacyprovision.ResolveIdentifierResponse, error) {
if user.Client == nil {
return http.StatusUnauthorized, nil, errors.New("not currently connected to Signal")
}
@@ -199,14 +141,14 @@ func (prov *ProvisioningAPI) resolveIdentifier(ctx context.Context, user *User,
Msg("Found DM target user")
var targetServiceID libsignalgo.ServiceID
- var otherUserInfo *ResolveIdentifierResponseOtherUser
+ var otherUserInfo *legacyprovision.ResolveIdentifierResponseOtherUser
if aci != uuid.Nil {
targetServiceID = libsignalgo.NewACIServiceID(aci)
puppet := prov.bridge.GetPuppetBySignalID(aci)
- otherUserInfo = &ResolveIdentifierResponseOtherUser{
- MXID: puppet.MXID.String(),
+ otherUserInfo = &legacyprovision.ResolveIdentifierResponseOtherUser{
+ MXID: puppet.MXID,
DisplayName: puppet.Name,
- AvatarURL: puppet.AvatarURL.String(),
+ AvatarURL: puppet.AvatarURL,
}
} else {
targetServiceID = libsignalgo.NewPNIServiceID(pni)
@@ -214,9 +156,9 @@ func (prov *ProvisioningAPI) resolveIdentifier(ctx context.Context, user *User,
}
portal := user.GetPortalByChatID(targetServiceID.String())
- return http.StatusOK, &ResolveIdentifierResponse{
+ return http.StatusOK, &legacyprovision.ResolveIdentifierResponse{
RoomID: portal.MXID,
- ChatID: ResolveIdentifierResponseChatID{
+ ChatID: legacyprovision.ResolveIdentifierResponseChatID{
UUID: targetServiceID.String(),
Number: e164String,
},
@@ -245,14 +187,14 @@ func (prov *ProvisioningAPI) ResolveIdentifier(w http.ResponseWriter, r *http.Re
} else {
log.Err(err).Msg("error looking up contact")
}
- jsonResponse(w, status, Error{
+ legacyprovision.JSONResponse(w, status, legacyprovision.Error{
Success: false,
Error: err.Error(),
ErrCode: errCode,
})
return
}
- jsonResponse(w, status, Response{
+ legacyprovision.JSONResponse(w, status, legacyprovision.Response{
Success: true,
Status: "ok",
ResolveIdentifierResponse: resp,
@@ -280,7 +222,7 @@ func (prov *ProvisioningAPI) StartPM(w http.ResponseWriter, r *http.Request) {
} else {
log.Err(err).Msg("error looking up contact")
}
- jsonResponse(w, status, Error{
+ legacyprovision.JSONResponse(w, status, legacyprovision.Error{
Success: false,
Error: err.Error(),
ErrCode: errCode,
@@ -292,7 +234,7 @@ func (prov *ProvisioningAPI) StartPM(w http.ResponseWriter, r *http.Request) {
if portal.MXID == "" {
if err := portal.CreateMatrixRoom(r.Context(), user, 0); err != nil {
log.Err(err).Msg("error looking up contact")
- jsonResponse(w, http.StatusInternalServerError, Error{
+ legacyprovision.JSONResponse(w, http.StatusInternalServerError, legacyprovision.Error{
Success: false,
Error: "Error creating Matrix room",
ErrCode: "M_INTERNAL",
@@ -306,7 +248,7 @@ func (prov *ProvisioningAPI) StartPM(w http.ResponseWriter, r *http.Request) {
status = http.StatusCreated
}
- jsonResponse(w, status, Response{
+ legacyprovision.JSONResponse(w, status, legacyprovision.Response{
Success: true,
Status: "ok",
ResolveIdentifierResponse: resp,
@@ -401,7 +343,7 @@ func (prov *ProvisioningAPI) checkSessionAndReturnHandle(ctx context.Context, w
handle := prov.existingSession(user)
if handle == nil {
log.Warn().Msg("no session found")
- jsonResponse(w, http.StatusNotFound, Error{
+ legacyprovision.JSONResponse(w, http.StatusNotFound, legacyprovision.Error{
Success: false,
Error: "No session found",
ErrCode: "M_NOT_FOUND",
@@ -413,7 +355,7 @@ func (prov *ProvisioningAPI) checkSessionAndReturnHandle(ctx context.Context, w
Int("handle_id", handle.id).
Int("current_session", currentSession).
Msg("session_id does not match user's session_id")
- jsonResponse(w, http.StatusBadRequest, Error{
+ legacyprovision.JSONResponse(w, http.StatusBadRequest, legacyprovision.Error{
Success: false,
Error: "session_id does not match user's session_id",
ErrCode: "M_BAD_JSON",
@@ -431,12 +373,12 @@ func (prov *ProvisioningAPI) WhoAmI(w http.ResponseWriter, r *http.Request) {
Logger()
log.Debug().Msg("getting whoami")
- data := WhoAmIResponse{
+ data := legacyprovision.WhoAmIResponse{
Permissions: int(user.PermissionLevel),
MXID: user.MXID.String(),
}
if user.IsLoggedIn() {
- data.Signal = &WhoAmIResponseSignal{
+ data.Signal = &legacyprovision.WhoAmIResponseSignal{
Number: user.SignalUsername,
UUID: user.SignalID.String(),
Ok: user.Client.IsConnected(),
@@ -446,7 +388,7 @@ func (prov *ProvisioningAPI) WhoAmI(w http.ResponseWriter, r *http.Request) {
data.Signal.Name = puppet.Name
}
}
- jsonResponse(w, http.StatusOK, data)
+ legacyprovision.JSONResponse(w, http.StatusOK, data)
}
func (prov *ProvisioningAPI) LinkNew(w http.ResponseWriter, r *http.Request) {
@@ -460,7 +402,7 @@ func (prov *ProvisioningAPI) LinkNew(w http.ResponseWriter, r *http.Request) {
handle, err := prov.loginOrSendError(ctx, w, user)
if err != nil {
- jsonResponse(w, http.StatusInternalServerError, Error{
+ legacyprovision.JSONResponse(w, http.StatusInternalServerError, legacyprovision.Error{
Success: false,
Error: err.Error(),
ErrCode: "M_INTERNAL",
@@ -475,7 +417,7 @@ func (prov *ProvisioningAPI) LinkNew(w http.ResponseWriter, r *http.Request) {
case resp := <-handle.channel:
if resp.Err != nil || resp.State == signalmeow.StateProvisioningError {
log.Err(resp.Err).Msg("Error getting provisioning URL")
- jsonResponse(w, http.StatusInternalServerError, Error{
+ legacyprovision.JSONResponse(w, http.StatusInternalServerError, legacyprovision.Error{
Success: false,
Error: resp.Err.Error(),
ErrCode: "M_INTERNAL",
@@ -484,7 +426,7 @@ func (prov *ProvisioningAPI) LinkNew(w http.ResponseWriter, r *http.Request) {
}
if resp.State != signalmeow.StateProvisioningURLReceived {
log.Err(resp.Err).Stringer("state", resp.State).Msg("unexpected state")
- jsonResponse(w, http.StatusInternalServerError, Error{
+ legacyprovision.JSONResponse(w, http.StatusInternalServerError, legacyprovision.Error{
Success: false,
Error: fmt.Sprintf("Unexpected state %s", resp.State.String()),
ErrCode: "M_INTERNAL",
@@ -493,7 +435,7 @@ func (prov *ProvisioningAPI) LinkNew(w http.ResponseWriter, r *http.Request) {
}
log.Debug().Str("provisioning_url", resp.ProvisioningURL).Msg("provisioning URL received")
- jsonResponse(w, http.StatusOK, Response{
+ legacyprovision.JSONResponse(w, http.StatusOK, legacyprovision.Response{
Success: true,
Status: "provisioning_url_received",
SessionID: fmt.Sprintf("%d", handle.id),
@@ -501,7 +443,7 @@ func (prov *ProvisioningAPI) LinkNew(w http.ResponseWriter, r *http.Request) {
})
case <-time.After(30 * time.Second):
log.Warn().Msg("Timeout waiting for provisioning response (new)")
- jsonResponse(w, http.StatusGatewayTimeout, Error{
+ legacyprovision.JSONResponse(w, http.StatusGatewayTimeout, legacyprovision.Error{
Success: false,
Error: "Timeout waiting for provisioning response (new)",
ErrCode: "M_TIMEOUT",
@@ -509,17 +451,13 @@ func (prov *ProvisioningAPI) LinkNew(w http.ResponseWriter, r *http.Request) {
}
}
-type LinkWaitForScanRequest struct {
- SessionID string `json:"session_id"`
-}
-
func (prov *ProvisioningAPI) LinkWaitForScan(w http.ResponseWriter, r *http.Request) {
user := r.Context().Value(provisioningUserKey).(*User)
- var body LinkWaitForScanRequest
+ var body legacyprovision.LinkWaitForScanRequest
err := json.NewDecoder(r.Body).Decode(&body)
if err != nil {
- jsonResponse(w, http.StatusBadRequest, Error{
+ legacyprovision.JSONResponse(w, http.StatusBadRequest, legacyprovision.Error{
Success: false,
Error: "Error decoding JSON body",
ErrCode: "M_BAD_JSON",
@@ -528,7 +466,7 @@ func (prov *ProvisioningAPI) LinkWaitForScan(w http.ResponseWriter, r *http.Requ
}
sessionID, err := strconv.Atoi(body.SessionID)
if err != nil {
- jsonResponse(w, http.StatusBadRequest, Error{
+ legacyprovision.JSONResponse(w, http.StatusBadRequest, legacyprovision.Error{
Success: false,
Error: "Error decoding session ID in JSON body",
ErrCode: "M_BAD_JSON",
@@ -561,7 +499,7 @@ func (prov *ProvisioningAPI) LinkWaitForScan(w http.ResponseWriter, r *http.Requ
// If we error waiting for the scan, treat it as a normal error not 5xx
// so that the client will retry quietly. Also, it's really not an internal
// error, sitting with a WS open waiting for a scan is inherently flaky.
- jsonResponse(w, http.StatusBadRequest, Error{
+ legacyprovision.JSONResponse(w, http.StatusBadRequest, legacyprovision.Error{
Success: false,
Error: resp.Err.Error(),
ErrCode: "M_INTERNAL",
@@ -570,7 +508,7 @@ func (prov *ProvisioningAPI) LinkWaitForScan(w http.ResponseWriter, r *http.Requ
}
if resp.State != signalmeow.StateProvisioningDataReceived {
log.Err(resp.Err).Stringer("state", resp.State).Msg("unexpected state")
- jsonResponse(w, http.StatusInternalServerError, Error{
+ legacyprovision.JSONResponse(w, http.StatusInternalServerError, legacyprovision.Error{
Success: false,
Error: fmt.Sprintf("Unexpected state %s", resp.State.String()),
ErrCode: "M_INTERNAL",
@@ -578,7 +516,7 @@ func (prov *ProvisioningAPI) LinkWaitForScan(w http.ResponseWriter, r *http.Requ
return
}
log.Debug().Msg("provisioning data received")
- jsonResponse(w, http.StatusOK, Response{
+ legacyprovision.JSONResponse(w, http.StatusOK, legacyprovision.Response{
Success: true,
Status: "provisioning_data_received",
})
@@ -591,7 +529,7 @@ func (prov *ProvisioningAPI) LinkWaitForScan(w http.ResponseWriter, r *http.Requ
case <-time.After(45 * time.Second):
log.Warn().Msg("Timeout waiting for provisioning response (scan)")
// Using 400 here to match the old bridge
- jsonResponse(w, http.StatusBadRequest, Error{
+ legacyprovision.JSONResponse(w, http.StatusBadRequest, legacyprovision.Error{
Success: false,
Error: "Timeout waiting for QR code scan",
ErrCode: "M_BAD_REQUEST",
@@ -600,18 +538,13 @@ func (prov *ProvisioningAPI) LinkWaitForScan(w http.ResponseWriter, r *http.Requ
}
}
-type LinkWaitForAccountRequest struct {
- SessionID string `json:"session_id"`
- DeviceName string `json:"device_name"` // TODO this seems to not be used anywhere
-}
-
func (prov *ProvisioningAPI) LinkWaitForAccount(w http.ResponseWriter, r *http.Request) {
user := r.Context().Value(provisioningUserKey).(*User)
- var body LinkWaitForAccountRequest
+ var body legacyprovision.LinkWaitForAccountRequest
err := json.NewDecoder(r.Body).Decode(&body)
if err != nil {
- jsonResponse(w, http.StatusBadRequest, Error{
+ legacyprovision.JSONResponse(w, http.StatusBadRequest, legacyprovision.Error{
Success: false,
Error: "Error decoding JSON body",
ErrCode: "M_BAD_JSON",
@@ -620,7 +553,7 @@ func (prov *ProvisioningAPI) LinkWaitForAccount(w http.ResponseWriter, r *http.R
}
sessionID, err := strconv.Atoi(body.SessionID)
if err != nil {
- jsonResponse(w, http.StatusBadRequest, Error{
+ legacyprovision.JSONResponse(w, http.StatusBadRequest, legacyprovision.Error{
Success: false,
Error: "Error decoding session ID in JSON body",
ErrCode: "M_BAD_JSON",
@@ -647,7 +580,7 @@ func (prov *ProvisioningAPI) LinkWaitForAccount(w http.ResponseWriter, r *http.R
case resp := <-handle.channel:
if resp.Err != nil || resp.State == signalmeow.StateProvisioningError {
log.Err(resp.Err).Msg("Error waiting for account")
- jsonResponse(w, http.StatusInternalServerError, Error{
+ legacyprovision.JSONResponse(w, http.StatusInternalServerError, legacyprovision.Error{
Success: false,
Error: resp.Err.Error(),
ErrCode: "M_INTERNAL",
@@ -656,7 +589,7 @@ func (prov *ProvisioningAPI) LinkWaitForAccount(w http.ResponseWriter, r *http.R
}
if resp.State != signalmeow.StateProvisioningPreKeysRegistered {
log.Err(resp.Err).Stringer("state", resp.State).Msg("unexpected state")
- jsonResponse(w, http.StatusInternalServerError, Error{
+ legacyprovision.JSONResponse(w, http.StatusInternalServerError, legacyprovision.Error{
Success: false,
Error: fmt.Sprintf("Unexpected state %s", resp.State.String()),
ErrCode: "M_INTERNAL",
@@ -665,7 +598,7 @@ func (prov *ProvisioningAPI) LinkWaitForAccount(w http.ResponseWriter, r *http.R
}
log.Debug().Msg("prekeys registered")
- jsonResponse(w, http.StatusOK, Response{
+ legacyprovision.JSONResponse(w, http.StatusOK, legacyprovision.Response{
Success: true,
Status: "prekeys_registered",
UUID: user.SignalID.String(),
@@ -677,7 +610,7 @@ func (prov *ProvisioningAPI) LinkWaitForAccount(w http.ResponseWriter, r *http.R
return
case <-time.After(30 * time.Second):
log.Warn().Msg("Timeout waiting for provisioning response (account)")
- jsonResponse(w, http.StatusGatewayTimeout, Error{
+ legacyprovision.JSONResponse(w, http.StatusGatewayTimeout, legacyprovision.Error{
Success: false,
Error: "Timeout waiting for provisioning response (account)",
ErrCode: "M_TIMEOUT",
@@ -700,7 +633,7 @@ func (prov *ProvisioningAPI) Logout(w http.ResponseWriter, r *http.Request) {
// For now do nothing - we need this API to return 200 to be compatible with
// the old Signal bridge, which needed a call to Logout before allowing LinkNew
// to be called, but we don't actually want to logout, we want to allow a reconnect.
- jsonResponse(w, http.StatusOK, Response{
+ legacyprovision.JSONResponse(w, http.StatusOK, legacyprovision.Response{
Success: true,
Status: "logged_out",
})