diff --git a/docker/DockerSettings.yaml b/docker/DockerSettings.yaml index a38e327a..7a2ea17b 100644 --- a/docker/DockerSettings.yaml +++ b/docker/DockerSettings.yaml @@ -1,6 +1,6 @@ --- -vault_version: "v2025.1.0" -vault_image_digest: "sha256:72d636334b4ad6fe9ba1d12e0cda562cd31772cf28772f6b2fe4121a537b72a8" +vault_version: "v2025.1.1" +vault_image_digest: "sha256:cb6b2095a4afc1d9d243a33f6d09211f40e3d82c7ae829fd025df5ff175a4918" # Cross Compile Docker Helper Scripts v1.6.1 # We use the linux/amd64 platform shell scripts since there is no difference between the different platform scripts # https://github.com/tonistiigi/xx | https://hub.docker.com/r/tonistiigi/xx/tags diff --git a/docker/Dockerfile.alpine b/docker/Dockerfile.alpine index 2757f6cc..3335aa62 100644 --- a/docker/Dockerfile.alpine +++ b/docker/Dockerfile.alpine @@ -19,15 +19,15 @@ # - From https://hub.docker.com/r/vaultwarden/web-vault/tags, # click the tag name to view the digest of the image it currently points to. # - From the command line: -# $ docker pull docker.io/vaultwarden/web-vault:v2025.1.0 -# $ docker image inspect --format "{{.RepoDigests}}" docker.io/vaultwarden/web-vault:v2025.1.0 -# [docker.io/vaultwarden/web-vault@sha256:72d636334b4ad6fe9ba1d12e0cda562cd31772cf28772f6b2fe4121a537b72a8] +# $ docker pull docker.io/vaultwarden/web-vault:v2025.1.1 +# $ docker image inspect --format "{{.RepoDigests}}" docker.io/vaultwarden/web-vault:v2025.1.1 +# [docker.io/vaultwarden/web-vault@sha256:cb6b2095a4afc1d9d243a33f6d09211f40e3d82c7ae829fd025df5ff175a4918] # # - Conversely, to get the tag name from the digest: -# $ docker image inspect --format "{{.RepoTags}}" docker.io/vaultwarden/web-vault@sha256:72d636334b4ad6fe9ba1d12e0cda562cd31772cf28772f6b2fe4121a537b72a8 -# [docker.io/vaultwarden/web-vault:v2025.1.0] +# $ docker image inspect --format "{{.RepoTags}}" docker.io/vaultwarden/web-vault@sha256:cb6b2095a4afc1d9d243a33f6d09211f40e3d82c7ae829fd025df5ff175a4918 +# [docker.io/vaultwarden/web-vault:v2025.1.1] # -FROM --platform=linux/amd64 docker.io/vaultwarden/web-vault@sha256:72d636334b4ad6fe9ba1d12e0cda562cd31772cf28772f6b2fe4121a537b72a8 AS vault +FROM --platform=linux/amd64 docker.io/vaultwarden/web-vault@sha256:cb6b2095a4afc1d9d243a33f6d09211f40e3d82c7ae829fd025df5ff175a4918 AS vault ########################## ALPINE BUILD IMAGES ########################## ## NOTE: The Alpine Base Images do not support other platforms then linux/amd64 diff --git a/docker/Dockerfile.debian b/docker/Dockerfile.debian index ff1ff453..cf45a36d 100644 --- a/docker/Dockerfile.debian +++ b/docker/Dockerfile.debian @@ -19,15 +19,15 @@ # - From https://hub.docker.com/r/vaultwarden/web-vault/tags, # click the tag name to view the digest of the image it currently points to. # - From the command line: -# $ docker pull docker.io/vaultwarden/web-vault:v2025.1.0 -# $ docker image inspect --format "{{.RepoDigests}}" docker.io/vaultwarden/web-vault:v2025.1.0 -# [docker.io/vaultwarden/web-vault@sha256:72d636334b4ad6fe9ba1d12e0cda562cd31772cf28772f6b2fe4121a537b72a8] +# $ docker pull docker.io/vaultwarden/web-vault:v2025.1.1 +# $ docker image inspect --format "{{.RepoDigests}}" docker.io/vaultwarden/web-vault:v2025.1.1 +# [docker.io/vaultwarden/web-vault@sha256:cb6b2095a4afc1d9d243a33f6d09211f40e3d82c7ae829fd025df5ff175a4918] # # - Conversely, to get the tag name from the digest: -# $ docker image inspect --format "{{.RepoTags}}" docker.io/vaultwarden/web-vault@sha256:72d636334b4ad6fe9ba1d12e0cda562cd31772cf28772f6b2fe4121a537b72a8 -# [docker.io/vaultwarden/web-vault:v2025.1.0] +# $ docker image inspect --format "{{.RepoTags}}" docker.io/vaultwarden/web-vault@sha256:cb6b2095a4afc1d9d243a33f6d09211f40e3d82c7ae829fd025df5ff175a4918 +# [docker.io/vaultwarden/web-vault:v2025.1.1] # -FROM --platform=linux/amd64 docker.io/vaultwarden/web-vault@sha256:72d636334b4ad6fe9ba1d12e0cda562cd31772cf28772f6b2fe4121a537b72a8 AS vault +FROM --platform=linux/amd64 docker.io/vaultwarden/web-vault@sha256:cb6b2095a4afc1d9d243a33f6d09211f40e3d82c7ae829fd025df5ff175a4918 AS vault ########################## Cross Compile Docker Helper Scripts ########################## ## We use the linux/amd64 no matter which Build Platform, since these are all bash scripts diff --git a/src/api/core/accounts.rs b/src/api/core/accounts.rs index 89dcadea..473c0c86 100644 --- a/src/api/core/accounts.rs +++ b/src/api/core/accounts.rs @@ -30,6 +30,7 @@ pub fn routes() -> Vec { profile, put_profile, post_profile, + put_avatar, get_public_keys, post_keys, post_password, @@ -42,9 +43,8 @@ pub fn routes() -> Vec { post_verify_email_token, post_delete_recover, post_delete_recover_token, - post_device_token, - delete_account, post_delete_account, + delete_account, revision_date, password_hint, prelogin, @@ -52,7 +52,9 @@ pub fn routes() -> Vec { api_key, rotate_api_key, get_known_device, - put_avatar, + get_all_devices, + get_device, + post_device_token, put_device_token, put_clear_device_token, post_clear_device_token, @@ -1068,6 +1070,26 @@ impl<'r> FromRequest<'r> for KnownDevice { } } +#[get("/devices")] +async fn get_all_devices(headers: Headers, mut conn: DbConn) -> JsonResult { + let devices = Device::find_with_auth_request_by_user(&headers.user.uuid, &mut conn).await; + let devices = devices.iter().map(|device| device.to_json()).collect::>(); + + Ok(Json(json!({ + "data": devices, + "continuationToken": null, + "object": "list" + }))) +} + +#[get("/devices/identifier/")] +async fn get_device(device_id: DeviceId, headers: Headers, mut conn: DbConn) -> JsonResult { + let Some(device) = Device::find_by_uuid_and_user(&device_id, &headers.user.uuid, &mut conn).await else { + err!("No device found"); + }; + Ok(Json(device.to_json())) +} + #[derive(Deserialize)] #[serde(rename_all = "camelCase")] struct PushToken { diff --git a/src/db/models/auth_request.rs b/src/db/models/auth_request.rs index dd4f098a..d8ca3fac 100644 --- a/src/db/models/auth_request.rs +++ b/src/db/models/auth_request.rs @@ -1,8 +1,9 @@ use super::{DeviceId, OrganizationId, UserId}; -use crate::crypto::ct_eq; +use crate::{crypto::ct_eq, util::format_date}; use chrono::{NaiveDateTime, Utc}; use derive_more::{AsRef, Deref, Display, From}; use macros::UuidFromParam; +use serde_json::Value; db_object! { #[derive(Debug, Identifiable, Queryable, Insertable, AsChangeset, Deserialize, Serialize)] @@ -64,6 +65,13 @@ impl AuthRequest { authentication_date: None, } } + + pub fn to_json_for_pending_device(&self) -> Value { + json!({ + "id": self.uuid, + "creationDate": format_date(&self.creation_date), + }) + } } use crate::db::DbConn; @@ -133,6 +141,20 @@ impl AuthRequest { }} } + pub async fn find_by_user_and_requested_device( + user_uuid: &UserId, + device_uuid: &DeviceId, + conn: &mut DbConn, + ) -> Option { + db_run! {conn: { + auth_requests::table + .filter(auth_requests::user_uuid.eq(user_uuid)) + .filter(auth_requests::request_device_identifier.eq(device_uuid)) + .order_by(auth_requests::creation_date.desc()) + .first::(conn).ok().from_db() + }} + } + pub async fn find_created_before(dt: &NaiveDateTime, conn: &mut DbConn) -> Vec { db_run! {conn: { auth_requests::table diff --git a/src/db/models/device.rs b/src/db/models/device.rs index 0f1afd0f..74ef46d2 100644 --- a/src/db/models/device.rs +++ b/src/db/models/device.rs @@ -1,8 +1,9 @@ use chrono::{NaiveDateTime, Utc}; use derive_more::{Display, From}; +use serde_json::Value; -use super::UserId; -use crate::{crypto, CONFIG}; +use super::{AuthRequest, UserId}; +use crate::{crypto, util::format_date, CONFIG}; use macros::IdFromParam; db_object! { @@ -23,7 +24,6 @@ db_object! { pub push_token: Option, pub refresh_token: String, - pub twofactor_remember: Option, } } @@ -49,6 +49,18 @@ impl Device { } } + pub fn to_json(&self) -> Value { + json!({ + "id": self.uuid, + "name": self.name, + "type": self.atype, + "identifier": self.push_uuid, + "creationDate": format_date(&self.created_at), + "isTrusted": false, + "object":"device" + }) + } + pub fn refresh_twofactor_remember(&mut self) -> String { use data_encoding::BASE64; let twofactor_remember = crypto::encode_random_bytes::<180>(BASE64); @@ -125,6 +137,36 @@ impl Device { } } +pub struct DeviceWithAuthRequest { + pub device: Device, + pub pending_auth_request: Option, +} + +impl DeviceWithAuthRequest { + pub fn to_json(&self) -> Value { + let auth_request = match &self.pending_auth_request { + Some(auth_request) => auth_request.to_json_for_pending_device(), + None => Value::Null, + }; + json!({ + "id": self.device.uuid, + "name": self.device.name, + "type": self.device.atype, + "identifier": self.device.push_uuid, + "creationDate": format_date(&self.device.created_at), + "devicePendingAuthRequest": auth_request, + "isTrusted": false, + "object": "device", + }) + } + + pub fn from(c: Device, a: Option) -> Self { + Self { + device: c, + pending_auth_request: a, + } + } +} use crate::db::DbConn; use crate::api::EmptyResult; @@ -171,6 +213,16 @@ impl Device { }} } + pub async fn find_with_auth_request_by_user(user_uuid: &UserId, conn: &mut DbConn) -> Vec { + let devices = Self::find_by_user(user_uuid, conn).await; + let mut result = Vec::new(); + for device in devices { + let auth_request = AuthRequest::find_by_user_and_requested_device(user_uuid, &device.uuid, conn).await; + result.push(DeviceWithAuthRequest::from(device, auth_request)); + } + result + } + pub async fn find_by_user(user_uuid: &UserId, conn: &mut DbConn) -> Vec { db_run! { conn: { devices::table