Skip to content

Commit 40a5ca6

Browse files
committed
feat: implements allow_new_users setting
Refs: #1484 #1566 #1629 Closes: #1429
1 parent 391addb commit 40a5ca6

9 files changed

Lines changed: 102 additions & 2 deletions

File tree

docs/src/config.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ The following configuration options are available.
106106
| <span id="SYNC_TOKENSERVER__STATSD_LABEL"></span>SYNC_TOKENSERVER__STATSD_LABEL | syncstorage.tokenserver | StatsD metrics label prefix |
107107
| <span id="SYNC_TOKENSERVER__TOKEN_DURATION"></span>SYNC_TOKENSERVER__TOKEN_DURATION | 3600 | Token TTL (1 hour) |
108108
| <span id="SYNC_TOKENSERVER__FXA_WEBHOOK_ENABLED"></span>SYNC_TOKENSERVER__FXA_WEBHOOK_ENABLED | false | Enable the FxA webhook endpoint. When disabled, the route is not registered. |
109+
| <span id="SYNC_TOKENSERVER__ALLOW_NEW_USERS"></span>SYNC_TOKENSERVER__ALLOW_NEW_USERS | true | Whether new users may be created. When disabled, only previously registered users can use the tokenserver service. |
109110

110111
### Tokenserver+FxA Integration
111112

syncserver/src/tokenserver/extractors.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,7 @@ impl FromRequest for TokenserverRequest {
249249
client_state: auth_data.client_state.clone(),
250250
keys_changed_at: auth_data.keys_changed_at,
251251
capacity_release_rate: state.node_capacity_release_rate,
252+
allow_new_users: state.allow_new_users,
252253
})
253254
.await?;
254255
log_items_mutator.insert("first_seen_at".to_owned(), user.first_seen_at.to_string());
@@ -1345,6 +1346,7 @@ mod tests {
13451346
token_duration: TOKEN_DURATION,
13461347
set_verifiers: Vec::new(),
13471348
fxa_webhook_enabled: false,
1349+
allow_new_users: true,
13481350
}
13491351
}
13501352

@@ -1367,6 +1369,7 @@ mod tests {
13671369
token_duration: TOKEN_DURATION,
13681370
set_verifiers,
13691371
fxa_webhook_enabled: true,
1372+
allow_new_users: true,
13701373
}
13711374
}
13721375

syncserver/src/tokenserver/handlers.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -444,6 +444,7 @@ mod tests {
444444
token_duration: 3600,
445445
set_verifiers,
446446
fxa_webhook_enabled: true,
447+
allow_new_users: true,
447448
}
448449
}
449450

syncserver/src/tokenserver/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ pub struct ServerState {
3434
pub token_duration: u64,
3535
pub set_verifiers: Vec<SETVerifierImpl>,
3636
pub fxa_webhook_enabled: bool,
37+
pub allow_new_users: bool,
3738
}
3839

3940
impl ServerState {
@@ -115,6 +116,7 @@ impl ServerState {
115116
token_duration: settings.token_duration,
116117
set_verifiers,
117118
fxa_webhook_enabled: settings.fxa_webhook_enabled,
119+
allow_new_users: settings.allow_new_users,
118120
})
119121
}
120122

tokenserver-db-common/src/error.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@ pub struct DbError {
1818
}
1919

