Skip to content

Commit a17eef7

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

9 files changed

Lines changed: 79 additions & 3 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: 1 addition & 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());

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

syncstorage-db-common/src/diesel.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,10 @@ impl DbError {
3131
DbErrorKind::Common(SyncstorageDbError::collection_not_found()).into()
3232
}
3333

34+
pub fn user_not_found() -> Self {
35+
DbErrorKind::Common(SyncstorageDbError::user_not_found()).into()
36+
}
37+
3438
pub fn conflict() -> Self {
3539
DbErrorKind::Common(SyncstorageDbError::conflict()).into()
3640
}

syncstorage-db-common/src/error.rs

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@ enum SyncstorageDbErrorKind {
2828
#[error("Specified collection does not exist")]
2929
CollectionNotFound,
3030

31+
/// User cannot be found.
32+
#[error("Specified user does not exist")]
33+
UserNotFound,
34+
3135
/// BSO object cannot be found.
3236
#[error("Specified bso does not exist")]
3337
BsoNotFound,
@@ -65,6 +69,10 @@ impl SyncstorageDbError {
6569
SyncstorageDbErrorKind::CollectionNotFound.into()
6670
}
6771

72+
pub fn user_not_found() -> Self {
73+
SyncstorageDbErrorKind::UserNotFound.into()
74+
}
75+
6876
pub fn conflict() -> Self {
6977
SyncstorageDbErrorKind::Conflict.into()
7078
}
@@ -82,6 +90,7 @@ impl SyncstorageDbError {
8290
/// `SyncstorageDbErrorKind` matches the kind passed in.
8391
pub trait DbErrorIntrospect {
8492
fn is_collection_not_found(&self) -> bool;
93+
fn is_user_not_found(&self) -> bool;
8594
fn is_conflict(&self) -> bool;
8695
fn is_quota(&self) -> bool;
8796
fn is_bso_not_found(&self) -> bool;
@@ -95,6 +104,10 @@ impl DbErrorIntrospect for SyncstorageDbError {
95104
matches!(self.kind, SyncstorageDbErrorKind::CollectionNotFound)
96105
}
97106

107+
fn is_user_not_found(&self) -> bool {
108+
matches!(self.kind, SyncstorageDbErrorKind::UserNotFound)
109+
}
110+
98111
fn is_conflict(&self) -> bool {
99112
matches!(self.kind, SyncstorageDbErrorKind::Conflict)
100113
}
@@ -140,7 +153,11 @@ impl From<SyncstorageDbErrorKind> for SyncstorageDbError {
140153
/// Fills in the HTTP status and a new backtrace automatically.
141154
fn from(kind: SyncstorageDbErrorKind) -> Self {
142155
let status = match kind {
143-
SyncstorageDbErrorKind::CollectionNotFound | SyncstorageDbErrorKind::BsoNotFound => {
156+
(
157+
SyncstorageDbErrorKind::CollectionNotFound |
158+
SyncstorageDbErrorKind::UserNotFound |
159+
SyncstorageDbErrorKind::BsoNotFound
160+
) => {
144161
StatusCode::NOT_FOUND
145162
}
146163
// Matching the Python code here (a 400 vs 404)

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,12 @@ 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+
warn!("New users registration is disabled by configuration"; "email" => params.email);
133+
return Err(DbError::user_not_found());
134+
}
135+
131136
let allocate_user_result = self
132137
.allocate_user(params.clone() as params::AllocateUser)
133138
.await?;

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: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1270,6 +1270,47 @@ async fn test_correct_created_at_used_during_user_retrieval() -> DbResult<()> {
12701270
Ok(())
12711271
}
12721272

1273+
#[tokio::test]
1274+
async fn test_no_new_user_allocation() -> DbResult<()> {
1275+
let pool = db_pool().await?;
1276+
let mut db = pool.get().await?;
1277+
1278+
let service_id = db
1279+
.get_service_id(params::GetServiceId {
1280+
service: "sync-1.5".to_owned(),
1281+
})
1282+
.await?
1283+
.id;
1284+
1285+
// Add a downed node
1286+
db.post_node(params::PostNode {
1287+
service_id,
1288+
node: "https://node1".to_owned(),
1289+
current_load: 0,
1290+
capacity: 100,
1291+
available: 100,
1292+
downed: 1,
1293+
..Default::default()
1294+
})
1295+
.await?;
1296+
1297+
// User allocation fails because users allocation is disabled
1298+
let result = db
1299+
.allocate_user(params::AllocateUser {
1300+
service_id,
1301+
generation: 1234,
1302+
email: "test@test.com".to_owned(),
1303+
client_state: "aaaa".to_owned(),
1304+
keys_changed_at: Some(1234),
1305+
capacity_release_rate: None,
1306+
allow_new_users: false,
1307+
})
1308+
.await;
1309+
assert!(result.unwrap_err().is_user_not_found());
1310+
1311+
Ok(())
1312+
}
1313+
12731314
#[tokio::test]
12741315
async fn test_latest_created_at() -> DbResult<()> {
12751316
let pool = db_pool().await?;

tokenserver-settings/src/lib.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,9 @@ pub struct Settings {
6666
/// Whether to enable the FxA webhook endpoint.
6767
/// Defaults to false.
6868
pub fxa_webhook_enabled: bool,
69+
/// Whether new users may register to the Tokenserver.
70+
/// Defaults to true.
71+
pub allow_new_users: bool,
6972
}
7073

7174
impl Default for Settings {
@@ -93,6 +96,7 @@ impl Default for Settings {
9396
init_node_url: None,
9497
init_node_capacity: 100000,
9598
fxa_webhook_enabled: false,
99+
allow_new_users: true,
96100
}
97101
}
98102
}

0 commit comments

Comments
 (0)