Skip to content

Commit

Permalink
Added PasswordPolicy for managing password expiry period data
Browse files Browse the repository at this point in the history
  • Loading branch information
henry0715-dev committed Aug 28, 2024
1 parent 42a05b0 commit 2e4b2eb
Show file tree
Hide file tree
Showing 4 changed files with 99 additions and 7 deletions.
6 changes: 5 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

### Added

- Added `PasswordPolicy` for managing password expiry period data.

### Changed

- Extended the `Table<'d, Account>::update` method signature to include the
Expand Down Expand Up @@ -113,7 +117,7 @@ Versioning](https://semver.org/spec/v2.0.0.html).
- Changed return type of `Store::outlier_map` to `Table<OutlierInfo>`.
- Moved `OutlierInfo` from `crate::outlier` to `crate`.
- Included `model_id`, `timestamp`, and `is_saved` fields in `OutlierInfo`.
- Changed return type of `Store::account_policy_map` to `Table<AccountPlicy>`.
- Changed return type of `Store::account_policy_map` to `Table<AccountPolicy>`.
- Removed redundant log messages in the backup module.

### Removed
Expand Down
14 changes: 10 additions & 4 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,10 +69,10 @@ pub use self::tables::{
CsvColumnExtra as CsvColumnExtraConfig, Customer, CustomerNetwork, CustomerUpdate, DataSource,
DataSourceUpdate, DataType, Filter, Giganto, IndexedTable, Iterable, ModelIndicator, Network,
NetworkUpdate, Node, NodeProfile, NodeTable, NodeUpdate, OutlierInfo, OutlierInfoKey,
OutlierInfoValue, PacketAttr, ProtocolPorts, Response, ResponseKind, SamplingInterval,
SamplingKind, SamplingPeriod, SamplingPolicy, SamplingPolicyUpdate, Structured,
StructuredClusteringAlgorithm, Table, Template, Ti, TiCmpKind, Tidb, TidbKind, TidbRule,
TorExitNode, TrafficFilter, TriagePolicy, TriagePolicyUpdate, TriageResponse,
OutlierInfoValue, PacketAttr, PasswordPolicy, ProtocolPorts, Response, ResponseKind,
SamplingInterval, SamplingKind, SamplingPeriod, SamplingPolicy, SamplingPolicyUpdate,
Structured, StructuredClusteringAlgorithm, Table, Template, Ti, TiCmpKind, Tidb, TidbKind,
TidbRule, TorExitNode, TrafficFilter, TriagePolicy, TriagePolicyUpdate, TriageResponse,
TriageResponseUpdate, TrustedDomain, TrustedUserAgent, UniqueKey, Unstructured,
UnstructuredClusteringAlgorithm, ValueKind,
};
Expand Down Expand Up @@ -157,6 +157,12 @@ impl Store {
self.states.account_policy()
}

#[must_use]
#[allow(clippy::missing_panics_doc)]
pub fn password_policy_map(&self) -> Table<PasswordPolicy> {
self.states.password_policy()
}

#[must_use]
#[allow(clippy::missing_panics_doc)]
pub fn agents_map(&self) -> Table<Agent> {
Expand Down
8 changes: 7 additions & 1 deletion src/tables.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ use anyhow::{anyhow, Result};
use serde::{Deserialize, Serialize};

pub use self::access_token::AccessToken;
pub use self::account_policy::AccountPolicy;
pub use self::account_policy::{AccountPolicy, PasswordPolicy};
pub use self::agent::{Agent, Config as AgentConfig, Kind as AgentKind, Status as AgentStatus};
pub use self::allow_network::{AllowNetwork, Update as AllowNetworkUpdate};
pub use self::block_network::{BlockNetwork, Update as BlockNetworkUpdate};
Expand Down Expand Up @@ -180,6 +180,12 @@ impl StateDb {
Table::<AccountPolicy>::open(inner).expect("{ACCOUNT_POLICY} table must be present")
}

#[must_use]
pub(crate) fn password_policy(&self) -> Table<PasswordPolicy> {
let inner = self.inner.as_ref().expect("database must be open");
Table::<PasswordPolicy>::open(inner).expect("{PASSWORD_POLICY} table must be present")
}

#[must_use]
pub(crate) fn agents(&self) -> Table<Agent> {
let inner = self.inner.as_ref().expect("database must be open");
Expand Down
78 changes: 77 additions & 1 deletion src/tables/account_policy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use serde::{Deserialize, Serialize};
use crate::{Map, Table};

pub(crate) const ACCOUNT_POLICY_KEY: &[u8] = b"account policy key";

pub(crate) const PASSWORD_EXPIRATION_PERIOD_KEY: &[u8] = b"password expiration period";
#[derive(Serialize, Deserialize)]
pub struct AccountPolicy {
pub(crate) expiry_period_in_secs: u32,
Expand Down Expand Up @@ -73,6 +73,69 @@ impl<'d> Table<'d, AccountPolicy> {
}
}

#[derive(Serialize, Deserialize)]
pub struct PasswordPolicy {
pub(crate) expiry_password_period_in_days: u32,
}

impl<'d> Table<'d, PasswordPolicy> {
/// Opens the `account_policy` map in the database.
///
/// Returns `None` if the map does not exist.
pub(super) fn open(db: &'d OptimisticTransactionDB) -> Option<Self> {
Map::open(db, super::ACCOUNT_POLICY).map(Table::new)
}

/// Initializes the expiry period.
///
/// # Errors
///
/// Returns an error if it has already been initialized or
/// if database operation fails.
pub fn init_password_expiry_period(&self, days: u32) -> Result<()> {
let init = PasswordPolicy {
expiry_password_period_in_days: days,
};
self.map
.insert(PASSWORD_EXPIRATION_PERIOD_KEY, &super::serialize(&init)?)
}

/// Updates or initializes the password expiry period.
///
/// # Errors
///
/// Returns an error if database operation fails.
pub fn update_password_expiry_period(&self, days: u32) -> Result<()> {
if let Some(old) = self.map.get(PASSWORD_EXPIRATION_PERIOD_KEY)? {
let update = super::serialize(&PasswordPolicy {
expiry_password_period_in_days: days,
})?;
self.map.update(
(PASSWORD_EXPIRATION_PERIOD_KEY, old.as_ref()),
(PASSWORD_EXPIRATION_PERIOD_KEY, &update),
)
} else {
self.init_password_expiry_period(days)
}
}

/// Returns the current password expiry period,
/// or `None` if it hasn't been initialized.
///
/// # Errors
///
/// Returns an error if database operation fails.
pub fn current_password_expiry_period(&self) -> Result<Option<u32>> {
self.map
.get(PASSWORD_EXPIRATION_PERIOD_KEY)?
.map(|p| {
super::deserialize(p.as_ref())
.map(|p: PasswordPolicy| p.expiry_password_period_in_days)
})
.transpose()
}
}

#[cfg(test)]
mod tests {
use std::sync::Arc;
Expand All @@ -91,4 +154,17 @@ mod tests {
assert!(table.update_expiry_period(20).is_ok());
assert_eq!(table.current_expiry_period().unwrap(), Some(20));
}

#[test]
fn password_policy_operations() {
let db_dir = tempfile::tempdir().unwrap();
let backup_dir = tempfile::tempdir().unwrap();
let store = Arc::new(Store::new(db_dir.path(), backup_dir.path()).unwrap());
let table = store.password_policy_map();

assert!(table.update_password_expiry_period(90).is_ok());
assert_eq!(table.current_password_expiry_period().unwrap(), Some(90));
assert!(table.update_password_expiry_period(180).is_ok());
assert_eq!(table.current_password_expiry_period().unwrap(), Some(180));
}
}

0 comments on commit 2e4b2eb

Please sign in to comment.