Skip to content

Commit a586fc3

Browse files
authored
Merge pull request #24 from SakaDream/support-sqlite
Support sqlite
2 parents 6f12db1 + a033ad3 commit a586fc3

File tree

15 files changed

+431
-17
lines changed

15 files changed

+431
-17
lines changed

.env.sample

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
11
APP_HOST=localhost
22
APP_PORT=8000
3-
DATABASE_URL=postgres://username:password@server/db_name
3+
# For Postgres
4+
DATABASE_URL=postgres://username:password@server/db_name
5+
# For SQLite
6+
DATABASE_URL=file://path/to/database/file.db

.github/workflows/ci_action.yml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,12 @@ jobs:
6767
command: clippy
6868
args: -- -D warnings
6969

70+
- name: Run cargo test
71+
uses: actions-rs/cargo@v1
72+
with:
73+
command: test
74+
args: -- --nocapture
75+
7076
- name: Run cargo build
7177
uses: actions-rs/cargo@v1
7278
with:
@@ -138,6 +144,14 @@ jobs:
138144
command: clippy
139145
args: -- -D warnings
140146

147+
- name: Run cargo test
148+
uses: actions-rs/cargo@v1
149+
with:
150+
command: test
151+
args: -- --nocapture
152+
env:
153+
RUSTFLAGS: -L D:\a\actix-web-rest-api-with-jwt\actix-web-rest-api-with-jwt\libs\windows
154+
141155
- name: Run cargo build
142156
uses: actions-rs/cargo@v1
143157
with:
@@ -210,6 +224,12 @@ jobs:
210224
command: clippy
211225
args: -- -D warnings
212226

227+
- name: Run cargo test
228+
uses: actions-rs/cargo@v1
229+
with:
230+
command: test
231+
args: -- --nocapture
232+
213233
- name: Run cargo build
214234
uses: actions-rs/cargo@v1
215235
with:

Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,3 +33,7 @@ features = ["serde"]
3333
[dependencies.uuid]
3434
version = "0.8.1"
3535
features = ["v4"]
36+
37+
[dev-dependencies.diesel]
38+
version = "1.4.5"
39+
features = ["sqlite", "r2d2", "chrono"]

libs/windows/sqlite3.lib

60.4 KB
Binary file not shown.

rustfmt.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
reorder_imports = true

src/api/account_controller.rs

