Disable groups by default and Some optimizations

- Put groups support behind a feature flag, and disabled by default.
  The reason is that it has some known issues, but we want to keep
  optimizing this feature. Putting it behind a feature flag could help
  some users, and the developers into optimizing this feature without to
  much trouble.

Further:

- Updates Rust to v1.66.0
- Updated GHA workflows
- Updated Alpine to 3.17
- Updated jquery to v3.6.2
- Moved jdenticon.js to load at the bottom, fixes an issue on chromium
- Added autocomplete attribute to admin login password field
- Added some extra CSP options (Tested this on Safari, Firefox, Chrome, Bitwarden Desktop)
- Moved uppercase convertion from runtime to compile-time using `paste`
  for building the environment variables, lowers heap allocations.
This commit is contained in:
BlackDex 2022-12-15 17:15:48 +01:00
parent d0b53a6a3d
commit 8b6dfe48b7
No known key found for this signature in database
GPG key ID: 58C80A2AA6C765E1
35 changed files with 229 additions and 94 deletions

View file

@ -90,6 +90,13 @@
## If unset (the default), events are kept indefinitely and the scheduled job is disabled!
# EVENTS_DAYS_RETAIN=
## BETA FEATURE: Groups
## Controls whether group support is enabled for organizations
## This setting applies to organizations.
## Disabled by default because this is a beta feature, it contains known issues!
## KNOW WHAT YOU ARE DOING!
# ORG_GROUPS_ENABLED=false
## Job scheduler settings
##
## Job schedules use a cron-like syntax (as parsed by https://crates.io/crates/cron),

View file

@ -21,6 +21,7 @@ on:
jobs:
build:
runs-on: ubuntu-20.04
timeout-minutes: 120
# Make warnings errors, this is to prevent warnings slipping through.
# This is done globally to prevent rebuilds when the RUSTFLAGS env variable changes.
env:
@ -40,7 +41,7 @@ jobs:
steps:
# Checkout the repo
- name: "Checkout"
uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # v3.1.0
uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b # v3.2.0
# End Checkout the repo
# Install dependencies
@ -78,7 +79,7 @@ jobs:
# Enable Rust Caching
- uses: Swatinem/rust-cache@b5ec9edd911d3bf82c74038b0a28791e0aa24d6f # v2.0.2
- uses: Swatinem/rust-cache@359a70e43a0bb8a13953b04a90f76428b4959bb6 # v2.2.0
# End Enable Rust Caching

View file

@ -9,10 +9,11 @@ jobs:
hadolint:
name: Validate Dockerfile syntax
runs-on: ubuntu-20.04
timeout-minutes: 30
steps:
# Checkout the repo
- name: Checkout
uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # v3.1.0
uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b # v3.2.0
# End Checkout the repo
@ -23,7 +24,7 @@ jobs:
sudo curl -L https://github.com/hadolint/hadolint/releases/download/v${HADOLINT_VERSION}/hadolint-$(uname -s)-$(uname -m) -o /usr/local/bin/hadolint && \
sudo chmod +x /usr/local/bin/hadolint
env:
HADOLINT_VERSION: 2.10.0
HADOLINT_VERSION: 2.12.0
# End Download hadolint
# Test Dockerfiles

View file

@ -31,7 +31,7 @@ jobs:
steps:
- name: Skip Duplicates Actions
id: skip_check
uses: fkirc/skip-duplicate-actions@f11521568414503656a5af807dc3018c012552c4 # v5.2.0
uses: fkirc/skip-duplicate-actions@12aca0a884f6137d619d6a8a09fcc3406ced5281 # v5.3.0
with:
cancel_others: 'true'
# Only run this when not creating a tag
@ -39,6 +39,7 @@ jobs:
docker-build:
runs-on: ubuntu-20.04
timeout-minutes: 120
needs: skip_check
# Start a local docker registry to be used to generate multi-arch images.
services:
@ -60,7 +61,7 @@ jobs:
steps:
# Checkout the repo
- name: Checkout
uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # v3.1.0
uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b # v3.2.0
with:
fetch-depth: 0

View file

@ -27,7 +27,7 @@ repos:
language: system
args: ["--features", "sqlite,mysql,postgresql,enable_mimalloc", "--"]
types_or: [rust, file]
files: (Cargo.toml|Cargo.lock|.*\.rs$)
files: (Cargo.toml|Cargo.lock|rust-toolchain|.*\.rs$)
pass_filenames: false
- id: cargo-clippy
name: cargo clippy
@ -36,5 +36,5 @@ repos:
language: system
args: ["--features", "sqlite,mysql,postgresql,enable_mimalloc", "--", "-D", "warnings"]
types_or: [rust, file]
files: (Cargo.toml|Cargo.lock|.*\.rs$)
files: (Cargo.toml|Cargo.lock|rust-toolchain|.*\.rs$)
pass_filenames: false

41
Cargo.lock generated
View file

