• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

divviup / divviup-api / 24201451234

09 Apr 2026 04:29PM UTC coverage: 56.915% (+0.02%) from 56.897%
24201451234

Pull #2192

github

web-flow
Merge af475a6e6 into 7ffeedd98
Pull Request #2192: Add max-length validation on string input fields

2 of 3 new or added lines in 1 file covered. (66.67%)

1 existing line in 1 file now uncovered.

4074 of 7158 relevant lines covered (56.92%)

59.07 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

98.67
/src/entity/task/update_task.rs
1
use janus_messages::Time as JanusTime;
2
use sea_orm::{ActiveModelTrait, ActiveValue, IntoActiveModel};
3
use serde::Deserialize;
4
use time::OffsetDateTime;
5
use tokio::try_join;
6
use trillium_client::Client;
7
use validator::{Validate, ValidationError, ValidationErrors};
8

9
use crate::{deserialize_some, entity::Aggregator, handler::Error, Crypter, Db};
10

11
use super::assert_same;
12

13
#[derive(Default, Deserialize, Validate, Debug)]
14
pub struct UpdateTask {
15
    #[validate(custom(function = "validate_name"))]
16
    name: Option<String>,
17
    #[serde(default, deserialize_with = "deserialize_some")]
18
    expiration: Option<Expiration>,
19
}
20

21
#[derive(Debug, Deserialize, Clone, Copy)]
22
struct Expiration(#[serde(default, with = "time::serde::rfc3339::option")] Option<OffsetDateTime>);
23

24
fn validate_name(name: &str) -> Result<(), ValidationError> {
7✔
25
    if name.is_empty() {
7✔
26
        return Err(ValidationError::new("name-too-short"));
1✔
27
    }
6✔
28
    if name.len() > 255 {
6✔
NEW
29
        return Err(ValidationError::new("name-too-long"));
×
30
    }
6✔
31
    Ok(())
6✔
32
}
7✔
33

34
impl UpdateTask {
35
    pub async fn update_aggregator_expiration(
28✔
36
        &self,
28✔
37
        aggregator: Aggregator,
28✔
38
        task_id: &str,
28✔
39
        http_client: &Client,
28✔
40
        crypter: &Crypter,
28✔
41
    ) -> Result<(), Error> {
28✔
42
        let expiration = self
27✔
43
            .expiration
27✔
44
            .as_ref()
27✔
45
            .unwrap()
27✔
46
            .0
27✔
47
            .map(|expiration| {
27✔
48
                let seconds: u64 = expiration.unix_timestamp().try_into().map_err(|_| {
23✔
49
                    let mut ve = ValidationErrors::new();
1✔
50
                    ve.add("expiration", ValidationError::new("pre-epoch-timestamp"));
1✔
51
                    Error::from(ve)
1✔
52
                })?;
1✔
53
                Ok::<_, Error>(JanusTime::from_seconds_since_epoch(seconds))
22✔
54
            })
23✔
55
            .transpose()?;
27✔
56
        let response = aggregator
26✔
57
            .client(http_client.clone(), crypter)?
26✔
58
            .update_task_expiration(task_id, expiration)
26✔
59
            .await?;
26✔
60
        assert_same(expiration, response.task_expiration, "expiration")?;
24✔
61
        Ok(())
24✔
62
    }
27✔
63

64
    /// Validates the request. Updates task definitions in the aggregators, if necessary. Returns
65
    /// an [`ActiveModel`] for committing to the database.
66
    pub async fn update(
12✔
67
        self,
12✔
68
        http_client: &Client,
12✔
69
        db: &Db,
12✔
70
        crypter: &Crypter,
12✔
71
        model: super::Model,
12✔
72
    ) -> Result<super::ActiveModel, Error> {
12✔
73
        self.validate()?;
12✔
74
        let mut am = model.clone().into_active_model();
11✔
75
        if let Some(ref name) = self.name {
11✔
76
            am.name = ActiveValue::Set(name.clone());
6✔
77
        }
6✔
78
        if let Some(ref expiration) = self.expiration {
11✔
79
            try_join!(
6✔
80
                self.update_aggregator_expiration(
6✔
81
                    model.leader_aggregator(db).await?,
6✔
82
                    &model.id,
6✔
83
                    http_client,
6✔
84
                    crypter
6✔
85
                ),
86
                self.update_aggregator_expiration(
6✔
87
                    model.helper_aggregator(db).await?,
6✔
88
                    &model.id,
6✔
89
                    http_client,
6✔
90
                    crypter
6✔
91
                )
92
            )?;
1✔
93
            am.expiration = ActiveValue::set(expiration.0);
5✔
94
        }
5✔
95
        if am.is_changed() {
10✔
96
            am.updated_at = ActiveValue::Set(OffsetDateTime::now_utc());
10✔
97
        }
10✔
98
        Ok(am)
10✔
99
    }
12✔
100

101
    pub fn expiration(expiration: Option<OffsetDateTime>) -> Self {
8✔
102
        Self {
8✔
103
            expiration: Some(Expiration(expiration)),
8✔
104
            ..Default::default()
8✔
105
        }
8✔
106
    }
8✔
107
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc