Basic password changing with prompt.
This commit is contained in:
commit
1ed21658e6
4 changed files with 1502 additions and 0 deletions
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
/target
|
||||||
|
.env
|
1371
Cargo.lock
generated
Normal file
1371
Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load diff
17
Cargo.toml
Normal file
17
Cargo.toml
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
[package]
|
||||||
|
name = "matrix-dendrite-admin"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
text_io = "0.1.12"
|
||||||
|
dotenvy = "0.15.7"
|
||||||
|
rustify = "0.5.3"
|
||||||
|
rustify_derive = "0.5.2"
|
||||||
|
http = "0.2.9"
|
||||||
|
derive_builder = "0.12.0"
|
||||||
|
serde = "1.0.164"
|
||||||
|
tokio = { version = "1.29.1", features = ["rt-multi-thread", "macros"] }
|
||||||
|
serde_json = "1.0.99"
|
112
src/main.rs
Normal file
112
src/main.rs
Normal file
|
@ -0,0 +1,112 @@
|
||||||
|
use derive_builder::Builder;
|
||||||
|
use dotenvy::dotenv;
|
||||||
|
use http::Request;
|
||||||
|
use rustify::{errors::ClientError, Client, Endpoint, MiddleWare};
|
||||||
|
use rustify_derive::Endpoint;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use std::env;
|
||||||
|
use std::io::{stdout, Write};
|
||||||
|
use std::str;
|
||||||
|
use text_io::read;
|
||||||
|
|
||||||
|
#[derive(Debug, Builder, Default, Endpoint, Serialize)]
|
||||||
|
#[endpoint(
|
||||||
|
path = "_dendrite/admin/resetPassword/{self.user_id}",
|
||||||
|
method = "POST",
|
||||||
|
response = "ResetPasswordResponse",
|
||||||
|
builder = "true"
|
||||||
|
)]
|
||||||
|
struct ResetPasswordRequest {
|
||||||
|
#[endpoint(skip)]
|
||||||
|
pub user_id: String,
|
||||||
|
pub password: String,
|
||||||
|
pub logout_devices: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
#[allow(dead_code)]
|
||||||
|
struct ResetPasswordResponse {
|
||||||
|
pub password_updated: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct AdminMiddleware {
|
||||||
|
pub access_token: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AdminMiddleware {
|
||||||
|
pub fn new(access_token: String) -> Self {
|
||||||
|
AdminMiddleware { access_token }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
#[allow(dead_code)]
|
||||||
|
struct DendriteError {
|
||||||
|
pub errcode: String,
|
||||||
|
pub error: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MiddleWare for AdminMiddleware {
|
||||||
|
fn request<E: Endpoint>(
|
||||||
|
&self,
|
||||||
|
_endpoint: &E,
|
||||||
|
req: &mut Request<Vec<u8>>,
|
||||||
|
) -> Result<(), rustify::errors::ClientError> {
|
||||||
|
req.headers_mut().append(
|
||||||
|
"Authorization",
|
||||||
|
http::HeaderValue::from_str(&format!("Bearer {}", self.access_token)).unwrap(),
|
||||||
|
);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn response<E: Endpoint>(
|
||||||
|
&self,
|
||||||
|
_endpoint: &E,
|
||||||
|
_resp: &mut http::Response<Vec<u8>>,
|
||||||
|
) -> Result<(), rustify::errors::ClientError> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::main]
|
||||||
|
async fn main() {
|
||||||
|
dotenv().ok();
|
||||||
|
|
||||||
|
let token = env::var("ACCESS_TOKEN").expect("ACCESS_TOKEN is a required env setting");
|
||||||
|
let instance = env::var("INSTANCE_URL").expect("INSTANCE_URL is a required env setting");
|
||||||
|
let domain = env::var("INSTANCE_DOMAIN").expect("INSTANCE_DOMAIN is a required env setting");
|
||||||
|
|
||||||
|
let middleware = AdminMiddleware::new(token);
|
||||||
|
let client = Client::default(&instance);
|
||||||
|
|
||||||
|
print!("Enter local user id for {} account: @", domain);
|
||||||
|
let _ = stdout().flush();
|
||||||
|
let username: String = read!("{}\n");
|
||||||
|
|
||||||
|
print!("Enter new pass for @{}:{}: ", username, domain);
|
||||||
|
let _ = stdout().flush();
|
||||||
|
let pass: String = read!("{}\n");
|
||||||
|
|
||||||
|
let endpoint = ResetPasswordRequest::builder()
|
||||||
|
.user_id(format!("@{}:{}", username, domain))
|
||||||
|
.password(pass)
|
||||||
|
.logout_devices(false)
|
||||||
|
.build()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
match endpoint.with_middleware(&middleware).exec(&client).await {
|
||||||
|
Ok(result) => {
|
||||||
|
println!("{:#?}", result.parse().unwrap());
|
||||||
|
}
|
||||||
|
Err(ClientError::ServerResponseError { content, .. }) => {
|
||||||
|
println!(
|
||||||
|
"{:#?}",
|
||||||
|
serde_json::from_str::<DendriteError>(&content.unwrap()).unwrap()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
e => {
|
||||||
|
e.unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue