Skip to content

Commit 46d4ab9

Browse files
committed
Implement request topic validation
1 parent 4c1b98a commit 46d4ab9

File tree

3 files changed

+181
-3
lines changed

3 files changed

+181
-3
lines changed

up-subscription/src/handlers/subscribe.rs

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,11 @@ impl RequestHandler for SubscriptionRequestHandler {
5959
));
6060
};
6161

62+
// [impl->dsn~usubscription-subscribe-invalid-topic~1]
63+
helpers::validate_uri(topic).map_err(|e| {
64+
ServiceInvocationError::InvalidArgument(format!("Invalid topic uri '{topic}': {e}"))
65+
})?;
66+
6267
// Provisionally compute milliseconds to subscription expiry, from protobuf.google.Timestamp input in second granularity (we ignore the nanos).
6368
// Likely to change in the future, when we get rid of the protobuf.google.Timestamp type and track in milliseconds throughought.
6469
let expiry: Option<usubscription::ExpiryTimestamp> =
@@ -117,8 +122,10 @@ impl RequestHandler for SubscriptionRequestHandler {
117122
#[cfg(test)]
118123
mod tests {
119124
use super::*;
125+
use test_case::test_case;
120126
use tokio::sync::mpsc::{self};
121-
use up_rust::core::usubscription::State;
127+
128+
use up_rust::{core::usubscription::State, UUri};
122129

123130
use crate::{helpers, tests::test_lib};
124131

@@ -387,4 +394,54 @@ mod tests {
387394

388395
assert!(result.is_err_and(|e| matches!(e, ServiceInvocationError::InvalidArgument(_))));
389396
}
397+
398+
// [utest->dsn~usubscription-subscribe-invalid-topic~1]
399+
#[test_case(UUri::default(); "Bad topic UUri")]
400+
#[test_case(UUri {
401+
authority_name: String::from("*"),
402+
ue_id: test_lib::helpers::TOPIC_LOCAL1_ID,
403+
ue_version_major: test_lib::helpers::TOPIC_LOCAL1_VERSION as u32,
404+
resource_id: test_lib::helpers::TOPIC_LOCAL1_RESOURCE as u32,
405+
..Default::default()
406+
}; "Wildcard authority in topic UUri")]
407+
#[test_case(UUri {
408+
authority_name: test_lib::helpers::LOCAL_AUTHORITY.into(),
409+
ue_id: 0xFFFF_0000,
410+
ue_version_major: test_lib::helpers::TOPIC_LOCAL1_VERSION as u32,
411+
resource_id: test_lib::helpers::TOPIC_LOCAL1_RESOURCE as u32,
412+
..Default::default()
413+
}; "Wildcard entity id in topic UUri")]
414+
#[test_case(UUri {
415+
authority_name: test_lib::helpers::LOCAL_AUTHORITY.into(),
416+
ue_id: test_lib::helpers::TOPIC_LOCAL1_ID,
417+
ue_version_major: test_lib::helpers::TOPIC_LOCAL1_VERSION as u32,
418+
resource_id: 0x0000_FFFF,
419+
..Default::default()
420+
}; "Wildcard resource id in topic UUri")]
421+
#[tokio::test]
422+
async fn test_invalid_topic_uri(topic: UUri) {
423+
helpers::init_once();
424+
425+
// create request and other required object(s)
426+
let subscribe_request = test_lib::helpers::subscription_request(topic, None);
427+
let request_payload = UPayload::try_from_protobuf(subscribe_request.clone()).unwrap();
428+
let message_attributes = UAttributes {
429+
source: Some(test_lib::helpers::subscriber_uri1()).into(),
430+
..Default::default()
431+
};
432+
let (subscription_sender, _) = mpsc::channel::<SubscriptionEvent>(1);
433+
434+
// create handler and perform tested operation
435+
let request_handler = SubscriptionRequestHandler::new(subscription_sender);
436+
437+
let result = request_handler
438+
.handle_request(
439+
up_rust::core::usubscription::RESOURCE_ID_SUBSCRIBE,
440+
&message_attributes,
441+
Some(request_payload),
442+
)
443+
.await;
444+
445+
assert!(result.is_err_and(|err| matches!(err, ServiceInvocationError::InvalidArgument(_))));
446+
}
390447
}

up-subscription/src/handlers/unregister_for_notifications.rs

