Skip to content

Commit aae9ebf

Browse files
committed
wip(workspace-details): Move workspace accent color to workspace vCard
1 parent bac1a85 commit aae9ebf

24 files changed

+233
-200
lines changed

.zed/settings.json

+3
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@
1010
},
1111
"Markdown": {
1212
"wrap_guides": [96]
13+
},
14+
"Gherkin": {
15+
"format_on_save": "off"
1316
}
1417
},
1518
"language_overrides": {

Cargo.lock

+5-5
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ rustls = { version = "0.23", default-features = false }
7676
# `prose-xmpp` and its dependencies.
7777
# NOTE: See <https://github.com/prose-im/prose-core-client/blob/master/Cargo.toml>
7878
# for up-to-date versions (make sure to switch to the appropriate tag).
79-
prose-xmpp = { git = "https://github.com/prose-im/prose-core-client.git", tag = "0.1.101", default-features = false }
79+
prose-xmpp = { git = "https://github.com/prose-im/prose-core-client.git", branch = "vcard4-private-properties", default-features = false }
8080
jid = { version = "0.11", default-features = false }
8181
minidom = { version = "0.16", default-features = false }
8282
xmpp-parsers = { version = "0.21", default-features = false }

crates/rest-api/src/features/init/init_workspace.rs

+8-9
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,10 @@ use std::sync::Arc;
88
use axum::{http::HeaderValue, Json};
99
use serde::{Deserialize, Serialize};
1010
use service::{
11-
init::{InitService, InitWorkspaceError, WorkspaceCreateForm},
11+
init::{InitService, InitWorkspaceError},
1212
secrets::SecretsStore,
1313
server_config::ServerConfig,
14-
workspace::WorkspaceServiceError,
14+
workspace::{Workspace, WorkspaceServiceError},
1515
xmpp::XmppServiceInner,
1616
AppConfig,
1717
};
@@ -98,8 +98,7 @@ impl CustomErrorCode for InitWorkspaceError {
9898
match self {
9999
Self::WorkspaceAlreadyInitialized => ErrorCode::WORKSPACE_ALREADY_INITIALIZED,
100100
Self::XmppAccountNotInitialized => ErrorCode::SERVER_CONFIG_NOT_INITIALIZED,
101-
Self::CouldNotSetWorkspaceName(err) => err.code(),
102-
Self::DbErr(err) => err.code(),
101+
Self::CouldNotSetWorkspaceVCard(err) => err.code(),
103102
}
104103
}
105104
}
@@ -110,7 +109,6 @@ impl HttpApiError for WorkspaceServiceError {
110109
match self {
111110
Self::WorkspaceNotInitialized => WorkspaceNotInitialized.code(),
112111
Self::XmppServiceError(err) => err.code(),
113-
Self::DbErr(err) => err.code(),
114112
}
115113
}
116114
fn message(&self) -> String {
@@ -126,11 +124,12 @@ impl HttpApiError for WorkspaceServiceError {
126124

127125
// BOILERPLATE
128126

129-
impl Into<WorkspaceCreateForm> for InitWorkspaceRequest {
130-
fn into(self) -> WorkspaceCreateForm {
131-
WorkspaceCreateForm {
127+
impl Into<Workspace> for InitWorkspaceRequest {
128+
fn into(self) -> Workspace {
129+
Workspace {
132130
name: self.name,
133-
accent_color: Some(self.accent_color),
131+
accent_color: self.accent_color,
132+
icon: None,
134133
}
135134
}
136135
}

crates/rest-api/src/features/workspace_details/guards/workspace_service.rs

-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ impl FromRequestParts<AppState> for WorkspaceService {
2020
let server_config = ServerConfig::from_request_parts(parts, state).await?;
2121

2222
WorkspaceService::new(
23-
Arc::new(state.db.clone()),
2423
Arc::new(state.xmpp_service.clone()),
2524
Arc::new(state.app_config.clone()),
2625
&server_config,

crates/rest-api/src/features/workspace_details/util/vcard4_mapping.rs

+18-2
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
use std::str::FromStr as _;
77

88
use service::prose_xmpp::stanza::{vcard4 as prose_xmpp_properties, VCard4};
9-
use vcard4::property as vcard4_properties;
9+
use vcard4::property::{self as vcard4_properties, ExtensionProperty};
1010

1111
pub fn prose_xmpp_vcard4_to_vcard4_vcard(
1212
VCard4 {
@@ -22,6 +22,7 @@ pub fn prose_xmpp_vcard4_to_vcard4_vcard(
2222
tel,
2323
title,
2424
url,
25+
extensions,
2526
}: VCard4,
2627
) -> Result<vcard4::Vcard, vcard4::Error> {
2728
let mut formatted_names = fn_.into_iter();
@@ -67,7 +68,17 @@ pub fn prose_xmpp_vcard4_to_vcard4_vcard(
6768
builder = builder.url(vcard4::Uri::from_str(&url.value)?);
6869
}
6970

70-
Ok(builder.finish())
71+
let mut vcard = builder.finish();
72+
for (name, value) in extensions.into_iter() {
73+
vcard.extensions.push(ExtensionProperty {
74+
name: name.to_ascii_uppercase(),
75+
value: vcard4_properties::AnyProperty::Text(value),
76+
group: Default::default(),
77+
parameters: Default::default(),
78+
});
79+
}
80+
81+
Ok(vcard)
7182
}
7283

7384
pub fn vcard4_vcard_to_prose_xmpp_vcard4(
@@ -84,6 +95,7 @@ pub fn vcard4_vcard_to_prose_xmpp_vcard4(
8495
role,
8596
org,
8697
note,
98+
extensions,
8799
..
88100
}: &vcard4::Vcard,
89101
) -> Result<VCard4, vcard4::Error> {
@@ -157,6 +169,10 @@ pub fn vcard4_vcard_to_prose_xmpp_vcard4(
157169
value: s.to_string(),
158170
})
159171
.collect(),
172+
extensions: extensions
173+
.iter()
174+
.map(|p| (p.name.to_ascii_lowercase(), p.value.to_string()))
175+
.collect(),
160176
})
161177
}
162178

crates/rest-api/src/features/workspace_details/workspace_accent_color.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -33,5 +33,5 @@ pub async fn set_workspace_accent_color_route(
3333
let color = workspace_service
3434
.set_workspace_accent_color(req.color)
3535
.await?;
36-
Ok(Json(GetWorkspaceAccentColorResponse { color }))
36+
Ok(Json(GetWorkspaceAccentColorResponse { color: Some(color) }))
3737
}

crates/rest-api/tests/features/init.rs

+5-4
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
// License: Mozilla Public License v2.0 (MPL v2.0)
55

66
use prose_pod_api::features::init::*;
7-
use service::init::*;
7+
use service::workspace::Workspace;
88

99
use super::prelude::*;
1010

@@ -31,9 +31,10 @@ fn given_workspace_not_initialized(_world: &mut TestWorld) {
3131

3232
#[given("the workspace has been initialized")]
3333
async fn given_workspace_initialized(world: &mut TestWorld) -> Result<(), Error> {
34-
let form = WorkspaceCreateForm {
34+
let workspace = Workspace {
3535
name: DEFAULT_WORKSPACE_NAME.to_string(),
3636
accent_color: None,
37+
icon: None,
3738
};
3839

3940
world
@@ -43,7 +44,7 @@ async fn given_workspace_initialized(world: &mut TestWorld) -> Result<(), Error>
4344
Arc::new(world.secrets_store.clone()),
4445
Arc::new(world.xmpp_service.clone()),
4546
&world.server_config().await?,
46-
form,
47+
workspace,
4748
)
4849
.await?;
4950

@@ -118,7 +119,7 @@ async fn init_first_account(api: &TestServer, node: &JidNode, nickname: &String)
118119
.add_header(CONTENT_TYPE, "application/json")
119120
.json(&json!(InitFirstAccountRequest {
120121
username: node.to_owned(),
121-
password: SecretString::new("test.password".to_string()).into(),
122+
password: SecretString::from("test.password").into(),
122123
nickname: nickname.to_owned(),
123124
}))
124125
.await

crates/rest-api/tests/features/roles.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ async fn given_admin(world: &mut TestWorld, name: String) -> Result<(), Error> {
2525
.create_user(
2626
db,
2727
&jid,
28-
&SecretString::new("password".to_owned()),
28+
&"password".into(),
2929
&name,
3030
&Some(MemberRole::Admin),
3131
)
@@ -50,7 +50,7 @@ async fn given_not_admin(world: &mut TestWorld, name: String) -> Result<(), Erro
5050
.create_user(
5151
db,
5252
&jid,
53-
&SecretString::new("password".to_owned()),
53+
&"password".into(),
5454
&name,
5555
&Some(MemberRole::Member),
5656
)

crates/rest-api/tests/features/workspace_details.rs

+32-1
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,21 @@ async fn then_workspace_icon_should_be(
126126
Ok(())
127127
}
128128

129+
// WORKSPACE ACCENT COLOR
130+
131+
#[given(expr = "the workspace accent color is {string}")]
132+
async fn given_workspace_accent_color(
133+
world: &mut TestWorld,
134+
accent_color: String,
135+
) -> Result<(), Error> {
136+
world
137+
.workspace_service()
138+
.await
139+
.set_workspace_accent_color(accent_color)
140+
.await?;
141+
Ok(())
142+
}
143+
129144
// WORKSPACE VCARD
130145

131146
api_call_fn!(
@@ -137,9 +152,10 @@ api_call_fn!(get_workspace_vcard, GET, "/v1/workspace", accept: "text/vcard");
137152
api_call_fn!(set_workspace_vcard, PUT, "/v1/workspace", content_type: "text/vcard");
138153

139154
#[given(expr = "the workspace vCard is {string}")]
140-
async fn given_workspace_vcard(world: &mut TestWorld, vcard_data: String) -> Result<(), Error> {
155+
async fn given_workspace_vcard(world: &mut TestWorld, mut vcard_data: String) -> Result<(), Error> {
141156
let server_config = world.server_config().await?;
142157

158+
vcard_data = vcard_data.replace("\\n", "\n");
143159
let vcards = vcard4::parse(vcard_data).unwrap();
144160
let vcard = vcards.first().unwrap();
145161
let prose_xmpp_vcard4 = vcard4_vcard_to_prose_xmpp_vcard4(vcard).unwrap();
@@ -196,3 +212,18 @@ async fn then_workspace_vcard_should_be(
196212
assert_eq!(vcard.to_string(), vcard_data);
197213
Ok(())
198214
}
215+
216+
#[then(expr = "the workspace vCard should contain {string}")]
217+
async fn then_workspace_vcard_should_contain(
218+
world: &mut TestWorld,
219+
pattern: String,
220+
) -> Result<(), Error> {
221+
let prose_xmpp_vcard4 = world
222+
.workspace_service()
223+
.await
224+
.get_workspace_vcard()
225+
.await?;
226+
let vcard = prose_xmpp_vcard4_to_vcard4_vcard(prose_xmpp_vcard4).unwrap();
227+
assert!(vcard.to_string().contains(&pattern), "vcard={vcard}");
228+
Ok(())
229+
}

crates/rest-api/tests/prelude/mocks/mock_auth_service.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ impl MockAuthService {
4747
pub fn log_in_unchecked(&self, jid: &BareJid) -> Result<AuthToken, auth_service::Error> {
4848
let json = serde_json::to_string(&UserInfo { jid: jid.clone() }).unwrap();
4949
let base64 = Base64.encode(json);
50-
let token = SecretString::new(base64);
50+
let token = SecretString::from(base64);
5151

5252
Ok(AuthToken(token))
5353
}

crates/rest-api/tests/prelude/test_world.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
use std::{
77
collections::HashMap,
88
path::Path,
9-
str::FromStr as _,
109
sync::{Arc, RwLock, RwLockReadGuard, RwLockWriteGuard},
1110
};
1211

@@ -119,7 +118,6 @@ impl TestWorld {
119118

120119
pub async fn workspace_service(&self) -> WorkspaceService {
121120
WorkspaceService::new(
122-
Arc::new(self.db().clone()),
123121
Arc::new(self.xmpp_service.clone()),
124122
Arc::new(self.app_config.clone()),
125123
&self
@@ -198,7 +196,7 @@ impl TestWorld {
198196
impl TestWorld {
199197
async fn new() -> Self {
200198
// NOTE: Behavior tests don't need to read the environment, therefore we have to set the required variables.
201-
let api_xmpp_password = SecretString::from_str("anything").unwrap();
199+
let api_xmpp_password = SecretString::from("anything");
202200
std::env::set_var(
203201
"PROSE_BOOTSTRAP__PROSE_POD_API_XMPP_PASSWORD",
204202
&api_xmpp_password.expose_secret(),

0 commit comments

Comments
 (0)