Lines changed: 297 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,3 +34,300 @@ pub async fn logout(req: HttpRequest, pool: web::Data<Pool>) -> Result<HttpRespo
3434
Ok(HttpResponse::BadRequest().json(ResponseBody::new(constants::MESSAGE_TOKEN_MISSING, constants::EMPTY)))
3535
}
3636
}
37+
38+
#[cfg(test)]
39+
mod tests {
40+
use crate::{App, config};
41+
use actix_cors::Cors;
42+
use actix_service::Service;
43+
use actix_web::{test, http, http::StatusCode};
44+
use futures::FutureExt;
45+
use http::header;
46+
47+
#[actix_rt::test]
48+
async fn test_signup_ok() {
49+
let mut app = test::init_service(
50+
App::new()
51+
.wrap(Cors::new()
52+
.send_wildcard()
53+
.allowed_methods(vec!["GET", "POST", "PUT", "DELETE"])
54+
.allowed_header(http::header::CONTENT_TYPE)
55+
.max_age(3600)
56+
.finish())
57+
.data(config::db::migrate_and_config_db(":memory:"))
58+
.wrap(actix_web::middleware::Logger::default())
59+
.wrap(crate::middleware::authen_middleware::Authentication)
60+
.wrap_fn(|req, srv| {
61+
srv.call(req).map(|res| res)
62+
})
63+
.configure(crate::config::app::config_services)
64+
).await;
65+
66+
let resp = test::TestRequest::post()
67+
.uri("/api/auth/signup")
68+
.set(header::ContentType::json())
69+
.set_payload(r#"{"username":"admin","email":"admin@gmail.com","password":"123456"}"#.as_bytes())
70+
.send_request(&mut app)
71+
.await;
72+
73+
// let data = test::read_body(resp).await;
74+
75+
// println!("{:#?}", &data);
76+
assert_eq!(resp.status(), StatusCode::OK);
77+
}
78+
79+
#[actix_rt::test]
80+
async fn test_signup_duplicate_user() {
81+
let mut app = test::init_service(
82+
App::new()
83+
.wrap(Cors::new()
84+
.send_wildcard()
85+
.allowed_methods(vec!["GET", "POST", "PUT", "DELETE"])
86+
.allowed_header(http::header::CONTENT_TYPE)
87+
.max_age(3600)
88+
.finish())
89+
.data(config::db::migrate_and_config_db(":memory:"))
90+
.wrap(actix_web::middleware::Logger::default())
91+
.wrap(crate::middleware::authen_middleware::Authentication)
92+
.wrap_fn(|req, srv| {
93+
srv.call(req).map(|res| res)
94+
})
95+
.configure(crate::config::app::config_services)
96+
).await;
97+
98+
test::TestRequest::post()
99+
.uri("/api/auth/signup")
100+
.set(header::ContentType::json())
101+
.set_payload(r#"{"username":"admin","email":"admin@gmail.com","password":"123456"}"#.as_bytes())
102+
.send_request(&mut app)
103+
.await;
104+
105+
let resp = test::TestRequest::post()
106+
.uri("/api/auth/signup")
107+
.set(header::ContentType::json())
108+
.set_payload(r#"{"username":"admin","email":"admin@gmail.com","password":"123456"}"#.as_bytes())
109+
.send_request(&mut app)
110+
.await;
111+
112+
// let data = test::read_body(resp).await;
113+
114+
// println!("{:#?}", &data);
115+
assert_eq!(resp.status(), StatusCode::BAD_REQUEST);
116+
}
117+
118+
#[actix_rt::test]
119+
async fn test_login_ok_with_username() {
120+
let mut app = test::init_service(
121+
App::new()
122+
.wrap(Cors::new()
123+
.send_wildcard()
124+
.allowed_methods(vec!["GET", "POST", "PUT", "DELETE"])
125+
.allowed_header(http::header::CONTENT_TYPE)
126+
.max_age(3600)
127+
.finish())
128+
.data(config::db::migrate_and_config_db(":memory:"))
129+
.wrap(actix_web::middleware::Logger::default())
130+
.wrap(crate::middleware::authen_middleware::Authentication)
131+
.wrap_fn(|req, srv| {
132+
srv.call(req).map(|res| res)
133+
})
134+
.configure(crate::config::app::config_services)
135+
).await;
136+
137+
test::TestRequest::post()
138+
.uri("/api/auth/signup")
139+
.set(header::ContentType::json())
140+
.set_payload(r#"{"username":"admin","email":"admin@gmail.com","password":"123456"}"#.as_bytes())
141+
.send_request(&mut app)
142+
.await;
143+
144+
let resp = test::TestRequest::post()
145+
.uri("/api/auth/login")
146+
.set(header::ContentType::json())
147+
.set_payload(r#"{"username_or_email":"admin","password":"123456"}"#.as_bytes())
148+
.send_request(&mut app)
149+
.await;
150+
151+
assert_eq!(resp.status(), StatusCode::OK);
152+
}
153+
154+
#[actix_rt::test]
155+
async fn test_login_ok_with_email() {
156+
let mut app = test::init_service(
157+
App::new()
158+
.wrap(Cors::new()
159+
.send_wildcard()
160+
.allowed_methods(vec!["GET", "POST", "PUT", "DELETE"])
161+
.allowed_header(http::header::CONTENT_TYPE)
162+
.max_age(3600)
163+
.finish())
164+
.data(config::db::migrate_and_config_db(":memory:"))
165+
.wrap(actix_web::middleware::Logger::default())
166+
.wrap(crate::middleware::authen_middleware::Authentication)
167+
.wrap_fn(|req, srv| {
168+
srv.call(req).map(|res| res)
169+
})
170+
.configure(crate::config::app::config_services)
171+
).await;
172+
173+
test::TestRequest::post()
174+
.uri("/api/auth/signup")
175+
.set(header::ContentType::json())
176+
.set_payload(r#"{"username":"admin","email":"admin@gmail.com","password":"123456"}"#.as_bytes())
177+
.send_request(&mut app)
178+
.await;
179+
180+
let resp = test::TestRequest::post()
181+
.uri("/api/auth/login")
182+
.set(header::ContentType::json())
183+
.set_payload(r#"{"username_or_email":"admin@gmail.com","password":"123456"}"#.as_bytes())
184+
.send_request(&mut app)
185+
.await;
186+
187+
assert_eq!(resp.status(), StatusCode::OK);
188+
}
189+
190+
#[actix_rt::test]
191+
async fn test_login_password_incorrect_with_username() {
192+
let mut app = test::init_service(
193+
App::new()
194+
.wrap(Cors::new()
195+
.send_wildcard()
196+
.allowed_methods(vec!["GET", "POST", "PUT", "DELETE"])
197+
.allowed_header(http::header::CONTENT_TYPE)
198+
.max_age(3600)
199+
.finish())
200+
.data(config::db::migrate_and_config_db(":memory:"))
201+
.wrap(actix_web::middleware::Logger::default())
202+
.wrap(crate::middleware::authen_middleware::Authentication)
203+
.wrap_fn(|req, srv| {
204+
srv.call(req).map(|res| res)
205+
})
206+
.configure(crate::config::app::config_services)
207+
).await;
208+
209+
test::TestRequest::post()
210+
.uri("/api/auth/signup")
211+
.set(header::ContentType::json())
212+
.set_payload(r#"{"username":"admin","email":"admin@gmail.com","password":"123456"}"#.as_bytes())
213+
.send_request(&mut app)
214+
.await;
215+
216+
let resp = test::TestRequest::post()
217+
.uri("/api/auth/login")
218+
.set(header::ContentType::json())
219+
.set_payload(r#"{"username_or_email":"admin","password":"password"}"#.as_bytes())
220+
.send_request(&mut app)
221+
.await;
222+
223+
assert_eq!(resp.status(), StatusCode::UNAUTHORIZED);
224+
}
225+
226+
#[actix_rt::test]
227+
async fn test_login_password_incorrect_with_email() {
228+
let mut app = test::init_service(
229+
App::new()
230+
.wrap(Cors::new()
231+
.send_wildcard()
232+
.allowed_methods(vec!["GET", "POST", "PUT", "DELETE"])
233+
.allowed_header(http::header::CONTENT_TYPE)
234+
.max_age(3600)
235+
.finish())
236+
.data(config::db::migrate_and_config_db(":memory:"))
237+
.wrap(actix_web::middleware::Logger::default())
238+
.wrap(crate::middleware::authen_middleware::Authentication)
239+
.wrap_fn(|req, srv| {
240+
srv.call(req).map(|res| res)
241+
})
242+
.configure(crate::config::app::config_services)
243+
).await;
244+
245+
test::TestRequest::post()
246+
.uri("/api/auth/signup")
247+
.set(header::ContentType::json())
248+
.set_payload(r#"{"username":"admin","email":"admin@gmail.com","password":"123456"}"#.as_bytes())
249+
.send_request(&mut app)
250+
.await;
251+
252+
let resp = test::TestRequest::post()
253+
.uri("/api/auth/login")
254+
.set(header::ContentType::json())
255+
.set_payload(r#"{"username_or_email":"admin@gmail.com","password":"password"}"#.as_bytes())
256+
.send_request(&mut app)
257+
.await;
258+
259+
assert_eq!(resp.status(), StatusCode::UNAUTHORIZED);
260+
}
261+
262+
#[actix_rt::test]
263+
async fn test_login_user_not_found_with_username() {
264+
let mut app = test::init_service(
265+
App::new()
266+
.wrap(Cors::new()
267+
.send_wildcard()
268+
.allowed_methods(vec!["GET", "POST", "PUT", "DELETE"])
269+
.allowed_header(http::header::CONTENT_TYPE)
270+
.max_age(3600)
271+
.finish())
272+
.data(config::db::migrate_and_config_db(":memory:"))
273+
.wrap(actix_web::middleware::Logger::default())
274+
.wrap(crate::middleware::authen_middleware::Authentication)
275+
.wrap_fn(|req, srv| {
276+
srv.call(req).map(|res| res)
277+
})
278+
.configure(crate::config::app::config_services)
279+
).await;
280+
281+
test::TestRequest::post()
282+
.uri("/api/auth/signup")
283+
.set(header::ContentType::json())
284+
.set_payload(r#"{"username":"admin","email":"admin@gmail.com","password":"password"}"#.as_bytes())
285+
.send_request(&mut app)
286+
.await;
287+
288+
let resp = test::TestRequest::post()
289+
.uri("/api/auth/login")
290+
.set(header::ContentType::json())
291+
.set_payload(r#"{"username_or_email":"abc","password":"123456"}"#.as_bytes())
292+
.send_request(&mut app)
293+
.await;
294+
295+
assert_eq!(resp.status(), StatusCode::UNAUTHORIZED);
296+
}
297+
298+
#[actix_rt::test]
299+
async fn test_login_user_not_found_with_email() {
300+
let mut app = test::init_service(
301+
App::new()
302+
.wrap(Cors::new()
303+
.send_wildcard()
304+
.allowed_methods(vec!["GET", "POST", "PUT", "DELETE"])
305+
.allowed_header(http::header::CONTENT_TYPE)
306+
.max_age(3600)
307+
.finish())
308+
.data(config::db::migrate_and_config_db(":memory:"))
309+
.wrap(actix_web::middleware::Logger::default())
310+
.wrap(crate::middleware::authen_middleware::Authentication)
311+
.wrap_fn(|req, srv| {
312+
srv.call(req).map(|res| res)
313+
})
314+
.configure(crate::config::app::config_services)
315+
).await;
316+
317+
test::TestRequest::post()
318+
.uri("/api/auth/signup")
319+
.set(header::ContentType::json())
320+
.set_payload(r#"{"username":"admin","email":"admin@gmail.com","password":"password"}"#.as_bytes())
321+
.send_request(&mut app)
322+
.await;
323+
324+
let resp = test::TestRequest::post()
325+
.uri("/api/auth/login")
326+
.set(header::ContentType::json())
327+
.set_payload(r#"{"username_or_email":"abc@gmail.com","password":"123456"}"#.as_bytes())
328+
.send_request(&mut app)
329+
.await;
330+
331+
assert_eq!(resp.status(), StatusCode::UNAUTHORIZED);
332+
}
333+
}

src/api/ping_controller.rs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,37 @@ fn ping() -> HttpResponse {
55
HttpResponse::Ok()
66
.body("pong!".to_string())
77
}
8+
9+
#[cfg(test)]
10+
mod tests {
11+
use crate::{App, config};
12+
use actix_cors::Cors;
13+
use actix_service::Service;
14+
use actix_web::{test, http, http::StatusCode};
15+
use futures::FutureExt;
16+
17+
#[actix_rt::test]
18+
async fn test_ping_ok() {
19+
let mut app = test::init_service(
20+
App::new()
21+
.wrap(Cors::new()
22+
.send_wildcard()
23+
.allowed_methods(vec!["GET", "POST", "PUT", "DELETE"])
24+
.allowed_header(http::header::CONTENT_TYPE)
25+
.max_age(3600)
26+
.finish())
27+
.data(config::db::migrate_and_config_db(":memory:"))
28+
.wrap(actix_web::middleware::Logger::default())
29+
.wrap(crate::middleware::authen_middleware::Authentication)
30+
.wrap_fn(|req, srv| {
31+
srv.call(req).map(|res| res)
32+
})
33+
.configure(crate::config::app::config_services)
34+
).await;
35+
36+
let req = test::TestRequest::get().uri("/api/ping").to_request();
37+
let resp = test::call_service(&mut app, req).await;
38+
39+
assert_eq!(resp.status(), StatusCode::OK);
40+
}
41+
}

0 commit comments

Comments
 (0)