mirror of https://github.com/mautrix/go.git
111 lines
3.6 KiB
Go
111 lines
3.6 KiB
Go
// Copyright (c) 2023 Tulir Asokan
|
|
//
|
|
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
|
package synapseadmin
|
|
|
|
import (
|
|
"context"
|
|
"crypto/hmac"
|
|
"crypto/sha1"
|
|
"encoding/hex"
|
|
"fmt"
|
|
"net/http"
|
|
|
|
"maunium.net/go/mautrix"
|
|
)
|
|
|
|
type respGetRegisterNonce struct {
|
|
Nonce string `json:"nonce"`
|
|
}
|
|
|
|
// ReqSharedSecretRegister is the request content for Client.SharedSecretRegister.
|
|
type ReqSharedSecretRegister struct {
|
|
// The username to register. Required.
|
|
Username string `json:"username"`
|
|
// The new password for the user. Required.
|
|
Password string `json:"password"`
|
|
|
|
// Initial displayname for the user. By default, the server will use the username as the displayname.
|
|
Displayname string `json:"displayname,omitempty"`
|
|
// The type of user to register. Defaults to empty (normal user).
|
|
// Officially allowed values are "support" or "bot".
|
|
//
|
|
// Currently, the only effect is that synapse skips consent requirements for those two user types,
|
|
// other than that the user type does absolutely nothing.
|
|
UserType string `json:"user_type,omitempty"`
|
|
// Whether the created user should be a server admin.
|
|
Admin bool `json:"admin"`
|
|
// Disable generating a new device along with the registration.
|
|
// If true, the access_token and device_id fields in the response will be empty.
|
|
InhibitLogin bool `json:"inhibit_login,omitempty"`
|
|
|
|
// A single-use nonce from GetRegisterNonce. This is automatically filled by Client.SharedSecretRegister if left empty.
|
|
Nonce string `json:"nonce"`
|
|
// The checksum for the request. This is automatically generated by Client.SharedSecretRegister using Sign.
|
|
SHA1Checksum string `json:"mac"`
|
|
}
|
|
|
|
func (req *ReqSharedSecretRegister) Sign(secret string) string {
|
|
signer := hmac.New(sha1.New, []byte(secret))
|
|
signer.Write([]byte(req.Nonce))
|
|
signer.Write([]byte{0})
|
|
signer.Write([]byte(req.Username))
|
|
signer.Write([]byte{0})
|
|
signer.Write([]byte(req.Password))
|
|
signer.Write([]byte{0})
|
|
if req.Admin {
|
|
signer.Write([]byte("admin"))
|
|
} else {
|
|
signer.Write([]byte("notadmin"))
|
|
}
|
|
if req.UserType != "" {
|
|
signer.Write([]byte{0})
|
|
signer.Write([]byte(req.UserType))
|
|
}
|
|
return hex.EncodeToString(signer.Sum(nil))
|
|
}
|
|
|
|
// GetRegisterNonce gets a nonce that can be used for SharedSecretRegister.
|
|
//
|
|
// This does not need to be called manually as SharedSecretRegister will automatically call this if no nonce is provided.
|
|
func (cli *Client) GetRegisterNonce(ctx context.Context) (string, error) {
|
|
var resp respGetRegisterNonce
|
|
_, err := cli.MakeFullRequest(ctx, mautrix.FullRequest{
|
|
Method: http.MethodGet,
|
|
URL: cli.BuildURL(mautrix.SynapseAdminURLPath{"v1", "register"}),
|
|
ResponseJSON: &resp,
|
|
})
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
return resp.Nonce, nil
|
|
}
|
|
|
|
// SharedSecretRegister creates a new account using a shared secret.
|
|
//
|
|
// https://matrix-org.github.io/synapse/latest/admin_api/register_api.html
|
|
func (cli *Client) SharedSecretRegister(ctx context.Context, sharedSecret string, req ReqSharedSecretRegister) (*mautrix.RespRegister, error) {
|
|
var err error
|
|
if req.Nonce == "" {
|
|
req.Nonce, err = cli.GetRegisterNonce(ctx)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to get nonce: %w", err)
|
|
}
|
|
}
|
|
req.SHA1Checksum = req.Sign(sharedSecret)
|
|
var resp mautrix.RespRegister
|
|
_, err = cli.MakeFullRequest(ctx, mautrix.FullRequest{
|
|
Method: http.MethodPost,
|
|
URL: cli.BuildURL(mautrix.SynapseAdminURLPath{"v1", "register"}),
|
|
RequestJSON: req,
|
|
ResponseJSON: &resp,
|
|
})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &resp, nil
|
|
}
|