Verified Commit ab0d28ea authored by Mattia Righetti's avatar Mattia Righetti
Browse files

fix(details): misc fixes

+ fix query ambiguity for columns that belonged to multiple tables
+ fix relay and bridge builder
+ fix correctly parse json array of strings in summary and details responses
parent 42bf0b30
Loading
Loading
Loading
Loading
+67 −61
Original line number Diff line number Diff line
@@ -79,35 +79,38 @@ pub async fn relay_details(

    let mut q = Query::select()
        .columns([
            ServerStatus::Nickname,
            ServerStatus::Fingerprint,
            ServerStatus::LastSeen,
            ServerStatus::FirstSeen,
            ServerStatus::Running,
            ServerStatus::Flags,
            ServerStatus::Country,
            ServerStatus::CountryName,
            ServerStatus::AsName,
            ServerStatus::AutonomousSystem,
            ServerStatus::VerifiedHostNames,
            ServerStatus::LastRestarted,
            ServerStatus::Version,
            ServerStatus::Platform,
            ServerStatus::VersionStatus,
            ServerStatus::EffectiveFamily,
            ServerStatus::DeclaredFamily,
            (ServerStatus::Table, ServerStatus::Nickname),
            (ServerStatus::Table, ServerStatus::Fingerprint),
            (ServerStatus::Table, ServerStatus::LastSeen),
            (ServerStatus::Table, ServerStatus::FirstSeen),
            (ServerStatus::Table, ServerStatus::Running),
            (ServerStatus::Table, ServerStatus::Flags),
            (ServerStatus::Table, ServerStatus::Country),
            (ServerStatus::Table, ServerStatus::CountryName),
            (ServerStatus::Table, ServerStatus::AsName),
            (ServerStatus::Table, ServerStatus::AutonomousSystem),
            (ServerStatus::Table, ServerStatus::VerifiedHostNames),
            (ServerStatus::Table, ServerStatus::LastRestarted),
            (ServerStatus::Table, ServerStatus::Version),
            (ServerStatus::Table, ServerStatus::Platform),
            (ServerStatus::Table, ServerStatus::VersionStatus),
            (ServerStatus::Table, ServerStatus::EffectiveFamily),
            (ServerStatus::Table, ServerStatus::DeclaredFamily),
        ])
        .columns([
            ServerDescriptor::OrAddresses,
            ServerDescriptor::DirPort,
            ServerDescriptor::IsHibernating,
            ServerDescriptor::BandwidthRate,
            ServerDescriptor::BandwidthBurst,
            ServerDescriptor::BandwidthObserved,
            (ServerDescriptor::Table, ServerDescriptor::OrAddresses),
            (ServerDescriptor::Table, ServerDescriptor::DirPort),
            (ServerDescriptor::Table, ServerDescriptor::IsHibernating),
            (ServerDescriptor::Table, ServerDescriptor::BandwidthRate),
            (ServerDescriptor::Table, ServerDescriptor::BandwidthBurst),
            (ServerDescriptor::Table, ServerDescriptor::BandwidthObserved),
            (
                ServerDescriptor::Table,
                ServerDescriptor::OverloadGeneralTimestamp,
            ServerDescriptor::ExitPolicy,
            ServerDescriptor::Ipv6DefaultPolicy,
            ServerDescriptor::Contact,
            ),
            (ServerDescriptor::Table, ServerDescriptor::ExitPolicy),
            (ServerDescriptor::Table, ServerDescriptor::Ipv6DefaultPolicy),
            (ServerDescriptor::Table, ServerDescriptor::Contact),
        ])
        .from(ServerStatus::Table)
        .left_join(
@@ -125,32 +128,32 @@ pub async fn relay_details(
        )
        .to_owned();

    q.and_where(Expr::col(ServerStatus::IsBridge).eq(false));
    q.and_where(Expr::col((ServerStatus::Table, ServerStatus::IsBridge)).eq(false));

    if let Some(ref r#as) = filters.r#as {
        q.and_where(Expr::col(ServerStatus::AutonomousSystem).eq(r#as));
        q.and_where(Expr::col((ServerStatus::Table, ServerStatus::AutonomousSystem)).eq(r#as));
    }

    if let Some(ref fs) = filters.first_seen_since {
        let timestamp_stmt = format!("to_timestamp('{}', 'YYYY-MM-DD')", fs);
        q.and_where(Expr::col(ServerStatus::FirstSeen).gte(timestamp_stmt));
        q.and_where(Expr::col((ServerStatus::Table, ServerStatus::FirstSeen)).gte(timestamp_stmt));
    }

    if let Some(ref ls) = filters.last_seen_since {
        let timestamp_stmt = format!("to_timestamp('{}', 'YYYY-MM-DD')", ls);
        q.and_where(Expr::col(ServerStatus::LastSeen).gte(timestamp_stmt));
        q.and_where(Expr::col((ServerStatus::Table, ServerStatus::LastSeen)).gte(timestamp_stmt));
    }

    if let Some(running) = filters.running {
        q.and_where(Expr::col(ServerStatus::Running).eq(running));
        q.and_where(Expr::col((ServerStatus::Table, ServerStatus::Running)).eq(running));
    }

    if let Some(ref country) = filters.country {
        q.and_where(Expr::col(ServerStatus::Country).eq(country.as_ref()));
        q.and_where(Expr::col((ServerStatus::Table, ServerStatus::Country)).eq(country.as_ref()));
    }

    if let Some(ref as_name) = filters.as_name {
        q.and_where(Expr::col(ServerStatus::AsName).eq(as_name));
        q.and_where(Expr::col((ServerStatus::Table, ServerStatus::AsName)).eq(as_name));
    }

    let limit = match filters.limit {
@@ -228,24 +231,27 @@ pub async fn bridge_details(

    let mut q = Query::select()
        .columns([
            ServerStatus::Nickname,
            ServerStatus::Fingerprint,
            ServerStatus::OrAddresses,
            ServerStatus::LastSeen,
            ServerStatus::FirstSeen,
            ServerStatus::Running,
            ServerStatus::Version,
            ServerStatus::Platform,
            ServerStatus::VersionStatus,
            ServerStatus::Transport,
            ServerStatus::Blocklist,
            ServerStatus::BridgedbDistributor,
            ServerStatus::Flags,
            ServerStatus::LastRestarted,
            ServerStatus::Country,
            ServerStatus::CountryName,
            (ServerStatus::Table, ServerStatus::Nickname),
            (ServerStatus::Table, ServerStatus::Fingerprint),
            (ServerStatus::Table, ServerStatus::OrAddresses),
            (ServerStatus::Table, ServerStatus::LastSeen),
            (ServerStatus::Table, ServerStatus::FirstSeen),
            (ServerStatus::Table, ServerStatus::Running),
            (ServerStatus::Table, ServerStatus::Version),
            (ServerStatus::Table, ServerStatus::Platform),
            (ServerStatus::Table, ServerStatus::VersionStatus),
            (ServerStatus::Table, ServerStatus::Transport),
            (ServerStatus::Table, ServerStatus::Blocklist),
            (ServerStatus::Table, ServerStatus::BridgedbDistributor),
            (ServerStatus::Table, ServerStatus::Flags),
            (ServerStatus::Table, ServerStatus::LastRestarted),
            (ServerStatus::Table, ServerStatus::Country),
            (ServerStatus::Table, ServerStatus::CountryName),
        ])
        .column(ServerDescriptor::OverloadGeneralTimestamp)
        .column((
            ServerDescriptor::Table,
            ServerDescriptor::OverloadGeneralTimestamp,
        ))
        .from(ServerStatus::Table)
        .left_join(
            ServerDescriptor::Table,
@@ -262,32 +268,32 @@ pub async fn bridge_details(
        )
        .to_owned();

    q.and_where(Expr::col(ServerStatus::IsBridge).eq(true));

    if let Some(running) = filters.running {
        q.and_where(Expr::col(ServerStatus::Running).eq(running));
    }
    q.and_where(Expr::col((ServerStatus::Table, ServerStatus::IsBridge)).eq(true));

    if let Some(ref r#as) = filters.r#as {
        q.and_where(Expr::col(ServerStatus::AutonomousSystem).eq(r#as));
        q.and_where(Expr::col((ServerStatus::Table, ServerStatus::AutonomousSystem)).eq(r#as));
    }

    if let Some(ref fs) = filters.first_seen_since {
        let timestamp_stmt = format!("to_timestamp('{}', 'YYYY-MM-DD')", fs);
        q.and_where(Expr::col(ServerStatus::FirstSeen).gte(timestamp_stmt));
        q.and_where(Expr::col((ServerStatus::Table, ServerStatus::FirstSeen)).gte(timestamp_stmt));
    }

    if let Some(ref ls) = filters.last_seen_since {
        let timestamp_stmt = format!("to_timestamp('{}', 'YYYY-MM-DD')", ls);
        q.and_where(Expr::col(ServerStatus::LastSeen).gte(timestamp_stmt));
        q.and_where(Expr::col((ServerStatus::Table, ServerStatus::LastSeen)).gte(timestamp_stmt));
    }

    if let Some(running) = filters.running {
        q.and_where(Expr::col((ServerStatus::Table, ServerStatus::Running)).eq(running));
    }

    if let Some(ref country) = filters.country {
        q.and_where(Expr::col(ServerStatus::Country).eq(country.as_ref()));
        q.and_where(Expr::col((ServerStatus::Table, ServerStatus::Country)).eq(country.as_ref()));
    }

    if let Some(ref as_name) = filters.as_name {
        q.and_where(Expr::col(ServerStatus::AsName).eq(as_name));
        q.and_where(Expr::col((ServerStatus::Table, ServerStatus::AsName)).eq(as_name));
    }

    let limit = match filters.limit {
+35 −61
Original line number Diff line number Diff line
@@ -257,27 +257,20 @@ impl From<metrics::RelayDetailsRow> for RelayDetails {
        relay_details.nickname(value.nickname);
        relay_details.fingerprint(value.fingerprint);

        if let Some(or_addresses) = value.or_addresses {
            let or_addresses: Vec<_> = or_addresses.split(',').map(String::from).collect();
            if !or_addresses.is_empty() {
                relay_details.or_addresses(or_addresses);
            } else {
                relay_details.or_addresses(vec![]);
            }
        if let Some(ref or_addresses) = value.or_addresses {
            relay_details.or_addresses(serde_json::from_str(or_addresses).unwrap_or_default());
        }

        relay_details.dir_address(value.dir_port);
        relay_details.last_seen(value.last_seen.to_string());
        // TODO relay_details.last_changed_address_or_port("".into());
        // TODO fix as it's set empty for now
        relay_details.last_changed_address_or_port("".into());
        relay_details.first_seen(value.first_seen.to_string());
        relay_details.running(value.running.unwrap_or(false));
        relay_details.hibernating(value.is_hibernating);

        if let Some(flags) = value.flags {
            let flags = string_vec(flags);
            if !flags.is_empty() {
                relay_details.flags(Some(flags));
            }
        if let Some(ref flags) = value.flags {
            relay_details.flags(serde_json::from_str(flags).ok());
        }

        relay_details.country(value.country);
@@ -294,13 +287,13 @@ impl From<metrics::RelayDetailsRow> for RelayDetails {
        relay_details.r#as(value.autonomous_system);
        relay_details.as_name(value.as_name);

        if let Some(verified_host_names) = value.verified_host_names {
            let verified_host_names = string_vec(verified_host_names);
            if !verified_host_names.is_empty() {
                relay_details.verified_host_names(Some(verified_host_names));
            }
        if let Some(ref verified_host_names) = value.verified_host_names {
            relay_details.verified_host_names(serde_json::from_str(verified_host_names).ok());
        }

        // TODO
        relay_details.alleged_family(None);

        // TODO
        relay_details.unverified_host_names(None);
        relay_details.last_restarted(Some(value.last_restarted.to_string()));
@@ -311,13 +304,12 @@ impl From<metrics::RelayDetailsRow> for RelayDetails {
        relay_details.advertised_bandwidth(None);
        relay_details.overload_general_timestamp(value.overload_general_timestamp);

        if let Some(exit_policy) = value.exit_policy {
            let exit_policy = string_vec(exit_policy);
            if !exit_policy.is_empty() {
                relay_details.exit_policy(Some(exit_policy));
        if let Some(ref exit_policy) = value.exit_policy {
            relay_details.exit_policy(serde_json::from_str(exit_policy).ok());
        }
        }
        // relay_details.exit_policy_v6_summary(value.exit_addresses);

        // TODO
        relay_details.exit_policy_v6_summary(None);
        relay_details.contact(value.contact);
        relay_details.version(value.version);
        relay_details.platform(value.platform);
@@ -325,19 +317,14 @@ impl From<metrics::RelayDetailsRow> for RelayDetails {
        relay_details.recommended_version(None);
        relay_details.version_status(value.version_status);

        if let Some(effective_family) = value.effective_family {
            let effective_family = string_vec(effective_family);
            if !effective_family.is_empty() {
                relay_details.effective_family(Some(effective_family));
            }
        if let Some(ref effective_family) = value.effective_family {
            relay_details.effective_family(serde_json::from_str(effective_family).ok());
        }

        if let Some(declared_family) = value.declared_family {
            let declared_family = string_vec(declared_family);
            if !declared_family.is_empty() {
                relay_details.effective_family(Some(declared_family));
            }
        if let Some(ref declared_family) = value.declared_family {
            relay_details.effective_family(serde_json::from_str(declared_family).ok());
        }

        // TODO
        relay_details.indirect_family(None);

@@ -458,51 +445,38 @@ impl From<metrics::BridgeDetailsRow> for BridgeDetails {
        bridge_details.nickname(value.nickname);
        bridge_details.hashed_fingerprint(value.fingerprint);

        if let Some(or_addresses) = value.or_addresses {
            let or_addresses: Vec<_> = or_addresses.split(',').map(String::from).collect();
            if !or_addresses.is_empty() {
                bridge_details.or_addresses(or_addresses);
            } else {
                bridge_details.or_addresses(vec![]);
            }
        if let Some(ref or_addresses) = value.or_addresses {
            bridge_details.or_addresses(serde_json::from_str(or_addresses).unwrap_or_default());
        }

        bridge_details.first_seen(value.first_seen.to_string());
        bridge_details.last_seen(value.last_seen.to_string());
        bridge_details.running(value.running.unwrap_or(false));

        if let Some(flags) = value.flags {
            let flags = string_vec(flags);
            if !flags.is_empty() {
                bridge_details.flags(Some(flags));
            }
        if let Some(ref flags) = value.flags {
            bridge_details.flags(serde_json::from_str(flags).ok());
        }

        bridge_details.last_restarted(Some(value.last_restarted.to_string()));
        bridge_details.overload_general_timestamp(value.overload_general_timestamp);
        bridge_details.platform(value.platform);
        // TODO bridge_details.recommended_version();
        bridge_details.version_status(value.version_status);

        if let Some(transport) = value.transport {
            let transport: Vec<_> = string_vec(transport);
            if !transport.is_empty() {
                bridge_details.transports(Some(transport));
            }
        if let Some(ref transport) = value.transport {
            bridge_details.transports(serde_json::from_str(transport).ok());
        }

        if let Some(blocklist) = value.blocklist {
            let blocklist: Vec<_> = blocklist.split(',').map(String::from).collect();
            if !blocklist.is_empty() {
                bridge_details.blocklist(Some(blocklist));
            }
        if let Some(ref blocklist) = value.blocklist {
            bridge_details.blocklist(serde_json::from_str(blocklist).ok());
        }

        // TODO
        bridge_details.advertised_bandwidth(None);
        bridge_details.version(value.version);
        // TODO
        bridge_details.recommended_version(None);

        bridge_details.bridgedb_distributor(value.bridgedb_distributor);
        bridge_details.build().unwrap()
    }
}

fn string_vec(s: String) -> Vec<String> {
    s.split(',').map(String::from).collect()
}
+1 −4
Original line number Diff line number Diff line
@@ -23,7 +23,7 @@ pub struct RelaySummary {

impl From<RelaySummaryRow> for RelaySummary {
    fn from(value: RelaySummaryRow) -> Self {
        let or_addresses: Vec<_> = value.or_addresses.split(',').map(String::from).collect();
        let or_addresses: Vec<_> = serde_json::from_str(&value.or_addresses).unwrap_or_default();

        Self {
            n: value.nickname,
@@ -37,17 +37,14 @@ impl From<RelaySummaryRow> for RelaySummary {
#[derive(Debug, Serialize, Deserialize, Clone, sqlx::FromRow)]
pub struct BridgeSummary {
    /// Relay nickname consisting of 1–19 alphanumerical characters.
    #[sqlx(rename = "nickname")]
    pub n: String,

    /// SHA-1 hash of the bridge fingerprint consisting of 40 upper-case hexadecimal
    /// characters.
    #[sqlx(rename = "fingerprint")]
    pub h: String,

    /// Boolean field saying whether this bridge was listed as running in the last
    /// bridge network status.
    #[sqlx(rename = "running")]
    pub r: bool,
}