2020
impl DbError {
21+
pub fn user_not_found(user: String) -> Self {
22+
DbErrorKind::UserNotFound(user).into()
23+
}
24+
2125
pub fn internal(msg: String) -> Self {
2226
DbErrorKind::Internal(msg).into()
2327
}
@@ -26,6 +30,11 @@ impl DbError {
2630
DbErrorKind::PoolTimeout(timeout_type).into()
2731
}
2832

33+
#[cfg(debug_assertions)]
34+
pub fn is_user_not_found(&self) -> bool {
35+
matches!(&self.kind, DbErrorKind::UserNotFound(_))
36+
}
37+
2938
#[cfg(debug_assertions)]
3039
pub fn is_diesel_not_found(&self) -> bool {
3140
matches!(&self.kind, DbErrorKind::Sql(e) if e.is_diesel_not_found())
@@ -59,6 +68,9 @@ impl ReportableError for DbError {
5968

6069
#[derive(Debug, Error)]
6170
enum DbErrorKind {
71+
#[error("Specified user does not exist (new users are disallowed): {}", _0)]
72+
UserNotFound(String),
73+
6274
#[error("{}", _0)]
6375
Sql(SqlError),
6476

@@ -72,6 +84,11 @@ enum DbErrorKind {
7284
impl From<DbErrorKind> for DbError {
7385
fn from(kind: DbErrorKind) -> Self {
7486
match kind {
87+
DbErrorKind::UserNotFound(_) => Self {
88+
kind,
89+
status: StatusCode::NOT_FOUND,
90+
backtrace: Box::new(Backtrace::new_unresolved()),
91+
},
7592
DbErrorKind::Sql(ref sqle) => Self {
7693
status: sqle.status,
7794
backtrace: Box::new(sqle.backtrace.clone()),

tokenserver-db-common/src/lib.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ pub trait Db {
113113
fn metrics(&self) -> &Metrics;
114114

115115
/// Gets the user with the given email and service ID.
116-
/// If one doesn't exist, allocates a new user.
116+
/// If one doesn't exist, and when configuration allows it, allocates a new user.
117117
async fn get_or_create_user(
118118
&mut self,
119119
params: params::GetOrCreateUser,
@@ -127,7 +127,11 @@ pub trait Db {
127127

128128
if raw_users.is_empty() {
129129
// There are no users in the database with the given email and service ID, so
130-
// allocate a new one.
130+
// allocate a new one if allowed by configuration.
131+
if !params.allow_new_users {
132+
return Err(DbError::user_not_found(params.email.clone()));
133+
}
134+
131135
let allocate_user_result = self
132136
.allocate_user(params.clone() as params::AllocateUser)
133137
.await?;
@@ -193,6 +197,7 @@ pub trait Db {
193197
client_state: raw_user.client_state.clone(),
194198
keys_changed_at: raw_user.keys_changed_at,
195199
capacity_release_rate: params.capacity_release_rate,
200+
allow_new_users: params.allow_new_users,
196201
})
197202
.await?
198203
};

tokenserver-db-common/src/params.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ pub struct GetOrCreateUser {
3535
pub client_state: String,
3636
pub keys_changed_at: Option<i64>,
3737
pub capacity_release_rate: Option<f32>,
38+
pub allow_new_users: bool,
3839
}
3940

4041
pub type AllocateUser = GetOrCreateUser;

tokenserver-db/src/tests.rs

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -556,6 +556,7 @@ async fn test_node_allocation() -> DbResult<()> {
556556
client_state: "aaaa".to_owned(),
557557
keys_changed_at: Some(1234),
558558
capacity_release_rate: None,
559+
allow_new_users: true,
559560
})
560561
.await?;
561562
assert_eq!(user.node, "https://node1");
@@ -609,6 +610,7 @@ async fn test_allocation_to_least_loaded_node() -> DbResult<()> {
609610
client_state: "aaaa".to_owned(),
610611
keys_changed_at: Some(1234),
611612
capacity_release_rate: None,
613+
allow_new_users: true,
612614
})
613615
.await?;
614616

@@ -620,6 +622,7 @@ async fn test_allocation_to_least_loaded_node() -> DbResult<()> {
620622
client_state: "aaaa".to_owned(),
621623
keys_changed_at: Some(1234),
622624
capacity_release_rate: None,
625+
allow_new_users: true,
623626
})
624627
.await?;
625628

@@ -663,6 +666,7 @@ async fn test_allocation_is_not_allowed_to_downed_nodes() -> DbResult<()> {
663666
client_state: "aaaa".to_owned(),
664667
keys_changed_at: Some(1234),
665668
capacity_release_rate: None,
669+
allow_new_users: true,
666670
})
667671
.await;
668672
let error = result.unwrap_err();
@@ -704,6 +708,7 @@ async fn test_allocation_is_not_allowed_to_backoff_nodes() -> DbResult<()> {
704708
client_state: "aaaa".to_owned(),
705709
keys_changed_at: Some(1234),
706710
capacity_release_rate: None,
711+
allow_new_users: true,
707712
})
708713
.await;
709714
let error = result.unwrap_err();
@@ -744,6 +749,7 @@ async fn test_node_reassignment_when_records_are_replaced() -> DbResult<()> {
744749
client_state: "aaaa".to_owned(),
745750
keys_changed_at: Some(1234),
746751
capacity_release_rate: None,
752+
allow_new_users: true,
747753
})
748754
.await?;
749755
let user1 = db
@@ -768,6 +774,7 @@ async fn test_node_reassignment_when_records_are_replaced() -> DbResult<()> {
768774
client_state: "bbbb".to_owned(),
769775
keys_changed_at: Some(1235),
770776
capacity_release_rate: None,
777+
allow_new_users: true,
771778
})
772779
.await?;
773780

@@ -816,6 +823,7 @@ async fn test_node_reassignment_not_done_for_retired_users() -> DbResult<()> {
816823
client_state: "aaaa".to_owned(),
817824
keys_changed_at: Some(1234),
818825
capacity_release_rate: None,
826+
allow_new_users: true,
819827
})
820828
.await?;
821829

@@ -827,6 +835,7 @@ async fn test_node_reassignment_not_done_for_retired_users() -> DbResult<()> {
827835
client_state: "aaaa".to_owned(),
828836
keys_changed_at: Some(1234),
829837
capacity_release_rate: None,
838+
allow_new_users: true,
830839
})
831840
.await?;
832841

@@ -884,6 +893,7 @@ async fn test_node_reassignment_and_removal() -> DbResult<()> {
884893
client_state: "aaaa".to_owned(),
885894
keys_changed_at: Some(1234),
886895
capacity_release_rate: None,
896+
allow_new_users: true,
887897
})
888898
.await?;
889899

@@ -895,6 +905,7 @@ async fn test_node_reassignment_and_removal() -> DbResult<()> {
895905
client_state: "aaaa".to_owned(),
896906
keys_changed_at: Some(1234),
897907
capacity_release_rate: None,
908+
allow_new_users: true,
898909
})
899910
.await?;
900911

