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

Unleash / unleash-edge / 15441274495

04 Jun 2025 11:37AM UTC coverage: 78.265% (+10.3%) from 67.995%
15441274495

push

github

web-flow
task(rust): Update Rust version to 1.87.0 (#970)

10140 of 12956 relevant lines covered (78.26%)

158.36 hits per line

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

94.66
/server/src/edge_api.rs
1
use actix_web::{
2
    HttpRequest, post,
3
    web::{self, Data, Json},
4
};
5
use dashmap::DashMap;
6
use utoipa;
7

8
use crate::auth::token_validator::TokenValidator;
9
use crate::types::{
10
    EdgeJsonResult, EdgeToken, TokenStrings, TokenValidationStatus, ValidatedTokens,
11
};
12

13
#[utoipa::path(
×
14
    path = "/edge/validate",
×
15
    responses(
×
16
        (status = 200, description = "Return valid tokens from list of tokens passed in to validate", body = ValidatedTokens)
×
17
    ),
×
18
    request_body = TokenStrings
×
19
)]
×
20
#[post("/validate")]
16✔
21
pub async fn validate(
13✔
22
    token_cache: web::Data<DashMap<String, EdgeToken>>,
13✔
23
    req: HttpRequest,
13✔
24
    tokens: Json<TokenStrings>,
13✔
25
) -> EdgeJsonResult<ValidatedTokens> {
13✔
26
    let maybe_validator = req.app_data::<Data<TokenValidator>>();
13✔
27
    match maybe_validator {
13✔
28
        Some(validator) => {
11✔
29
            let known_tokens = validator
11✔
30
                .register_tokens(tokens.into_inner().tokens)
11✔
31
                .await?;
11✔
32
            Ok(Json(ValidatedTokens {
11✔
33
                tokens: known_tokens
11✔
34
                    .into_iter()
11✔
35
                    .filter(|t| t.status == TokenValidationStatus::Validated)
13✔
36
                    .collect(),
11✔
37
            }))
11✔
38
        }
39
        None => {
40
            let tokens_to_check = tokens.into_inner().tokens;
2✔
41
            let valid_tokens: Vec<EdgeToken> = tokens_to_check
2✔
42
                .iter()
2✔
43
                .filter_map(|t| token_cache.get(t).map(|e| e.value().clone()))
3✔
44
                .collect();
2✔
45
            Ok(Json(ValidatedTokens {
2✔
46
                tokens: valid_tokens,
2✔
47
            }))
2✔
48
        }
49
    }
50
}
13✔
51

52
pub fn configure_edge_api(cfg: &mut web::ServiceConfig) {
11✔
53
    cfg.service(validate);
11✔
54
}
11✔
55

