mirror of
https://mau.dev/mautrix/go.git
synced 2026-03-14 14:25:53 +01:00
Add some synapse admin API wrappers
This commit is contained in:
parent
f87063cb7f
commit
44006bd068
3 changed files with 191 additions and 0 deletions
18
synapseadmin/client.go
Normal file
18
synapseadmin/client.go
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
// 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 (
|
||||
"maunium.net/go/mautrix"
|
||||
)
|
||||
|
||||
// Client is a wrapper for the mautrix.Client struct that includes methods for accessing the Synapse admin API.
|
||||
//
|
||||
// https://matrix-org.github.io/synapse/latest/usage/administration/admin_api/index.html
|
||||
type Client struct {
|
||||
*mautrix.Client
|
||||
}
|
||||
112
synapseadmin/register.go
Normal file
112
synapseadmin/register.go
Normal file
|
|
@ -0,0 +1,112 @@
|
|||
// 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(mautrix.FullRequest{
|
||||
Method: http.MethodGet,
|
||||
URL: cli.BuildURL(mautrix.SynapseAdminURLPath{"v1", "register"}),
|
||||
ResponseJSON: &resp,
|
||||
Context: ctx,
|
||||
})
|
||||
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(mautrix.FullRequest{
|
||||
Method: http.MethodPost,
|
||||
URL: cli.BuildURL(mautrix.SynapseAdminURLPath{"v1", "register"}),
|
||||
RequestJSON: req,
|
||||
ResponseJSON: &resp,
|
||||
Context: ctx,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &resp, nil
|
||||
}
|
||||
61
synapseadmin/userapi.go
Normal file
61
synapseadmin/userapi.go
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
// 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"
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"maunium.net/go/mautrix"
|
||||
"maunium.net/go/mautrix/id"
|
||||
)
|
||||
|
||||
// ReqResetPassword is the request content for Client.ResetPassword.
|
||||
type ReqResetPassword struct {
|
||||
// The user whose password to reset.
|
||||
UserID id.UserID `json:"-"`
|
||||
|
||||
// The new password for the user. Required.
|
||||
NewPassword string `json:"new_password"`
|
||||
// Whether all the user's existing devices should be logged out after the password change.
|
||||
LogoutDevices bool `json:"logout_devices"`
|
||||
}
|
||||
|
||||
// ResetPassword changes the password of another user using
|
||||
//
|
||||
// https://matrix-org.github.io/synapse/latest/admin_api/user_admin_api.html#reset-password
|
||||
func (cli *Client) ResetPassword(ctx context.Context, req ReqResetPassword) error {
|
||||
reqURL := cli.BuildURL(mautrix.SynapseAdminURLPath{"v1", "reset_password", req.UserID})
|
||||
_, err := cli.MakeFullRequest(mautrix.FullRequest{
|
||||
Method: http.MethodPost,
|
||||
URL: reqURL,
|
||||
RequestJSON: &req,
|
||||
Context: ctx,
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
// UsernameAvailable checks if a username is valid and available for registration on the server using the admin API.
|
||||
//
|
||||
// The response format is the same as mautrix.Client.RegisterAvailable,
|
||||
// but it works even if registration is disabled on the server.
|
||||
//
|
||||
// https://matrix-org.github.io/synapse/latest/admin_api/user_admin_api.html#check-username-availability
|
||||
func (cli *Client) UsernameAvailable(ctx context.Context, username string) (resp *mautrix.RespRegisterAvailable, err error) {
|
||||
u := cli.BuildURLWithQuery(mautrix.SynapseAdminURLPath{"v1", "username_available"}, map[string]string{"username": username})
|
||||
_, err = cli.MakeFullRequest(mautrix.FullRequest{
|
||||
Method: http.MethodGet,
|
||||
URL: u,
|
||||
ResponseJSON: &resp,
|
||||
Context: ctx,
|
||||
})
|
||||
if err == nil && !resp.Available {
|
||||
err = fmt.Errorf(`request returned OK status without "available": true`)
|
||||
}
|
||||
return
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue