kafrust_protocol/api/
alter_user_scram_credentials.rs1use crate::codec::{Decoder, Encoder};
2use crate::error::Result;
3use crate::header::RequestHeader;
4
5pub const API_KEY: i16 = 51;
6
7#[derive(Debug, Clone, PartialEq, Eq)]
8pub struct AlterUserScramCredentialsRequestV0 {
9 pub correlation_id: i32,
10 pub client_id: Option<String>,
11 pub deletions: Vec<AlterUserScramCredentialsDeletionV0>,
12 pub upsertions: Vec<AlterUserScramCredentialsUpsertionV0>,
13}
14
15impl AlterUserScramCredentialsRequestV0 {
16 pub fn encode(&self) -> Result<Vec<u8>> {
17 let mut encoder = Encoder::new();
18 RequestHeader {
19 api_key: API_KEY,
20 api_version: 0,
21 correlation_id: self.correlation_id,
22 client_id: self.client_id.clone(),
23 }
24 .encode_v2(&mut encoder)?;
25 encoder.write_compact_array(Some(&self.deletions), |encoder, deletion| {
26 encoder.write_compact_string(&deletion.name)?;
27 encoder.write_i8(deletion.mechanism);
28 encoder.write_empty_tagged_fields();
29 Ok(())
30 })?;
31 encoder.write_compact_array(Some(&self.upsertions), |encoder, upsertion| {
32 encoder.write_compact_string(&upsertion.name)?;
33 encoder.write_i8(upsertion.mechanism);
34 encoder.write_i32(upsertion.iterations);
35 encoder.write_compact_bytes(&upsertion.salt)?;
36 encoder.write_compact_bytes(&upsertion.salted_password)?;
37 encoder.write_empty_tagged_fields();
38 Ok(())
39 })?;
40 encoder.write_empty_tagged_fields();
41 Ok(encoder.into_bytes())
42 }
43}
44
45#[derive(Debug, Clone, PartialEq, Eq)]
46pub struct AlterUserScramCredentialsDeletionV0 {
47 pub name: String,
48 pub mechanism: i8,
49}
50
51#[derive(Debug, Clone, PartialEq, Eq)]
52pub struct AlterUserScramCredentialsUpsertionV0 {
53 pub name: String,
54 pub mechanism: i8,
55 pub iterations: i32,
56 pub salt: Vec<u8>,
57 pub salted_password: Vec<u8>,
58}
59
60#[derive(Debug, Clone, PartialEq, Eq)]
61pub struct AlterUserScramCredentialsResponseV0 {
62 pub throttle_time_ms: i32,
63 pub results: Vec<AlterUserScramCredentialsResultV0>,
64}
65
66impl AlterUserScramCredentialsResponseV0 {
67 pub fn decode_body(decoder: &mut Decoder<'_>) -> Result<Self> {
68 let throttle_time_ms = decoder.read_i32()?;
69 let results = decoder
70 .read_compact_array(
71 "alter user SCRAM credential results",
72 AlterUserScramCredentialsResultV0::decode,
73 )?
74 .unwrap_or_default();
75 decoder.read_tagged_fields()?;
76 Ok(Self {
77 throttle_time_ms,
78 results,
79 })
80 }
81}
82
83#[derive(Debug, Clone, PartialEq, Eq)]
84pub struct AlterUserScramCredentialsResultV0 {
85 pub user: String,
86 pub error_code: i16,
87 pub error_message: Option<String>,
88}
89
90impl AlterUserScramCredentialsResultV0 {
91 fn decode(decoder: &mut Decoder<'_>) -> Result<Self> {
92 let user = decoder.read_compact_string()?;
93 let error_code = decoder.read_i16()?;
94 let error_message = decoder.read_compact_nullable_string()?;
95 decoder.read_tagged_fields()?;
96 Ok(Self {
97 user,
98 error_code,
99 error_message,
100 })
101 }
102}
103
104#[cfg(test)]
105#[allow(clippy::unwrap_used)]
106mod tests {
107 use super::{
108 AlterUserScramCredentialsDeletionV0, AlterUserScramCredentialsRequestV0,
109 AlterUserScramCredentialsResponseV0, AlterUserScramCredentialsUpsertionV0, API_KEY,
110 };
111 use crate::codec::{Decoder, Encoder};
112
113 #[test]
114 fn encodes_alter_user_scram_credentials_v0_request() {
115 let request = AlterUserScramCredentialsRequestV0 {
116 correlation_id: 29,
117 client_id: None,
118 deletions: vec![AlterUserScramCredentialsDeletionV0 {
119 name: "alice".to_owned(),
120 mechanism: 1,
121 }],
122 upsertions: vec![AlterUserScramCredentialsUpsertionV0 {
123 name: "bob".to_owned(),
124 mechanism: 2,
125 iterations: 4096,
126 salt: vec![1, 2, 3],
127 salted_password: vec![4, 5, 6],
128 }],
129 };
130
131 let bytes = request.encode().unwrap();
132 assert_eq!(&bytes[0..4], &[0, API_KEY as u8, 0, 0]);
133 assert_eq!(&bytes[4..8], &[0, 0, 0, 29]);
134 assert_eq!(bytes[bytes.len() - 2..], [0, 0]);
135 }
136
137 #[test]
138 fn decodes_alter_user_scram_credentials_v0_response() {
139 let mut bytes = Encoder::new();
140 bytes.write_i32(4);
141 bytes.write_unsigned_varint(2); bytes.write_compact_string("alice").unwrap();
143 bytes.write_i16(31);
144 bytes.write_compact_nullable_string(Some("denied")).unwrap();
145 bytes.write_empty_tagged_fields();
146 bytes.write_empty_tagged_fields();
147 let bytes = bytes.into_bytes();
148 let mut decoder = Decoder::new(&bytes);
149
150 let response = AlterUserScramCredentialsResponseV0::decode_body(&mut decoder).unwrap();
151
152 assert_eq!(response.throttle_time_ms, 4);
153 assert_eq!(response.results[0].user, "alice");
154 assert_eq!(response.results[0].error_code, 31);
155 assert_eq!(response.results[0].error_message.as_deref(), Some("denied"));
156 assert!(decoder.is_empty());
157 }
158}