Lines changed: 65 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,13 +46,24 @@ impl RequestHandler for UnregisterNotificationsRequestHandler {
4646
request_payload: Option<UPayload>,
4747
) -> Result<Option<UPayload>, ServiceInvocationError> {
4848
// [impl->dsn~usubscription-unregister-notifications-protobuf~1]
49-
let (_subscription_request, source) = helpers::extract_inputs::<NotificationsRequest>(
49+
let (notification_request, source) = helpers::extract_inputs::<NotificationsRequest>(
5050
RESOURCE_ID_UNREGISTER_FOR_NOTIFICATIONS,
5151
resource_id,
5252
&request_payload,
5353
message_attributes,
5454
)?;
5555

56+
let Some(topic) = notification_request.topic.as_ref() else {
57+
return Err(ServiceInvocationError::InvalidArgument(
58+
"No topic defined in request".to_string(),
59+
));
60+
};
61+
62+
// [impl->dsn~usubscription-unregister-notifications-invalid-topic~1]
63+
helpers::validate_uri(topic).map_err(|e| {
64+
ServiceInvocationError::InvalidArgument(format!("Invalid topic uri '{topic}': {e}"))
65+
})?;
66+
5667
// Interact with notification manager backend
5768
let se = NotificationEvent::RemoveNotifyee {
5869
subscriber: source.clone(),
@@ -78,8 +89,11 @@ impl RequestHandler for UnregisterNotificationsRequestHandler {
7889
#[cfg(test)]
7990
mod tests {
8091
use super::*;
92+
use test_case::test_case;
8193
use tokio::sync::mpsc::{self};
8294

95+
use up_rust::UUri;
96+
8397
use crate::{helpers, tests::test_lib};
8498

8599
// [utest->dsn~usubscription-unregister-notifications-protobuf~1]
@@ -236,4 +250,54 @@ mod tests {
236250

237251
assert!(result.is_err_and(|err| matches!(err, ServiceInvocationError::InvalidArgument(_))));
238252
}
253+
254+
// [utest->dsn~usubscription-unregister-notifications-invalid-topic~1]
255+
#[test_case(UUri::default(); "Bad topic UUri")]
256+
#[test_case(UUri {
257+
authority_name: String::from("*"),
258+
ue_id: test_lib::helpers::TOPIC_LOCAL1_ID,
259+
ue_version_major: test_lib::helpers::TOPIC_LOCAL1_VERSION as u32,
260+
resource_id: test_lib::helpers::TOPIC_LOCAL1_RESOURCE as u32,
261+
..Default::default()
262+
}; "Wildcard authority in topic UUri")]
263+
#[test_case(UUri {
264+
authority_name: test_lib::helpers::LOCAL_AUTHORITY.into(),
265+
ue_id: 0xFFFF_0000,
266+
ue_version_major: test_lib::helpers::TOPIC_LOCAL1_VERSION as u32,
267+
resource_id: test_lib::helpers::TOPIC_LOCAL1_RESOURCE as u32,
268+
..Default::default()
269+
}; "Wildcard entity id in topic UUri")]
270+
#[test_case(UUri {
271+
authority_name: test_lib::helpers::LOCAL_AUTHORITY.into(),
272+
ue_id: test_lib::helpers::TOPIC_LOCAL1_ID,
273+
ue_version_major: test_lib::helpers::TOPIC_LOCAL1_VERSION as u32,
274+
resource_id: 0x0000_FFFF,
275+
..Default::default()
276+
}; "Wildcard resource id in topic UUri")]
277+
#[tokio::test]
278+
async fn test_invalid_topic_uri(topic: UUri) {
279+
helpers::init_once();
280+
281+
// create request and other required object(s)
282+
let subscribe_request = test_lib::helpers::subscription_request(topic, None);
283+
let request_payload = UPayload::try_from_protobuf(subscribe_request.clone()).unwrap();
284+
let message_attributes = UAttributes {
285+
source: Some(test_lib::helpers::subscriber_uri1()).into(),
286+
..Default::default()
287+
};
288+
let (subscription_sender, _) = mpsc::channel::<NotificationEvent>(1);
289+
290+
// create handler and perform tested operation
291+
let request_handler = UnregisterNotificationsRequestHandler::new(subscription_sender);
292+
293+
let result = request_handler
294+
.handle_request(
295+
up_rust::core::usubscription::RESOURCE_ID_UNREGISTER_FOR_NOTIFICATIONS,
296+
&message_attributes,
297+
Some(request_payload),
298+
)
299+
.await;
300+
301+
assert!(result.is_err_and(|err| matches!(err, ServiceInvocationError::InvalidArgument(_))));
302+
}
239303
}