@ -4,9 +4,9 @@ version = 3
[[package]]
name = "addr2line"
version = "0.17.0"
version = "0.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9ecd88a8c8378ca913a680cd98f0f13ac67383d35993f86c90a70e3f137816b"
checksum = "a76fd60b23679b7d19bd066031410fb7e458ccc5e958eb5c325888ce4baedc97"
dependencies = [
"gimli",
]
@ -165,15 +165,15 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
name = "backtrace"
version = "0.3.66"
version = "0.3.67"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cab84319d616cfb654d03394f38ab7e6f0919e181b1b57e1fd15e7fb4077d9a7"
checksum = "233d376d6d185f2a3093e58f283f60f880315b6c60075b01f36b3b85154564ca"
dependencies = [
"addr2line",
"cc",
"cfg-if",
"libc",
"miniz_oxide 0.5.4",
"miniz_oxide",
"object",
"rustc-demangle",
]
@ -283,9 +283,9 @@ checksum = "3a4f925191b4367301851c6d99b09890311d74b0d43f274c0b34c86d308a3663"
[[package]]
name = "cc"
version = "1.0.77"
version = "1.0.78"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e9f73505338f7d905b19d18738976aae232eb46b8efc15554ffc56deb5d9ebe4"
checksum = "a20104e2335ce8a659d6dd92a51a767a0c062599c73b343fd152cb401e828c3d"
[[package]]
name = "cfg-if"
@ -773,7 +773,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a8a2db397cb1c8772f31494cb8917e48cd1e64f0fa7efac59fbd741a0a8ce841"
dependencies = [
"crc32fast",
"miniz_oxide 0.6.2",
"miniz_oxide",
]
[[package]]
@ -947,9 +947,9 @@ dependencies = [
[[package]]
name = "gimli"
version = "0.26.2"
version = "0.27.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "22030e2c5a68ec659fde1e949a745124b48e6fa8b045b7ed5bd1fe4ccc5c4e5d"
checksum = "dec7af912d60cdbd3677c1af9352ebae6fb8394d165568a2234df0fa00f87793"
[[package]]
name = "glob"
@ -1492,15 +1492,6 @@ version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
[[package]]
name = "miniz_oxide"
version = "0.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "96590ba8f175222643a85693f33d26e9c8a015f599c216509b1a6894af675d34"
dependencies = [
"adler",
]
[[package]]
name = "miniz_oxide"
version = "0.6.2"
@ -1663,9 +1654,9 @@ dependencies = [
[[package]]
name = "object"
version = "0.29.0"
version = "0.30.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "21158b2c33aa6d4561f1c0a6ea283ca92bc54802a93b263e910746d679a7eb53"
checksum = "239da7f290cfa979f43f85a8efeee9a8a76d0827c356d37f9d3d7254d6b537fb"
dependencies = [
"memchr",
]
@ -1777,9 +1768,9 @@ dependencies = [
[[package]]
name = "paste"
version = "1.0.9"
version = "1.0.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1de2e551fb905ac83f73f7aedf2f0cb4a0da7e35efa24a202a936269f1f18e1"
checksum = "cf1c2c742266c2f1041c914ba65355a83ae8747b05f208319784083583494b4b"
[[package]]
name = "pear"
@ -2891,9 +2882,9 @@ dependencies = [
[[package]]
name = "toml"
version = "0.5.9"
version = "0.5.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8d82e1a7758622a465f8cee077614c73484dac5b836c02ff6a40d5d1010324d7"
checksum = "1333c76748e868a4d9d1017b5ab53171dfd095f70c712fdb4653a406547f598f"
dependencies = [
"serde",
]

View file

@ -44,7 +44,7 @@ log = "0.4.17"
fern = { version = "0.6.1", features = ["syslog-6"] }
tracing = { version = "0.1.37", features = ["log"] } # Needed to have lettre and webauthn-rs trace logging to work
backtrace = "0.3.66" # Logging panics to logfile instead stderr only
backtrace = "0.3.67" # Logging panics to logfile instead stderr only
# A `dotenv` implementation for Rust
dotenvy = { version = "0.15.6", default-features = false }
@ -142,7 +142,7 @@ openssl = "0.10.44"
pico-args = "0.5.0"
# Macro ident concatenation
paste = "1.0.9"
paste = "1.0.10"
governor = "0.5.1"
# Check client versions for specific features.

View file

@ -3,23 +3,23 @@
# This file was generated using a Jinja2 template.
# Please make your changes in `Dockerfile.j2` and then `make` the individual Dockerfiles.
{% set build_stage_base_image = "rust:1.65-bullseye" %}
{% set build_stage_base_image = "rust:1.66-bullseye" %}
{% if "alpine" in target_file %}
{% if "amd64" in target_file %}
{% set build_stage_base_image = "blackdex/rust-musl:x86_64-musl-stable-1.65.0" %}
{% set runtime_stage_base_image = "alpine:3.16" %}
{% set build_stage_base_image = "blackdex/rust-musl:x86_64-musl-stable-1.66.0" %}
{% set runtime_stage_base_image = "alpine:3.17" %}
{% set package_arch_target = "x86_64-unknown-linux-musl" %}
{% elif "armv7" in target_file %}
{% set build_stage_base_image = "blackdex/rust-musl:armv7-musleabihf-stable-1.65.0" %}
{% set runtime_stage_base_image = "balenalib/armv7hf-alpine:3.16" %}
{% set build_stage_base_image = "blackdex/rust-musl:armv7-musleabihf-stable-1.66.0" %}
{% set runtime_stage_base_image = "balenalib/armv7hf-alpine:3.17" %}
{% set package_arch_target = "armv7-unknown-linux-musleabihf" %}
{% elif "armv6" in target_file %}
{% set build_stage_base_image = "blackdex/rust-musl:arm-musleabi-stable-1.65.0" %}
{% set runtime_stage_base_image = "balenalib/rpi-alpine:3.16" %}
{% set build_stage_base_image = "blackdex/rust-musl:arm-musleabi-stable-1.66.0" %}
{% set runtime_stage_base_image = "balenalib/rpi-alpine:3.17" %}
{% set package_arch_target = "arm-unknown-linux-musleabi" %}
{% elif "arm64" in target_file %}
{% set build_stage_base_image = "blackdex/rust-musl:aarch64-musl-stable-1.65.0" %}
{% set runtime_stage_base_image = "balenalib/aarch64-alpine:3.16" %}
{% set build_stage_base_image = "blackdex/rust-musl:aarch64-musl-stable-1.66.0" %}
{% set runtime_stage_base_image = "balenalib/aarch64-alpine:3.17" %}
{% set package_arch_target = "aarch64-unknown-linux-musl" %}
{% endif %}
{% elif "amd64" in target_file %}

View file

@ -27,7 +27,7 @@
FROM vaultwarden/web-vault@sha256:1f124e2d1a8e9678d7b9d17587b6340fba0db298e96995552698108a43f5c1c1 as vault
########################## BUILD IMAGE ##########################
FROM rust:1.65-bullseye as build
FROM rust:1.66-bullseye as build

View file

@ -27,7 +27,7 @@
FROM vaultwarden/web-vault@sha256:1f124e2d1a8e9678d7b9d17587b6340fba0db298e96995552698108a43f5c1c1 as vault
########################## BUILD IMAGE ##########################
FROM blackdex/rust-musl:x86_64-musl-stable-1.65.0 as build
FROM blackdex/rust-musl:x86_64-musl-stable-1.66.0 as build
@ -81,7 +81,7 @@ RUN cargo build --features ${DB} --release --target=x86_64-unknown-linux-musl
######################## RUNTIME IMAGE ########################
# Create a new stage with a minimal image
# because we already have a binary built
FROM alpine:3.16
FROM alpine:3.17
ENV ROCKET_PROFILE="release" \
ROCKET_ADDRESS=0.0.0.0 \

View file

@ -27,7 +27,7 @@
FROM vaultwarden/web-vault@sha256:1f124e2d1a8e9678d7b9d17587b6340fba0db298e96995552698108a43f5c1c1 as vault
########################## BUILD IMAGE ##########################
FROM rust:1.65-bullseye as build
FROM rust:1.66-bullseye as build

View file

@ -27,7 +27,7 @@
FROM vaultwarden/web-vault@sha256:1f124e2d1a8e9678d7b9d17587b6340fba0db298e96995552698108a43f5c1c1 as vault
########################## BUILD IMAGE ##########################
FROM blackdex/rust-musl:x86_64-musl-stable-1.65.0 as build
FROM blackdex/rust-musl:x86_64-musl-stable-1.66.0 as build
@ -81,7 +81,7 @@ RUN --mount=type=cache,target=/root/.cargo/git --mount=type=cache,target=/root/.
######################## RUNTIME IMAGE ########################
# Create a new stage with a minimal image
# because we already have a binary built
FROM alpine:3.16
FROM alpine:3.17
ENV ROCKET_PROFILE="release" \
ROCKET_ADDRESS=0.0.0.0 \

View file

@ -27,7 +27,7 @@
FROM vaultwarden/web-vault@sha256:1f124e2d1a8e9678d7b9d17587b6340fba0db298e96995552698108a43f5c1c1 as vault
########################## BUILD IMAGE ##########################
FROM rust:1.65-bullseye as build
FROM rust:1.66-bullseye as build

View file

@ -27,7 +27,7 @@
FROM vaultwarden/web-vault@sha256:1f124e2d1a8e9678d7b9d17587b6340fba0db298e96995552698108a43f5c1c1 as vault
########################## BUILD IMAGE ##########################
FROM blackdex/rust-musl:aarch64-musl-stable-1.65.0 as build
FROM blackdex/rust-musl:aarch64-musl-stable-1.66.0 as build
@ -81,7 +81,7 @@ RUN cargo build --features ${DB} --release --target=aarch64-unknown-linux-musl
######################## RUNTIME IMAGE ########################
# Create a new stage with a minimal image
# because we already have a binary built
FROM balenalib/aarch64-alpine:3.16
FROM balenalib/aarch64-alpine:3.17
ENV ROCKET_PROFILE="release" \
ROCKET_ADDRESS=0.0.0.0 \

View file

@ -27,7 +27,7 @@
FROM vaultwarden/web-vault@sha256:1f124e2d1a8e9678d7b9d17587b6340fba0db298e96995552698108a43f5c1c1 as vault
########################## BUILD IMAGE ##########################
FROM rust:1.65-bullseye as build
FROM rust:1.66-bullseye as build

View file

@ -27,7 +27,7 @@
FROM vaultwarden/web-vault@sha256:1f124e2d1a8e9678d7b9d17587b6340fba0db298e96995552698108a43f5c1c1 as vault
########################## BUILD IMAGE ##########################
FROM blackdex/rust-musl:aarch64-musl-stable-1.65.0 as build
FROM blackdex/rust-musl:aarch64-musl-stable-1.66.0 as build
@ -81,7 +81,7 @@ RUN --mount=type=cache,target=/root/.cargo/git --mount=type=cache,target=/root/.
######################## RUNTIME IMAGE ########################
# Create a new stage with a minimal image
# because we already have a binary built
FROM balenalib/aarch64-alpine:3.16
FROM balenalib/aarch64-alpine:3.17
ENV ROCKET_PROFILE="release" \
ROCKET_ADDRESS=0.0.0.0 \

View file

@ -27,7 +27,7 @@
FROM vaultwarden/web-vault@sha256:1f124e2d1a8e9678d7b9d17587b6340fba0db298e96995552698108a43f5c1c1 as vault
########################## BUILD IMAGE ##########################
FROM rust:1.65-bullseye as build
FROM rust:1.66-bullseye as build

View file

@ -27,7 +27,7 @@
FROM vaultwarden/web-vault@sha256:1f124e2d1a8e9678d7b9d17587b6340fba0db298e96995552698108a43f5c1c1 as vault
########################## BUILD IMAGE ##########################
FROM blackdex/rust-musl:arm-musleabi-stable-1.65.0 as build
FROM blackdex/rust-musl:arm-musleabi-stable-1.66.0 as build
@ -83,7 +83,7 @@ RUN cargo build --features ${DB} --release --target=arm-unknown-linux-musleabi
######################## RUNTIME IMAGE ########################
# Create a new stage with a minimal image
# because we already have a binary built
FROM balenalib/rpi-alpine:3.16
FROM balenalib/rpi-alpine:3.17
ENV ROCKET_PROFILE="release" \
ROCKET_ADDRESS=0.0.0.0 \

View file

@ -27,7 +27,7 @@
FROM vaultwarden/web-vault@sha256:1f124e2d1a8e9678d7b9d17587b6340fba0db298e96995552698108a43f5c1c1 as vault
########################## BUILD IMAGE ##########################
FROM rust:1.65-bullseye as build
FROM rust:1.66-bullseye as build

View file

@ -27,7 +27,7 @@
FROM vaultwarden/web-vault@sha256:1f124e2d1a8e9678d7b9d17587b6340fba0db298e96995552698108a43f5c1c1 as vault
########################## BUILD IMAGE ##########################
FROM blackdex/rust-musl:arm-musleabi-stable-1.65.0 as build
FROM blackdex/rust-musl:arm-musleabi-stable-1.66.0 as build
@ -83,7 +83,7 @@ RUN --mount=type=cache,target=/root/.cargo/git --mount=type=cache,target=/root/.
######################## RUNTIME IMAGE ########################
# Create a new stage with a minimal image
# because we already have a binary built
FROM balenalib/rpi-alpine:3.16
FROM balenalib/rpi-alpine:3.17
ENV ROCKET_PROFILE="release" \
ROCKET_ADDRESS=0.0.0.0 \

View file

@ -27,7 +27,7 @@
FROM vaultwarden/web-vault@sha256:1f124e2d1a8e9678d7b9d17587b6340fba0db298e96995552698108a43f5c1c1 as vault
########################## BUILD IMAGE ##########################
FROM rust:1.65-bullseye as build
FROM rust:1.66-bullseye as build

View file

@ -27,7 +27,7 @@
FROM vaultwarden/web-vault@sha256:1f124e2d1a8e9678d7b9d17587b6340fba0db298e96995552698108a43f5c1c1 as vault
########################## BUILD IMAGE ##########################
FROM blackdex/rust-musl:armv7-musleabihf-stable-1.65.0 as build
FROM blackdex/rust-musl:armv7-musleabihf-stable-1.66.0 as build
@ -81,7 +81,7 @@ RUN cargo build --features ${DB} --release --target=armv7-unknown-linux-musleabi
######################## RUNTIME IMAGE ########################
# Create a new stage with a minimal image
# because we already have a binary built
FROM balenalib/armv7hf-alpine:3.16
FROM balenalib/armv7hf-alpine:3.17
ENV ROCKET_PROFILE="release" \
ROCKET_ADDRESS=0.0.0.0 \

View file

@ -27,7 +27,7 @@
FROM vaultwarden/web-vault@sha256:1f124e2d1a8e9678d7b9d17587b6340fba0db298e96995552698108a43f5c1c1 as vault
########################## BUILD IMAGE ##########################
FROM rust:1.65-bullseye as build
FROM rust:1.66-bullseye as build

View file

@ -27,7 +27,7 @@
FROM vaultwarden/web-vault@sha256:1f124e2d1a8e9678d7b9d17587b6340fba0db298e96995552698108a43f5c1c1 as vault
########################## BUILD IMAGE ##########################
FROM blackdex/rust-musl:armv7-musleabihf-stable-1.65.0 as build
FROM blackdex/rust-musl:armv7-musleabihf-stable-1.66.0 as build
@ -81,7 +81,7 @@ RUN --mount=type=cache,target=/root/.cargo/git --mount=type=cache,target=/root/.
######################## RUNTIME IMAGE ########################
# Create a new stage with a minimal image
# because we already have a binary built
FROM balenalib/armv7hf-alpine:3.16
FROM balenalib/armv7hf-alpine:3.17
ENV ROCKET_PROFILE="release" \
ROCKET_ADDRESS=0.0.0.0 \

View file

@ -1 +1 @@
1.65.0
1.66.0

View file

@ -1990,6 +1990,10 @@ async fn _restore_organization_user(
#[get("/organizations/<org_id>/groups")]
async fn get_groups(org_id: String, _headers: ManagerHeadersLoose, mut conn: DbConn) -> JsonResult {
if !CONFIG.org_groups_enabled() {
err!("Group support is disabled");
}
let groups = Group::find_by_organization(&org_id, &mut conn).await.iter().map(Group::to_json).collect::<Value>();
Ok(Json(json!({
@ -2089,6 +2093,10 @@ async fn post_groups(
mut conn: DbConn,
ip: ClientIp,
) -> JsonResult {
if !CONFIG.org_groups_enabled() {
err!("Group support is disabled");
}
let group_request = data.into_inner().data;
let group = group_request.to_group(&org_id)?;
@ -2115,6 +2123,10 @@ async fn put_group(
mut conn: DbConn,
ip: ClientIp,
) -> JsonResult {
if !CONFIG.org_groups_enabled() {
err!("Group support is disabled");
}
let group = match Group::find_by_uuid(&group_id, &mut conn).await {
Some(group) => group,
None => err!("Group not found"),
@ -2159,6 +2171,10 @@ async fn add_update_group(mut group: Group, collections: Vec<SelectionReadOnly>,
#[get("/organizations/<_org_id>/groups/<group_id>/details")]
async fn get_group_details(_org_id: String, group_id: String, _headers: AdminHeaders, mut conn: DbConn) -> JsonResult {
if !CONFIG.org_groups_enabled() {
err!("Group support is disabled");
}
let group = match Group::find_by_uuid(&group_id, &mut conn).await {
Some(group) => group,
_ => err!("Group could not be found!"),
@ -2199,6 +2215,10 @@ async fn delete_group(
mut conn: DbConn,
ip: ClientIp,
) -> EmptyResult {
if !CONFIG.org_groups_enabled() {
err!("Group support is disabled");
}
let group = match Group::find_by_uuid(&group_id, &mut conn).await {
Some(group) => group,
_ => err!("Group not found"),
@ -2220,6 +2240,10 @@ async fn delete_group(
#[get("/organizations/<_org_id>/groups/<group_id>")]
async fn get_group(_org_id: String, group_id: String, _headers: AdminHeaders, mut conn: DbConn) -> JsonResult {
if !CONFIG.org_groups_enabled() {
err!("Group support is disabled");
}
let group = match Group::find_by_uuid(&group_id, &mut conn).await {
Some(group) => group,
_ => err!("Group not found"),
@ -2230,6 +2254,10 @@ async fn get_group(_org_id: String, group_id: String, _headers: AdminHeaders, mu
#[get("/organizations/<_org_id>/groups/<group_id>/users")]
async fn get_group_users(_org_id: String, group_id: String, _headers: AdminHeaders, mut conn: DbConn) -> JsonResult {
if !CONFIG.org_groups_enabled() {
err!("Group support is disabled");
}
match Group::find_by_uuid(&group_id, &mut conn).await {
Some(_) => { /* Do nothing */ }
_ => err!("Group could not be found!"),
@ -2253,6 +2281,10 @@ async fn put_group_users(
mut conn: DbConn,
ip: ClientIp,
) -> EmptyResult {
if !CONFIG.org_groups_enabled() {
err!("Group support is disabled");
}
match Group::find_by_uuid(&group_id, &mut conn).await {
Some(_) => { /* Do nothing */ }
_ => err!("Group could not be found!"),
@ -2282,6 +2314,10 @@ async fn put_group_users(
#[get("/organizations/<_org_id>/users/<user_id>/groups")]
async fn get_user_groups(_org_id: String, user_id: String, _headers: AdminHeaders, mut conn: DbConn) -> JsonResult {
if !CONFIG.org_groups_enabled() {
err!("Group support is disabled");
}
match UserOrganization::find_by_uuid(&user_id, &mut conn).await {
Some(_) => { /* Do nothing */ }
_ => err!("User could not be found!"),
@ -2320,6 +2356,10 @@ async fn put_user_groups(
mut conn: DbConn,
ip: ClientIp,
) -> EmptyResult {
if !CONFIG.org_groups_enabled() {
err!("Group support is disabled");
}
match UserOrganization::find_by_uuid(&org_user_id, &mut conn).await {
Some(_) => { /* Do nothing */ }
_ => err!("User could not be found!"),
@ -2368,6 +2408,10 @@ async fn delete_group_user(
mut conn: DbConn,
ip: ClientIp,
) -> EmptyResult {
if !CONFIG.org_groups_enabled() {
err!("Group support is disabled");
}
match UserOrganization::find_by_uuid(&org_user_id, &mut conn).await {
Some(_) => { /* Do nothing */ }
_ => err!("User could not be found!"),

View file

@ -107,8 +107,8 @@ pub fn static_files(filename: String) -> Result<(ContentType, &'static [u8]), Er
"jdenticon.js" => Ok((ContentType::JavaScript, include_bytes!("../static/scripts/jdenticon.js"))),
"datatables.js" => Ok((ContentType::JavaScript, include_bytes!("../static/scripts/datatables.js"))),
"datatables.css" => Ok((ContentType::CSS, include_bytes!("../static/scripts/datatables.css"))),
"jquery-3.6.1.slim.js" => {
Ok((ContentType::JavaScript, include_bytes!("../static/scripts/jquery-3.6.1.slim.js")))
"jquery-3.6.2.slim.js" => {
Ok((ContentType::JavaScript, include_bytes!("../static/scripts/jquery-3.6.2.slim.js")))
}
_ => err!(format!("Static file not found: {}", filename)),
}

View file

@ -85,7 +85,7 @@ macro_rules! make_config {
let mut builder = ConfigBuilder::default();
$($(
builder.$name = make_config! { @getenv &stringify!($name).to_uppercase(), $ty };
builder.$name = make_config! { @getenv paste::paste!(stringify!([<$name:upper>])), $ty };
)+)+
builder
@ -105,7 +105,7 @@ macro_rules! make_config {
builder.$name = v.clone();
if self.$name.is_some() {
overrides.push(stringify!($name).to_uppercase());
overrides.push(paste::paste!(stringify!([<$name:upper>])).into());
}
}
)+)+
@ -195,7 +195,7 @@ macro_rules! make_config {
element.insert("default".into(), serde_json::to_value(def.$name).unwrap());
element.insert("type".into(), (_get_form_type(stringify!($ty))).into());
element.insert("doc".into(), (_get_doc(concat!($($doc),+))).into());
element.insert("overridden".into(), (overriden.contains(&stringify!($name).to_uppercase())).into());
element.insert("overridden".into(), (overriden.contains(&paste::paste!(stringify!([<$name:upper>])).into())).into());
element
}),
)+
@ -564,6 +564,9 @@ make_config! {
admin_ratelimit_seconds: u64, false, def, 300;
/// Max burst size for admin login requests |> Allow a burst of requests of up to this size, while maintaining the average indicated by `admin_ratelimit_seconds`
admin_ratelimit_max_burst: u32, false, def, 3;
/// Enable groups (BETA!) (Know the risks!) |> Enables groups support for organizations (Currently contains known issues!).
org_groups_enabled: bool, false, def, false;
},
/// Yubikey settings

View file

@ -149,7 +149,7 @@ impl Organization {
"Use2fa": true,
"UseDirectory": false, // Is supported, but this value isn't checked anywhere (yet)
"UseEvents": CONFIG.org_events_enabled(),
"UseGroups": true,
"UseGroups": CONFIG.org_groups_enabled(),
"UseTotp": true,
"UsePolicies": true,
// "UseScim": false, // Not supported (Not AGPLv3 Licensed)
@ -304,7 +304,7 @@ impl UserOrganization {
"Use2fa": true,
"UseDirectory": false, // Is supported, but this value isn't checked anywhere (yet)
"UseEvents": CONFIG.org_events_enabled(),
"UseGroups": true,
"UseGroups": CONFIG.org_groups_enabled(),
"UseTotp": true,
// "UseScim": false, // Not supported (Not AGPLv3 Licensed)
"UsePolicies": true,

View file

@ -1,5 +1,5 @@
/*!
* jQuery JavaScript Library v3.6.1 -ajax,-ajax/jsonp,-ajax/load,-ajax/script,-ajax/var/location,-ajax/var/nonce,-ajax/var/rquery,-ajax/xhr,-manipulation/_evalUrl,-deprecated/ajax-event-alias,-effects,-effects/Tween,-effects/animatedSelector
* jQuery JavaScript Library v3.6.2 -ajax,-ajax/jsonp,-ajax/load,-ajax/script,-ajax/var/location,-ajax/var/nonce,-ajax/var/rquery,-ajax/xhr,-manipulation/_evalUrl,-deprecated/ajax-event-alias,-effects,-effects/Tween,-effects/animatedSelector
* https://jquery.com/
*
* Includes Sizzle.js
@ -9,7 +9,7 @@
* Released under the MIT license
* https://jquery.org/license
*
* Date: 2022-08-26T17:52Z
* Date: 2022-12-13T14:56Z
*/
( function( global, factory ) {
@ -151,7 +151,7 @@ function toType( obj ) {
var
version = "3.6.1 -ajax,-ajax/jsonp,-ajax/load,-ajax/script,-ajax/var/location,-ajax/var/nonce,-ajax/var/rquery,-ajax/xhr,-manipulation/_evalUrl,-deprecated/ajax-event-alias,-effects,-effects/Tween,-effects/animatedSelector",
version = "3.6.2 -ajax,-ajax/jsonp,-ajax/load,-ajax/script,-ajax/var/location,-ajax/var/nonce,-ajax/var/rquery,-ajax/xhr,-manipulation/_evalUrl,-deprecated/ajax-event-alias,-effects,-effects/Tween,-effects/animatedSelector",
// Define a local copy of jQuery
jQuery = function( selector, context ) {
@ -522,14 +522,14 @@ function isArrayLike( obj ) {
}
var Sizzle =
/*!
* Sizzle CSS Selector Engine v2.3.6
* Sizzle CSS Selector Engine v2.3.8
* https://sizzlejs.com/
*
* Copyright JS Foundation and other contributors
* Released under the MIT license
* https://js.foundation/
*
* Date: 2021-02-16
* Date: 2022-11-16
*/
( function( window ) {
var i,
@ -879,6 +879,27 @@ function Sizzle( selector, context, results, seed ) {
}
try {
// `qSA` may not throw for unrecognized parts using forgiving parsing:
// https://drafts.csswg.org/selectors/#forgiving-selector
// like the `:has()` pseudo-class:
// https://drafts.csswg.org/selectors/#relational
// `CSS.supports` is still expected to return `false` then:
// https://drafts.csswg.org/css-conditional-4/#typedef-supports-selector-fn
// https://drafts.csswg.org/css-conditional-4/#dfn-support-selector
if ( support.cssSupportsSelector &&
// eslint-disable-next-line no-undef
!CSS.supports( "selector(" + newSelector + ")" ) ) {
// Support: IE 11+
// Throw to get to the same code path as an error directly in qSA.
// Note: once we only support browser supporting
// `CSS.supports('selector(...)')`, we can most likely drop
// the `try-catch`. IE doesn't implement the API.
throw new Error();
}
push.apply( results,
newContext.querySelectorAll( newSelector )
);
@ -1174,6 +1195,31 @@ setDocument = Sizzle.setDocument = function( node ) {
!el.querySelectorAll( ":scope fieldset div" ).length;
} );
// Support: Chrome 105+, Firefox 104+, Safari 15.4+
// Make sure forgiving mode is not used in `CSS.supports( "selector(...)" )`.
//
// `:is()` uses a forgiving selector list as an argument and is widely
// implemented, so it's a good one to test against.
support.cssSupportsSelector = assert( function() {
/* eslint-disable no-undef */
return CSS.supports( "selector(*)" ) &&
// Support: Firefox 78-81 only
// In old Firefox, `:is()` didn't use forgiving parsing. In that case,
// fail this test as there's no selector to test against that.
// `CSS.supports` uses unforgiving parsing
document.querySelectorAll( ":is(:jqfake)" ) &&
// `*` is needed as Safari & newer Chrome implemented something in between
// for `:has()` - it throws in `qSA` if it only contains an unsupported
// argument but multiple ones, one of which is supported, are fine.
// We want to play safe in case `:is()` gets the same treatment.
!CSS.supports( "selector(:is(*,:jqfake))" );
/* eslint-enable */
} );
/* Attributes
---------------------------------------------------------------------- */
@ -1440,6 +1486,18 @@ setDocument = Sizzle.setDocument = function( node ) {
} );
}
if ( !support.cssSupportsSelector ) {
// Support: Chrome 105+, Safari 15.4+
// `:has()` uses a forgiving selector list as an argument so our regular
// `try-catch` mechanism fails to catch `:has()` with arguments not supported
// natively like `:has(:contains("Foo"))`. Where supported & spec-compliant,
// we now use `CSS.supports("selector(SELECTOR_TO_BE_TESTED)")` but outside
// that, let's mark `:has` as buggy to always use jQuery traversal for
// `:has()`.
rbuggyQSA.push( ":has" );
}
rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join( "|" ) );
rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join( "|" ) );
@ -1452,7 +1510,14 @@ setDocument = Sizzle.setDocument = function( node ) {
// As in, an element does not contain itself
contains = hasCompare || rnative.test( docElem.contains ) ?
function( a, b ) {
var adown = a.nodeType === 9 ? a.documentElement : a,
// Support: IE <9 only
// IE doesn't have `contains` on `document` so we need to check for
// `documentElement` presence.
// We need to fall back to `a` when `documentElement` is missing
// as `ownerDocument` of elements within `<template/>` may have
// a null one - a default behavior of all modern browsers.
var adown = a.nodeType === 9 && a.documentElement || a,
bup = b && b.parentNode;
return a === bup || !!( bup && bup.nodeType === 1 && (
adown.contains ?
@ -2242,7 +2307,7 @@ Expr = Sizzle.selectors = {
return elem.nodeName.toLowerCase() === "input" &&
elem.type === "text" &&
// Support: IE<8
// Support: IE <10 only
// New HTML5 attribute values (e.g., "search") appear with elem.type === "text"
( ( attr = elem.getAttribute( "type" ) ) == null ||
attr.toLowerCase() === "text" );
@ -6608,17 +6673,37 @@ function curCSS( elem, name, computed ) {
// .css('filter') (IE 9 only, trac-12537)
// .css('--customProperty) (gh-3144)
if ( computed ) {
// Support: IE <=9 - 11+
// IE only supports `"float"` in `getPropertyValue`; in computed styles
// it's only available as `"cssFloat"`. We no longer modify properties
// sent to `.css()` apart from camelCasing, so we need to check both.
// Normally, this would create difference in behavior: if
// `getPropertyValue` returns an empty string, the value returned
// by `.css()` would be `undefined`. This is usually the case for
// disconnected elements. However, in IE even disconnected elements
// with no styles return `"none"` for `getPropertyValue( "float" )`
ret = computed.getPropertyValue( name ) || computed[ name ];
// trim whitespace for custom property (issue gh-4926)
if ( isCustomProp ) {
if ( isCustomProp && ret ) {
// rtrim treats U+000D CARRIAGE RETURN and U+000C FORM FEED
// Support: Firefox 105+, Chrome <=105+
// Spec requires trimming whitespace for custom properties (gh-4926).
// Firefox only trims leading whitespace. Chrome just collapses
// both leading & trailing whitespace to a single space.
//
// Fall back to `undefined` if empty string returned.
// This collapses a missing definition with property defined
// and set to an empty string but there's no standard API
// allowing us to differentiate them without a performance penalty
// and returning `undefined` aligns with older jQuery.
//
// rtrimCSS treats U+000D CARRIAGE RETURN and U+000C FORM FEED
// as whitespace while CSS does not, but this is not a problem
// because CSS preprocessing replaces them with U+000A LINE FEED
// (which *is* CSS whitespace)
// https://www.w3.org/TR/css-syntax-3/#input-preprocessing
ret = ret.replace( rtrimCSS, "$1" );
ret = ret.replace( rtrimCSS, "$1" ) || undefined;
}
if ( ret === "" && !isAttached( elem ) ) {

View file

@ -28,7 +28,6 @@
border: var(--bs-alert-border);
}
</style>
<script src="{{urlpath}}/vw_static/jdenticon.js"></script>
<script>
'use strict';
@ -141,6 +140,7 @@
}
})();
</script>
<script src="{{urlpath}}/vw_static/jdenticon.js"></script>
<script src="{{urlpath}}/vw_static/bootstrap-native.js"></script>
</body>
</html>

View file

@ -13,7 +13,7 @@
<small>Please provide it below:</small>
<form class="form-inline" method="post" action="{{urlpath}}/admin">
<input type="password" class="form-control w-50 mr-2" name="token" placeholder="Enter admin token" autofocus="autofocus">
<input type="password" autocomplete="password" class="form-control w-50 mr-2" name="token" placeholder="Enter admin token" autofocus="autofocus">
{{#if redirect}}
<input type="hidden" id="redirect" name="redirect" value="/{{redirect}}">
{{/if}}

View file

@ -49,7 +49,7 @@
</main>
<link rel="stylesheet" href="{{urlpath}}/vw_static/datatables.css" />
<script src="{{urlpath}}/vw_static/jquery-3.6.1.slim.js"></script>
<script src="{{urlpath}}/vw_static/jquery-3.6.2.slim.js"></script>
<script src="{{urlpath}}/vw_static/datatables.js"></script>
<script>
'use strict';

View file

@ -136,7 +136,7 @@
</main>
<link rel="stylesheet" href="{{urlpath}}/vw_static/datatables.css" />
<script src="{{urlpath}}/vw_static/jquery-3.6.1.slim.js"></script>
<script src="{{urlpath}}/vw_static/jquery-3.6.2.slim.js"></script>
<script src="{{urlpath}}/vw_static/datatables.js"></script>
<script>
'use strict';

View file

@ -63,6 +63,8 @@ impl Fairing for AppHeaders {
// app.simplelogin.io, app.anonaddy.com, api.fastmail.com, quack.duckduckgo.com
let csp = format!(
"default-src 'self'; \
base-uri 'self'; \
form-action 'self'; \
object-src 'self' blob:; \
script-src 'self'{script_src}; \
style-src 'self' 'unsafe-inline'; \
@ -74,12 +76,12 @@ impl Fairing for AppHeaders {
moz-extension://* \
{allowed_iframe_ancestors}; \
img-src 'self' data: \
https://haveibeenpwned.com/ \
https://haveibeenpwned.com \
https://www.gravatar.com \
{icon_service_csp}; \
connect-src 'self' \
https://api.pwnedpasswords.com/range/ \
https://2fa.directory/api/ \
https://api.pwnedpasswords.com \
https://2fa.directory \
https://app.simplelogin.io/api/ \
https://app.anonaddy.com/api/ \
https://api.fastmail.com/ \