@@ -906,6 +917,7 @@ async fn test_node_reassignment_and_removal() -> DbResult<()> {
906917
client_state: "aaaa".to_owned(),
907918
keys_changed_at: Some(1234),
908919
capacity_release_rate: None,
920+
allow_new_users: true,
909921
})
910922
.await?;
911923

@@ -917,6 +929,7 @@ async fn test_node_reassignment_and_removal() -> DbResult<()> {
917929
client_state: "aaaa".to_owned(),
918930
keys_changed_at: Some(1234),
919931
capacity_release_rate: None,
932+
allow_new_users: true,
920933
})
921934
.await?;
922935

@@ -949,6 +962,7 @@ async fn test_node_reassignment_and_removal() -> DbResult<()> {
949962
client_state: user.client_state.clone(),
950963
keys_changed_at: user.keys_changed_at,
951964
capacity_release_rate: None,
965+
allow_new_users: true,
952966
})
953967
.await?;
954968

@@ -978,6 +992,7 @@ async fn test_node_reassignment_and_removal() -> DbResult<()> {
978992
client_state: user.client_state.clone(),
979993
keys_changed_at: user.keys_changed_at,
980994
capacity_release_rate: None,
995+
allow_new_users: true,
981996
})
982997
.await?;
983998

@@ -1034,6 +1049,7 @@ async fn test_gradual_release_of_node_capacity() -> DbResult<()> {
10341049
client_state: "aaaa".to_owned(),
10351050
keys_changed_at: Some(1234),
10361051
capacity_release_rate: None,
1052+
allow_new_users: true,
10371053
})
10381054
.await?;
10391055

@@ -1051,6 +1067,7 @@ async fn test_gradual_release_of_node_capacity() -> DbResult<()> {
10511067
client_state: "aaaa".to_owned(),
10521068
keys_changed_at: Some(1234),
10531069
capacity_release_rate: None,
1070+
allow_new_users: true,
10541071
})
10551072
.await?;
10561073

@@ -1070,6 +1087,7 @@ async fn test_gradual_release_of_node_capacity() -> DbResult<()> {
10701087
client_state: "aaaa".to_owned(),
10711088
keys_changed_at: Some(1234),
10721089
capacity_release_rate: None,
1090+
allow_new_users: true,
10731091
})
10741092
.await?;
10751093