up-subscription/src/handlers/unsubscribe.rs

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,11 @@ impl RequestHandler for UnubscribeRequestHandler {
5858
));
5959
};
6060

61+
// [impl->dsn~usubscription-unsubscribe-invalid-topic~1]
62+
helpers::validate_uri(topic).map_err(|e| {
63+
ServiceInvocationError::InvalidArgument(format!("Invalid topic uri '{topic}': {e}"))
64+
})?;
65+
6166
let (respond_to, receive_from) = oneshot::channel::<SubscriptionStatus>();
6267
let se = SubscriptionEvent::RemoveSubscription {
6368
subscriber: source.clone(),
@@ -91,8 +96,10 @@ impl RequestHandler for UnubscribeRequestHandler {
9196
#[cfg(test)]
9297
mod tests {
9398
use super::*;
99+
use test_case::test_case;
94100
use tokio::sync::mpsc::{self};
95-
use up_rust::core::usubscription::State;
101+
102+
use up_rust::{core::usubscription::State, UUri};
96103

97104
use crate::{helpers, tests::test_lib};
98105

@@ -258,4 +265,54 @@ mod tests {
258265

259266
assert!(result.is_err_and(|err| matches!(err, ServiceInvocationError::InvalidArgument(_))));
260267
}
268+
269+
// [utest->dsn~usubscription-unsubscribe-invalid-topic~1]
270+
#[test_case(UUri::default(); "Bad topic UUri")]
271+
#[test_case(UUri {
272+
authority_name: String::from("*"),
273+
ue_id: test_lib::helpers::TOPIC_LOCAL1_ID,
274+
ue_version_major: test_lib::helpers::TOPIC_LOCAL1_VERSION as u32,
275+
resource_id: test_lib::helpers::TOPIC_LOCAL1_RESOURCE as u32,
276+
..Default::default()
277+
}; "Wildcard authority in topic UUri")]
278+
#[test_case(UUri {
279+
authority_name: test_lib::helpers::LOCAL_AUTHORITY.into(),
280+
ue_id: 0xFFFF_0000,
281+
ue_version_major: test_lib::helpers::TOPIC_LOCAL1_VERSION as u32,
282+
resource_id: test_lib::helpers::TOPIC_LOCAL1_RESOURCE as u32,
283+
..Default::default()
284+
}; "Wildcard entity id in topic UUri")]
285+
#[test_case(UUri {
286+
authority_name: test_lib::helpers::LOCAL_AUTHORITY.into(),
287+
ue_id: test_lib::helpers::TOPIC_LOCAL1_ID,
288+
ue_version_major: test_lib::helpers::TOPIC_LOCAL1_VERSION as u32,
289+
resource_id: 0x0000_FFFF,
290+
..Default::default()
291+
}; "Wildcard resource id in topic UUri")]
292+
#[tokio::test]
293+
async fn test_invalid_topic_uri(topic: UUri) {
294+
helpers::init_once();
295+
296+
// create request and other required object(s)
297+
let subscribe_request = test_lib::helpers::subscription_request(topic, None);
298+
let request_payload = UPayload::try_from_protobuf(subscribe_request.clone()).unwrap();
299+
let message_attributes = UAttributes {
300+
source: Some(test_lib::helpers::subscriber_uri1()).into(),
301+
..Default::default()
302+
};
303+
let (subscription_sender, _) = mpsc::channel::<SubscriptionEvent>(1);
304+
305+
// create handler and perform tested operation
306+
let request_handler = UnubscribeRequestHandler::new(subscription_sender);
307+
308+
let result = request_handler
309+
.handle_request(
310+
up_rust::core::usubscription::RESOURCE_ID_UNSUBSCRIBE,
311+
&message_attributes,
312+
Some(request_payload),
313+
)
314+
.await;
315+
316+
assert!(result.is_err_and(|err| matches!(err, ServiceInvocationError::InvalidArgument(_))));
317+
}
261318
}

0 commit comments

Comments
 (0)