56
#[cfg(test)]
57
mod tests {
58
    use std::sync::Arc;
59

60
    use actix_web::http::header::ContentType;
61
    use actix_web::web::Json;
62
    use actix_web::{App, test, web};
63
    use dashmap::DashMap;
64

65
    use crate::auth::token_validator::TokenValidator;
66
    use crate::edge_api::validate;
67
    use crate::types::{
68
        EdgeToken, TokenStrings, TokenType, TokenValidationStatus, ValidatedTokens,
69
    };
70

71
    #[tokio::test]
72
    pub async fn validating_incorrect_tokens_returns_empty_list() {
1✔
73
        let token_cache: Arc<DashMap<String, EdgeToken>> = Arc::new(DashMap::default());
1✔
74
        let app = test::init_service(
1✔
75
            App::new()
1✔
76
                .app_data(web::Data::from(token_cache.clone()))
1✔
77
                .service(web::scope("/edge").service(validate)),
1✔
78
        )
1✔
79
        .await;
1✔
80
        let mut valid_token =
1✔
81
            EdgeToken::try_from("test-app:development.abcdefghijklmnopqrstu".to_string()).unwrap();
1✔
82
        valid_token.token_type = Some(TokenType::Client);
1✔
83
        valid_token.status = TokenValidationStatus::Validated;
1✔
84
        token_cache.insert(valid_token.token.clone(), valid_token.clone());
1✔
85
        let token_strings = TokenStrings {
1✔
86
            tokens: vec!["random_token:rqweqwew.qweqwjeqwkejlqwe".into()],
1✔
87
        };
1✔
88
        let req = test::TestRequest::post()
1✔
89
            .uri("/edge/validate")
1✔
90
            .insert_header(ContentType::json())
1✔
91
            .set_json(Json(token_strings))
1✔
92
            .to_request();
1✔
93
        let res: ValidatedTokens = test::call_and_read_body_json(&app, req).await;
1✔
94
        assert_eq!(res.tokens.len(), 0);
1✔
95
    }
1✔
96

97
    #[tokio::test]
98
    pub async fn validating_a_mix_of_tokens_only_returns_valid_tokens() {
1✔
99
        let token_cache: Arc<DashMap<String, EdgeToken>> = Arc::new(DashMap::default());
1✔
100
        let app = test::init_service(
1✔
101
            App::new()
1✔
102
                .app_data(web::Data::from(token_cache.clone()))
1✔
103
                .service(web::scope("/edge").service(validate)),
1✔
104
        )
1✔
105
        .await;
1✔
106
        let mut valid_token =
1✔
107
            EdgeToken::try_from("test-app:development.abcdefghijklmnopqrstu".to_string()).unwrap();
1✔
108
        valid_token.token_type = Some(TokenType::Client);
1✔
109
        valid_token.status = TokenValidationStatus::Validated;
1✔
110
        token_cache.insert(valid_token.token.clone(), valid_token.clone());
1✔
111

1✔
112
        let token_strings = TokenStrings {
1✔
113
            tokens: vec![
1✔
114
                "test-app:development.abcdefghijklmnopqrstu".into(),
1✔
115
                "probablyaninvalidproject:development.some_crazy_secret".into(),
1✔
116
            ],
1✔
117
        };
1✔
118
        let req = test::TestRequest::post()
1✔
119
            .uri("/edge/validate")
1✔
120
            .insert_header(ContentType::json())
1✔
121
            .set_json(Json(token_strings))
1✔
122
            .to_request();
1✔
123
        let res: ValidatedTokens = test::call_and_read_body_json(&app, req).await;
1✔
124
        assert_eq!(res.tokens.len(), 1);
1✔
125
        assert!(res.tokens.iter().any(|t| t.token == valid_token.token));
1✔
126
    }
1✔
127

128
    #[tokio::test]
129
    pub async fn adding_a_token_validator_filters_so_only_validated_tokens_are_returned() {
1✔
130
        let token_cache: Arc<DashMap<String, EdgeToken>> = Arc::new(DashMap::default());
1✔
131
        let token_validator = TokenValidator {
1✔
132
            unleash_client: Arc::new(Default::default()),
1✔
133
            token_cache: token_cache.clone(),
1✔
134
            persistence: None,
1✔
135
        };
1✔
136
        let app = test::init_service(
1✔
137
            App::new()
1✔
138
                .app_data(web::Data::from(token_cache.clone()))
1✔
139
                .app_data(web::Data::new(token_validator))
1✔
140
                .service(web::scope("/edge").service(validate)),
1✔
141
        )
1✔
142
        .await;
1✔
143
        let mut valid_token =
1✔
144
            EdgeToken::try_from("test-app:development.abcdefghijklmnopqrstu".to_string()).unwrap();
1✔
145
        valid_token.token_type = Some(TokenType::Client);
1✔
146
        valid_token.status = TokenValidationStatus::Validated;
1✔
147
        let mut invalid_token = EdgeToken::try_from(
1✔
148
            "probablyaninvalidproject:development.some_crazy_secret".to_string(),
1✔
149
        )
1✔
150
        .unwrap();
1✔
151
        invalid_token.status = TokenValidationStatus::Invalid;
1✔
152
        invalid_token.token_type = Some(TokenType::Admin);
1✔
153
        token_cache.insert(valid_token.token.clone(), valid_token.clone());
1✔
154
        token_cache.insert(invalid_token.token.clone(), invalid_token.clone());
1✔
155
        let token_strings = TokenStrings {
1✔
156
            tokens: vec![
1✔
157
                "test-app:development.abcdefghijklmnopqrstu".into(),
1✔
158
                "probablyaninvalidproject:development.some_crazy_secret".into(),
1✔
159
            ],
1✔
160
        };
1✔
161
        let req = test::TestRequest::post()
1✔
162
            .uri("/edge/validate")
1✔
163
            .insert_header(ContentType::json())
1✔
164
            .set_json(Json(token_strings))
1✔
165
            .to_request();
1✔
166
        let res: ValidatedTokens = test::call_and_read_body_json(&app, req).await;
1✔
167
        assert_eq!(res.tokens.len(), 1);
1✔
168
        assert!(res.tokens.iter().any(|t| t.token == valid_token.token));
1✔
169
    }
1✔
170
}
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