Skip to content

Commit

Permalink
Use case-sensitive names for resources such as streams, topics, users…
Browse files Browse the repository at this point in the history
… etc. (#1482)

Remove the existing convention which would rename the received resourcename to lowercase, replace whitespace characters with dots etc. - let the user decide and be responsible for naming the things.
  • Loading branch information
spetz authored Feb 3, 2025
1 parent 70b44e6 commit d16a15f
Show file tree
Hide file tree
Showing 21 changed files with 62 additions and 144 deletions.
6 changes: 2 additions & 4 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 1 addition & 3 deletions sdk/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "iggy"
version = "0.6.93"
version = "0.6.100"
description = "Iggy is the persistent message streaming platform written in Rust, supporting QUIC, TCP and HTTP transport protocols, capable of processing millions of messages per second."
edition = "2021"
license = "Apache-2.0"
Expand Down Expand Up @@ -41,10 +41,8 @@ keyring = { version = "3.6.1", optional = true, features = [
"sync-secret-service",
"vendored",
] }
lazy_static = "1.5.0"
passterm = { version = "2.0.1", optional = true }
quinn = { version = "0.11.6" }
regex = "1.11.1"
reqwest = { version = "0.12.12", default-features = false, features = [
"json",
"rustls-tls",
Expand Down
7 changes: 1 addition & 6 deletions sdk/src/consumer_groups/create_consumer_group.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ use crate::consumer_groups::MAX_NAME_LENGTH;
use crate::error::IggyError;
use crate::identifier::Identifier;
use crate::utils::sizeable::Sizeable;
use crate::utils::text;
use crate::validatable::Validatable;
use bytes::{BufMut, Bytes, BytesMut};
use serde::{Deserialize, Serialize};
Expand All @@ -16,7 +15,7 @@ use std::str::from_utf8;
/// - `stream_id` - unique stream ID (numeric or name).
/// - `topic_id` - unique topic ID (numeric or name).
/// - `group_id` - unique consumer group ID.
/// - `name` - unique consumer group name, max length is 255 characters. The name will be always converted to lowercase and all whitespaces will be replaced with dots.
/// - `name` - unique consumer group name, max length is 255 characters.
#[derive(Debug, Serialize, Deserialize, PartialEq)]
pub struct CreateConsumerGroup {
/// Unique stream ID (numeric or name).
Expand Down Expand Up @@ -60,10 +59,6 @@ impl Validatable<IggyError> for CreateConsumerGroup {
return Err(IggyError::InvalidConsumerGroupName);
}

if !text::is_resource_name_valid(&self.name) {
return Err(IggyError::InvalidConsumerGroupName);
}

Ok(())
}
}
Expand Down
4 changes: 1 addition & 3 deletions sdk/src/identifier.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ use crate::bytes_serializable::BytesSerializable;
use crate::error::IggyError;
use crate::utils::byte_size::IggyByteSize;
use crate::utils::sizeable::Sizeable;
use crate::utils::text::to_lowercase_non_whitespace;
use crate::validatable::Validatable;
use bytes::{BufMut, Bytes, BytesMut};
use serde::{Deserialize, Serialize};
Expand Down Expand Up @@ -151,14 +150,13 @@ impl Identifier {
})
}

