1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
// Author: D.S. Ljungmark <spider@skuggor.se>, Modio AB
// SPDX-License-Identifier: AGPL-3.0-or-later
use crate::logger::LogErr;
use crate::timefail::Timefail;
use crate::types::Metadata;
use modio_logger_db::Datastore;

use log::{debug, info};
use zbus::dbus_interface;

mod builder;
pub use builder::Builder;

pub struct Submit1 {
    customer: bool,
    ds: Datastore,
    _timefail: Timefail,
}

impl Submit1 {
    pub async fn new(timefail: Timefail, ds: Datastore, customer: bool) -> Result<Self, LogErr> {
        if timefail.is_timefail() {
            info!("Failing all pending change requests due to TIMEFAIL");
            ds.transaction_fail_pending().await?;
        }
        Ok(Self {
            ds,
            _timefail: timefail,
            customer,
        })
    }

    #[must_use]
    pub fn builder() -> Builder {
        Builder::new()
    }
}

#[dbus_interface(name = "se.modio.logger.Submit1")]
impl Submit1 {
    /// Returns a vector of all metadata objects.
    pub(crate) async fn get_all_metadata(&mut self) -> Result<Vec<Metadata>, LogErr> {
        use std::convert::Into;

        debug!("Retrieving all metadata");
        let mut res = self.ds.get_all_metadata().await?;
        if self.customer {
            res.retain(|x| !x.n.starts_with("modio."));
        } else {
            res.retain(|x| x.n.starts_with("modio."));
        };

        let arr: Vec<Metadata> = res.drain(..).map(Into::into).collect();
        debug!("Returning {} metadata items", arr.len());
        Ok(arr)
    }
}

#[cfg(test)]
mod test {
    use crate::submit1::Submit1;
    use modio_logger_db::Datastore;
    use std::error::Error;

    #[tokio::test]
    async fn metadata_filters_for_modio() -> Result<(), Box<dyn Error>> {
        let _elog = env_logger::builder().is_test(true).try_init();
        let ds = Datastore::temporary().await;
        ds.metadata_set_name("modio.key.key", "Internal only")
            .await?;
        ds.metadata_set_name("key.key.key.one", "Some Test Name")
            .await?;
        ds.metadata_set_name("key.key.key.two", "Some Test Name")
            .await?;
        ds.metadata_set_name("key.key.key.three", "Some Test Name")
            .await?;

        let mut submit1 = Submit1::builder()
            .development(true)
            .datastore(ds)
            .customer(false)
            .build()
            .await?;

        let res = submit1.get_all_metadata().await?;
        // Should have 1 key
        assert_eq!(res.len(), 1);
        assert!(res[0].n.starts_with("modio."));
        Ok(())
    }

    #[tokio::test]
    async fn metadata_filters_on_customer() -> Result<(), Box<dyn Error>> {
        let _elog = env_logger::builder().is_test(true).try_init();
        let ds = Datastore::temporary().await;
        ds.metadata_set_name("modio.key.key", "Internal only")
            .await?;
        ds.metadata_set_name("key.key.key.one", "Some Test Name")
            .await?;
        ds.metadata_set_name("key.key.key.two", "Some Test Name")
            .await?;
        ds.metadata_set_name("key.key.key.three", "Some Test Name")
            .await?;

        let mut submit1 = Submit1::builder()
            .development(true)
            .datastore(ds)
            .customer(true)
            .build()
            .await?;

        let res = submit1.get_all_metadata().await?;
        // should have "key.key...." but not "modio...."
        assert_eq!(res.len(), 3);
        assert!(res[0].n.starts_with("key.key.key"));
        Ok(())
    }
}