Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@

# env file
.env
.vscode/
2,598 changes: 1,329 additions & 1,269 deletions Cargo.lock

Large diffs are not rendered by default.

36 changes: 18 additions & 18 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,33 +1,33 @@
[package]
name = "conduit"
version = "0.1.0"
authors = ["grey <[email protected]>"]
edition = "2018"
authors = ["grey <[email protected]>", "thaddeus <[email protected]"]
edition = "2021"

[dependencies]
actix = "0.8.3"
actix-web = "1.0.7"
actix-cors = "0.1.0"
actix-service = "0.4.2"
actix-http = "0.2.10"
blob-uuid = "0.3.0"
actix = "0.13.0"
actix-rt = "2.7.0"
actix-web = "4.1.2"
actix-cors = "0.6.4"
actix-service = "2.0.2"
actix-http = "3.2.2"
blob-uuid = "0.5.0"
chrono = "0.4.6"
diesel = { version = "1.4.2", features = ["chrono", "postgres", "r2d2", "uuidv07", "serde_json"] }
dotenv = "0.14.1"
env_logger = "0.6.1"
diesel = { version = "2.0.2", features = ["chrono", "postgres", "r2d2", "uuid", "serde_json"] }
dotenv = "0.15.0"
env_logger = "0.9.3"
failure = "0.1.5"
futures = "0.1.25"
http = "0.1.16"
jsonwebtoken = "5.0.1"
futures = "0.3.25"
http = "0.2.8"
jsonwebtoken = "8.1.1"
lazy_static = "1.3.0"
libreauth = "0.11.0"
libreauth = "0.15.0"
log = "0.4.6"
num_cpus = "1.10.0"
regex = "1.1.6"
serde = "1.0.91"
serde_derive = "1.0.91"
serde_json = "1.0.39"
slug = "0.1.4"
uuid = { version = "0.7.4", features = ["serde", "v4"] }
validator = "0.8.0"
validator_derive = "0.8.0"
uuid = { version = "1.2", features = ["serde", "v4"] }
validator = { version = "0.16", features = ["derive"] }
2 changes: 0 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@

> ### [Actix](https://actix.rs/) codebase containing real world examples (CRUD, auth, advanced patterns, etc) that adheres to the [RealWorld](https://github.com/gothinkster/realworld) spec and API.

❗ (2021/05/13) This codebase is currently unmaintained, and I am not interested in maintaining it. This relies on an old version of Actix -- developers who want to learn Actix should probably read the latest docs at the [Actix website](https://actix.rs/).

This codebase was created to demonstrate a fully fledged fullstack application built with [Actix](https://actix.rs/) including CRUD operations, authentication, routing, pagination, and more. CORS, however, is not yet added.

This implementation is not reviewed. See the [Contributing](#contributing) section below.
Expand Down
103 changes: 44 additions & 59 deletions src/app/articles/comments.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
use actix_web::{HttpRequest, HttpResponse, web::Json, web::Path, web::Data};
use actix_http::error::ResponseError;
use futures::{future::result, Future};
use actix_web::{web::Data, web::Json, web::Path, HttpRequest, HttpResponse};
use validator::Validate;

use super::super::AppState;
Expand Down Expand Up @@ -30,7 +28,7 @@ pub struct ArticleCommentPath {

#[derive(Debug, Validate, Deserialize)]
pub struct AddComment {
#[validate(length(min = "1", message = "fails validation - cannot be empty"))]
#[validate(length(min = 1, message = "fails validation - cannot be empty"))]
pub body: String,
}

Expand Down Expand Up @@ -78,72 +76,59 @@ pub struct CommentListResponse {

// Route handlers ↓

pub fn add(
pub async fn add(
state: Data<AppState>,
(path, form, req): (
Path<ArticlePath>,
Json<In<AddComment>>,
HttpRequest,
),
) -> impl Future<Item = HttpResponse, Error = Error> {
(path, form, req): (Path<ArticlePath>, Json<In<AddComment>>, HttpRequest),
) -> Result<HttpResponse, Error> {
let comment = form.into_inner().comment;

let db = state.db.clone();

result(comment.validate())
.from_err()
.and_then(move |_| authenticate(&state, &req))
.and_then(move |auth| {
db.send(AddCommentOuter {
auth,
slug: path.slug.to_owned(),
comment,
})
.from_err()
})
.and_then(|res| match res {
Ok(res) => Ok(HttpResponse::Ok().json(res)),
Err(e) => Ok(e.error_response()),
comment.validate()?;

let auth = authenticate(&state, &req).await?;
let res = state
.db
.send(AddCommentOuter {
auth,
slug: path.slug.to_owned(),
comment,
})
.await??;

Ok(HttpResponse::Ok().json(res))
}

pub fn list(
pub async fn list(
state: Data<AppState>,
(path, req): (Path<ArticlePath>, HttpRequest),
) -> impl Future<Item = HttpResponse, Error = Error> {
let db = state.db.clone();

authenticate(&state, &req)
.then(move |auth| {
db.send(GetComments {
auth: auth.ok(),
slug: path.slug.to_owned(),
})
.from_err()
})
.and_then(|res| match res {
Ok(res) => Ok(HttpResponse::Ok().json(res)),
Err(e) => Ok(e.error_response()),
) -> Result<HttpResponse, Error> {
let auth = authenticate(&state, &req)
.await
.map(|auth| Some(auth))
.unwrap_or(None);

let res = state
.db
.send(GetComments {
auth,
slug: path.slug.to_owned(),
})
.await??;

Ok(HttpResponse::Ok().json(res))
}

pub fn delete(
pub async fn delete(
state: Data<AppState>,
(path, req): (Path<ArticleCommentPath>, HttpRequest),
) -> impl Future<Item = HttpResponse, Error = Error> {
let db = state.db.clone();

authenticate(&state, &req)
.and_then(move |auth| {
db.send(DeleteComment {
auth,
slug: path.slug.to_owned(),
comment_id: path.comment_id.to_owned(),
})
.from_err()
})
.and_then(|res| match res {
Ok(_) => Ok(HttpResponse::Ok().finish()),
Err(e) => Ok(e.error_response()),
) -> Result<HttpResponse, Error> {
let auth = authenticate(&state, &req).await?;
let res = state
.db
.send(DeleteComment {
auth,
slug: path.slug.to_owned(),
comment_id: path.comment_id.to_owned(),
})
.await??;

Ok(HttpResponse::Ok().json(res))
}
Loading