Skip to content

Commit 3b983b0

Browse files
committed
Add an option to disable the requirement for email verification before publishing
1 parent 84504ab commit 3b983b0

File tree

6 files changed

+128
-9
lines changed

6 files changed

+128
-9
lines changed

.env.sample

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,3 +60,7 @@ export GH_CLIENT_SECRET=
6060
# Credentials for connecting to the Sentry error reporting service.
6161
# export SENTRY_DSN_API=
6262
export SENTRY_ENV_API=local
63+
64+
# If you don't require users to complete email verification before
65+
# they can publish a crate, uncomment this line.
66+
# export DISABLE_EMAIL_VERIFICATION_REQUIREMENT=1

src/config.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ pub struct Config {
1818
pub blocked_traffic: Vec<(String, Vec<String>)>,
1919
pub domain_name: String,
2020
pub allowed_origins: Vec<String>,
21+
pub require_email_verification: bool,
2122
}
2223

2324
impl Default for Config {
@@ -44,6 +45,8 @@ impl Default for Config {
4445
/// - `READ_ONLY_REPLICA_URL`: The URL of an optional postgres read-only replica database.
4546
/// - `BLOCKED_TRAFFIC`: A list of headers and environment variables to use for blocking
4647
///. traffic. See the `block_traffic` module for more documentation.
48+
/// - `DISABLE_EMAIL_VERIFICATION_REQUIREMENT`: Disable the requirement that email must be
49+
///. verified before publishing a crate.
4750
fn default() -> Config {
4851
let api_protocol = String::from("https");
4952
let mirror = if dotenv::var("MIRROR").is_ok() {
@@ -142,6 +145,7 @@ impl Default for Config {
142145
blocked_traffic: blocked_traffic(),
143146
domain_name: domain_name(),
144147
allowed_origins,
148+
require_email_verification: require_email_verification(),
145149
}
146150
}
147151
}
@@ -150,6 +154,10 @@ pub(crate) fn domain_name() -> String {
150154
dotenv::var("DOMAIN_NAME").unwrap_or_else(|_| "crates.io".into())
151155
}
152156

157+
fn require_email_verification() -> bool {
158+
!dotenv::var("DISABLE_EMAIL_VERIFICATION_REQUIREMENT").is_ok()
159+
}
160+
153161
fn blocked_traffic() -> Vec<(String, Vec<String>)> {
154162
let pattern_list = dotenv::var("BLOCKED_TRAFFIC").unwrap_or_default();
155163
parse_traffic_patterns(&pattern_list)

src/controllers/krate/publish.rs

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -49,14 +49,25 @@ pub fn publish(req: &mut dyn RequestExt) -> EndpointResult {
4949
let api_token_id = ids.api_token_id();
5050
let user = ids.user();
5151

52-
let verified_email_address = user.verified_email(&conn)?;
53-
let verified_email_address = verified_email_address.ok_or_else(|| {
54-
cargo_err(&format!(
55-
"A verified email address is required to publish crates to crates.io. \
56-
Visit https://{}/me to set and verify your email address.",
57-
app.config.domain_name,
58-
))
59-
})?;
52+
let email_address = if app.config.require_email_verification {
53+
let verified_email_address = user.verified_email(&conn)?;
54+
verified_email_address.ok_or_else(|| {
55+
cargo_err(&format!(
56+
"A verified email address is required to publish crates to crates.io. \
57+
Visit https://{}/me to set and verify your email address.",
58+
app.config.domain_name,
59+
))
60+
})?
61+
} else {
62+
let email_address = user.email(&conn)?;
63+
email_address.ok_or_else(|| {
64+
cargo_err(&format!(
65+
"An email address is required to publish crates to crates.io. \
66+
Visit https://{}/me to set and verify your email address.",
67+
app.config.domain_name,
68+
))
69+
})?
70+
};
6071

6172
// Create a transaction on the database, if there are no errors,
6273
// commit the transactions to record a new or updated crate.
@@ -151,7 +162,7 @@ pub fn publish(req: &mut dyn RequestExt) -> EndpointResult {
151162
file_length as i32,
152163
user.id,
153164
)?
154-
.save(&conn, &new_crate.authors, &verified_email_address)?;
165+
.save(&conn, &new_crate.authors, &email_address)?;
155166

156167
insert_version_owner_action(
157168
&conn,

src/tests/all.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@ fn simple_config() -> Config {
140140
blocked_traffic: Default::default(),
141141
domain_name: "crates.io".into(),
142142
allowed_origins: Vec::new(),
143+
require_email_verification: true,
143144
}
144145
}
145146

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
[
2+
{
3+
"request": {
4+
"uri": "http://alexcrichton-test.s3.amazonaws.com/crates/foo_unverified_email/foo_unverified_email-1.0.0.crate",
5+
"method": "PUT",
6+
"headers": [
7+
[
8+
"accept",
9+
"*/*"
10+
],
11+
[
12+
"content-length",
13+
"35"
14+
],
15+
[
16+
"host",
17+
"alexcrichton-test.s3.amazonaws.com"
18+
],
19+
[
20+
"accept-encoding",
21+
"gzip"
22+
],
23+
[
24+
"content-type",
25+
"application/x-tar"
26+
],
27+
[
28+
"authorization",
29+
"AWS AKIAICL5IWUZYWWKA7JA:uDc39eNdF6CcwB+q+JwKsoDLQc4="
30+
],
31+
[
32+
"date",
33+
"Fri, 15 Sep 2017 07:53:06 -0700"
34+
]
35+
],
36+
"body": "H4sIAAAAAAAA/+3AAQEAAACCIP+vbkhQwKsBLq+17wAEAAA="
37+
},
38+
"response": {
39+
"status": 200,
40+
"headers": [
41+
[
42+
"x-amz-request-id",
43+
"26589A5E52F8395C"
44+
],
45+
[
46+
"ETag",
47+
"\"f9016ad360cebb4fe2e6e96e5949f022\""
48+
],
49+
[
50+
"date",
51+
"Fri, 15 Sep 2017 14:53:07 GMT"
52+
],
53+
[
54+
"content-length",
55+
"0"
56+
],
57+
[
58+
"x-amz-id-2",
59+
"JdIvnNTw53aqXjBIqBLNuN4kxf/w1XWX+xuIiGBDYy7yzOSDuAMtBSrTW4ZWetcCIdqCUHuQ51A="
60+
],
61+
[
62+
"Server",
63+
"AmazonS3"
64+
]
65+
],
66+
"body": ""
67+
}
68+
}
69+
]

src/tests/krate/publish.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -619,6 +619,32 @@ fn new_krate_with_unverified_email_fails() {
619619
);
620620
}
621621

622+
#[test]
623+
fn new_krate_records_with_unverified_email_if_email_verification_disabled() {
624+
let (app, _, _, token) = TestApp::full()
625+
.with_config(|c| c.require_email_verification = false)
626+
.with_token();
627+
628+
app.db(|conn| {
629+
update(emails::table)
630+
.set((emails::verified.eq(false),))
631+
.execute(conn)
632+
.unwrap();
633+
});
634+
635+
let crate_to_publish = PublishBuilder::new("foo_unverified_email");
636+
637+
token.enqueue_publish(crate_to_publish).good();
638+
639+
app.db(|conn| {
640+
let email: String = versions_published_by::table
641+
.select(versions_published_by::email)
642+
.first(conn)
643+
.unwrap();
644+
assert_eq!(email, "[email protected]");
645+
});
646+
}
647+
622648
#[test]
623649
fn new_krate_records_verified_email() {
624650
let (app, _, _, token) = TestApp::full().with_token();

0 commit comments

Comments
 (0)