Skip to content

Commit 2a46845

Browse files
committed
Use PUT instead of POST to mitigate CSRF
1 parent e8cae0e commit 2a46845

File tree

4 files changed

+27
-18
lines changed

4 files changed

+27
-18
lines changed

app/adapters/api-token.js

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,14 @@ export default DS.RESTAdapter.extend({
44
namespace: 'api/v1/me',
55
pathForType() {
66
return 'tokens';
7-
}
7+
},
8+
createRecord(store, type, snapshot) {
9+
let data = {};
10+
let serializer = store.serializerFor(type.modelName);
11+
let url = this.buildURL(type.modelName, null, snapshot, 'createRecord');
12+
13+
serializer.serializeIntoHash(data, type, snapshot, { includeId: true });
14+
15+
return this.ajax(url, 'PUT', { data });
16+
},
817
});

src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,7 @@ pub fn middleware(app: Arc<App>) -> MiddlewareBuilder {
206206
api_router.get("/me", C(user::me));
207207
api_router.get("/me/updates", C(user::updates));
208208
api_router.get("/me/tokens", C(token::list));
209-
api_router.post("/me/tokens", C(token::new));
209+
api_router.put("/me/tokens", C(token::new));
210210
api_router.delete("/me/tokens/:id", C(token::revoke));
211211
api_router.get(
212212
"/me/crate_owner_invitations",

src/tests/token.rs

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ fn list_tokens() {
8787
#[test]
8888
fn create_token_logged_out() {
8989
let (_b, app, middle) = ::app();
90-
let mut req = ::req(app.clone(), Method::Post, "/api/v1/me/tokens");
90+
let mut req = ::req(app.clone(), Method::Put, "/api/v1/me/tokens");
9191

9292
req.with_body(br#"{ "api_token": { "name": "bar" } }"#);
9393

@@ -98,7 +98,7 @@ fn create_token_logged_out() {
9898
#[test]
9999
fn create_token_invalid_request() {
100100
let (_b, app, middle) = ::app();
101-
let mut req = ::req(app.clone(), Method::Post, "/api/v1/me/tokens");
101+
let mut req = ::req(app.clone(), Method::Put, "/api/v1/me/tokens");
102102

103103
let user = {
104104
let conn = t!(app.diesel_database.get());
@@ -117,7 +117,7 @@ fn create_token_invalid_request() {
117117
#[test]
118118
fn create_token_no_name() {
119119
let (_b, app, middle) = ::app();
120-
let mut req = ::req(app.clone(), Method::Post, "/api/v1/me/tokens");
120+
let mut req = ::req(app.clone(), Method::Put, "/api/v1/me/tokens");
121121

122122
let user = {
123123
let conn = t!(app.diesel_database.get());
@@ -136,7 +136,7 @@ fn create_token_no_name() {
136136
#[test]
137137
fn create_token_long_body() {
138138
let (_b, app, middle) = ::app();
139-
let mut req = ::req(app.clone(), Method::Post, "/api/v1/me/tokens");
139+
let mut req = ::req(app.clone(), Method::Put, "/api/v1/me/tokens");
140140

141141
let user = {
142142
let conn = t!(app.diesel_database.get());
@@ -149,13 +149,13 @@ fn create_token_long_body() {
149149
let json: ::Bad = ::json(&mut response);
150150

151151
assert_eq!(response.status.0, 400);
152-
assert_contains!(json.errors[0].detail, "max post size");
152+
assert_contains!(json.errors[0].detail, "max content length");
153153
}
154154

155155
#[test]
156156
fn create_token_exceeded_tokens_per_user() {
157157
let (_b, app, middle) = ::app();
158-
let mut req = ::req(app.clone(), Method::Post, "/api/v1/me/tokens");
158+
let mut req = ::req(app.clone(), Method::Put, "/api/v1/me/tokens");
159159

160160
let user;
161161
{
@@ -178,7 +178,7 @@ fn create_token_exceeded_tokens_per_user() {
178178
#[test]
179179
fn create_token_success() {
180180
let (_b, app, middle) = ::app();
181-
let mut req = ::req(app.clone(), Method::Post, "/api/v1/me/tokens");
181+
let mut req = ::req(app.clone(), Method::Put, "/api/v1/me/tokens");
182182

183183
let user = {
184184
let conn = t!(app.diesel_database.get());
@@ -211,14 +211,14 @@ fn create_token_multiple_have_different_values() {
211211
};
212212

213213
let first = {
214-
let mut req = ::req(app.clone(), Method::Post, "/api/v1/me/tokens");
214+
let mut req = ::req(app.clone(), Method::Put, "/api/v1/me/tokens");
215215
::sign_in_as(&mut req, &user);
216216
req.with_body(br#"{ "api_token": { "name": "bar" } }"#);
217217
::json::<NewResponse>(&mut ok_resp!(middle.call(&mut req)))
218218
};
219219

220220
let second = {
221-
let mut req = ::req(app.clone(), Method::Post, "/api/v1/me/tokens");
221+
let mut req = ::req(app.clone(), Method::Put, "/api/v1/me/tokens");
222222
::sign_in_as(&mut req, &user);
223223
req.with_body(br#"{ "api_token": { "name": "bar" } }"#);
224224
::json::<NewResponse>(&mut ok_resp!(middle.call(&mut req)))
@@ -242,14 +242,14 @@ fn create_token_multiple_users_have_different_values() {
242242
};
243243

244244
let first_token = {
245-
let mut req = ::req(app.clone(), Method::Post, "/api/v1/me/tokens");
245+
let mut req = ::req(app.clone(), Method::Put, "/api/v1/me/tokens");
246246
::sign_in_as(&mut req, &first_user);
247247
req.with_body(br#"{ "api_token": { "name": "baz" } }"#);
248248
::json::<NewResponse>(&mut ok_resp!(middle.call(&mut req)))
249249
};
250250

251251
let second_token = {
252-
let mut req = ::req(app.clone(), Method::Post, "/api/v1/me/tokens");
252+
let mut req = ::req(app.clone(), Method::Put, "/api/v1/me/tokens");
253253
::sign_in_as(&mut req, &second_user);
254254
req.with_body(br#"{ "api_token": { "name": "baz" } }"#);
255255
::json::<NewResponse>(&mut ok_resp!(middle.call(&mut req)))
@@ -261,7 +261,7 @@ fn create_token_multiple_users_have_different_values() {
261261
#[test]
262262
fn create_token_with_token() {
263263
let (_b, app, middle) = ::app();
264-
let mut req = ::req(app.clone(), Method::Post, "/api/v1/me/tokens");
264+
let mut req = ::req(app.clone(), Method::Put, "/api/v1/me/tokens");
265265

266266
let (user, token);
267267
{

src/token.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ pub fn list(req: &mut Request) -> CargoResult<Response> {
6969
Ok(req.json(&R { api_tokens: tokens }))
7070
}
7171

72-
/// Handles the `POST /me/tokens` route.
72+
/// Handles the `PUT /me/tokens` route.
7373
pub fn new(req: &mut Request) -> CargoResult<Response> {
7474
/// The incoming serialization format for the `ApiToken` model.
7575
#[derive(Deserialize, Serialize)]
@@ -89,12 +89,12 @@ pub fn new(req: &mut Request) -> CargoResult<Response> {
8989
));
9090
}
9191

92-
let max_post_size = 2000;
92+
let max_size = 2000;
9393
let length = req.content_length()
9494
.chain_error(|| bad_request("missing header: Content-Length"))?;
9595

96-
if length > max_post_size {
97-
return Err(bad_request(&format!("max post size is: {}", max_post_size)));
96+
if length > max_size {
97+
return Err(bad_request(&format!("max content length is: {}", max_size)));
9898
}
9999

100100
let mut json = vec![0; length as usize];

0 commit comments

Comments
 (0)