Skip to content

Commit d350041

Browse files
authored
feat!: Add update-secret to the connection (#155)
One more function had to be added to the ConnectionCallback
1 parent 30381c4 commit d350041

File tree

7 files changed

+97
-1
lines changed

7 files changed

+97
-1
lines changed

amqprs/src/api/callbacks.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,9 @@ pub trait ConnectionCallback {
5454

5555
/// Callback to handle connection `unblocked` indication from server
5656
async fn unblocked(&mut self, connection: &Connection);
57+
58+
/// Callback to handle secret updated indication from server
59+
async fn secret_updated(&mut self, connection: &Connection);
5760
}
5861

5962
/// Default type that implements `ConnectionCallback`.
@@ -87,6 +90,14 @@ impl ConnectionCallback for DefaultConnectionCallback {
8790
connection
8891
);
8992
}
93+
94+
async fn secret_updated(&mut self, connection: &Connection) {
95+
#[cfg(feature = "traces")]
96+
info!(
97+
"handle secret updated notification for connection {}",
98+
connection
99+
);
100+
}
90101
}
91102

92103
/////////////////////////////////////////////////////////////////////////////

amqprs/src/api/connection.rs

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,8 @@ use tokio::sync::{broadcast, mpsc, oneshot};
5050
use crate::{
5151
frame::{
5252
Blocked, Close, CloseOk, Frame, MethodHeader, Open, OpenChannel, OpenChannelOk,
53-
ProtocolHeader, StartOk, TuneOk, Unblocked, DEFAULT_CONN_CHANNEL, FRAME_MIN_SIZE,
53+
ProtocolHeader, StartOk, TuneOk, Unblocked, UpdateSecret, UpdateSecretOk,
54+
DEFAULT_CONN_CHANNEL, FRAME_MIN_SIZE,
5455
},
5556
net::{
5657
ChannelResource, ConnManagementCommand, IncomingMessage, OutgoingMessage, ReaderHandler,
@@ -1244,6 +1245,32 @@ impl Connection {
12441245
let mut shutdown_listener = self.shared.shutdown_subscriber.subscribe();
12451246
(shutdown_listener.recv().await).unwrap_or(false)
12461247
}
1248+
1249+
/// Update the secret used by some authentication module such as OAuth2.
1250+
///
1251+
/// # Errors
1252+
///
1253+
/// Returns error if fails to send indication to server.
1254+
pub async fn update_secret(&self, new_secret: &str, reason: &str) -> Result<()> {
1255+
let responder_rx = self
1256+
.register_responder(DEFAULT_CONN_CHANNEL, UpdateSecretOk::header())
1257+
.await?;
1258+
1259+
let update_secret = UpdateSecret::new(
1260+
new_secret.to_owned().try_into().unwrap(),
1261+
reason.to_owned().try_into().unwrap(),
1262+
);
1263+
1264+
synchronous_request!(
1265+
self.shared.outgoing_tx,
1266+
(DEFAULT_CONN_CHANNEL, update_secret.into_frame()),
1267+
responder_rx,
1268+
Frame::UpdateSecretOk,
1269+
Error::UpdateSecretError
1270+
)?;
1271+
1272+
Ok(())
1273+
}
12471274
}
12481275

12491276
impl Drop for DropGuard {

amqprs/src/api/error.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ pub enum Error {
3030
/// Error in sending or receiving messages via internal communication channel.
3131
/// Usually due to incorrect usage by user.
3232
InternalChannelError(String),
33+
/// Error during updating the secret
34+
UpdateSecretError(String),
3335
}
3436

3537
#[cfg(feature = "urispec")]
@@ -71,6 +73,7 @@ impl fmt::Display for Error {
7173
Error::InternalChannelError(msg) => {
7274
write!(f, "AMQP internal communication error: {}", msg)
7375
}
76+
Error::UpdateSecretError(msg) => write!(f, "AMQP update secret error: {}", msg),
7477
}
7578
}
7679
}

amqprs/src/frame/method/connection.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,5 +219,11 @@ pub struct UpdateSecret {
219219
pub(crate) reason: ShortStr,
220220
}
221221

222+
impl UpdateSecret {
223+
pub fn new(new_secret: LongStr, reason: ShortStr) -> Self {
224+
Self { new_secret, reason }
225+
}
226+
}
227+
222228
#[derive(Debug, Serialize, Deserialize, Default)]
223229
pub struct UpdateSecretOk;

amqprs/src/net/reader_handler.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,20 @@ impl ReaderHandler {
190190
}
191191
Ok(())
192192
}
193+
Frame::UpdateSecretOk(method_header, update_secret_ok) => {
194+
let responder = self
195+
.channel_manager
196+
.remove_responder(&channel_id, method_header)
197+
.expect("responder must be registered");
198+
responder
199+
.send(update_secret_ok.into_frame())
200+
.map_err(|err_frame| {
201+
Error::SyncChannel(format!(
202+
"failed to forward {} to connection {}",
203+
err_frame, self.amqp_connection
204+
))
205+
})
206+
}
193207
// dispatch other frames to channel dispatcher
194208
_ => {
195209
let dispatcher = self.channel_manager.get_dispatcher(&channel_id);

amqprs/tests/test_update_secret.rs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
use amqprs::{
2+
callbacks::{DefaultChannelCallback, DefaultConnectionCallback},
3+
connection::Connection,
4+
};
5+
mod common;
6+
7+
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
8+
async fn test_update_secret() {
9+
common::setup_logging();
10+
11+
// open a connection to RabbitMQ server
12+
let args = common::build_conn_args();
13+
14+
let connection = Connection::open(&args).await.unwrap();
15+
connection
16+
.register_callback(DefaultConnectionCallback)
17+
.await
18+
.unwrap();
19+
// open a channel on the connection
20+
let channel = connection.open_channel(None).await.unwrap();
21+
channel
22+
.register_callback(DefaultChannelCallback)
23+
.await
24+
.unwrap();
25+
26+
connection
27+
.update_secret("123456", "secret expired")
28+
.await
29+
.unwrap();
30+
31+
// close
32+
channel.close().await.unwrap();
33+
connection.close().await.unwrap();
34+
}

examples/src/callbacks_impl.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ impl ConnectionCallback for ExampleConnectionCallback {
2323

2424
async fn blocked(&mut self, connection: &Connection, reason: String) {}
2525
async fn unblocked(&mut self, connection: &Connection) {}
26+
async fn secret_updated(&mut self, connection: &Connection) {}
2627
}
2728

2829
////////////////////////////////////////////////////////////////////////////////

0 commit comments

Comments
 (0)