mirror of
https://github.com/dani-garcia/vaultwarden.wiki.git
synced 2026-10-25 01:26:50 +03:00
Compare commits
5
Commits
1.37.4
...
c687cacb6b
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c687cacb6b | ||
|
|
8b56926077 | ||
|
|
de6d2066b3 | ||
|
|
415df400f4 | ||
|
|
42aa3ee1c7 |
No files matched your search
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
This allows running integration tests using [Playwright](https://playwright.dev/).
|
This allows running integration tests using [Playwright](https://playwright.dev/).
|
||||||
\
|
\
|
||||||
It usse its own [test.env](/test/scenarios/test.env) with different ports to not collide with a running dev instance.
|
It uses its own [test.env](./test.env) with different ports to not collide with a running dev instance.
|
||||||
|
|
||||||
## Install
|
## Install
|
||||||
|
|
||||||
@@ -62,7 +62,7 @@ DOCKER_BUILDKIT=1 docker compose --profile playwright --env-file test.env run Pl
|
|||||||
|
|
||||||
### Keep services running
|
### Keep services running
|
||||||
|
|
||||||
If you want you can keep the DB and Keycloak runnning (states are not impacted by the tests):
|
If you want you can keep the DB and Keycloak running (states are not impacted by the tests):
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
PW_KEEP_SERVICE_RUNNING=true npx playwright test
|
PW_KEEP_SERVICE_RUNNING=true npx playwright test
|
||||||
|
|||||||
@@ -137,9 +137,13 @@ async fn ldap_import(data: Json<OrgImportData>, token: PublicToken, conn: DbConn
|
|||||||
|
|
||||||
if CONFIG.org_groups_enabled() {
|
if CONFIG.org_groups_enabled() {
|
||||||
for group_data in &data.groups {
|
for group_data in &data.groups {
|
||||||
let group_uuid = if let Some(group) =
|
let group_uuid = if let Some(mut group) =
|
||||||
Group::find_by_external_id_and_org(&group_data.external_id, &org_id, &conn).await
|
Group::find_by_external_id_and_org(&group_data.external_id, &org_id, &conn).await
|
||||||
{
|
{
|
||||||
|
if group.name != group_data.name {
|
||||||
|
group.name = group_data.name.clone();
|
||||||
|
group.save(&conn).await?;
|
||||||
|
}
|
||||||
group.uuid
|
group.uuid
|
||||||
} else {
|
} else {
|
||||||
let mut group =
|
let mut group =
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use std::{
|
use std::{
|
||||||
net::IpAddr,
|
net::IpAddr,
|
||||||
sync::{Arc, LazyLock},
|
sync::{Arc, LazyLock},
|
||||||
time::Duration,
|
time::{Duration, Instant},
|
||||||
};
|
};
|
||||||
|
|
||||||
use chrono::{NaiveDateTime, Utc};
|
use chrono::{NaiveDateTime, Utc};
|
||||||
@@ -41,6 +41,14 @@ pub static WS_ANONYMOUS_SUBSCRIPTIONS: LazyLock<Arc<AnonymousWebSocketSubscripti
|
|||||||
/// One connection is needed per pending login request, several at once are only expected behind NAT.
|
/// One connection is needed per pending login request, several at once are only expected behind NAT.
|
||||||
const MAX_ANONYMOUS_CONNECTIONS_PER_IP: u32 = 25;
|
const MAX_ANONYMOUS_CONNECTIONS_PER_IP: u32 = 25;
|
||||||
|
|
||||||
|
/// How often a Ping is sent to the client.
|
||||||
|
const WS_PING_INTERVAL: Duration = Duration::from_secs(15);
|
||||||
|
|
||||||
|
/// Close the connection if nothing, not even a Pong, was received from the client for this long.
|
||||||
|
/// Otherwise half-open connections (client gone without a FIN, e.g. behind a proxy or NAT) are kept forever.
|
||||||
|
/// Same as the default `ClientTimeoutInterval` of ASP.NET Core SignalR, which the official server uses.
|
||||||
|
const WS_CLIENT_TIMEOUT: Duration = Duration::from_secs(30);
|
||||||
|
|
||||||
static NOTIFICATIONS_DISABLED: LazyLock<bool> = LazyLock::new(|| !CONFIG.enable_websocket() && !CONFIG.push_enabled());
|
static NOTIFICATIONS_DISABLED: LazyLock<bool> = LazyLock::new(|| !CONFIG.enable_websocket() && !CONFIG.push_enabled());
|
||||||
|
|
||||||
pub fn routes() -> Vec<Route> {
|
pub fn routes() -> Vec<Route> {
|
||||||
@@ -156,12 +164,16 @@ fn websockets_hub<'r>(
|
|||||||
rocket_ws::Stream! { ws => {
|
rocket_ws::Stream! { ws => {
|
||||||
let mut ws = ws;
|
let mut ws = ws;
|
||||||
let _guard = guard;
|
let _guard = guard;
|
||||||
let mut interval = tokio::time::interval(Duration::from_secs(15));
|
let mut interval = tokio::time::interval(WS_PING_INTERVAL);
|
||||||
|
let mut last_received = Instant::now();
|
||||||
loop {
|
loop {
|
||||||
tokio::select! {
|
tokio::select! {
|
||||||
res = ws.next() => {
|
res = ws.next() => {
|
||||||
match res {
|
match res {
|
||||||
Some(Ok(message)) => {
|
Some(Ok(message)) => {
|
||||||
|
// Any message, including a Pong, means the client is still there
|
||||||
|
last_received = Instant::now();
|
||||||
|
|
||||||
match message {
|
match message {
|
||||||
// Respond to any pings
|
// Respond to any pings
|
||||||
Message::Ping(ping) => yield Message::Pong(ping),
|
Message::Ping(ping) => yield Message::Pong(ping),
|
||||||
@@ -195,7 +207,13 @@ fn websockets_hub<'r>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_ = interval.tick() => yield Message::Ping(create_ping())
|
_ = interval.tick() => {
|
||||||
|
// The client stopped responding without closing the connection, drop it
|
||||||
|
if last_received.elapsed() > WS_CLIENT_TIMEOUT {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
yield Message::Ping(create_ping());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
@@ -229,12 +247,16 @@ fn anonymous_websockets_hub<'r>(ws: WebSocket, token: String, ip: ClientIp) -> R
|
|||||||
rocket_ws::Stream! { ws => {
|
rocket_ws::Stream! { ws => {
|
||||||
let mut ws = ws;
|
let mut ws = ws;
|
||||||
let _guard = guard;
|
let _guard = guard;
|
||||||
let mut interval = tokio::time::interval(Duration::from_secs(15));
|
let mut interval = tokio::time::interval(WS_PING_INTERVAL);
|
||||||
|
let mut last_received = Instant::now();
|
||||||
loop {
|
loop {
|
||||||
tokio::select! {
|
tokio::select! {
|
||||||
res = ws.next() => {
|
res = ws.next() => {
|
||||||
match res {
|
match res {
|
||||||
Some(Ok(message)) => {
|
Some(Ok(message)) => {
|
||||||
|
// Any message, including a Pong, means the client is still there
|
||||||
|
last_received = Instant::now();
|
||||||
|
|
||||||
match message {
|
match message {
|
||||||
// Respond to any pings
|
// Respond to any pings
|
||||||
Message::Ping(ping) => yield Message::Pong(ping),
|
Message::Ping(ping) => yield Message::Pong(ping),
|
||||||
@@ -268,7 +290,13 @@ fn anonymous_websockets_hub<'r>(ws: WebSocket, token: String, ip: ClientIp) -> R
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_ = interval.tick() => yield Message::Ping(create_ping())
|
_ = interval.tick() => {
|
||||||
|
// The client stopped responding without closing the connection, drop it
|
||||||
|
if last_received.elapsed() > WS_CLIENT_TIMEOUT {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
yield Message::Ping(create_ping());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
|
|||||||
@@ -1266,6 +1266,14 @@ fn validate_config(cfg: &ConfigItems, on_update: bool) -> Result<(), Error> {
|
|||||||
err!("`AUTH_REQUEST_PURGE_SCHEDULE` is not a valid cron expression")
|
err!("`AUTH_REQUEST_PURGE_SCHEDULE` is not a valid cron expression")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !cfg.duo_context_purge_schedule.is_empty() && cfg.duo_context_purge_schedule.parse::<Schedule>().is_err() {
|
||||||
|
err!("`DUO_CONTEXT_PURGE_SCHEDULE` is not a valid cron expression")
|
||||||
|
}
|
||||||
|
|
||||||
|
if !cfg.purge_incomplete_sso_auth.is_empty() && cfg.purge_incomplete_sso_auth.parse::<Schedule>().is_err() {
|
||||||
|
err!("`PURGE_INCOMPLETE_SSO_AUTH` is not a valid cron expression")
|
||||||
|
}
|
||||||
|
|
||||||
if !cfg.disable_admin_token {
|
if !cfg.disable_admin_token {
|
||||||
match cfg.admin_token.as_ref() {
|
match cfg.admin_token.as_ref() {
|
||||||
Some(t) if t.starts_with("$argon2") => {
|
Some(t) if t.starts_with("$argon2") => {
|
||||||
|
|||||||
Reference in new issue
Block a user