Compare commits
No commits in common. "35f706b537b116fbff7b3cb8053a27abd9ef2952" and "e894e8eb1838554ef975a700a46d543138c155e3" have entirely different histories.
35f706b537
...
e894e8eb18
10 changed files with 44 additions and 274 deletions
140
Cargo.lock
generated
140
Cargo.lock
generated
|
@ -252,26 +252,6 @@ version = "1.6.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b"
|
||||
|
||||
[[package]]
|
||||
name = "bindgen"
|
||||
version = "0.69.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "271383c67ccabffb7381723dea0672a673f292304fcb45c01cc648c7a8d58088"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"cexpr",
|
||||
"clang-sys",
|
||||
"itertools",
|
||||
"lazy_static",
|
||||
"lazycell",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"regex",
|
||||
"rustc-hash 1.1.0",
|
||||
"shlex",
|
||||
"syn 2.0.79",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "2.6.0"
|
||||
|
@ -317,31 +297,12 @@ dependencies = [
|
|||
"shlex",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cexpr"
|
||||
version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766"
|
||||
dependencies = [
|
||||
"nom",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "clang-sys"
|
||||
version = "1.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4"
|
||||
dependencies = [
|
||||
"glob",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.5.20"
|
||||
|
@ -535,17 +496,6 @@ dependencies = [
|
|||
"powerfmt",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "derive-debug"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e53ef7e1cf756fd5a8e74b9a0a9504ec446eddde86c3063a76ff26a13b7773b1"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "digest"
|
||||
version = "0.10.7"
|
||||
|
@ -593,18 +543,6 @@ dependencies = [
|
|||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "enum_dispatch"
|
||||
version = "0.3.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "aa18ce2bc66555b3218614519ac839ddb759a7d6720732f979ef8d13be147ecd"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.79",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "equivalent"
|
||||
version = "1.0.1"
|
||||
|
@ -662,13 +600,10 @@ dependencies = [
|
|||
"base64 0.22.1",
|
||||
"clap",
|
||||
"color-eyre",
|
||||
"derive-debug",
|
||||
"enum_dispatch",
|
||||
"hex",
|
||||
"hmac",
|
||||
"ldap3",
|
||||
"md-5",
|
||||
"pam",
|
||||
"rand",
|
||||
"reqwest",
|
||||
"secrecy",
|
||||
|
@ -844,12 +779,6 @@ version = "0.28.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253"
|
||||
|
||||
[[package]]
|
||||
name = "glob"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b"
|
||||
|
||||
[[package]]
|
||||
name = "h2"
|
||||
version = "0.4.6"
|
||||
|
@ -1084,15 +1013,6 @@ version = "1.70.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf"
|
||||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
version = "0.12.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569"
|
||||
dependencies = [
|
||||
"either",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "1.0.11"
|
||||
|
@ -1117,12 +1037,6 @@ dependencies = [
|
|||
"spin 0.9.8",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lazycell"
|
||||
version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
|
||||
|
||||
[[package]]
|
||||
name = "lber"
|
||||
version = "0.4.2"
|
||||
|
@ -1394,40 +1308,6 @@ version = "3.5.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f"
|
||||
|
||||
[[package]]
|
||||
name = "pam"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8ab553c52103edb295d8f7d6a3b593dc22a30b1fb99643c777a8f36915e285ba"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"memchr",
|
||||
"pam-macros",
|
||||
"pam-sys",
|
||||
"users",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pam-macros"
|
||||
version = "0.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c94f3b9b97df3c6d4e51a14916639b24e02c7d15d1dba686ce9b1118277cb811"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pam-sys"
|
||||
version = "1.0.0-alpha5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ce9484729b3e52c0bacdc5191cb6a6a5f31ef4c09c5e4ab1209d3340ad9e997b"
|
||||
dependencies = [
|
||||
"bindgen",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "parking"
|
||||
version = "2.2.1"
|
||||
|
@ -1551,7 +1431,7 @@ dependencies = [
|
|||
"pin-project-lite",
|
||||
"quinn-proto",
|
||||
"quinn-udp",
|
||||
"rustc-hash 2.0.0",
|
||||
"rustc-hash",
|
||||
"rustls 0.23.14",
|
||||
"socket2",
|
||||
"thiserror",
|
||||
|
@ -1568,7 +1448,7 @@ dependencies = [
|
|||
"bytes",
|
||||
"rand",
|
||||
"ring 0.17.8",
|
||||
"rustc-hash 2.0.0",
|
||||
"rustc-hash",
|
||||
"rustls 0.23.14",
|
||||
"slab",
|
||||
"thiserror",
|
||||
|
@ -1782,12 +1662,6 @@ version = "0.1.24"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f"
|
||||
|
||||
[[package]]
|
||||
name = "rustc-hash"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
|
||||
|
||||
[[package]]
|
||||
name = "rustc-hash"
|
||||
version = "2.0.0"
|
||||
|
@ -2816,16 +2690,6 @@ dependencies = [
|
|||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "users"
|
||||
version = "0.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "aa4227e95324a443c9fcb06e03d4d85e91aabe9a5a02aa818688b6918b6af486"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"log",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "utf8parse"
|
||||
version = "0.2.2"
|
||||
|
|
|
@ -21,13 +21,10 @@ axum = "0.7.4"
|
|||
base64 = "0.22.0"
|
||||
clap = { version = "4.5.0", features = ["derive"] }
|
||||
color-eyre = { version = "0.6.2" }
|
||||
derive-debug = "0.1.2"
|
||||
enum_dispatch = "0.3.13"
|
||||
hex = { version = "0.4.3", features = ["serde"] }
|
||||
hmac = "0.12.1"
|
||||
ldap3 = { version = "0.11.3", default-features = false, features = ["tls-rustls"] }
|
||||
md-5 = "0.10.6"
|
||||
pam = "0.8.0"
|
||||
rand = "0.8.5"
|
||||
reqwest = { version = "0.12.0", default-features = false, features = ["charset", "http2", "macos-system-configuration", "json", "rustls-tls-native-roots"] }
|
||||
secrecy = { version = "0.10.0", features = ["serde"] }
|
||||
|
|
|
@ -13,8 +13,8 @@ which is no good, especially for PvP scenarios! Wouldn't it be great if you coul
|
|||
authentication server?
|
||||
|
||||
factoriauth is exactly that. It allows clients to log in as custom users provided by one of several
|
||||
authentication backends (e.g. local users via PAM, LDAP, or a passwd-style file), and allows servers
|
||||
to validate that these custom users are properly authenticated.
|
||||
authentication backends (e.g. LDAP or a passwd-style file), and allows servers to validate that
|
||||
these custom users are properly authenticated.
|
||||
|
||||
## Roadmap
|
||||
|
||||
|
@ -25,13 +25,12 @@ to validate that these custom users are properly authenticated.
|
|||
- [user token generation](https://wiki.factorio.com/Web_authentication_API) and storage (`POST
|
||||
/api-login`)
|
||||
- LDAP authentication backend
|
||||
- PAM authentication backend
|
||||
- server padlock proxying (to allow e.g. factorio.com users to join servers using a custom auth
|
||||
server)
|
||||
|
||||
### Planned
|
||||
|
||||
- more authentication backends: user file
|
||||
- more authentication backends: user file, PAM(?)
|
||||
|
||||
### Unplanned
|
||||
|
||||
|
|
|
@ -7,14 +7,8 @@ secret = ""
|
|||
[database]
|
||||
connection-string = "sqlite://sqlite.db"
|
||||
|
||||
# uncomment to allow login as local user via PAM
|
||||
#[[auth-backends]]
|
||||
#type = "PAM"
|
||||
#service-name = "system-auth"
|
||||
|
||||
# uncomment and configure to allow login via LDAP
|
||||
#[[auth-backends]]
|
||||
#type = "LDAP"
|
||||
#server-address = "ldap://ldap.example.com"
|
||||
#search-base = "ou=users,dc=example,dc=com"
|
||||
#user-filter = "(|(uid=%s)(mail=%s))"
|
||||
[[auth-backends]]
|
||||
type = "LDAP"
|
||||
server-address = "ldap://ldap.example.com"
|
||||
search-base = "ou=users,dc=example,dc=com"
|
||||
user-filter = "(|(uid=%s)(mail=%s))"
|
||||
|
|
|
@ -5,9 +5,19 @@ use secrecy::ExposeSecret;
|
|||
use tokio::{sync::Mutex, time::sleep};
|
||||
use tracing::{event, instrument, Level};
|
||||
|
||||
use crate::{auth::AuthenticationError, config::LdapBackendConfig, secrets::Password};
|
||||
use crate::{config::LdapBackendConfig, secrets::Password};
|
||||
|
||||
use super::ValidateLogin;
|
||||
use super::AuthenticationError;
|
||||
|
||||
pub trait ValidateLogin {
|
||||
/// Validates that the given username and password combination is correct, and returns the
|
||||
/// (normalized) user ID.
|
||||
async fn validate_login(
|
||||
&self,
|
||||
username: &str,
|
||||
password: &Password,
|
||||
) -> Result<String, AuthenticationError>;
|
||||
}
|
||||
|
||||
#[instrument]
|
||||
async fn start_ldap_connection(
|
|
@ -1,14 +0,0 @@
|
|||
use crate::{auth::AuthenticationError, secrets::Password};
|
||||
|
||||
pub mod ldap_backend;
|
||||
pub mod pam_backend;
|
||||
|
||||
pub trait ValidateLogin {
|
||||
/// Validates that the given username and password combination is correct, and returns the
|
||||
/// (normalized) user ID.
|
||||
async fn validate_login(
|
||||
&self,
|
||||
username: &str,
|
||||
password: &Password,
|
||||
) -> Result<String, AuthenticationError>;
|
||||
}
|
|
@ -1,57 +0,0 @@
|
|||
use derive_debug::Dbg;
|
||||
use secrecy::ExposeSecret;
|
||||
use std::sync::Arc;
|
||||
use tokio::sync::Mutex;
|
||||
use tracing::{event, Level};
|
||||
|
||||
use pam::{Client, PasswordConv};
|
||||
|
||||
use crate::{auth::AuthenticationError, config::PamBackendConfig, secrets::Password};
|
||||
|
||||
use super::ValidateLogin;
|
||||
|
||||
#[derive(Dbg)]
|
||||
pub struct PamBackend<'a> {
|
||||
#[dbg(skip)]
|
||||
pam: Arc<Mutex<pam::Client<'a, PasswordConv>>>,
|
||||
config: PamBackendConfig,
|
||||
}
|
||||
|
||||
impl PamBackend<'_> {
|
||||
pub fn new(config: PamBackendConfig) -> Result<Arc<Self>, AuthenticationError> {
|
||||
let pam = Client::with_password(&config.service_name)?;
|
||||
|
||||
event!(Level::INFO, "PAM client initialized");
|
||||
|
||||
Ok(Arc::new(Self {
|
||||
pam: Arc::new(Mutex::new(pam)),
|
||||
config,
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
impl ValidateLogin for PamBackend<'_> {
|
||||
async fn validate_login(
|
||||
&self,
|
||||
username: &str,
|
||||
password: &Password,
|
||||
) -> Result<String, AuthenticationError> {
|
||||
let mut pam = self.pam.lock().await;
|
||||
|
||||
pam.conversation_mut()
|
||||
.set_credentials(username, password.0.expose_secret());
|
||||
|
||||
if let Err(pam_error) = pam.authenticate() {
|
||||
event!(
|
||||
Level::INFO,
|
||||
username,
|
||||
pam_error = pam_error.to_string(),
|
||||
"PAM authentication failed"
|
||||
);
|
||||
return Err(AuthenticationError::InvalidUserOrPassword);
|
||||
}
|
||||
|
||||
event!(Level::INFO, username, "PAM authentication succeeded");
|
||||
Ok(username.to_string())
|
||||
}
|
||||
}
|
|
@ -1,6 +1,5 @@
|
|||
use std::sync::Arc;
|
||||
|
||||
use backends::pam_backend::PamBackend;
|
||||
use base64::{prelude::BASE64_STANDARD, Engine};
|
||||
use hmac::{Hmac, Mac};
|
||||
use md5::Md5;
|
||||
|
@ -25,7 +24,7 @@ use crate::{
|
|||
},
|
||||
};
|
||||
|
||||
use self::backends::{ldap_backend::LdapBackend, ValidateLogin};
|
||||
use self::backends::{LdapBackend, ValidateLogin};
|
||||
|
||||
pub mod backends;
|
||||
|
||||
|
@ -39,10 +38,8 @@ pub enum AuthenticationError {
|
|||
InvalidServerHash,
|
||||
#[error("Database error")]
|
||||
Database(#[from] sqlx::Error),
|
||||
#[error("LDAP backend error")]
|
||||
LdapBackend(#[from] ldap3::LdapError),
|
||||
#[error("PAM backend error")]
|
||||
PamBackend(#[from] pam::PamError),
|
||||
#[error("Authentication backend error")]
|
||||
Backend(#[from] ldap3::LdapError),
|
||||
#[error("Padlock proxy error")]
|
||||
PadlockProxy(#[from] PadlockProxyError),
|
||||
#[error("No authentication backends available")]
|
||||
|
@ -50,21 +47,19 @@ pub enum AuthenticationError {
|
|||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum AuthenticationBackend<'a> {
|
||||
pub enum AuthenticationBackend {
|
||||
Ldap(Arc<LdapBackend>),
|
||||
Pam(Arc<PamBackend<'a>>),
|
||||
}
|
||||
|
||||
impl AuthenticationBackend<'_> {
|
||||
impl AuthenticationBackend {
|
||||
pub async fn new(config: AuthBackendConfig) -> Result<Self, AuthenticationError> {
|
||||
match config {
|
||||
AuthBackendConfig::Ldap(c) => Ok(Self::Ldap(LdapBackend::new(c).await?)),
|
||||
AuthBackendConfig::Pam(c) => Ok(Self::Pam(PamBackend::new(c)?)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ValidateLogin for AuthenticationBackend<'_> {
|
||||
impl ValidateLogin for AuthenticationBackend {
|
||||
async fn validate_login(
|
||||
&self,
|
||||
username: &str,
|
||||
|
@ -72,23 +67,22 @@ impl ValidateLogin for AuthenticationBackend<'_> {
|
|||
) -> Result<String, AuthenticationError> {
|
||||
match self {
|
||||
AuthenticationBackend::Ldap(b) => b.validate_login(username, password).await,
|
||||
AuthenticationBackend::Pam(b) => b.validate_login(username, password).await,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct UserAuthenticator<'a> {
|
||||
pub struct UserAuthenticator {
|
||||
db: Arc<Mutex<Box<dyn Database + Send>>>,
|
||||
backends: Vec<AuthenticationBackend<'a>>,
|
||||
backends: Vec<AuthenticationBackend>,
|
||||
}
|
||||
|
||||
impl<'a> UserAuthenticator<'a> {
|
||||
impl UserAuthenticator {
|
||||
const TOKEN_LEN: usize = 30;
|
||||
|
||||
pub fn new(
|
||||
db: Arc<Mutex<Box<dyn Database + Send>>>,
|
||||
backends: Vec<AuthenticationBackend<'a>>,
|
||||
backends: Vec<AuthenticationBackend>,
|
||||
) -> Self {
|
||||
Self { db, backends }
|
||||
}
|
||||
|
@ -304,14 +298,14 @@ impl ServerPadlockGenerator {
|
|||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct UserServerKeyGenerator<'a> {
|
||||
user_authenticator: Arc<UserAuthenticator<'a>>,
|
||||
pub struct UserServerKeyGenerator {
|
||||
user_authenticator: Arc<UserAuthenticator>,
|
||||
padlock_generator: Arc<ServerPadlockGenerator>,
|
||||
}
|
||||
|
||||
impl<'a> UserServerKeyGenerator<'a> {
|
||||
impl UserServerKeyGenerator {
|
||||
pub fn new(
|
||||
user_authenticator: Arc<UserAuthenticator<'a>>,
|
||||
user_authenticator: Arc<UserAuthenticator>,
|
||||
padlock_generator: Arc<ServerPadlockGenerator>,
|
||||
) -> Self {
|
||||
Self {
|
||||
|
|
|
@ -42,8 +42,6 @@ pub struct DatabaseConfig {
|
|||
pub enum AuthBackendConfig {
|
||||
#[serde(rename = "LDAP")]
|
||||
Ldap(LdapBackendConfig),
|
||||
#[serde(rename = "PAM")]
|
||||
Pam(PamBackendConfig)
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
|
@ -55,18 +53,3 @@ pub struct LdapBackendConfig {
|
|||
/// User filter template. All occurences of `%s` will be replaced with the username.
|
||||
pub user_filter: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
#[serde(rename_all = "kebab-case")]
|
||||
#[allow(clippy::module_name_repetitions)]
|
||||
pub struct PamBackendConfig {
|
||||
pub service_name: String,
|
||||
}
|
||||
|
||||
impl Default for PamBackendConfig {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
service_name: "system-auth".to_string()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,18 +18,18 @@ use crate::auth::{
|
|||
use crate::secrets::{Password, ServerHash, UserToken};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
struct AppState<'a> {
|
||||
user_authenticator: Arc<UserAuthenticator<'a>>,
|
||||
struct AppState {
|
||||
user_authenticator: Arc<UserAuthenticator>,
|
||||
server_padlock_generator: Arc<ServerPadlockGenerator>,
|
||||
user_server_key_generator: Arc<UserServerKeyGenerator<'a>>,
|
||||
user_server_key_generator: Arc<UserServerKeyGenerator>,
|
||||
}
|
||||
|
||||
#[instrument]
|
||||
pub async fn run(
|
||||
listen: SocketAddr,
|
||||
user_authenticator: Arc<UserAuthenticator<'static>>,
|
||||
user_authenticator: Arc<UserAuthenticator>,
|
||||
server_padlock_generator: Arc<ServerPadlockGenerator>,
|
||||
user_server_key_generator: Arc<UserServerKeyGenerator<'static>>,
|
||||
user_server_key_generator: Arc<UserServerKeyGenerator>,
|
||||
) -> color_eyre::Result<()> {
|
||||
let app_state = AppState {
|
||||
user_authenticator,
|
||||
|
@ -110,7 +110,7 @@ struct LoginResponse {
|
|||
async fn api_login(
|
||||
State(AppState {
|
||||
user_authenticator, ..
|
||||
}): State<AppState<'_>>,
|
||||
}): State<AppState>,
|
||||
Query(ApiVersion { api_version }): Query<ApiVersion>,
|
||||
Form(LoginRequest { username, password }): Form<LoginRequest>,
|
||||
) -> ApiResult<Json<LoginResponse>> {
|
||||
|
@ -144,7 +144,7 @@ async fn generate_user_server_key_2(
|
|||
State(AppState {
|
||||
user_server_key_generator,
|
||||
..
|
||||
}): State<AppState<'_>>,
|
||||
}): State<AppState>,
|
||||
Query(ApiVersion { api_version }): Query<ApiVersion>,
|
||||
Form(UserServerKeyRequest {
|
||||
username,
|
||||
|
@ -175,7 +175,7 @@ async fn generate_server_padlock_2(
|
|||
State(AppState {
|
||||
server_padlock_generator,
|
||||
..
|
||||
}): State<AppState<'_>>,
|
||||
}): State<AppState>,
|
||||
Query(ApiVersion { api_version }): Query<ApiVersion>,
|
||||
) -> ApiResult<Json<ServerPadlockResponse>> {
|
||||
event!(Level::INFO, "Creating server padlock");
|
||||
|
|
Loading…
Reference in a new issue