@@ -1087,6 +1105,7 @@ async fn test_gradual_release_of_node_capacity() -> DbResult<()> {
10871105
client_state: "aaaa".to_owned(),
10881106
keys_changed_at: Some(1234),
10891107
capacity_release_rate: None,
1108+
allow_new_users: true,
10901109
})
10911110
.await?;
10921111

@@ -1105,6 +1124,7 @@ async fn test_gradual_release_of_node_capacity() -> DbResult<()> {
11051124
client_state: "aaaa".to_owned(),
11061125
keys_changed_at: Some(1234),
11071126
capacity_release_rate: None,
1127+
allow_new_users: true,
11081128
})
11091129
.await?;
11101130

@@ -1122,6 +1142,7 @@ async fn test_gradual_release_of_node_capacity() -> DbResult<()> {
11221142
client_state: "aaaa".to_owned(),
11231143
keys_changed_at: Some(1234),
11241144
capacity_release_rate: None,
1145+
allow_new_users: true,
11251146
})
11261147
.await?;
11271148

@@ -1140,6 +1161,7 @@ async fn test_gradual_release_of_node_capacity() -> DbResult<()> {
11401161
client_state: "aaaa".to_owned(),
11411162
keys_changed_at: Some(1234),
11421163
capacity_release_rate: None,
1164+
allow_new_users: true,
11431165
})
11441166
.await;
11451167

@@ -1185,6 +1207,7 @@ async fn test_correct_created_at_used_during_node_reassignment() -> DbResult<()>
11851207
client_state: "aaaa".to_owned(),
11861208
keys_changed_at: Some(1234),
11871209
capacity_release_rate: None,
1210+
allow_new_users: true,
11881211
})
11891212
.await?;
11901213

@@ -1204,6 +1227,7 @@ async fn test_correct_created_at_used_during_node_reassignment() -> DbResult<()>
12041227
client_state: "aaaa".to_owned(),
12051228
keys_changed_at: Some(1234),
12061229
capacity_release_rate: None,
1230+
allow_new_users: true,
12071231
})
12081232
.await?;
12091233

@@ -1245,6 +1269,7 @@ async fn test_correct_created_at_used_during_user_retrieval() -> DbResult<()> {
12451269
client_state: "aaaa".to_owned(),
12461270
keys_changed_at: Some(1234),
12471271
capacity_release_rate: None,
1272+
allow_new_users: true,
12481273
})
12491274
.await?;
12501275

@@ -1261,6 +1286,7 @@ async fn test_correct_created_at_used_during_user_retrieval() -> DbResult<()> {
12611286
client_state: "aaaa".to_owned(),
12621287
keys_changed_at: Some(1234),
12631288
capacity_release_rate: None,
1289+
allow_new_users: true,
12641290
})
12651291
.await?;
12661292

@@ -1270,6 +1296,46 @@ async fn test_correct_created_at_used_during_user_retrieval() -> DbResult<()> {
12701296
Ok(())
12711297
}
12721298

1299+
#[tokio::test]
1300+
async fn test_no_new_user_allocation() -> DbResult<()> {
1301+
let pool = db_pool().await?;
1302+
let mut db = pool.get().await?;
1303+
1304+
let service_id = db
1305+
.get_service_id(params::GetServiceId {
1306+
service: "sync-1.5".to_owned(),
1307+
})
1308+
.await?
1309+
.id;
1310+
1311+
// Add a node
1312+
db.post_node(params::PostNode {
1313+
service_id,
1314+
node: "https://node1".to_owned(),
1315+
current_load: 4,
1316+
capacity: 8,
1317+
available: 1,
1318+
..Default::default()
1319+
})
1320+
.await?;
1321+
1322+
// Try to create a user
1323+
let result = db
1324+
.get_or_create_user(params::GetOrCreateUser {
1325+
service_id,
1326+
generation: 1234,
1327+
email: "test4@test.com".to_owned(),
1328+
client_state: "aaaa".to_owned(),
1329+
keys_changed_at: Some(1234),
1330+
capacity_release_rate: None,
1331+
allow_new_users: false,
1332+
})
1333+
.await;
1334+
assert!(result.unwrap_err().is_user_not_found());
1335+
1336+
Ok(())
1337+
}
1338+
12731339
#[tokio::test]
12741340
async fn test_latest_created_at() -> DbResult<()> {
12751341
let pool = db_pool().await?;

0 commit comments

Comments
 (0)