/// Creates a new identifier from the given string value. The name will always be converted to lowercase and all whitespaces will be replaced with dots.
/// Creates a new identifier from the given string value.
pub fn named(value: &str) -> Result<Self, IggyError> {
let length = value.len();
if length == 0 || length > 255 {
return Err(IggyError::InvalidIdentifier);
}

let value = to_lowercase_non_whitespace(value);
Ok(Self {
kind: IdKind::String,
#[allow(clippy::cast_possible_truncation)]
Expand Down
8 changes: 4 additions & 4 deletions sdk/src/models/topic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ use serde::{Deserialize, Serialize};
/// - `created_at`: the timestamp when the topic was created.
/// - `name`: the unique name of the topic.
/// - `size`: the total size of the topic in bytes.
/// - `message_expiry`: the optional expiry of the messages in the topic in seconds.
/// - `max_topic_size`: the optional maximum size of the topic in bytes.
/// - `message_expiry`: the expiry of the messages in the topic.
/// - `max_topic_size`: the maximum size of the topic.
/// - `replication_factor`: replication factor for the topic.
/// - `messages_count`: the total number of messages in the topic.
/// - `partitions_count`: the total number of partitions in the topic.
Expand Down Expand Up @@ -48,8 +48,8 @@ pub struct Topic {
/// - `created_at`: the timestamp when the topic was created.
/// - `name`: the unique name of the topic.
/// - `size`: the total size of the topic.
/// - `message_expiry`: the optional expiry of the messages in the topic in seconds.
/// - `max_topic_size`: the optional maximum size of the topic.
/// - `message_expiry`: the expiry of the messages in the topic.
/// - `max_topic_size`: the maximum size of the topic.
/// - `replication_factor`: replication factor for the topic.
/// - `messages_count`: the total number of messages in the topic.
/// - `partitions_count`: the total number of partitions in the topic.
Expand Down
11 changes: 3 additions & 8 deletions sdk/src/personal_access_tokens/create_personal_access_token.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ use crate::command::{Command, CREATE_PERSONAL_ACCESS_TOKEN_CODE};
use crate::error::IggyError;
use crate::users::defaults::*;
use crate::utils::expiry::IggyExpiry;
use crate::utils::text;
use crate::validatable::Validatable;
use bytes::{BufMut, Bytes, BytesMut};
use serde::{Deserialize, Serialize};
Expand All @@ -12,13 +11,13 @@ use std::str::from_utf8;

/// `CreatePersonalAccessToken` command is used to create a new personal access token for the authenticated user.
/// It has additional payload:
/// - `name` - unique name of the token, must be between 3 and 30 characters long. The name will be always converted to lowercase and all whitespaces will be replaced with dots.
/// - `expiry` - expiry in seconds (optional), if provided, must be between 1 and 4294967295. Otherwise, the token will never expire.
/// - `name` - unique name of the token, must be between 3 and 30 characters long.
/// - `expiry` - expiry of the token.
#[derive(Debug, Serialize, Deserialize, PartialEq)]
pub struct CreatePersonalAccessToken {
/// Unique name of the token, must be between 3 and 30 characters long.
pub name: String,
/// Expiry in seconds (optional), if provided, must be between 1 and 4294967295. Otherwise, the token will never expire.
/// Expiry of the token.
pub expiry: IggyExpiry,
}

Expand Down Expand Up @@ -46,10 +45,6 @@ impl Validatable<IggyError> for CreatePersonalAccessToken {
return Err(IggyError::InvalidPersonalAccessTokenName);
}

if !text::is_resource_name_valid(&self.name) {
return Err(IggyError::InvalidPersonalAccessTokenName);
}

Ok(())
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ use crate::bytes_serializable::BytesSerializable;
use crate::command::{Command, DELETE_PERSONAL_ACCESS_TOKEN_CODE};
use crate::error::IggyError;
use crate::users::defaults::*;
use crate::utils::text;
use crate::validatable::Validatable;
use bytes::{BufMut, Bytes, BytesMut};
use serde::{Deserialize, Serialize};
Expand All @@ -11,7 +10,7 @@ use std::str::from_utf8;

/// `DeletePersonalAccessToken` command is used to delete a personal access token for the authenticated user.
/// It has additional payload:
/// - `name` - unique name of the token, must be between 3 and 30 characters long. The name will be always converted to lowercase and all whitespaces will be replaced with dots.
/// - `name` - unique name of the token, must be between 3 and 30 characters long.
#[derive(Debug, Serialize, Deserialize, PartialEq)]
pub struct DeletePersonalAccessToken {
/// Unique name of the token, must be between 3 and 30 characters long.
Expand Down Expand Up @@ -41,10 +40,6 @@ impl Validatable<IggyError> for DeletePersonalAccessToken {
return Err(IggyError::InvalidPersonalAccessTokenName);
}

if !text::is_resource_name_valid(&self.name) {
return Err(IggyError::InvalidPersonalAccessTokenName);
}

Ok(())
}
}
Expand Down
7 changes: 1 addition & 6 deletions sdk/src/streams/create_stream.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ use crate::bytes_serializable::BytesSerializable;
use crate::command::{Command, CREATE_STREAM_CODE};
use crate::error::IggyError;
use crate::streams::MAX_NAME_LENGTH;
use crate::utils::text;
use crate::validatable::Validatable;
use bytes::{BufMut, Bytes, BytesMut};
use serde::{Deserialize, Serialize};
Expand All @@ -12,7 +11,7 @@ use std::str::from_utf8;
/// `CreateStream` command is used to create a new stream.
/// It has additional payload:
/// - `stream_id` - unique stream ID (numeric)
/// - `name` - unique stream name (string), max length is 255 characters. The name will be always converted to lowercase and all whitespaces will be replaced with dots.
/// - `name` - unique stream name (string), max length is 255 characters.
#[derive(Debug, Serialize, Deserialize, PartialEq)]
pub struct CreateStream {
/// Unique stream ID (numeric), if None is provided then the server will automatically assign it.
Expand Down Expand Up @@ -48,10 +47,6 @@ impl Validatable<IggyError> for CreateStream {
return Err(IggyError::InvalidStreamName);
}

if !text::is_resource_name_valid(&self.name) {
return Err(IggyError::InvalidStreamName);
}

Ok(())
}
}
Expand Down
5 changes: 0 additions & 5 deletions sdk/src/streams/update_stream.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ use crate::error::IggyError;
use crate::identifier::Identifier;
use crate::streams::MAX_NAME_LENGTH;
use crate::utils::sizeable::Sizeable;
use crate::utils::text;
use crate::validatable::Validatable;
use bytes::{BufMut, Bytes, BytesMut};
use serde::{Deserialize, Serialize};
Expand Down Expand Up @@ -45,10 +44,6 @@ impl Validatable<IggyError> for UpdateStream {
return Err(IggyError::InvalidStreamName);
}

if !text::is_resource_name_valid(&self.name) {
return Err(IggyError::InvalidStreamName);
}

Ok(())
}
}
Expand Down
16 changes: 6 additions & 10 deletions sdk/src/topics/create_topic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ use crate::identifier::Identifier;
use crate::topics::{MAX_NAME_LENGTH, MAX_PARTITIONS_COUNT};
use crate::utils::expiry::IggyExpiry;
use crate::utils::sizeable::Sizeable;
use crate::utils::text;
use crate::utils::topic_size::MaxTopicSize;
use crate::validatable::Validatable;
use bytes::{BufMut, Bytes, BytesMut};
Expand All @@ -19,11 +18,11 @@ use std::str::from_utf8;
/// - `stream_id` - unique stream ID (numeric or name).
/// - `topic_id` - unique topic ID (numeric).
/// - `partitions_count` - number of partitions in the topic, max value is 1000.
/// - `message_expiry` - optional message expiry in seconds, if `None` then messages will never expire.
/// - `max_topic_size` - optional maximum size of the topic, if `None` then topic size is unlimited.
/// - `message_expiry` - message expiry, if `NeverExpire` then messages will never expire.
/// - `max_topic_size` - maximum size of the topic, if `Unlimited` then topic size is unlimited.
/// Can't be lower than segment size in the config.
/// - `replication_factor` - replication factor for the topic.
/// - `name` - unique topic name, max length is 255 characters. The name will be always converted to lowercase and all whitespaces will be replaced with dots.
/// - `name` - unique topic name, max length is 255 characters.
#[derive(Debug, Serialize, Deserialize, PartialEq)]
pub struct CreateTopic {
/// Unique stream ID (numeric or name).
Expand All @@ -35,9 +34,10 @@ pub struct CreateTopic {
pub partitions_count: u32,
/// Compression algorithm for the topic.
pub compression_algorithm: CompressionAlgorithm,
/// Optional message expiry.
/// Message expiry, if `NeverExpire` then messages will never expire.
pub message_expiry: IggyExpiry,
/// The maximum size of the topic.
/// Max topic size, if `Unlimited` then topic size is unlimited.
/// Can't be lower than segment size in the config.
pub max_topic_size: MaxTopicSize,
/// Replication factor for the topic.
pub replication_factor: Option<u8>,
Expand Down Expand Up @@ -78,10 +78,6 @@ impl Validatable<IggyError> for CreateTopic {
return Err(IggyError::InvalidTopicName);
}

if !text::is_resource_name_valid(&self.name) {
return Err(IggyError::InvalidTopicName);
}

if !(0..=MAX_PARTITIONS_COUNT).contains(&self.partitions_count) {
return Err(IggyError::TooManyPartitions);
}
Expand Down
13 changes: 4 additions & 9 deletions sdk/src/topics/update_topic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ use crate::identifier::Identifier;
use crate::topics::MAX_NAME_LENGTH;
use crate::utils::expiry::IggyExpiry;
use crate::utils::sizeable::Sizeable;
use crate::utils::text;
use crate::utils::topic_size::MaxTopicSize;
use crate::validatable::Validatable;
use bytes::{BufMut, Bytes, BytesMut};
Expand All @@ -18,8 +17,8 @@ use std::str::from_utf8;
/// It has additional payload:
/// - `stream_id` - unique stream ID (numeric or name).
/// - `topic_id` - unique topic ID (numeric or name).
/// - `message_expiry` - optional message expiry in seconds, if `None` then messages will never expire.
/// - `max_topic_size` - optional maximum size of the topic in bytes, if `None` then topic size is unlimited.
/// - `message_expiry` - message expiry, if `NeverExpire` then messages will never expire.
/// - `max_topic_size` - maximum size of the topic in bytes, if `Unlimited` then topic size is unlimited.
/// Can't be lower than segment size in the config.
/// - `replication_factor` - replication factor for the topic.
/// - `name` - unique topic name, max length is 255 characters.
Expand All @@ -33,9 +32,9 @@ pub struct UpdateTopic {
pub topic_id: Identifier,
/// Compression algorithm for the topic.
pub compression_algorithm: CompressionAlgorithm,
/// Optional message expiry in seconds, if `None` then messages will never expire.
/// Message expiry, if `NeverExpire` then messages will never expire.
pub message_expiry: IggyExpiry,
/// Optional max topic size, if `None` then topic size is unlimited.
/// Max topic size, if `Unlimited` then topic size is unlimited.
/// Can't be lower than segment size in the config.
pub max_topic_size: MaxTopicSize,
/// Replication factor for the topic.
Expand Down Expand Up @@ -70,10 +69,6 @@ impl Validatable<IggyError> for UpdateTopic {
return Err(IggyError::InvalidTopicName);
}

if !text::is_resource_name_valid(&self.name) {
return Err(IggyError::InvalidTopicName);
}

if let Some(replication_factor) = self.replication_factor {
if replication_factor == 0 {
return Err(IggyError::InvalidReplicationFactor);
Expand Down
7 changes: 1 addition & 6 deletions sdk/src/users/create_user.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ use crate::error::IggyError;
use crate::models::permissions::Permissions;
use crate::models::user_status::UserStatus;
use crate::users::defaults::*;
use crate::utils::text;
use crate::validatable::Validatable;
use bytes::{BufMut, Bytes, BytesMut};
use serde::{Deserialize, Serialize};
Expand All @@ -13,7 +12,7 @@ use std::str::from_utf8;

/// `CreateUser` command is used to create a new user.
/// It has additional payload:
/// - `username` - unique name of the user, must be between 3 and 50 characters long. The name will be always converted to lowercase and all whitespaces will be replaced with dots.
/// - `username` - unique name of the user, must be between 3 and 50 characters long.
/// - `password` - password of the user, must be between 3 and 100 characters long.
/// - `status` - status of the user, can be either `active` or `inactive`.
/// - `permissions` - optional permissions of the user. If not provided, user will have no permissions.
Expand Down Expand Up @@ -55,10 +54,6 @@ impl Validatable<IggyError> for CreateUser {
return Err(IggyError::InvalidUsername);
}

if !text::is_resource_name_valid(&self.username) {
return Err(IggyError::InvalidUsername);
}

if self.password.is_empty()
|| self.password.len() > MAX_PASSWORD_LENGTH
|| self.password.len() < MIN_PASSWORD_LENGTH
Expand Down
5 changes: 0 additions & 5 deletions sdk/src/users/login_user.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ use crate::bytes_serializable::BytesSerializable;
use crate::command::{Command, LOGIN_USER_CODE};
use crate::error::IggyError;
use crate::users::defaults::*;
use crate::utils::text;
use crate::validatable::Validatable;
use bytes::{BufMut, Bytes, BytesMut};
use serde::{Deserialize, Serialize};
Expand Down Expand Up @@ -51,10 +50,6 @@ impl Validatable<IggyError> for LoginUser {
return Err(IggyError::InvalidUsername);
}

if !text::is_resource_name_valid(&self.username) {
return Err(IggyError::InvalidUsername);
}

if self.password.is_empty()
|| self.password.len() > MAX_PASSWORD_LENGTH
|| self.password.len() < MIN_PASSWORD_LENGTH
Expand Down
5 changes: 0 additions & 5 deletions sdk/src/users/update_user.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ use crate::identifier::Identifier;
use crate::models::user_status::UserStatus;
use crate::users::defaults::*;
use crate::utils::sizeable::Sizeable;
use crate::utils::text;
use crate::validatable::Validatable;
use bytes::{BufMut, Bytes, BytesMut};
use serde::{Deserialize, Serialize};
Expand Down Expand Up @@ -45,10 +44,6 @@ impl Validatable<IggyError> for UpdateUser {
return Err(IggyError::InvalidUsername);
}

if !text::is_resource_name_valid(username) {
return Err(IggyError::InvalidUsername);
}

Ok(())
}
}
Expand Down
Loading

0 comments on commit d16a15f

Please sign in to comment.