From 4468b383b0fee60aaa8d03864f5b32731852675c Mon Sep 17 00:00:00 2001 From: Romira915 <40430090+Romira915@users.noreply.github.com> Date: Wed, 8 Jun 2022 02:20:38 +0900 Subject: [PATCH 01/64] add: simple rust api server --- webapp/docker-compose.yml | 2 +- webapp/rust/.gitignore | 14 ++++++++++++++ webapp/rust/Cargo.toml | 10 ++++++++++ webapp/rust/Dockerfile | 7 +++++++ webapp/rust/src/main.rs | 37 +++++++++++++++++++++++++++++++++++++ 5 files changed, 69 insertions(+), 1 deletion(-) create mode 100644 webapp/rust/.gitignore create mode 100644 webapp/rust/Cargo.toml create mode 100644 webapp/rust/Dockerfile create mode 100644 webapp/rust/src/main.rs diff --git a/webapp/docker-compose.yml b/webapp/docker-compose.yml index 71963bb01..398b2d89c 100644 --- a/webapp/docker-compose.yml +++ b/webapp/docker-compose.yml @@ -14,7 +14,7 @@ services: cpus: 1 mem_limit: 1g # Go実装の場合は golang/ PHP実装の場合は php/ - build: ruby/ + build: rust/ environment: ISUCONP_DB_HOST: mysql ISUCONP_DB_PORT: 3306 diff --git a/webapp/rust/.gitignore b/webapp/rust/.gitignore new file mode 100644 index 000000000..6985cf1bd --- /dev/null +++ b/webapp/rust/.gitignore @@ -0,0 +1,14 @@ +# Generated by Cargo +# will have compiled files and executables +debug/ +target/ + +# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries +# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html +Cargo.lock + +# These are backup files generated by rustfmt +**/*.rs.bk + +# MSVC Windows builds of rustc generate these, which store debugging information +*.pdb diff --git a/webapp/rust/Cargo.toml b/webapp/rust/Cargo.toml new file mode 100644 index 000000000..9ced2b406 --- /dev/null +++ b/webapp/rust/Cargo.toml @@ -0,0 +1,10 @@ +[package] +edition = "2021" +name = "rust" +version = "0.1.0" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +actix-cors = "0.6.1" +actix-web = "4.0.1" diff --git a/webapp/rust/Dockerfile b/webapp/rust/Dockerfile new file mode 100644 index 000000000..b580cdb4f --- /dev/null +++ b/webapp/rust/Dockerfile @@ -0,0 +1,7 @@ +FROM rust:1.61.0 + +RUN mkdir -p /home/webapp +COPY . /home/webapp +WORKDIR /home/webapp +RUN cargo build --release +CMD ./target/release/rust diff --git a/webapp/rust/src/main.rs b/webapp/rust/src/main.rs new file mode 100644 index 000000000..d558bda2f --- /dev/null +++ b/webapp/rust/src/main.rs @@ -0,0 +1,37 @@ +use std::io; + +use actix_cors::Cors; +use actix_web::{ + error, + http::{Method, StatusCode}, + middleware, web, App, HttpRequest, HttpResponse, HttpServer, +}; + +#[actix_web::main] +async fn main() -> io::Result<()> { + HttpServer::new(move || { + App::new() + .wrap(middleware::Logger::default()) + .wrap(if cfg!(debug_assertions) { + Cors::permissive() + } else { + Cors::default().supports_credentials() + }) + .service( + web::resource("/test").to(|req: HttpRequest| match *req.method() { + Method::GET => HttpResponse::Ok(), + Method::POST => HttpResponse::MethodNotAllowed(), + _ => HttpResponse::NotFound(), + }), + ) + .service(web::resource("/").to(|| async { + error::InternalError::new( + io::Error::new(io::ErrorKind::Other, "test"), + StatusCode::INTERNAL_SERVER_ERROR, + ) + })) + }) + .bind(("0.0.0.0", 8080))? + .run() + .await +} From 29c7bf83220789107a87b6a45910509740c90e56 Mon Sep 17 00:00:00 2001 From: Romira915 <40430090+Romira915@users.noreply.github.com> Date: Wed, 8 Jun 2022 02:30:40 +0900 Subject: [PATCH 02/64] fix: DB host and port --- webapp/rust/src/main.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/webapp/rust/src/main.rs b/webapp/rust/src/main.rs index d558bda2f..596ef2d54 100644 --- a/webapp/rust/src/main.rs +++ b/webapp/rust/src/main.rs @@ -1,4 +1,4 @@ -use std::io; +use std::{env, io}; use actix_cors::Cors; use actix_web::{ @@ -9,6 +9,9 @@ use actix_web::{ #[actix_web::main] async fn main() -> io::Result<()> { + let host = env::var("ISUCONP_DB_HOST").unwrap_or("localhost".to_string()); + let port = env::var("ISUCONP_DB_PORT").unwrap_or("3306".to_string()); + HttpServer::new(move || { App::new() .wrap(middleware::Logger::default()) From a9ef1115691066bac4dfb36f88afb86f09c68308 Mon Sep 17 00:00:00 2001 From: Romira915 <40430090+Romira915@users.noreply.github.com> Date: Wed, 8 Jun 2022 02:35:56 +0900 Subject: [PATCH 03/64] add: dsn --- webapp/rust/src/main.rs | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/webapp/rust/src/main.rs b/webapp/rust/src/main.rs index 596ef2d54..2afe79946 100644 --- a/webapp/rust/src/main.rs +++ b/webapp/rust/src/main.rs @@ -10,7 +10,19 @@ use actix_web::{ #[actix_web::main] async fn main() -> io::Result<()> { let host = env::var("ISUCONP_DB_HOST").unwrap_or("localhost".to_string()); - let port = env::var("ISUCONP_DB_PORT").unwrap_or("3306".to_string()); + let port: u32 = env::var("ISUCONP_DB_PORT") + .unwrap_or("3306".to_string()) + .parse() + .unwrap_or(3306); + + let user = env::var("ISUCONP_DB_USER").unwrap_or("root".to_string()); + let password = env::var("ISUCONP_DB_PASSWORD").expect("Failed to ISUCONP_DB_PASSWORD"); + let dbname = env::var("ISUCONP_DB_NAME").unwrap_or("isuconp".to_string()); + + let dsn = format!( + "{}:{}@tcp({}:{})/{}?charset=utf8mb4&parseTime=true&loc=Local", + &user, &password, &host, &port, &dbname + ); HttpServer::new(move || { App::new() From edbc5c0d5f3c3fbf4b4baffa1e9bfc0942c21b83 Mon Sep 17 00:00:00 2001 From: Romira915 <40430090+Romira915@users.noreply.github.com> Date: Wed, 8 Jun 2022 12:16:45 +0900 Subject: [PATCH 04/64] features: get initialize --- webapp/rust/.gitignore | 2 + webapp/rust/Cargo.toml | 8 ++++ webapp/rust/src/main.rs | 97 ++++++++++++++++++++++++++++++++++++++++- 3 files changed, 105 insertions(+), 2 deletions(-) diff --git a/webapp/rust/.gitignore b/webapp/rust/.gitignore index 6985cf1bd..a1835db1d 100644 --- a/webapp/rust/.gitignore +++ b/webapp/rust/.gitignore @@ -12,3 +12,5 @@ Cargo.lock # MSVC Windows builds of rustc generate these, which store debugging information *.pdb + +.env \ No newline at end of file diff --git a/webapp/rust/Cargo.toml b/webapp/rust/Cargo.toml index 9ced2b406..99f41da6c 100644 --- a/webapp/rust/Cargo.toml +++ b/webapp/rust/Cargo.toml @@ -8,3 +8,11 @@ version = "0.1.0" [dependencies] actix-cors = "0.6.1" actix-web = "4.0.1" + +sqlx = {version = "0.5.13", features = ["runtime-actix-native-tls", "mysql", "chrono", "uuid"]} + +anyhow = "1.0.57" +chrono = "0.4.19" +log = "0.4.17" +num_cpus = "1.13.1" +simplelog = "0.12.0" diff --git a/webapp/rust/src/main.rs b/webapp/rust/src/main.rs index 2afe79946..272dfd720 100644 --- a/webapp/rust/src/main.rs +++ b/webapp/rust/src/main.rs @@ -1,14 +1,96 @@ -use std::{env, io}; +use std::{env, io, path::Path, time::Duration}; use actix_cors::Cors; use actix_web::{ + cookie::time::UtcOffset, error, http::{Method, StatusCode}, - middleware, web, App, HttpRequest, HttpResponse, HttpServer, + middleware, + web::{self, Data}, + App, HttpRequest, HttpResponse, HttpServer, Result, }; +use anyhow::Context; +use chrono::{FixedOffset, Utc}; +use log::LevelFilter; +use simplelog::{ + ColorChoice, CombinedLogger, ConfigBuilder, SharedLogger, TermLogger, TerminalMode, WriteLogger, +}; +use sqlx::{MySql, Pool}; + +async fn db_initialize(pool: &Pool) -> anyhow::Result<()> { + sqlx::query!("DELETE FROM users WHERE id > 1000") + .execute(pool) + .await + .context("Failed to db_initialize")?; + sqlx::query!("DELETE FROM posts WHERE id > 10000",) + .execute(pool) + .await + .context("Failed to db_initialize")?; + sqlx::query!("DELETE FROM comments WHERE id > 100000") + .execute(pool) + .await + .context("Failed to db_initialize")?; + sqlx::query!("UPDATE users SET del_flg = 0") + .execute(pool) + .await + .context("Failed to db_initialize")?; + sqlx::query!("UPDATE users SET del_flg = 1 WHERE id % 50 = 0") + .execute(pool) + .await + .context("Failed to db_initialize")?; + + Ok(()) +} + +async fn get_initialize(pool: Data>) -> Result { + if let Err(e) = db_initialize(&pool).await { + log::error!("{:?}", &e); + } + Ok(HttpResponse::Ok().finish()) +} + +fn init_logger>(log_path: Option

) { + const JST_UTCOFFSET_SECS: i32 = 9 * 3600; + + let jst_now = { + let jst = Utc::now(); + jst.with_timezone(&FixedOffset::east(JST_UTCOFFSET_SECS)) + }; + + let offset = UtcOffset::from_whole_seconds(JST_UTCOFFSET_SECS).unwrap(); + + let mut config = ConfigBuilder::new(); + config.set_time_offset(offset); + + let mut logger: Vec> = vec![ + #[cfg(not(feature = "termcolor"))] + TermLogger::new( + if cfg!(debug_assertions) { + LevelFilter::Debug + } else { + LevelFilter::Info + }, + config.build(), + TerminalMode::Mixed, + ColorChoice::Always, + ), + ]; + if let Some(log_path) = log_path { + let log_path = log_path.as_ref(); + std::fs::create_dir_all(&log_path).unwrap(); + logger.push(WriteLogger::new( + LevelFilter::Info, + config.build(), + std::fs::File::create(log_path.join(format!("{}.log", jst_now))).unwrap(), + )); + } + CombinedLogger::init(logger).unwrap() +} #[actix_web::main] async fn main() -> io::Result<()> { + init_logger::<&str>(None); + let host = env::var("ISUCONP_DB_HOST").unwrap_or("localhost".to_string()); let port: u32 = env::var("ISUCONP_DB_PORT") .unwrap_or("3306".to_string()) @@ -24,6 +106,15 @@ async fn main() -> io::Result<()> { &user, &password, &host, &port, &dbname ); + let num_cpus = num_cpus::get(); + + let db = sqlx::mysql::MySqlPoolOptions::new() + .max_connections(num_cpus as u32) + .connect_timeout(Duration::from_secs(1)) + .connect(&dsn) + .await + .unwrap(); + HttpServer::new(move || { App::new() .wrap(middleware::Logger::default()) @@ -32,6 +123,8 @@ async fn main() -> io::Result<()> { } else { Cors::default().supports_credentials() }) + .app_data(Data::new(db.clone())) + .service(web::resource("/initialize").route(web::get().to(get_initialize))) .service( web::resource("/test").to(|req: HttpRequest| match *req.method() { Method::GET => HttpResponse::Ok(), From e47dc1208927614bbf75cb26baff8098dd9b9c97 Mon Sep 17 00:00:00 2001 From: Romira915 <40430090+Romira915@users.noreply.github.com> Date: Wed, 8 Jun 2022 17:31:30 +0900 Subject: [PATCH 05/64] add: todo func --- webapp/rust/Cargo.toml | 3 ++ webapp/rust/src/main.rs | 64 +++++++++++++++++++++++++++++ webapp/rust/templates/banned.html | 15 +++++++ webapp/rust/templates/index.html | 28 +++++++++++++ webapp/rust/templates/layout.html | 32 +++++++++++++++ webapp/rust/templates/login.html | 31 ++++++++++++++ webapp/rust/templates/post.html | 35 ++++++++++++++++ webapp/rust/templates/post_id.html | 3 ++ webapp/rust/templates/posts.html | 5 +++ webapp/rust/templates/register.html | 27 ++++++++++++ webapp/rust/templates/user.html | 10 +++++ 11 files changed, 253 insertions(+) create mode 100644 webapp/rust/templates/banned.html create mode 100644 webapp/rust/templates/index.html create mode 100644 webapp/rust/templates/layout.html create mode 100644 webapp/rust/templates/login.html create mode 100644 webapp/rust/templates/post.html create mode 100644 webapp/rust/templates/post_id.html create mode 100644 webapp/rust/templates/posts.html create mode 100644 webapp/rust/templates/register.html create mode 100644 webapp/rust/templates/user.html diff --git a/webapp/rust/Cargo.toml b/webapp/rust/Cargo.toml index 99f41da6c..e188af588 100644 --- a/webapp/rust/Cargo.toml +++ b/webapp/rust/Cargo.toml @@ -10,9 +10,12 @@ actix-cors = "0.6.1" actix-web = "4.0.1" sqlx = {version = "0.5.13", features = ["runtime-actix-native-tls", "mysql", "chrono", "uuid"]} +tinytemplate = "1.1" anyhow = "1.0.57" chrono = "0.4.19" log = "0.4.17" num_cpus = "1.13.1" +serde = {version = "1.0.137", features = ["derive"]} +serde_json = "1.0.81" simplelog = "0.12.0" diff --git a/webapp/rust/src/main.rs b/webapp/rust/src/main.rs index 272dfd720..e22b89220 100644 --- a/webapp/rust/src/main.rs +++ b/webapp/rust/src/main.rs @@ -16,6 +16,7 @@ use simplelog::{ ColorChoice, CombinedLogger, ConfigBuilder, SharedLogger, TermLogger, TerminalMode, WriteLogger, }; use sqlx::{MySql, Pool}; +use tinytemplate::TinyTemplate; async fn db_initialize(pool: &Pool) -> anyhow::Result<()> { sqlx::query!("DELETE FROM users WHERE id > 1000") @@ -49,6 +50,61 @@ async fn get_initialize(pool: Data>) -> Result { Ok(HttpResponse::Ok().finish()) } +async fn get_login(tmpl: web::Data>) -> Result { + todo!(); + + Ok(HttpResponse::Ok().finish()) +} + +async fn post_login() -> Result { + todo!(); + Ok(HttpResponse::Ok().finish()) +} + +async fn get_register() -> Result { + todo!() +} + +async fn post_register() -> Result { + todo!() +} + +async fn get_logout() -> Result { + todo!() +} + +async fn get_index() -> Result { + todo!() +} + +async fn get_posts() -> Result { + todo!() +} + +async fn get_posts_id() -> Result { + todo!() +} + +async fn post_index() -> Result { + todo!() +} + +async fn get_image() -> Result { + todo!() +} + +async fn post_comment() -> Result { + todo!() +} + +async fn get_admin_banned() -> Result { + todo!() +} + +async fn post_admin_banned() -> Result { + todo!() +} + fn init_logger>(log_path: Option

) { const JST_UTCOFFSET_SECS: i32 = 9 * 3600; @@ -116,6 +172,10 @@ async fn main() -> io::Result<()> { .unwrap(); HttpServer::new(move || { + let mut tt = TinyTemplate::new(); + tt.add_template("layout.html", LAYOUT).unwrap(); + tt.add_template("login.html", LOGIN).unwrap(); + App::new() .wrap(middleware::Logger::default()) .wrap(if cfg!(debug_assertions) { @@ -124,6 +184,7 @@ async fn main() -> io::Result<()> { Cors::default().supports_credentials() }) .app_data(Data::new(db.clone())) + .app_data(web::Data::new(tt)) .service(web::resource("/initialize").route(web::get().to(get_initialize))) .service( web::resource("/test").to(|req: HttpRequest| match *req.method() { @@ -143,3 +204,6 @@ async fn main() -> io::Result<()> { .run() .await } + +static LAYOUT: &str = include_str!("../templates/layout.html"); +static LOGIN: &str = include_str!("../templates/login.html"); diff --git a/webapp/rust/templates/banned.html b/webapp/rust/templates/banned.html new file mode 100644 index 000000000..ef7141992 --- /dev/null +++ b/webapp/rust/templates/banned.html @@ -0,0 +1,15 @@ +{{ define "content" }} +

+
+ {{ range .Users }} +
+ +
+ {{ end }} +
+ + +
+
+
+{{ end }} diff --git a/webapp/rust/templates/index.html b/webapp/rust/templates/index.html new file mode 100644 index 000000000..22ff9c254 --- /dev/null +++ b/webapp/rust/templates/index.html @@ -0,0 +1,28 @@ +{{ define "content" }} +
+
+
+ +
+
+ +
+
+ + +
+ {{if .Flash}} +
+ {{.Flash}} +
+ {{end}} +
+
+ +{{ template "posts.html" .Posts }} + +
+ + +
+{{ end }} diff --git a/webapp/rust/templates/layout.html b/webapp/rust/templates/layout.html new file mode 100644 index 000000000..426dbd77a --- /dev/null +++ b/webapp/rust/templates/layout.html @@ -0,0 +1,32 @@ + + + + + Iscogram + + + +
+
+
+

Iscogram

+
+
+ {{ if eq .Me.ID 0}} + + {{ else }} + + {{ if eq .Me.Authority 1 }} + + {{ end }} + + {{ end }} +
+
+ + {{ template "content" . }} +
+ + + + diff --git a/webapp/rust/templates/login.html b/webapp/rust/templates/login.html new file mode 100644 index 000000000..aad60e47d --- /dev/null +++ b/webapp/rust/templates/login.html @@ -0,0 +1,31 @@ +{{ define "content" }} +
+

ログイン

+
+ +{{if .Flash}} +
+ {{.Flash}} +
+{{end}} + +
+
+ +
+ パスワード + +
+
+ +
+
+
+ + +{{ end }} diff --git a/webapp/rust/templates/post.html b/webapp/rust/templates/post.html new file mode 100644 index 000000000..d7279d6a8 --- /dev/null +++ b/webapp/rust/templates/post.html @@ -0,0 +1,35 @@ +
+
+ + + + +
+
+ +
+
+ + {{ .Body }} +
+
+
+ comments: {{ .CommentCount }} +
+ + {{ range .Comments }} +
+ + {{.Comment}} +
+ {{ end }} +
+
+ + + + +
+
+
+
diff --git a/webapp/rust/templates/post_id.html b/webapp/rust/templates/post_id.html new file mode 100644 index 000000000..939948530 --- /dev/null +++ b/webapp/rust/templates/post_id.html @@ -0,0 +1,3 @@ +{{ define "content" }} +{{ template "post.html" .Post }} +{{ end }} diff --git a/webapp/rust/templates/posts.html b/webapp/rust/templates/posts.html new file mode 100644 index 000000000..1e27b8959 --- /dev/null +++ b/webapp/rust/templates/posts.html @@ -0,0 +1,5 @@ +
+ {{ range . }} + {{ template "post.html" . }} + {{ end }} +
diff --git a/webapp/rust/templates/register.html b/webapp/rust/templates/register.html new file mode 100644 index 000000000..6becf9da3 --- /dev/null +++ b/webapp/rust/templates/register.html @@ -0,0 +1,27 @@ +{{ define "content" }} +
+

ユーザー登録

+
+ +{{if .Flash}} +
+ {{.Flash}} +
+{{end}} + +
+
+ +
+ パスワード + +
+
+ +
+
+
+{{ end }} diff --git a/webapp/rust/templates/user.html b/webapp/rust/templates/user.html new file mode 100644 index 000000000..6e9a100ab --- /dev/null +++ b/webapp/rust/templates/user.html @@ -0,0 +1,10 @@ +{{ define "content" }} +
+
のページ
+
投稿数 {{ .PostCount }}
+
コメント数 {{ .CommentCount }}
+
被コメント数 {{ .CommentedCount }}
+
+ +{{ template "posts.html" .Posts }} +{{ end }} From 44df9acd064ed3de5bcfdb5999f016c4f02ff17c Mon Sep 17 00:00:00 2001 From: Romira915 <40430090+Romira915@users.noreply.github.com> Date: Thu, 9 Jun 2022 10:26:37 +0900 Subject: [PATCH 06/64] add: static dir --- webapp/docker-compose.yml | 2 +- webapp/rust/Cargo.toml | 1 + webapp/rust/src/main.rs | 27 +++++++++++++++++++++++++-- 3 files changed, 27 insertions(+), 3 deletions(-) diff --git a/webapp/docker-compose.yml b/webapp/docker-compose.yml index 398b2d89c..141e9b0c1 100644 --- a/webapp/docker-compose.yml +++ b/webapp/docker-compose.yml @@ -14,7 +14,7 @@ services: cpus: 1 mem_limit: 1g # Go実装の場合は golang/ PHP実装の場合は php/ - build: rust/ + build: golang/ environment: ISUCONP_DB_HOST: mysql ISUCONP_DB_PORT: 3306 diff --git a/webapp/rust/Cargo.toml b/webapp/rust/Cargo.toml index e188af588..9f65a65d3 100644 --- a/webapp/rust/Cargo.toml +++ b/webapp/rust/Cargo.toml @@ -14,6 +14,7 @@ tinytemplate = "1.1" anyhow = "1.0.57" chrono = "0.4.19" +derive_more = "0.99.17" log = "0.4.17" num_cpus = "1.13.1" serde = {version = "1.0.137", features = ["derive"]} diff --git a/webapp/rust/src/main.rs b/webapp/rust/src/main.rs index e22b89220..026acc862 100644 --- a/webapp/rust/src/main.rs +++ b/webapp/rust/src/main.rs @@ -10,14 +10,26 @@ use actix_web::{ App, HttpRequest, HttpResponse, HttpServer, Result, }; use anyhow::Context; -use chrono::{FixedOffset, Utc}; +use chrono::{FixedOffset, Local, Utc}; +use derive_more::Constructor; use log::LevelFilter; +use serde::{Deserialize, Serialize}; use simplelog::{ ColorChoice, CombinedLogger, ConfigBuilder, SharedLogger, TermLogger, TerminalMode, WriteLogger, }; use sqlx::{MySql, Pool}; use tinytemplate::TinyTemplate; +#[derive(Debug, Serialize, Deserialize, Constructor)] +struct User { + id: i32, + account_name: String, + passhash: String, + authority: i32, + del_flg: i32, + created_at: String, +} + async fn db_initialize(pool: &Pool) -> anyhow::Result<()> { sqlx::query!("DELETE FROM users WHERE id > 1000") .execute(pool) @@ -51,7 +63,18 @@ async fn get_initialize(pool: Data>) -> Result { } async fn get_login(tmpl: web::Data>) -> Result { - todo!(); + let body = { + let user = User::new( + 0, + "test".to_string(), + "pass".to_string(), + 999, + 500, + "datetime".to_string(), + ); + + let json = serde_json::to_value(user).unwrap(); + }; Ok(HttpResponse::Ok().finish()) } From 93f43942c2575b5386279ace6dbb82a53030eb51 Mon Sep 17 00:00:00 2001 From: Romira915 <40430090+Romira915@users.noreply.github.com> Date: Thu, 9 Jun 2022 19:25:14 +0900 Subject: [PATCH 07/64] =?UTF-8?q?add:=20html=20template=20=E5=88=86?= =?UTF-8?q?=E5=89=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- webapp/docker-compose.yml | 6 ++++ webapp/rust/Cargo.toml | 4 ++- webapp/rust/src/main.rs | 46 +++++++++++++++++------- webapp/rust/static/layout.html | 35 ++++++++++++++++++ webapp/rust/static/login.html | 32 +++++++++++++++++ webapp/rust/templates/layout.html | 59 ++++++++++++++++--------------- 6 files changed, 140 insertions(+), 42 deletions(-) create mode 100644 webapp/rust/static/layout.html create mode 100644 webapp/rust/static/login.html diff --git a/webapp/docker-compose.yml b/webapp/docker-compose.yml index 141e9b0c1..377a91f57 100644 --- a/webapp/docker-compose.yml +++ b/webapp/docker-compose.yml @@ -47,5 +47,11 @@ services: memcached: image: memcached:1.6 + redis: + image: redis:7.0.0 + restart: always + ports: + - 6379:6379 + volumes: mysql: diff --git a/webapp/rust/Cargo.toml b/webapp/rust/Cargo.toml index 9f65a65d3..855daf49a 100644 --- a/webapp/rust/Cargo.toml +++ b/webapp/rust/Cargo.toml @@ -7,10 +7,12 @@ version = "0.1.0" [dependencies] actix-cors = "0.6.1" +actix-redis = "0.10.0" +actix-session = "0.5.0" actix-web = "4.0.1" +handlebars = {version = "4.3.0", features = ["dir_source"]} sqlx = {version = "0.5.13", features = ["runtime-actix-native-tls", "mysql", "chrono", "uuid"]} -tinytemplate = "1.1" anyhow = "1.0.57" chrono = "0.4.19" diff --git a/webapp/rust/src/main.rs b/webapp/rust/src/main.rs index 026acc862..f61c0019b 100644 --- a/webapp/rust/src/main.rs +++ b/webapp/rust/src/main.rs @@ -1,9 +1,10 @@ use std::{env, io, path::Path, time::Duration}; use actix_cors::Cors; +use actix_redis::RedisSession; use actix_web::{ cookie::time::UtcOffset, - error, + error, get, http::{Method, StatusCode}, middleware, web::{self, Data}, @@ -12,13 +13,13 @@ use actix_web::{ use anyhow::Context; use chrono::{FixedOffset, Local, Utc}; use derive_more::Constructor; +use handlebars::{to_json, Handlebars}; use log::LevelFilter; use serde::{Deserialize, Serialize}; use simplelog::{ ColorChoice, CombinedLogger, ConfigBuilder, SharedLogger, TermLogger, TerminalMode, WriteLogger, }; use sqlx::{MySql, Pool}; -use tinytemplate::TinyTemplate; #[derive(Debug, Serialize, Deserialize, Constructor)] struct User { @@ -55,6 +56,7 @@ async fn db_initialize(pool: &Pool) -> anyhow::Result<()> { Ok(()) } +#[get("/initialize")] async fn get_initialize(pool: Data>) -> Result { if let Err(e) = db_initialize(&pool).await { log::error!("{:?}", &e); @@ -62,21 +64,29 @@ async fn get_initialize(pool: Data>) -> Result { Ok(HttpResponse::Ok().finish()) } -async fn get_login(tmpl: web::Data>) -> Result { +#[get("/login")] +async fn get_login(handlebars: Data>) -> Result { let body = { let user = User::new( 0, "test".to_string(), "pass".to_string(), - 999, + 0, 500, "datetime".to_string(), ); - let json = serde_json::to_value(user).unwrap(); + let mut json = serde_json::to_value(user).unwrap(); + let map = json.as_object_mut().unwrap(); + map.insert("flash".to_string(), to_json("notice")); + map.insert("parent".to_string(), to_json("layout")); + log::debug!("{:?}", &map); + + handlebars.render("login", map).unwrap() }; + log::debug!("{:?}", &body); - Ok(HttpResponse::Ok().finish()) + Ok(HttpResponse::Ok().body(body)) } async fn post_login() -> Result { @@ -84,6 +94,7 @@ async fn post_login() -> Result { Ok(HttpResponse::Ok().finish()) } +#[get("/register")] async fn get_register() -> Result { todo!() } @@ -174,16 +185,20 @@ async fn main() -> io::Result<()> { let port: u32 = env::var("ISUCONP_DB_PORT") .unwrap_or("3306".to_string()) .parse() - .unwrap_or(3306); + .unwrap(); let user = env::var("ISUCONP_DB_USER").unwrap_or("root".to_string()); - let password = env::var("ISUCONP_DB_PASSWORD").expect("Failed to ISUCONP_DB_PASSWORD"); + // let password = env::var("ISUCONP_DB_PASSWORD").expect("Failed to ISUCONP_DB_PASSWORD"); + let password = env::var("ISUCONP_DB_PASSWORD").unwrap_or("root".to_string()); let dbname = env::var("ISUCONP_DB_NAME").unwrap_or("isuconp".to_string()); + let redis_url = env::var("ISUCONP_REDIS_URL").unwrap_or("localhost:6379".to_string()); + let dsn = format!( "{}:{}@tcp({}:{})/{}?charset=utf8mb4&parseTime=true&loc=Local", &user, &password, &host, &port, &dbname ); + let dsn = "mysql://root:root@localhost:3306/isuconp".to_string(); let num_cpus = num_cpus::get(); @@ -194,10 +209,13 @@ async fn main() -> io::Result<()> { .await .unwrap(); + let private_key = actix_web::cookie::Key::generate(); + HttpServer::new(move || { - let mut tt = TinyTemplate::new(); - tt.add_template("layout.html", LAYOUT).unwrap(); - tt.add_template("login.html", LOGIN).unwrap(); + let mut handlebars = Handlebars::new(); + handlebars + .register_templates_directory(".html", "./static") + .unwrap(); App::new() .wrap(middleware::Logger::default()) @@ -206,9 +224,11 @@ async fn main() -> io::Result<()> { } else { Cors::default().supports_credentials() }) + .wrap(RedisSession::new(redis_url, private_key.master())) .app_data(Data::new(db.clone())) - .app_data(web::Data::new(tt)) - .service(web::resource("/initialize").route(web::get().to(get_initialize))) + .app_data(Data::new(handlebars)) + .service(get_initialize) + .service(get_login) .service( web::resource("/test").to(|req: HttpRequest| match *req.method() { Method::GET => HttpResponse::Ok(), diff --git a/webapp/rust/static/layout.html b/webapp/rust/static/layout.html new file mode 100644 index 000000000..a99e12ed1 --- /dev/null +++ b/webapp/rust/static/layout.html @@ -0,0 +1,35 @@ + + + + + + Iscogram + + + + +
+
+
+

Iscogram

+
+
+ {{#if (eq id 0)}} + + {{else}} + + {{#if (eq authority 1)}} + + {{/if}} + + {{/if}} +
+
+ + {{> login}} +
+ + + + + \ No newline at end of file diff --git a/webapp/rust/static/login.html b/webapp/rust/static/login.html new file mode 100644 index 000000000..b7942d34e --- /dev/null +++ b/webapp/rust/static/login.html @@ -0,0 +1,32 @@ +{{#*inline "login"}} +
+

ログイン

+
+ +{{#if flash}} +
+ {{flash}} +
+{{/if}} + +
+
+ +
+ パスワード + +
+
+ +
+
+
+ + +{{/inline}} +{{> (lookup this "parent")}} \ No newline at end of file diff --git a/webapp/rust/templates/layout.html b/webapp/rust/templates/layout.html index 426dbd77a..846b50e5d 100644 --- a/webapp/rust/templates/layout.html +++ b/webapp/rust/templates/layout.html @@ -1,32 +1,35 @@ - - - Iscogram - - - -
-
-
-

Iscogram

-
-
- {{ if eq .Me.ID 0}} - - {{ else }} - - {{ if eq .Me.Authority 1 }} - - {{ end }} - - {{ end }} -
-
- {{ template "content" . }} + + + Iscogram + + + + +
+
+
+

Iscogram

+
+
+ {{ if eq .Me.ID 0}} + + {{ else }} + + {{ if eq .Me.Authority 1 }} + + {{ end }} + + {{ end }} +
- - - - + + {{ template "content" . }} +
+ + + + + \ No newline at end of file From c1a18bbfadb543e9b18ca8ed31133f2e2a521488 Mon Sep 17 00:00:00 2001 From: Romira915 <40430090+Romira915@users.noreply.github.com> Date: Thu, 9 Jun 2022 19:29:33 +0900 Subject: [PATCH 08/64] add: register.html --- webapp/rust/src/main.rs | 5 +++++ webapp/rust/static/login.html | 2 +- webapp/rust/static/register.html | 28 ++++++++++++++++++++++++++++ 3 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 webapp/rust/static/register.html diff --git a/webapp/rust/src/main.rs b/webapp/rust/src/main.rs index f61c0019b..0e1d2fd4b 100644 --- a/webapp/rust/src/main.rs +++ b/webapp/rust/src/main.rs @@ -96,6 +96,11 @@ async fn post_login() -> Result { #[get("/register")] async fn get_register() -> Result { + // TODO: + // if isLogin(getSessionUser(r)) { + // http.Redirect(w, r, "/", http.StatusFound) + // return + // } todo!() } diff --git a/webapp/rust/static/login.html b/webapp/rust/static/login.html index b7942d34e..16ab68326 100644 --- a/webapp/rust/static/login.html +++ b/webapp/rust/static/login.html @@ -1,4 +1,4 @@ -{{#*inline "login"}} +{{#*inline "content"}}

ログイン

diff --git a/webapp/rust/static/register.html b/webapp/rust/static/register.html new file mode 100644 index 000000000..1c5487b76 --- /dev/null +++ b/webapp/rust/static/register.html @@ -0,0 +1,28 @@ +{{#*inline "content"}} +
+

ユーザー登録

+
+ +{{#if flash}} +
+ {{flash}} +
+{{end}} + +
+
+ +
+ パスワード + +
+
+ +
+
+
+{{/inline}} +{{> (lookup this "parent")}} \ No newline at end of file From 09df39a68f05dd96df3c1be2a09ea63a8fdf631f Mon Sep 17 00:00:00 2001 From: Romira915 <40430090+Romira915@users.noreply.github.com> Date: Thu, 9 Jun 2022 23:18:50 +0900 Subject: [PATCH 09/64] test tiny --- webapp/rust/src/main.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/webapp/rust/src/main.rs b/webapp/rust/src/main.rs index 026acc862..27b203d7d 100644 --- a/webapp/rust/src/main.rs +++ b/webapp/rust/src/main.rs @@ -74,6 +74,8 @@ async fn get_login(tmpl: web::Data>) -> Result { ); let json = serde_json::to_value(user).unwrap(); + + tmpl.render(template, context) }; Ok(HttpResponse::Ok().finish()) From 777f4ae64e191a8524a2f9722ac08f33176c2fe3 Mon Sep 17 00:00:00 2001 From: Romira915 <40430090+Romira915@users.noreply.github.com> Date: Fri, 10 Jun 2022 01:04:26 +0900 Subject: [PATCH 10/64] features: get get_register --- webapp/rust/src/main.rs | 71 +++++++++++++++++++++++++------- webapp/rust/static/layout.html | 2 +- webapp/rust/static/register.html | 2 +- 3 files changed, 57 insertions(+), 18 deletions(-) diff --git a/webapp/rust/src/main.rs b/webapp/rust/src/main.rs index 0d85064a4..af8853d02 100644 --- a/webapp/rust/src/main.rs +++ b/webapp/rust/src/main.rs @@ -6,7 +6,7 @@ use actix_session::Session; use actix_web::{ cookie::time::UtcOffset, error, get, - http::{Method, StatusCode}, + http::{header, Method, StatusCode}, middleware, web::{self, Data}, App, HttpRequest, HttpResponse, HttpServer, Result, @@ -35,8 +35,12 @@ struct User { impl Default for User { fn default() -> Self { Self { + id: Default::default(), + account_name: Default::default(), + passhash: Default::default(), + authority: Default::default(), + del_flg: Default::default(), created_at: Utc::now(), - ..Default::default() } } } @@ -74,21 +78,23 @@ async fn get_initialize(pool: Data>) -> Result { Ok(HttpResponse::Ok().finish()) } -async fn get_session_user(session: &Session, pool: &Pool) -> anyhow::Result> { - let uid = match session.get::("user_id") { - Ok(Some(uid)) => uid, - Err(e) => anyhow::bail!("Failed to session.get {}", &e), - _ => return Ok(None), - }; - +async fn get_session_user(uid: i32, pool: &Pool) -> anyhow::Result> { let user = sqlx::query_as!(User, "SELECT * FROM `users` WHERE `id` = ?", &uid) .fetch_optional(pool) .await .context("Failed to get_session_user")?; + log::debug!("query user"); Ok(user) } +fn is_login(u: Option<&User>) -> bool { + match u { + Some(u) => u.id != 0, + None => false, + } +} + #[get("/login")] async fn get_login(handlebars: Data>) -> Result { let body = { @@ -113,13 +119,45 @@ async fn post_login() -> Result { } #[get("/register")] -async fn get_register() -> Result { - // TODO: - // if isLogin(getSessionUser(r)) { - // http.Redirect(w, r, "/", http.StatusFound) - // return - // } - todo!() +async fn get_register( + session: Session, + pool: Data>, + handlebars: Data>, +) -> Result { + log::debug!("get register"); + let uid = match session.get::("user_id") { + Ok(Some(uid)) => uid, + Err(_e) => 0, + _ => 0, + }; + log::debug!("uid {}", uid); + + match get_session_user(uid, pool.as_ref()).await { + Ok(user) => { + if is_login(user.as_ref()) { + return Ok(HttpResponse::Found() + .insert_header((header::LOCATION, "/")) + .finish()); + } + } + Err(e) => log::error!("{:?}", &e), + }; + + log::debug!("render template"); + let body = { + let user = User::default(); + + let mut json = serde_json::to_value(user).unwrap(); + let map = json.as_object_mut().unwrap(); + map.insert("flash".to_string(), to_json("notice")); + map.insert("parent".to_string(), to_json("layout")); + log::debug!("map {:?}", &map); + + handlebars.render("register", map).unwrap() + }; + + log::debug!("return ok"); + Ok(HttpResponse::Ok().body(body)) } async fn post_register() -> Result { @@ -252,6 +290,7 @@ async fn main() -> io::Result<()> { .app_data(Data::new(handlebars)) .service(get_initialize) .service(get_login) + .service(get_register) .service( web::resource("/test").to(|req: HttpRequest| match *req.method() { Method::GET => HttpResponse::Ok(), diff --git a/webapp/rust/static/layout.html b/webapp/rust/static/layout.html index a99e12ed1..c1bb124bb 100644 --- a/webapp/rust/static/layout.html +++ b/webapp/rust/static/layout.html @@ -26,7 +26,7 @@

Iscogram

- {{> login}} + {{> content}} diff --git a/webapp/rust/static/register.html b/webapp/rust/static/register.html index 1c5487b76..173910b65 100644 --- a/webapp/rust/static/register.html +++ b/webapp/rust/static/register.html @@ -7,7 +7,7 @@

ユーザー登録

{{flash}}
-{{end}} +{{/if}}
From 8fc8e9092a43843050293541251e90f09b2777dc Mon Sep 17 00:00:00 2001 From: Romira915 <40430090+Romira915@users.noreply.github.com> Date: Fri, 10 Jun 2022 01:08:13 +0900 Subject: [PATCH 11/64] fix: session var --- webapp/rust/src/main.rs | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/webapp/rust/src/main.rs b/webapp/rust/src/main.rs index af8853d02..6568bd9a7 100644 --- a/webapp/rust/src/main.rs +++ b/webapp/rust/src/main.rs @@ -11,7 +11,7 @@ use actix_web::{ web::{self, Data}, App, HttpRequest, HttpResponse, HttpServer, Result, }; -use anyhow::Context; +use anyhow::{bail, Context}; use chrono::{DateTime, FixedOffset, Local, Utc}; use derive_more::Constructor; use handlebars::{to_json, Handlebars}; @@ -78,7 +78,13 @@ async fn get_initialize(pool: Data>) -> Result { Ok(HttpResponse::Ok().finish()) } -async fn get_session_user(uid: i32, pool: &Pool) -> anyhow::Result> { +async fn get_session_user(session: &Session, pool: &Pool) -> anyhow::Result> { + let uid = match session.get::("user_id") { + Ok(Some(uid)) => uid, + Err(e) => bail!("Failed to get_session_user {}", &e), + _ => return Ok(None), + }; + let user = sqlx::query_as!(User, "SELECT * FROM `users` WHERE `id` = ?", &uid) .fetch_optional(pool) .await @@ -124,15 +130,8 @@ async fn get_register( pool: Data>, handlebars: Data>, ) -> Result { - log::debug!("get register"); - let uid = match session.get::("user_id") { - Ok(Some(uid)) => uid, - Err(_e) => 0, - _ => 0, - }; - log::debug!("uid {}", uid); - - match get_session_user(uid, pool.as_ref()).await { + log::debug!("call get_register"); + match get_session_user(&session, pool.as_ref()).await { Ok(user) => { if is_login(user.as_ref()) { return Ok(HttpResponse::Found() From cea6822d4e01436a97a217252a9b5d9a68964927 Mon Sep 17 00:00:00 2001 From: Romira915 <40430090+Romira915@users.noreply.github.com> Date: Fri, 10 Jun 2022 12:52:36 +0900 Subject: [PATCH 12/64] add: regex --- webapp/rust/Cargo.toml | 1 + webapp/rust/src/main.rs | 23 ++++++++++++++++++++++- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/webapp/rust/Cargo.toml b/webapp/rust/Cargo.toml index 3e6f7c877..d5a43c74a 100644 --- a/webapp/rust/Cargo.toml +++ b/webapp/rust/Cargo.toml @@ -19,6 +19,7 @@ chrono = {version = "0.4.19", features = ["serde"]} derive_more = "0.99.17" log = "0.4.17" num_cpus = "1.13.1" +regex = "1" serde = {version = "1.0.137", features = ["derive"]} serde_json = "1.0.81" simplelog = "0.12.0" diff --git a/webapp/rust/src/main.rs b/webapp/rust/src/main.rs index 6568bd9a7..01c6611a7 100644 --- a/webapp/rust/src/main.rs +++ b/webapp/rust/src/main.rs @@ -16,6 +16,7 @@ use chrono::{DateTime, FixedOffset, Local, Utc}; use derive_more::Constructor; use handlebars::{to_json, Handlebars}; use log::LevelFilter; +use regex::Regex; use serde::{Deserialize, Serialize}; use simplelog::{ ColorChoice, CombinedLogger, ConfigBuilder, SharedLogger, TermLogger, TerminalMode, WriteLogger, @@ -45,6 +46,11 @@ impl Default for User { } } +struct RegisterForm { + account_name: String, + password: String, +} + async fn db_initialize(pool: &Pool) -> anyhow::Result<()> { sqlx::query!("DELETE FROM users WHERE id > 1000") .execute(pool) @@ -70,6 +76,10 @@ async fn db_initialize(pool: &Pool) -> anyhow::Result<()> { Ok(()) } +fn validate_user(accountName: &str, password: &str) -> bool { + Regex::new(#r"\A[0-9a-zA-Z_]{3,}\z").unwrap(); +} + #[get("/initialize")] async fn get_initialize(pool: Data>) -> Result { if let Err(e) = db_initialize(&pool).await { @@ -159,7 +169,18 @@ async fn get_register( Ok(HttpResponse::Ok().body(body)) } -async fn post_register() -> Result { +async fn post_register(session: Session, pool: Data>) -> Result { + match get_session_user(&session, pool.as_ref()).await { + Ok(user) => { + if is_login(user.as_ref()) { + return Ok(HttpResponse::Found() + .insert_header((header::LOCATION, "/")) + .finish()); + } + } + Err(e) => log::error!("{:?}", &e), + }; + todo!() } From 44f315d323f1efb16f0629edc944c88f4bdfe9d7 Mon Sep 17 00:00:00 2001 From: Romira915 <40430090+Romira915@users.noreply.github.com> Date: Fri, 10 Jun 2022 13:46:23 +0900 Subject: [PATCH 13/64] add: form --- webapp/rust/src/main.rs | 32 +++++++++++++++++++++++++++----- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/webapp/rust/src/main.rs b/webapp/rust/src/main.rs index 01c6611a7..8ddebe57d 100644 --- a/webapp/rust/src/main.rs +++ b/webapp/rust/src/main.rs @@ -8,7 +8,7 @@ use actix_web::{ error, get, http::{header, Method, StatusCode}, middleware, - web::{self, Data}, + web::{self, Data, Form}, App, HttpRequest, HttpResponse, HttpServer, Result, }; use anyhow::{bail, Context}; @@ -46,7 +46,7 @@ impl Default for User { } } -struct RegisterForm { +struct RegisterParams { account_name: String, password: String, } @@ -76,8 +76,11 @@ async fn db_initialize(pool: &Pool) -> anyhow::Result<()> { Ok(()) } -fn validate_user(accountName: &str, password: &str) -> bool { - Regex::new(#r"\A[0-9a-zA-Z_]{3,}\z").unwrap(); +fn validate_user(account_name: &str, password: &str) -> bool { + let name_regex = Regex::new(r"\A[0-9a-zA-Z_]{3,}\z").unwrap(); + let pass_regex = Regex::new(r"\A[0-9a-zA-Z_]{6,}\z").unwrap(); + + name_regex.is_match(account_name) && pass_regex.is_match(password) } #[get("/initialize")] @@ -169,7 +172,11 @@ async fn get_register( Ok(HttpResponse::Ok().body(body)) } -async fn post_register(session: Session, pool: Data>) -> Result { +async fn post_register( + session: Session, + pool: Data>, + params: Form, +) -> Result { match get_session_user(&session, pool.as_ref()).await { Ok(user) => { if is_login(user.as_ref()) { @@ -181,6 +188,21 @@ async fn post_register(session: Session, pool: Data>) -> Result log::error!("{:?}", &e), }; + let validated = validate_user(¶ms.account_name, ¶ms.password); + if !validated { + if let Err(e) = session.insert( + "notice", + "アカウント名は3文字以上、パスワードは6文字以上である必要があります", + ) { + log::error!("{:?}", &e); + return Ok(HttpResponse::InternalServerError().body(e.to_string())); + } + + return Ok(HttpResponse::Found() + .insert_header(((header::LOCATION, "/register"))) + .finish()); + } + todo!() } From cfc6da88c27b8f26e7ccb608c2656199c9041cbe Mon Sep 17 00:00:00 2001 From: Romira915 <40430090+Romira915@users.noreply.github.com> Date: Fri, 10 Jun 2022 17:30:46 +0900 Subject: [PATCH 14/64] features: register --- webapp/golang/app.go | 4 +- webapp/rust/.vscode/settings.json | 3 + webapp/rust/Cargo.toml | 3 + webapp/rust/src/main.rs | 134 ++++++++++++++++++++++++++++-- 4 files changed, 137 insertions(+), 7 deletions(-) create mode 100644 webapp/rust/.vscode/settings.json diff --git a/webapp/golang/app.go b/webapp/golang/app.go index 719285367..63edcd1b2 100644 --- a/webapp/golang/app.go +++ b/webapp/golang/app.go @@ -369,7 +369,9 @@ func postRegister(w http.ResponseWriter, r *http.Request) { return } session.Values["user_id"] = uid - session.Values["csrf_token"] = secureRandomStr(16) + rstr := secureRandomStr(16) + log.Print(rstr) + session.Values["csrf_token"] = rstr session.Save(r, w) http.Redirect(w, r, "/", http.StatusFound) diff --git a/webapp/rust/.vscode/settings.json b/webapp/rust/.vscode/settings.json new file mode 100644 index 000000000..aff611361 --- /dev/null +++ b/webapp/rust/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "codic.case": "SNAKE_CASE" +} \ No newline at end of file diff --git a/webapp/rust/Cargo.toml b/webapp/rust/Cargo.toml index d5a43c74a..ea5e4613d 100644 --- a/webapp/rust/Cargo.toml +++ b/webapp/rust/Cargo.toml @@ -17,8 +17,11 @@ sqlx = {version = "0.5.13", features = ["runtime-actix-native-tls", "mysql", "ch anyhow = "1.0.57" chrono = {version = "0.4.19", features = ["serde"]} derive_more = "0.99.17" +duct = "0.13.5" log = "0.4.17" num_cpus = "1.13.1" +once_cell = "1.10.0" +rand = "0.8.5" regex = "1" serde = {version = "1.0.137", features = ["derive"]} serde_json = "1.0.81" diff --git a/webapp/rust/src/main.rs b/webapp/rust/src/main.rs index 8ddebe57d..16e23b87e 100644 --- a/webapp/rust/src/main.rs +++ b/webapp/rust/src/main.rs @@ -1,4 +1,4 @@ -use std::{env, io, path::Path, time::Duration}; +use std::{any, env, io, path::Path, time::Duration}; use actix_cors::Cors; use actix_redis::RedisSession; @@ -7,15 +7,21 @@ use actix_web::{ cookie::time::UtcOffset, error, get, http::{header, Method, StatusCode}, - middleware, + middleware, post, web::{self, Data, Form}, App, HttpRequest, HttpResponse, HttpServer, Result, }; use anyhow::{bail, Context}; use chrono::{DateTime, FixedOffset, Local, Utc}; use derive_more::Constructor; +use duct::cmd; use handlebars::{to_json, Handlebars}; use log::LevelFilter; +use once_cell::sync::Lazy; +use rand::{ + prelude::{SliceRandom, StdRng}, + thread_rng, SeedableRng, +}; use regex::Regex; use serde::{Deserialize, Serialize}; use simplelog::{ @@ -23,6 +29,18 @@ use simplelog::{ }; use sqlx::{MySql, Pool}; +static AGGREGATION_LOWER_CASE_NUM: Lazy> = Lazy::new(|| { + let mut az09 = Vec::new(); + for az in 'a' as u32..('z' as u32 + 1) { + az09.push(char::from_u32(az).unwrap()); + } + for s09 in '0' as u32..('9' as u32 + 1) { + az09.push(char::from_u32(s09).unwrap()); + } + + az09 +}); + #[derive(Debug, Serialize, Deserialize, Constructor)] struct User { id: i32, @@ -46,6 +64,7 @@ impl Default for User { } } +#[derive(Debug, Serialize, Deserialize)] struct RegisterParams { account_name: String, password: String, @@ -76,6 +95,25 @@ async fn db_initialize(pool: &Pool) -> anyhow::Result<()> { Ok(()) } +fn escapeshellarg(arg: &str) -> String { + format!("'{}'", arg.replace("'", "'\\''")) +} + +fn digest(src: &str) -> anyhow::Result { + let output = cmd!( + "/bin/bash", + "-c", + format!( + r#"printf "%s" "+{}+" | openssl dgst -sha512 | sed 's/^.*= //'"#, + escapeshellarg(src) + ) + ) + .read() + .context("Failed to cmd")?; + + Ok(output.trim_end_matches("\n").to_string()) +} + fn validate_user(account_name: &str, password: &str) -> bool { let name_regex = Regex::new(r"\A[0-9a-zA-Z_]{3,}\z").unwrap(); let pass_regex = Regex::new(r"\A[0-9a-zA-Z_]{6,}\z").unwrap(); @@ -91,6 +129,14 @@ async fn get_initialize(pool: Data>) -> Result { Ok(HttpResponse::Ok().finish()) } +fn calculate_salt(account_name: &str) -> anyhow::Result { + digest(account_name) +} + +fn calculate_passhash(account_name: &str, password: &str) -> anyhow::Result { + digest(&format!("{}:{}", password, calculate_salt(account_name)?)) +} + async fn get_session_user(session: &Session, pool: &Pool) -> anyhow::Result> { let uid = match session.get::("user_id") { Ok(Some(uid)) => uid, @@ -114,6 +160,20 @@ fn is_login(u: Option<&User>) -> bool { } } +// goと違い文字数指定 +fn secure_random_str(b: u32) -> String { + let mut rng = StdRng::from_rng(thread_rng()).unwrap(); + + let mut rnd_str = Vec::new(); + for _ in 0..b { + rnd_str.push(AGGREGATION_LOWER_CASE_NUM.choose(&mut rng).unwrap()); + } + + let rnd_str = rnd_str.iter().map(|c| *c).collect(); + + rnd_str +} + #[get("/login")] async fn get_login(handlebars: Data>) -> Result { let body = { @@ -172,6 +232,7 @@ async fn get_register( Ok(HttpResponse::Ok().body(body)) } +#[post("/register")] async fn post_register( session: Session, pool: Data>, @@ -196,14 +257,74 @@ async fn post_register( ) { log::error!("{:?}", &e); return Ok(HttpResponse::InternalServerError().body(e.to_string())); + } else { + return Ok(HttpResponse::Found() + .insert_header((header::LOCATION, "/register")) + .finish()); } + } - return Ok(HttpResponse::Found() - .insert_header(((header::LOCATION, "/register"))) - .finish()); + let exists = match sqlx::query!( + "SELECT 1 AS _exists FROM users WHERE `account_name` = ?", + ¶ms.account_name + ) + .fetch_optional(pool.as_ref()) + .await + { + Ok(exists) => exists, + Err(e) => { + log::error!("{:?}", &e); + return Ok(HttpResponse::InternalServerError().body(e.to_string())); + } + }; + + if let Some(_) = exists { + if let Err(e) = session.insert("notice", "アカウント名がすでに使われています") + { + log::error!("{:?}", &e); + return Ok(HttpResponse::InternalServerError().body(e.to_string())); + } else { + return Ok(HttpResponse::Found() + .insert_header((header::LOCATION, "/register")) + .finish()); + } } - todo!() + let pass_hash = match calculate_passhash(¶ms.account_name, ¶ms.password) { + Ok(p) => p, + Err(e) => { + log::error!("{:?}", &e); + return Ok(HttpResponse::InternalServerError().body(e.to_string())); + } + }; + let uid = match sqlx::query!( + "INSERT INTO `users` (`account_name`, `passhash`) VALUES (?,?)", + ¶ms.account_name, + pass_hash + ) + .execute(pool.as_ref()) + .await + { + Ok(r) => r.last_insert_id(), + Err(e) => { + log::error!("{:?}", &e); + return Ok(HttpResponse::InternalServerError().body(e.to_string())); + } + }; + log::debug!("last insert id {}", &uid); + + if let Err(e) = session.insert("user_id", uid) { + log::error!("{:?}", &e); + return Ok(HttpResponse::InternalServerError().body(e.to_string())); + } + if let Err(e) = session.insert("csrf_token", secure_random_str(32)) { + log::error!("{:?}", &e); + return Ok(HttpResponse::InternalServerError().body(e.to_string())); + } + + Ok(HttpResponse::Found() + .insert_header((header::LOCATION, "/")) + .finish()) } async fn get_logout() -> Result { @@ -333,6 +454,7 @@ async fn main() -> io::Result<()> { .service(get_initialize) .service(get_login) .service(get_register) + .service(post_register) .service( web::resource("/test").to(|req: HttpRequest| match *req.method() { Method::GET => HttpResponse::Ok(), From 9967f489f456156aedf94e2935e59d7f084c791c Mon Sep 17 00:00:00 2001 From: Romira915 <40430090+Romira915@users.noreply.github.com> Date: Fri, 10 Jun 2022 17:35:31 +0900 Subject: [PATCH 15/64] add: todo get_flash --- webapp/rust/src/main.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/webapp/rust/src/main.rs b/webapp/rust/src/main.rs index 16e23b87e..939e72996 100644 --- a/webapp/rust/src/main.rs +++ b/webapp/rust/src/main.rs @@ -153,6 +153,10 @@ async fn get_session_user(session: &Session, pool: &Pool) -> anyhow::Resu Ok(user) } +fn get_flash() -> String { + todo!() +} + fn is_login(u: Option<&User>) -> bool { match u { Some(u) => u.id != 0, From d6ce708c71b2d696ef0e05fa22ffb48f63589b6d Mon Sep 17 00:00:00 2001 From: Romira915 <40430090+Romira915@users.noreply.github.com> Date: Fri, 10 Jun 2022 20:53:05 +0900 Subject: [PATCH 16/64] fix: get_flash in get_register --- webapp/rust/Cargo.toml | 1 + webapp/rust/src/main.rs | 20 +++++++++++++++++--- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/webapp/rust/Cargo.toml b/webapp/rust/Cargo.toml index ea5e4613d..2606d3def 100644 --- a/webapp/rust/Cargo.toml +++ b/webapp/rust/Cargo.toml @@ -7,6 +7,7 @@ version = "0.1.0" [dependencies] actix-cors = "0.6.1" +actix-files = "0.6.0" actix-redis = "0.10.0" actix-session = "0.5.0" actix-web = "4.0.1" diff --git a/webapp/rust/src/main.rs b/webapp/rust/src/main.rs index 939e72996..dae7816f1 100644 --- a/webapp/rust/src/main.rs +++ b/webapp/rust/src/main.rs @@ -1,10 +1,12 @@ use std::{any, env, io, path::Path, time::Duration}; use actix_cors::Cors; +use actix_files::Files; use actix_redis::RedisSession; use actix_session::Session; use actix_web::{ cookie::time::UtcOffset, + dev::ResourceDef, error, get, http::{header, Method, StatusCode}, middleware, post, @@ -153,8 +155,18 @@ async fn get_session_user(session: &Session, pool: &Pool) -> anyhow::Resu Ok(user) } -fn get_flash() -> String { - todo!() +fn get_flash(session: &Session, key: &str) -> Option { + match session.get(key) { + Ok(Some(value)) => { + session.remove(key); + value + } + Err(e) => { + log::error!("{:?}", &e); + None + } + _ => None, + } } fn is_login(u: Option<&User>) -> bool { @@ -225,7 +237,7 @@ async fn get_register( let mut json = serde_json::to_value(user).unwrap(); let map = json.as_object_mut().unwrap(); - map.insert("flash".to_string(), to_json("notice")); + map.insert("flash".to_string(), to_json(get_flash(&session, "notice"))); map.insert("parent".to_string(), to_json("layout")); log::debug!("map {:?}", &map); @@ -459,6 +471,8 @@ async fn main() -> io::Result<()> { .service(get_login) .service(get_register) .service(post_register) + // .service(ResourceDef::new("/{tail}*").) + .service(Files::new("/", "../public")) .service( web::resource("/test").to(|req: HttpRequest| match *req.method() { Method::GET => HttpResponse::Ok(), From 63edf8a2e75c41e4b05f4ae5b2c393e7cdc5ba0f Mon Sep 17 00:00:00 2001 From: Romira915 <40430090+Romira915@users.noreply.github.com> Date: Fri, 10 Jun 2022 21:41:57 +0900 Subject: [PATCH 17/64] features: post_login --- webapp/rust/.vscode/settings.json | 4 +- webapp/rust/src/main.rs | 66 ++++++++++++++++++++++++++++--- 2 files changed, 62 insertions(+), 8 deletions(-) diff --git a/webapp/rust/.vscode/settings.json b/webapp/rust/.vscode/settings.json index aff611361..0967ef424 100644 --- a/webapp/rust/.vscode/settings.json +++ b/webapp/rust/.vscode/settings.json @@ -1,3 +1 @@ -{ - "codic.case": "SNAKE_CASE" -} \ No newline at end of file +{} diff --git a/webapp/rust/src/main.rs b/webapp/rust/src/main.rs index dae7816f1..790285fb3 100644 --- a/webapp/rust/src/main.rs +++ b/webapp/rust/src/main.rs @@ -67,7 +67,7 @@ impl Default for User { } #[derive(Debug, Serialize, Deserialize)] -struct RegisterParams { +struct LoginRegisterParams { account_name: String, password: String, } @@ -97,6 +97,27 @@ async fn db_initialize(pool: &Pool) -> anyhow::Result<()> { Ok(()) } +async fn try_login(account_name: &str, password: &str, pool: &Pool) -> anyhow::Result { + let user = sqlx::query_as!( + User, + "SELECT * FROM users WHERE account_name = ? AND del_flg = 0", + account_name + ) + .fetch_optional(pool) + .await + .context("Failed to query try_login")?; + + if let Some(user) = user { + if calculate_passhash(&user.account_name, password)? == user.passhash { + Ok(user) + } else { + bail!("Incorrect password"); + } + } else { + bail!("User does not exist"); + } +} + fn escapeshellarg(arg: &str) -> String { format!("'{}'", arg.replace("'", "'\\''")) } @@ -208,9 +229,43 @@ async fn get_login(handlebars: Data>) -> Result { Ok(HttpResponse::Ok().body(body)) } -async fn post_login() -> Result { - todo!(); - Ok(HttpResponse::Ok().finish()) +#[post("/login")] +async fn post_login( + session: Session, + pool: Data>, + params: Form, +) -> Result { + match get_session_user(&session, pool.as_ref()).await { + Ok(user) => { + if is_login(user.as_ref()) { + return Ok(HttpResponse::Found() + .insert_header((header::LOCATION, "/")) + .finish()); + } + } + Err(e) => log::error!("{:?}", &e), + }; + + match try_login(¶ms.account_name, ¶ms.password, pool.as_ref()).await { + Ok(user) => { + session.insert("user_id", user.id).unwrap(); + session.insert("csrf_token", secure_random_str(32)).unwrap(); + + Ok(HttpResponse::Found() + .insert_header((header::LOCATION, "/")) + .finish()) + } + Err(e) => { + log::error!("{:?}", &e); + session + .insert("notice", "アカウント名かパスワードが間違っています") + .unwrap(); + + Ok(HttpResponse::Found() + .insert_header((header::LOCATION, "/login")) + .finish()) + } + } } #[get("/register")] @@ -252,7 +307,7 @@ async fn get_register( async fn post_register( session: Session, pool: Data>, - params: Form, + params: Form, ) -> Result { match get_session_user(&session, pool.as_ref()).await { Ok(user) => { @@ -469,6 +524,7 @@ async fn main() -> io::Result<()> { .app_data(Data::new(handlebars)) .service(get_initialize) .service(get_login) + .service(post_login) .service(get_register) .service(post_register) // .service(ResourceDef::new("/{tail}*").) From a0e5b96a5049d2525bd0df03fc56d70cfc50a8cf Mon Sep 17 00:00:00 2001 From: Romira915 <40430090+Romira915@users.noreply.github.com> Date: Fri, 10 Jun 2022 21:55:03 +0900 Subject: [PATCH 18/64] features: get_login --- webapp/rust/src/main.rs | 30 ++++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/webapp/rust/src/main.rs b/webapp/rust/src/main.rs index 790285fb3..dfa0e0b33 100644 --- a/webapp/rust/src/main.rs +++ b/webapp/rust/src/main.rs @@ -212,13 +212,35 @@ fn secure_random_str(b: u32) -> String { } #[get("/login")] -async fn get_login(handlebars: Data>) -> Result { - let body = { - let user = User::new(0, "test".to_string(), "pass".to_string(), 0, 0, Utc::now()); +async fn get_login( + session: Session, + pool: Data>, + handlebars: Data>, +) -> Result { + let user = match get_session_user(&session, pool.as_ref()).await { + Ok(user) => { + if is_login(user.as_ref()) { + return Ok(HttpResponse::Found() + .insert_header((header::LOCATION, "/")) + .finish()); + } + if let Some(user) = user { + user + } else { + User::default() + } + } + Err(e) => { + log::error!("{:?}", &e); + User::default() + } + }; + + let body = { let mut json = serde_json::to_value(user).unwrap(); let map = json.as_object_mut().unwrap(); - map.insert("flash".to_string(), to_json("notice")); + map.insert("flash".to_string(), to_json(get_flash(&session, "notice"))); map.insert("parent".to_string(), to_json("layout")); log::debug!("{:?}", &map); From f0992e8c3fff9c574d7843440c536b98a31b4f4a Mon Sep 17 00:00:00 2001 From: Romira915 <40430090+Romira915@users.noreply.github.com> Date: Fri, 10 Jun 2022 23:40:56 +0900 Subject: [PATCH 19/64] features: make_posts --- webapp/rust/.vscode/settings.json | 4 +- webapp/rust/src/main.rs | 138 +++++++++++++++++++++++++++++- 2 files changed, 137 insertions(+), 5 deletions(-) diff --git a/webapp/rust/.vscode/settings.json b/webapp/rust/.vscode/settings.json index 0967ef424..6378977b1 100644 --- a/webapp/rust/.vscode/settings.json +++ b/webapp/rust/.vscode/settings.json @@ -1 +1,3 @@ -{} +{ + "codic.case": "snake_case" +} diff --git a/webapp/rust/src/main.rs b/webapp/rust/src/main.rs index dfa0e0b33..33e910f35 100644 --- a/webapp/rust/src/main.rs +++ b/webapp/rust/src/main.rs @@ -31,6 +31,7 @@ use simplelog::{ }; use sqlx::{MySql, Pool}; +const POSTS_PER_PAGE: usize = 20; static AGGREGATION_LOWER_CASE_NUM: Lazy> = Lazy::new(|| { let mut az09 = Vec::new(); for az in 'a' as u32..('z' as u32 + 1) { @@ -66,6 +67,40 @@ impl Default for User { } } +#[derive(Debug, Serialize, Deserialize, Constructor)] +struct Post { + id: i32, + user_id: i32, + imgdata: Option>, + body: String, + mime: String, + created_at: chrono::DateTime, +} + +#[derive(Debug, Serialize, Deserialize, Constructor)] +struct GrantedInfoPost { + post: Post, + comment_count: i64, + comments: Vec, + user: User, + csrftoken: String, +} + +#[derive(Debug, Serialize, Deserialize, Constructor)] +struct Comment { + id: i32, + post_id: i32, + user_id: i32, + comment: String, + created_at: chrono::DateTime, +} + +#[derive(Debug, Serialize, Deserialize, Constructor)] +struct GrantedUserComment { + comment: Comment, + user: User, +} + #[derive(Debug, Serialize, Deserialize)] struct LoginRegisterParams { account_name: String, @@ -190,6 +225,84 @@ fn get_flash(session: &Session, key: &str) -> Option { } } +async fn make_post( + results: Vec, + csrf_token: String, + all_comments: bool, + pool: &Pool, +) -> anyhow::Result> { + let mut granted_info_posts = Vec::new(); + + for p in results { + let comment_count = sqlx::query!( + "SELECT COUNT(*) AS `count` FROM `comments` WHERE `post_id` = ?", + p.id + ) + .fetch_one(pool) + .await + .context("Failed to query comment_count")? + .count; + + let mut comments = if !all_comments { + sqlx::query_as!( + Comment, + "SELECT * FROM `comments` WHERE `post_id` = ? ORDER BY `created_at` DESC", + p.id + ) + .fetch_all(pool) + .await + } else { + sqlx::query_as!( + Comment, + "SELECT * FROM `comments` WHERE `post_id` = ? ORDER BY `created_at` DESC LIMIT 3", + p.id + ) + .fetch_all(pool) + .await + } + .context("Failed to query comments")?; + + let mut granted_comments = Vec::new(); + + for comment in comments { + let user = sqlx::query_as!( + User, + "SELECT * FROM `users` WHERE `id` = ?", + comment.user_id + ) + .fetch_optional(pool) + .await + .context("Failed to query user")? + .context("Not found user")?; + + granted_comments.push(GrantedUserComment::new(comment, user)); + } + + granted_comments.reverse(); + + let user = sqlx::query_as!(User, "SELECT * FROM `users` WHERE `id` = ?", p.user_id) + .fetch_optional(pool) + .await + .context("Failed to query user")? + .context("Not found user")?; + + if user.del_flg == 0 { + granted_info_posts.push(GrantedInfoPost::new( + p, + comment_count, + granted_comments, + user, + csrf_token.clone(), + )) + } + if granted_info_posts.len() >= POSTS_PER_PAGE { + break; + } + } + + Ok(granted_info_posts) +} + fn is_login(u: Option<&User>) -> bool { match u { Some(u) => u.id != 0, @@ -420,12 +533,27 @@ async fn post_register( .finish()) } -async fn get_logout() -> Result { - todo!() +#[get("/logout")] +async fn get_logout(session: Session) -> Result { + session.remove("user_id").unwrap_or_default(); + + Ok(HttpResponse::Found() + .insert_header((header::LOCATION, "/")) + .finish()) } -async fn get_index() -> Result { - todo!() +#[get("/")] +async fn get_index(session: Session, pool: Data>) -> Result { + let results = match sqlx::query_as_unchecked!(Post,"SELECT `id`, `user_id`, `body`, `mime`, `created_at`, NULL AS imgdata FROM `posts` ORDER BY `created_at` DESC").fetch_all(pool.as_ref()).await { + Ok(results) => results, + Err(e) => { + log::error!("{:?}",&e); + return Ok(HttpResponse::InternalServerError().body(e.to_string())); + } + }; + + // TODO: fn make_posts + Ok(HttpResponse::Ok().finish()) } async fn get_posts() -> Result { @@ -549,6 +677,8 @@ async fn main() -> io::Result<()> { .service(post_login) .service(get_register) .service(post_register) + .service(get_logout) + .service(get_index) // .service(ResourceDef::new("/{tail}*").) .service(Files::new("/", "../public")) .service( From e294c93ec28346e4e1f141aaeca01ca6657f9b4b Mon Sep 17 00:00:00 2001 From: Romira915 <40430090+Romira915@users.noreply.github.com> Date: Fri, 10 Jun 2022 23:51:22 +0900 Subject: [PATCH 20/64] add: todo --- webapp/rust/src/main.rs | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/webapp/rust/src/main.rs b/webapp/rust/src/main.rs index 33e910f35..b0cf97829 100644 --- a/webapp/rust/src/main.rs +++ b/webapp/rust/src/main.rs @@ -310,6 +310,10 @@ fn is_login(u: Option<&User>) -> bool { } } +fn get_csrf_token(session: &Session) -> Option { + session.get("csrf_token").unwrap_or_default() +} + // goと違い文字数指定 fn secure_random_str(b: u32) -> String { let mut rng = StdRng::from_rng(thread_rng()).unwrap(); @@ -548,11 +552,25 @@ async fn get_index(session: Session, pool: Data>) -> Result results, Err(e) => { log::error!("{:?}",&e); - return Ok(HttpResponse::InternalServerError().body(e.to_string())); + return Ok(HttpResponse::InternalServerError().body(e.to_string())); + } + }; + + let csrf_token = if let Some(token) = get_csrf_token(&session) { + token + } else { + log::error!("token is None"); + return Ok(HttpResponse::InternalServerError().finish()); + }; + let posts = match make_post(results, csrf_token, false, pool.as_ref()).await { + Ok(posts) => posts, + Err(e) => { + log::error!("{:?}", &e); + return Ok(HttpResponse::InternalServerError().body(e.to_string())); } }; - // TODO: fn make_posts + // TODO: after golang 406 line Ok(HttpResponse::Ok().finish()) } From c6b9fc33a2d43984ed6d2d95da8ff3dcacbda0a9 Mon Sep 17 00:00:00 2001 From: Romira915 <40430090+Romira915@users.noreply.github.com> Date: Sat, 11 Jun 2022 00:23:14 +0900 Subject: [PATCH 21/64] create: template html --- webapp/rust/static/index.html | 29 +++++++++++++++++++++++++++++ webapp/rust/static/post.html | 35 +++++++++++++++++++++++++++++++++++ webapp/rust/static/posts.html | 5 +++++ 3 files changed, 69 insertions(+) create mode 100644 webapp/rust/static/index.html create mode 100644 webapp/rust/static/post.html create mode 100644 webapp/rust/static/posts.html diff --git a/webapp/rust/static/index.html b/webapp/rust/static/index.html new file mode 100644 index 000000000..5882cda77 --- /dev/null +++ b/webapp/rust/static/index.html @@ -0,0 +1,29 @@ +{{#*inline "content"}} +
+ +
+ +
+
+ +
+
+ + +
+ {{#if flash}} +
+ {{flash}} +
+ {{/if}} + +
+ +{{> posts_html}} + +
+ + +
+{{/inline}} +{{> (lookup this "content_parent")}} \ No newline at end of file diff --git a/webapp/rust/static/post.html b/webapp/rust/static/post.html new file mode 100644 index 000000000..7718e91aa --- /dev/null +++ b/webapp/rust/static/post.html @@ -0,0 +1,35 @@ +
+
+ + + + +
+
+ +
+
+ + {{ .Body }} +
+
+
+ comments: {{ .CommentCount }} +
+ + {{ range .Comments }} +
+ + {{.Comment}} +
+ {{ end }} +
+
+ + + + +
+
+
+
\ No newline at end of file diff --git a/webapp/rust/static/posts.html b/webapp/rust/static/posts.html new file mode 100644 index 000000000..dfe2c8549 --- /dev/null +++ b/webapp/rust/static/posts.html @@ -0,0 +1,5 @@ +
+ {{#each post}} + {{> post_html}} + {{/each}} +
\ No newline at end of file From bb1bdee61331a82e81d6e94474349ed1eb8bbc4f Mon Sep 17 00:00:00 2001 From: Romira915 <40430090+Romira915@users.noreply.github.com> Date: Tue, 14 Jun 2022 16:40:51 +0900 Subject: [PATCH 22/64] fix: template html --- webapp/rust/src/main.rs | 8 ++++++-- webapp/rust/static/index.html | 2 +- webapp/rust/static/post.html | 26 +++++++++++++------------- 3 files changed, 20 insertions(+), 16 deletions(-) diff --git a/webapp/rust/src/main.rs b/webapp/rust/src/main.rs index b0cf97829..9ca07200b 100644 --- a/webapp/rust/src/main.rs +++ b/webapp/rust/src/main.rs @@ -83,7 +83,7 @@ struct GrantedInfoPost { comment_count: i64, comments: Vec, user: User, - csrftoken: String, + csrf_token: String, } #[derive(Debug, Serialize, Deserialize, Constructor)] @@ -547,7 +547,11 @@ async fn get_logout(session: Session) -> Result { } #[get("/")] -async fn get_index(session: Session, pool: Data>) -> Result { +async fn get_index( + session: Session, + pool: Data>, + handlebars: Data>, +) -> Result { let results = match sqlx::query_as_unchecked!(Post,"SELECT `id`, `user_id`, `body`, `mime`, `created_at`, NULL AS imgdata FROM `posts` ORDER BY `created_at` DESC").fetch_all(pool.as_ref()).await { Ok(results) => results, Err(e) => { diff --git a/webapp/rust/static/index.html b/webapp/rust/static/index.html index 5882cda77..108436a85 100644 --- a/webapp/rust/static/index.html +++ b/webapp/rust/static/index.html @@ -8,7 +8,7 @@
- +
{{#if flash}} diff --git a/webapp/rust/static/post.html b/webapp/rust/static/post.html index 7718e91aa..1e177e5d7 100644 --- a/webapp/rust/static/post.html +++ b/webapp/rust/static/post.html @@ -1,33 +1,33 @@ -
+
- - - + + +
- - {{ .Body }} + + {{body}}
- comments: {{ .CommentCount }} + comments: {{comment_count}}
- {{ range .Comments }} + {{#each comments}}
- - {{.Comment}} + + {{comment.comment}}
- {{ end }} + {{/each}}
- - + +
From ea152c4c6c478eab9a1febf9f7a536a2bd99ea65 Mon Sep 17 00:00:00 2001 From: Romira915 <40430090+Romira915@users.noreply.github.com> Date: Tue, 14 Jun 2022 16:43:20 +0900 Subject: [PATCH 23/64] add: image_url --- webapp/rust/src/main.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/webapp/rust/src/main.rs b/webapp/rust/src/main.rs index 9ca07200b..94c71979e 100644 --- a/webapp/rust/src/main.rs +++ b/webapp/rust/src/main.rs @@ -303,6 +303,17 @@ async fn make_post( Ok(granted_info_posts) } +fn image_url(p: &GrantedInfoPost) -> String { + let ext = match p.post.mime.as_str() { + "image/jpeg" => ".jpg", + "image/png" => ".png", + "image/gif" => ".gif", + _ => "", + }; + + format!("/image/{}{}", p.post.id, ext) +} + fn is_login(u: Option<&User>) -> bool { match u { Some(u) => u.id != 0, From 396202ca2335d954889df71575d8f6c80c56a959 Mon Sep 17 00:00:00 2001 From: Romira915 <40430090+Romira915@users.noreply.github.com> Date: Tue, 14 Jun 2022 18:43:13 +0900 Subject: [PATCH 24/64] features: index / --- webapp/docker-compose.yml | 3 +- webapp/rust/map.json | 3219 +++++++++++++++++++++++++++++++++ webapp/rust/src/main.rs | 98 +- webapp/rust/static/post.html | 21 +- webapp/rust/static/posts.html | 7 +- 5 files changed, 3313 insertions(+), 35 deletions(-) create mode 100644 webapp/rust/map.json diff --git a/webapp/docker-compose.yml b/webapp/docker-compose.yml index 377a91f57..940536331 100644 --- a/webapp/docker-compose.yml +++ b/webapp/docker-compose.yml @@ -14,7 +14,7 @@ services: cpus: 1 mem_limit: 1g # Go実装の場合は golang/ PHP実装の場合は php/ - build: golang/ + build: rust/ environment: ISUCONP_DB_HOST: mysql ISUCONP_DB_PORT: 3306 @@ -28,6 +28,7 @@ services: volumes: - ./public:/home/public init: true + depends_on: mysql mysql: cpus: 1 diff --git a/webapp/rust/map.json b/webapp/rust/map.json new file mode 100644 index 000000000..2e34bdccd --- /dev/null +++ b/webapp/rust/map.json @@ -0,0 +1,3219 @@ +{ + "content_parent": String( + "layout", + ), + "csrf_token": String( + "", + ), + "flash": Null, + "post_parent": String( + "posts", + ), + "posts": Array([ + Object({ + "comment_count": Number( + 0, + ), + "comments": Array([]), + "csrf_token": String( + "", + ), + "post": Object({ + "body": String( + "てsってst", + ), + "created_at": String( + "2022-06-14T08:24:48Z", + ), + "id": Number( + 10001, + ), + "imgdata": Null, + "mime": String( + "image/jpeg", + ), + "user_id": Number( + 1005, + ), + }), + "user": Object({ + "account_name": String( + "testtest", + ), + "authority": Number( + 0, + ), + "created_at": String( + "2022-06-14T08:23:28Z", + ), + "del_flg": Number( + 0, + ), + "id": Number( + 1005, + ), + "passhash": String( + "e1df2715a909d3ed434b95223f96a5e87974c8a6101f05d83c16aa86d2ac487951dcbfc33730a29230a375fdc2f4b8c12cfbd92ac3bb6c16dbe36617996dc2c9", + ), + }), + }), + Object({ + "comment_count": Number( + 11, + ), + "comments": Array([ + Object({ + "comment": Object({ + "comment": String( + "ヽ(^▽^@)ノ\u{3000}やぁ~", + ), + "created_at": String( + "2016-01-03T17:37:42Z", + ), + "id": Number( + 63462, + ), + "post_id": Number( + 10000, + ), + "user_id": Number( + 804, + ), + }), + "user": Object({ + "account_name": String( + "carmella", + ), + "authority": Number( + 0, + ), + "created_at": String( + "2016-01-01T00:13:24Z", + ), + "del_flg": Number( + 0, + ), + "id": Number( + 804, + ), + "passhash": String( + "a66b8705963efdbc8c4c9227cf98fd2497c96c5db8c05bf3e260e59d922f89eec771e049a9cec736278045e0afde96c3abbf8c535b4b9d677625f830b40cfa9b", + ), + }), + }), + Object({ + "comment": Object({ + "comment": String( + "(ノ^^)ノ―――――――※※☆★congratulations!!★☆", + ), + "created_at": String( + "2016-01-03T17:40:51Z", + ), + "id": Number( + 63651, + ), + "post_id": Number( + 10000, + ), + "user_id": Number( + 296, + ), + }), + "user": Object({ + "account_name": String( + "ramona", + ), + "authority": Number( + 0, + ), + "created_at": String( + "2016-01-01T00:04:56Z", + ), + "del_flg": Number( + 0, + ), + "id": Number( + 296, + ), + "passhash": String( + "e4d20709f5afad55a2685d586132dcbdd223d35a70e322ca08f929463205965f14dc3fd5873f0d4946e4df5190890bfc929120999fb4f0581b91a3a7d4ce4140", + ), + }), + }), + Object({ + "comment": Object({ + "comment": String( + "[壁]=\u{ff9f}▽\u{ff9f})ノ ヤァ♪", + ), + "created_at": String( + "2016-01-04T03:08:37Z", + ), + "id": Number( + 97717, + ), + "post_id": Number( + 10000, + ), + "user_id": Number( + 41, + ), + }), + "user": Object({ + "account_name": String( + "stephanie", + ), + "authority": Number( + 0, + ), + "created_at": String( + "2016-01-01T00:00:41Z", + ), + "del_flg": Number( + 0, + ), + "id": Number( + 41, + ), + "passhash": String( + "27a3a4ec313fcf9c85adb1e3811bfe8e217b4b7c6c62cd62f3e1f5d9cfbbed9c874d6a7f9847e282a60786344343f6d2c15ba6481f898367a9c026e59bd112d5", + ), + }), + }), + ]), + "csrf_token": String( + "", + ), + "post": Object({ + "body": String( + "ト\u{ff9e}モト\u{ff9e}モ\(^_^ ) ( ^_^)/ト\u{ff9e}モト\u{ff9e}モ", + ), + "created_at": String( + "2016-01-02T02:46:40Z", + ), + "id": Number( + 10000, + ), + "imgdata": Null, + "mime": String( + "image/png", + ), + "user_id": Number( + 112, + ), + }), + "user": Object({ + "account_name": String( + "rosa", + ), + "authority": Number( + 0, + ), + "created_at": String( + "2016-01-01T00:01:52Z", + ), + "del_flg": Number( + 0, + ), + "id": Number( + 112, + ), + "passhash": String( + "7ee7581f856795775c4f864ac6bbc1d687b6035f0560d3436a1d0e0138b07a6b9033f899a690c8ce3d46547a18a7a611ba80557a67f71ae50b48159b9f873dd8", + ), + }), + }), + Object({ + "comment_count": Number( + 11, + ), + "comments": Array([ + Object({ + "comment": Object({ + "comment": String( + "ハイ オメテ\u{ff9e}トネ( ゜σ ゜)Ξ(\u{3000}・_<)σ…----- ・ヒ\u{ff9f}ンッ! (^ ^ ;)ヤナカンシ\u{ff9e}", + ), + "created_at": String( + "2016-01-03T19:09:50Z", + ), + "id": Number( + 68990, + ), + "post_id": Number( + 9999, + ), + "user_id": Number( + 248, + ), + }), + "user": Object({ + "account_name": String( + "caroline", + ), + "authority": Number( + 0, + ), + "created_at": String( + "2016-01-01T00:04:08Z", + ), + "del_flg": Number( + 0, + ), + "id": Number( + 248, + ), + "passhash": String( + "2ac4e01921cab4bec906ca0171a69d8cad539d08501c8c209066e26781410f3ee1e177689d14aafdcd3736f8f4d3510173e22ef6910d6ae49076fab59d7ee017", + ), + }), + }), + Object({ + "comment": Object({ + "comment": String( + "睡魔→Ψ(`∀´#)ノ\_(T◇T)ノ\")),,,,,,,,,オヤスミー", + ), + "created_at": String( + "2016-01-03T23:09:36Z", + ), + "id": Number( + 83376, + ), + "post_id": Number( + 9999, + ), + "user_id": Number( + 410, + ), + }), + "user": Object({ + "account_name": String( + "muriel", + ), + "authority": Number( + 0, + ), + "created_at": String( + "2016-01-01T00:06:50Z", + ), + "del_flg": Number( + 0, + ), + "id": Number( + 410, + ), + "passhash": String( + "56fa35d0d22e863cecb79cb3fb0ff6eb2d073a682f1b5b21dbd0591e3c4fadc8544f9648c9d4c94ce113e39040e647225f1113ef9cde30ddc8ce71b81a44446b", + ), + }), + }), + Object({ + "comment": Object({ + "comment": String( + "v( ̄、 ̄)ノ\"ヨォッ!!ヒサシフ\u{ff9e}リ!!", + ), + "created_at": String( + "2016-01-04T02:36:31Z", + ), + "id": Number( + 95791, + ), + "post_id": Number( + 9999, + ), + "user_id": Number( + 357, + ), + }), + "user": Object({ + "account_name": String( + "lula", + ), + "authority": Number( + 0, + ), + "created_at": String( + "2016-01-01T00:05:57Z", + ), + "del_flg": Number( + 0, + ), + "id": Number( + 357, + ), + "passhash": String( + "e517cf650ffd37efc7106918e395f5f6f1b11fb1e2838a23ad58c1e7809708e4f63f431dfb941617ae94c7929c8ef2fdef6fc4213dd0dd40dbbedb22466890c5", + ), + }), + }), + ]), + "csrf_token": String( + "", + ), + "post": Object({ + "body": String( + "★*♪。☆*★*♪。☆*★*♪。☆*(^∇\u{ff9f}*)ノ\" オヤスミィ♪", + ), + "created_at": String( + "2016-01-02T02:46:39Z", + ), + "id": Number( + 9999, + ), + "imgdata": Null, + "mime": String( + "image/jpeg", + ), + "user_id": Number( + 792, + ), + }), + "user": Object({ + "account_name": String( + "jordan", + ), + "authority": Number( + 0, + ), + "created_at": String( + "2016-01-01T00:13:12Z", + ), + "del_flg": Number( + 0, + ), + "id": Number( + 792, + ), + "passhash": String( + "6530cd2f245b286042c5dfef368e23305475578c372bb56ddd4cb9e9303026ac3051976dd9bb10eb22a3b0a66fc892820411bc874a846fe9f59378104864342d", + ), + }), + }), + Object({ + "comment_count": Number( + 10, + ), + "comments": Array([ + Object({ + "comment": Object({ + "comment": String( + "オヒサ!((( ^^)爻(^^ )))オヒサ!", + ), + "created_at": String( + "2016-01-04T00:21:37Z", + ), + "id": Number( + 87697, + ), + "post_id": Number( + 9998, + ), + "user_id": Number( + 925, + ), + }), + "user": Object({ + "account_name": String( + "mai", + ), + "authority": Number( + 0, + ), + "created_at": String( + "2016-01-01T00:15:25Z", + ), + "del_flg": Number( + 0, + ), + "id": Number( + 925, + ), + "passhash": String( + "6733654598f5921dd8713cc3c7a1b05424d0171c54d5e1cbcb139496ef302ee3506d8e1d5fa931d916dc7560b05051f99f2b478720fdcbcdb84e5e0fb37272da", + ), + }), + }), + Object({ + "comment": Object({ + "comment": String( + "see you agein.....(/_・、)/~~", + ), + "created_at": String( + "2016-01-04T01:09:56Z", + ), + "id": Number( + 90596, + ), + "post_id": Number( + 9998, + ), + "user_id": Number( + 273, + ), + }), + "user": Object({ + "account_name": String( + "priscilla", + ), + "authority": Number( + 0, + ), + "created_at": String( + "2016-01-01T00:04:33Z", + ), + "del_flg": Number( + 0, + ), + "id": Number( + 273, + ), + "passhash": String( + "8a874793eb65c1b6aea4d66baab9b8803f2e00b5aaa0412be5f2d55a1c7125fc4468e2e004aab614a5b19252246a96a05958d424cd9e1e2ab282dd96c859a853", + ), + }), + }), + Object({ + "comment": Object({ + "comment": String( + "オメットマシ\u{ff9e}ックハント\u{ff9e}o((=\u{ff9f}エ\u{ff9f}=))oノXXXXXXXXXXXXX>C( )\u{ff9f}0\u{ff9f})ノノ", + ), + "created_at": String( + "2016-01-04T03:33:45Z", + ), + "id": Number( + 99225, + ), + "post_id": Number( + 9998, + ), + "user_id": Number( + 648, + ), + }), + "user": Object({ + "account_name": String( + "jeanine", + ), + "authority": Number( + 0, + ), + "created_at": String( + "2016-01-01T00:10:48Z", + ), + "del_flg": Number( + 0, + ), + "id": Number( + 648, + ), + "passhash": String( + "265f9c06fc79988e8dcfe3a27e68b98fd9c0694e5e79914f5ec97abb689ddb64e169354d4e0ce8367aad8b300713f4a67658dc4c79a96447614497d3e7aeacf9", + ), + }), + }), + ]), + "csrf_token": String( + "", + ), + "post": Object({ + "body": String( + "(^-^)ノ~~マタネー☆’.・*.・:★’.・*.・:☆’.・*.・:★", + ), + "created_at": String( + "2016-01-02T02:46:38Z", + ), + "id": Number( + 9998, + ), + "imgdata": Null, + "mime": String( + "image/jpeg", + ), + "user_id": Number( + 149, + ), + }), + "user": Object({ + "account_name": String( + "valerie", + ), + "authority": Number( + 0, + ), + "created_at": String( + "2016-01-01T00:02:29Z", + ), + "del_flg": Number( + 0, + ), + "id": Number( + 149, + ), + "passhash": String( + "8da0a01cb7ba509dbd29c0d03531659234ac08af0a90d86d72a37efad2a827a95359b28f6ef5a468edf346dd655dcfa2d465471b1f0dcdb9bb0ace7c77c79275", + ), + }), + }), + Object({ + "comment_count": Number( + 14, + ), + "comments": Array([ + Object({ + "comment": Object({ + "comment": String( + "(▼▼メ)/●~*【祝】*~●\(▼▼メ)", + ), + "created_at": String( + "2016-01-04T02:00:39Z", + ), + "id": Number( + 93639, + ), + "post_id": Number( + 9997, + ), + "user_id": Number( + 266, + ), + }), + "user": Object({ + "account_name": String( + "nora", + ), + "authority": Number( + 0, + ), + "created_at": String( + "2016-01-01T00:04:26Z", + ), + "del_flg": Number( + 0, + ), + "id": Number( + 266, + ), + "passhash": String( + "47fab786c3f1978cef77600a37c0db24d3a2ea582dfbafdb919f574c5669afceb9bc0ab07850c9f2d95a40957be7ad7c21df9e9b8122e3e69aedac650ece6ea3", + ), + }), + }), + Object({ + "comment": Object({ + "comment": String( + "(○\u{ff9f}▽\u{ff9f}○)/ ヨッ!!", + ), + "created_at": String( + "2016-01-04T02:04:50Z", + ), + "id": Number( + 93890, + ), + "post_id": Number( + 9997, + ), + "user_id": Number( + 838, + ), + }), + "user": Object({ + "account_name": String( + "jerry", + ), + "authority": Number( + 0, + ), + "created_at": String( + "2016-01-01T00:13:58Z", + ), + "del_flg": Number( + 0, + ), + "id": Number( + 838, + ), + "passhash": String( + "e025ec3ba311af1e6fa284dbaa8f94b95a54d4ec1ffc40158188bdaf00604be27bd6468fd1cb3352b122c9488f47cd292bd4146afb2eb2f13ca8c3cf1e2874fc", + ), + }), + }), + Object({ + "comment": Object({ + "comment": String( + "オメットナカ\u{ff9e}レホ\u{ff9e}シ(*'▽')ノ^---==ΞΞΞ☆", + ), + "created_at": String( + "2016-01-04T02:55:03Z", + ), + "id": Number( + 96903, + ), + "post_id": Number( + 9997, + ), + "user_id": Number( + 363, + ), + }), + "user": Object({ + "account_name": String( + "juana", + ), + "authority": Number( + 0, + ), + "created_at": String( + "2016-01-01T00:06:03Z", + ), + "del_flg": Number( + 0, + ), + "id": Number( + 363, + ), + "passhash": String( + "b2474ac1b1794af95b57e3fb1e7893a6975269f7290935ea728718d4ff8bfe618f6fee8498841ab3c6cde78576c0d8d2636d6c49db0f17195d481dee1c76b925", + ), + }), + }), + ]), + "csrf_token": String( + "", + ), + "post": Object({ + "body": String( + "ハ\u{ff9e}ヾ(*'O'*)イヾ(*'◇'*)ハ\u{ff9e}ヾ(*'□'*)ーヾ(*'□'*)イヾ(*'-'*)", + ), + "created_at": String( + "2016-01-02T02:46:37Z", + ), + "id": Number( + 9997, + ), + "imgdata": Null, + "mime": String( + "image/jpeg", + ), + "user_id": Number( + 89, + ), + }), + "user": Object({ + "account_name": String( + "julia", + ), + "authority": Number( + 0, + ), + "created_at": String( + "2016-01-01T00:01:29Z", + ), + "del_flg": Number( + 0, + ), + "id": Number( + 89, + ), + "passhash": String( + "1c80db58ddaa659bda70d61954231d8ef1dd33f3bc5817e9b02fdce0642be5a86c6582c78de0256b94d79856d0e5893854b5b11a677e3f361092f757ae4d849e", + ), + }), + }), + Object({ + "comment_count": Number( + 12, + ), + "comments": Array([ + Object({ + "comment": Object({ + "comment": String( + "電柱|・ω・`)ノ ヤァ", + ), + "created_at": String( + "2016-01-03T19:23:18Z", + ), + "id": Number( + 69798, + ), + "post_id": Number( + 9996, + ), + "user_id": Number( + 646, + ), + }), + "user": Object({ + "account_name": String( + "marisol", + ), + "authority": Number( + 0, + ), + "created_at": String( + "2016-01-01T00:10:46Z", + ), + "del_flg": Number( + 0, + ), + "id": Number( + 646, + ), + "passhash": String( + "a5c525e5dd29a1f9385feb91a28cf471f1e34374b228e4aec529c39484a2d4a6ac7fd6bf70ea38714294faee44cf919c7054be489cf265cffe4f40717d18b142", + ), + }), + }), + Object({ + "comment": Object({ + "comment": String( + "(キ▼⊿▼)ノ ヨォ!", + ), + "created_at": String( + "2016-01-03T21:30:50Z", + ), + "id": Number( + 77450, + ), + "post_id": Number( + 9996, + ), + "user_id": Number( + 573, + ), + }), + "user": Object({ + "account_name": String( + "janette", + ), + "authority": Number( + 0, + ), + "created_at": String( + "2016-01-01T00:09:33Z", + ), + "del_flg": Number( + 0, + ), + "id": Number( + 573, + ), + "passhash": String( + "7fba215169b327e4f914b75d7694f4c58beb71576c6ec7e683d9a03e27a1c87e281980a0a59ee1c2b525ccf6d83938dcd6f719be8f8e0718e012ed3597275bb6", + ), + }), + }), + Object({ + "comment": Object({ + "comment": String( + "(ノ`Д´)ノ^・:*:・\u{ff9f}'((●~*チチチ,。・:*:・\u{ff9f}'☆オメテ\u{ff9e}トォー!!", + ), + "created_at": String( + "2016-01-04T00:38:01Z", + ), + "id": Number( + 88681, + ), + "post_id": Number( + 9996, + ), + "user_id": Number( + 969, + ), + }), + "user": Object({ + "account_name": String( + "lolita", + ), + "authority": Number( + 0, + ), + "created_at": String( + "2016-01-01T00:16:09Z", + ), + "del_flg": Number( + 0, + ), + "id": Number( + 969, + ), + "passhash": String( + "327e0bedf08b755dd3f0981442e59da2ff725570279c5f8a53aa0a0d4203319eedb797a8b3f13e3425e3edcc4be08d20513bb6d41566c2eee20645265405aad3", + ), + }), + }), + ]), + "csrf_token": String( + "", + ), + "post": Object({ + "body": String( + "o( ̄∇ ̄o)ク\u{ff9e}ッ!!(∇ ̄ )クル(\u{3000}\u{3000})クル(  ̄∇)クル(o ̄∇ ̄)ノハ\u{ff9e}ーイ", + ), + "created_at": String( + "2016-01-02T02:46:36Z", + ), + "id": Number( + 9996, + ), + "imgdata": Null, + "mime": String( + "image/jpeg", + ), + "user_id": Number( + 876, + ), + }), + "user": Object({ + "account_name": String( + "elvia", + ), + "authority": Number( + 0, + ), + "created_at": String( + "2016-01-01T00:14:36Z", + ), + "del_flg": Number( + 0, + ), + "id": Number( + 876, + ), + "passhash": String( + "6d7bfe25c4afc7a05b03c5dcf5d202669536c59086b14019724eb1e33b83f3a0644c456d4ff4d5fedb3848d9847df7763096f13326c66d1fc80374eaa90e9401", + ), + }), + }), + Object({ + "comment_count": Number( + 6, + ), + "comments": Array([ + Object({ + "comment": Object({ + "comment": String( + "フ\u{ff9f}ンフ\u{ff9f}ン( ̄^ ̄メ)\(_ _ ;)ハンセイ…", + ), + "created_at": String( + "2016-01-03T17:33:32Z", + ), + "id": Number( + 63212, + ), + "post_id": Number( + 9995, + ), + "user_id": Number( + 395, + ), + }), + "user": Object({ + "account_name": String( + "rosalie", + ), + "authority": Number( + 0, + ), + "created_at": String( + "2016-01-01T00:06:35Z", + ), + "del_flg": Number( + 0, + ), + "id": Number( + 395, + ), + "passhash": String( + "f5f3b0940b8fca79d465ddb8179dbe136370260484d9c4c471d0e47fbb151f20d1a45aa2c6399e170a434cffa1496d8532b440383dbd6187027089d14eb4596d", + ), + }), + }), + Object({ + "comment": Object({ + "comment": String( + "(ノ_・。)/\u{ff9f}・:*【祝】*:・\u{ff9f}\(・_・、)", + ), + "created_at": String( + "2016-01-03T20:41:31Z", + ), + "id": Number( + 74491, + ), + "post_id": Number( + 9995, + ), + "user_id": Number( + 549, + ), + }), + "user": Object({ + "account_name": String( + "lourdes", + ), + "authority": Number( + 0, + ), + "created_at": String( + "2016-01-01T00:09:09Z", + ), + "del_flg": Number( + 0, + ), + "id": Number( + 549, + ), + "passhash": String( + "36b56a416cc99fd3d61dabef1f16910daec5772ea69c82db8ee3153f14350720cad1cac01c61df61acf4b4b72e35c011bae289a416e46d10a5491ad7329866bc", + ), + }), + }), + Object({ + "comment": Object({ + "comment": String( + "どもども( ^-^)∠※.。・:*:・°`☆、。・:*:・°`★", + ), + "created_at": String( + "2016-01-04T01:05:18Z", + ), + "id": Number( + 90318, + ), + "post_id": Number( + 9995, + ), + "user_id": Number( + 974, + ), + }), + "user": Object({ + "account_name": String( + "fanny", + ), + "authority": Number( + 0, + ), + "created_at": String( + "2016-01-01T00:16:14Z", + ), + "del_flg": Number( + 0, + ), + "id": Number( + 974, + ), + "passhash": String( + "379f797910aa9e1bc1e5190acd64b9c2b07b7932a7167965c159787161f1ec95f35258385adff53bb9712795f362e4a80b3b06ad1327b45045a9099457bb0db2", + ), + }), + }), + ]), + "csrf_token": String( + "", + ), + "post": Object({ + "body": String( + "ネシ\u{ff9e}ネシ\u{ff9e}ッ 8-(--)カタカタカタ-。。。。8-(^▽^)ノオメット!", + ), + "created_at": String( + "2016-01-02T02:46:35Z", + ), + "id": Number( + 9995, + ), + "imgdata": Null, + "mime": String( + "image/jpeg", + ), + "user_id": Number( + 517, + ), + }), + "user": Object({ + "account_name": String( + "adriana", + ), + "authority": Number( + 0, + ), + "created_at": String( + "2016-01-01T00:08:37Z", + ), + "del_flg": Number( + 0, + ), + "id": Number( + 517, + ), + "passhash": String( + "ecbacf7ca01829905ec159b691bebc4b0c1f20a81f7f4bea7d438ec24450e86166563d448a9dbb260e59e6de3a44c4a219d358781e26369a1405a588be1f07da", + ), + }), + }), + Object({ + "comment_count": Number( + 8, + ), + "comments": Array([ + Object({ + "comment": Object({ + "comment": String( + "オメットストーカー │電柱│_・) シ\u{ff9e}ィィ。。。 §;\u{ff9f}ロ\u{ff9f}§ ツケラレテイルワ!!", + ), + "created_at": String( + "2016-01-03T12:32:33Z", + ), + "id": Number( + 45153, + ), + "post_id": Number( + 9994, + ), + "user_id": Number( + 37, + ), + }), + "user": Object({ + "account_name": String( + "pamela", + ), + "authority": Number( + 0, + ), + "created_at": String( + "2016-01-01T00:00:37Z", + ), + "del_flg": Number( + 0, + ), + "id": Number( + 37, + ), + "passhash": String( + "60e5137c1867ee69f787e0d4ac63214209f6f8111538d102f6c7ae35c99e597dc05c3f41f150f503ab6b17dc3aa80f26ab4a6576daa7d2e6103c421d70f64f36", + ), + }), + }), + Object({ + "comment": Object({ + "comment": String( + "m(._.*)mヘ\u{ff9f}コッ", + ), + "created_at": String( + "2016-01-03T13:19:42Z", + ), + "id": Number( + 47982, + ), + "post_id": Number( + 9994, + ), + "user_id": Number( + 75, + ), + }), + "user": Object({ + "account_name": String( + "tammy", + ), + "authority": Number( + 0, + ), + "created_at": String( + "2016-01-01T00:01:15Z", + ), + "del_flg": Number( + 0, + ), + "id": Number( + 75, + ), + "passhash": String( + "8d0156ec5933427ff2df01865bf9eec613cda8a8fecddb57103b6983e8dec7d72133584906987962fd74e7dde69d08aebf136fd2ddf898a47489604e8038ac9e", + ), + }), + }), + Object({ + "comment": Object({ + "comment": String( + "ヾ@(o・ェ・)Uo・ェ・)\u{ff9f}Θ\u{ff9f})^・x・)ノ~~~ハ\u{ff9e}ハ\u{ff9e}~イ♪", + ), + "created_at": String( + "2016-01-03T22:24:03Z", + ), + "id": Number( + 80643, + ), + "post_id": Number( + 9994, + ), + "user_id": Number( + 395, + ), + }), + "user": Object({ + "account_name": String( + "rosalie", + ), + "authority": Number( + 0, + ), + "created_at": String( + "2016-01-01T00:06:35Z", + ), + "del_flg": Number( + 0, + ), + "id": Number( + 395, + ), + "passhash": String( + "f5f3b0940b8fca79d465ddb8179dbe136370260484d9c4c471d0e47fbb151f20d1a45aa2c6399e170a434cffa1496d8532b440383dbd6187027089d14eb4596d", + ), + }), + }), + ]), + "csrf_token": String( + "", + ), + "post": Object({ + "body": String( + "あ( ̄○ ̄)り( ̄◇ ̄)が( ̄△ ̄)と( ̄0 ̄)う", + ), + "created_at": String( + "2016-01-02T02:46:34Z", + ), + "id": Number( + 9994, + ), + "imgdata": Null, + "mime": String( + "image/jpeg", + ), + "user_id": Number( + 455, + ), + }), + "user": Object({ + "account_name": String( + "laverne", + ), + "authority": Number( + 0, + ), + "created_at": String( + "2016-01-01T00:07:35Z", + ), + "del_flg": Number( + 0, + ), + "id": Number( + 455, + ), + "passhash": String( + "b079c3079b1796e1ad545bab038578b510e3f94b228bbcc11102851aefd0b4a1b8acf58f04e0f32ef4e761c96cf83c931999735deb6f2206da62d171dfcc6569", + ), + }), + }), + Object({ + "comment_count": Number( + 9, + ), + "comments": Array([ + Object({ + "comment": Object({ + "comment": String( + "(・⊥・)/ ヤァ", + ), + "created_at": String( + "2016-01-03T18:59:01Z", + ), + "id": Number( + 68341, + ), + "post_id": Number( + 9993, + ), + "user_id": Number( + 230, + ), + }), + "user": Object({ + "account_name": String( + "joy", + ), + "authority": Number( + 0, + ), + "created_at": String( + "2016-01-01T00:03:50Z", + ), + "del_flg": Number( + 0, + ), + "id": Number( + 230, + ), + "passhash": String( + "69b3a18528fd3f9282694c84e05cd57ea0cca1fce1b0cb77b3315cdd3d36e74c4f89415888238bcf2beb307245fa80de239e523339b07a8a1b7106eacf572a3e", + ), + }), + }), + Object({ + "comment": Object({ + "comment": String( + "オメットフィッシンク\u{ff9e}!!( ・_・)ノシュッ~~~~~~くコ:彡", + ), + "created_at": String( + "2016-01-03T21:24:54Z", + ), + "id": Number( + 77094, + ), + "post_id": Number( + 9993, + ), + "user_id": Number( + 362, + ), + }), + "user": Object({ + "account_name": String( + "candice", + ), + "authority": Number( + 0, + ), + "created_at": String( + "2016-01-01T00:06:02Z", + ), + "del_flg": Number( + 0, + ), + "id": Number( + 362, + ), + "passhash": String( + "706acbeef752cb39360f0f02c39aed28e371301041c21b36cb40f3d4745aaa83cb065272515fa6eb2885a0b90dfaa684e12c153401be39ab1aaecb4c7fd74403", + ), + }), + }), + Object({ + "comment": Object({ + "comment": String( + "ハ\u{ff9e}イハ\u{ff9e}イノハ\u{ff9e}ーイ!!-=Ξヾ(ヾ(ヾ(ヾ(ヾ(ヾ(*´▽`)ツ", + ), + "created_at": String( + "2016-01-03T21:26:32Z", + ), + "id": Number( + 77192, + ), + "post_id": Number( + 9993, + ), + "user_id": Number( + 112, + ), + }), + "user": Object({ + "account_name": String( + "rosa", + ), + "authority": Number( + 0, + ), + "created_at": String( + "2016-01-01T00:01:52Z", + ), + "del_flg": Number( + 0, + ), + "id": Number( + 112, + ), + "passhash": String( + "7ee7581f856795775c4f864ac6bbc1d687b6035f0560d3436a1d0e0138b07a6b9033f899a690c8ce3d46547a18a7a611ba80557a67f71ae50b48159b9f873dd8", + ), + }), + }), + ]), + "csrf_token": String( + "", + ), + "post": Object({ + "body": String( + "サイナラ ~~~ヽ(`◇´;))))))) サササッ", + ), + "created_at": String( + "2016-01-02T02:46:33Z", + ), + "id": Number( + 9993, + ), + "imgdata": Null, + "mime": String( + "image/jpeg", + ), + "user_id": Number( + 945, + ), + }), + "user": Object({ + "account_name": String( + "dionne", + ), + "authority": Number( + 0, + ), + "created_at": String( + "2016-01-01T00:15:45Z", + ), + "del_flg": Number( + 0, + ), + "id": Number( + 945, + ), + "passhash": String( + "82c74b3684dfb07d905d62b0a809c746a9aeadbab292da1029ab6eb1e4614a1fe5e54d7ab7dba51bbb2d7a55512fd160c1ab4b747736f66c6e107b9b5f1b6ac2", + ), + }), + }), + Object({ + "comment_count": Number( + 12, + ), + "comments": Array([ + Object({ + "comment": Object({ + "comment": String( + "オメテ\u{ff9e}タ フフ\u{ff9e}キ ヒュゥゥウウ (*`◇)<氷氷氷氷≧∇≦) ヒヤッ!", + ), + "created_at": String( + "2016-01-03T23:28:25Z", + ), + "id": Number( + 84505, + ), + "post_id": Number( + 9991, + ), + "user_id": Number( + 487, + ), + }), + "user": Object({ + "account_name": String( + "shari", + ), + "authority": Number( + 0, + ), + "created_at": String( + "2016-01-01T00:08:07Z", + ), + "del_flg": Number( + 0, + ), + "id": Number( + 487, + ), + "passhash": String( + "cf098b2f40b21dd2ee05a5f25daa0b16e8c82724dd17853b656882106224b1f04d7623f8fe97e6ff029f74d0a08631eeefaec00f45df63b42e87cfff3fb63414", + ), + }), + }), + Object({ + "comment": Object({ + "comment": String( + "(*^^)/。・:*:・\u{ff9f}'★,。・:*:・\u{ff9f}'☆ Congratulations!!", + ), + "created_at": String( + "2016-01-04T01:28:59Z", + ), + "id": Number( + 91739, + ), + "post_id": Number( + 9991, + ), + "user_id": Number( + 598, + ), + }), + "user": Object({ + "account_name": String( + "rosario", + ), + "authority": Number( + 0, + ), + "created_at": String( + "2016-01-01T00:09:58Z", + ), + "del_flg": Number( + 0, + ), + "id": Number( + 598, + ), + "passhash": String( + "e345b3902bd221e11d7622c41df8dd21b629d77678fd353087b4756a1594ed94d349952d641a73ae84045cbd0775b4b83f148a0b17dda4d2d6a857904ad3bd07", + ), + }), + }), + Object({ + "comment": Object({ + "comment": String( + "ヾ(*'0'*)マ!!ヾ(*'O'*)タ!!ヾ(*'。'*)ネ!!", + ), + "created_at": String( + "2016-01-04T02:37:20Z", + ), + "id": Number( + 95840, + ), + "post_id": Number( + 9991, + ), + "user_id": Number( + 896, + ), + }), + "user": Object({ + "account_name": String( + "juliette", + ), + "authority": Number( + 0, + ), + "created_at": String( + "2016-01-01T00:14:56Z", + ), + "del_flg": Number( + 0, + ), + "id": Number( + 896, + ), + "passhash": String( + "4b7c5cc835698153a2a0899b1bfbfe228bad5730d19a80ef44e0429f6f9855c7facd14a812aa011876912baa1979025e10734c18f7cbb4d6208b97376494b7a7", + ), + }), + }), + ]), + "csrf_token": String( + "", + ), + "post": Object({ + "body": String( + "(*^o^*)サ(*^_^*)ヨ(*^O^*)ウ(*^_^*)ナ(*^O^*)ラ", + ), + "created_at": String( + "2016-01-02T02:46:31Z", + ), + "id": Number( + 9991, + ), + "imgdata": Null, + "mime": String( + "image/jpeg", + ), + "user_id": Number( + 618, + ), + }), + "user": Object({ + "account_name": String( + "daphne", + ), + "authority": Number( + 0, + ), + "created_at": String( + "2016-01-01T00:10:18Z", + ), + "del_flg": Number( + 0, + ), + "id": Number( + 618, + ), + "passhash": String( + "96449c36fd8d993f5c5df6d47cb7791fef9ea4332f5c9238228bef5c4925fc5938ca724ceac63a65e26bd790ad0dbc91159ebba2004ee7c83427fb14ec2a9530", + ), + }), + }), + Object({ + "comment_count": Number( + 11, + ), + "comments": Array([ + Object({ + "comment": Object({ + "comment": String( + "♪(*・д・)ノ●-●ぶらじゃぁフリフリばいばい~!", + ), + "created_at": String( + "2016-01-03T19:07:31Z", + ), + "id": Number( + 68851, + ), + "post_id": Number( + 9990, + ), + "user_id": Number( + 117, + ), + }), + "user": Object({ + "account_name": String( + "edith", + ), + "authority": Number( + 0, + ), + "created_at": String( + "2016-01-01T00:01:57Z", + ), + "del_flg": Number( + 0, + ), + "id": Number( + 117, + ), + "passhash": String( + "839f5986980bcf627420f1b8ab32d8236d8fd1d9975520e80b0cb24397f61ea90cef9c6d1ecf433a85cce478f9a1bcd3250844f684f02a258d877afc43b752c4", + ), + }), + }), + Object({ + "comment": Object({ + "comment": String( + "(TωT)ノ~~~ ハ\u{ff9e}イハ\u{ff9e}イ", + ), + "created_at": String( + "2016-01-03T20:49:21Z", + ), + "id": Number( + 74961, + ), + "post_id": Number( + 9990, + ), + "user_id": Number( + 342, + ), + }), + "user": Object({ + "account_name": String( + "kristine", + ), + "authority": Number( + 0, + ), + "created_at": String( + "2016-01-01T00:05:42Z", + ), + "del_flg": Number( + 0, + ), + "id": Number( + 342, + ), + "passhash": String( + "8986e52c35f185c4beebb28febe9d6b2430d65e728578db29d33125ef46f90fa9887c4c3d8589b1299a2f80111e4256fceb87791d96ee2e28f169a45ff4780e5", + ), + }), + }), + Object({ + "comment": Object({ + "comment": String( + "オメテ\u{ff9e}トーσ(⌒▽⌒)丿ワタシカ\u{ff9e}フリマシタ", + ), + "created_at": String( + "2016-01-04T03:41:42Z", + ), + "id": Number( + 99702, + ), + "post_id": Number( + 9990, + ), + "user_id": Number( + 442, + ), + }), + "user": Object({ + "account_name": String( + "eloise", + ), + "authority": Number( + 0, + ), + "created_at": String( + "2016-01-01T00:07:22Z", + ), + "del_flg": Number( + 0, + ), + "id": Number( + 442, + ), + "passhash": String( + "601fef1964b57f5a29b9d80ef39ed05cc18db76cee62d1fcc015b99e0641223e3d3cf32e0837bf5288d7ad34f63e28f4fdde3530cb7fd620b00029e4447dfa38", + ), + }), + }), + ]), + "csrf_token": String( + "", + ), + "post": Object({ + "body": String( + "(/*^^)/ハッロ-!!", + ), + "created_at": String( + "2016-01-02T02:46:30Z", + ), + "id": Number( + 9990, + ), + "imgdata": Null, + "mime": String( + "image/jpeg", + ), + "user_id": Number( + 304, + ), + }), + "user": Object({ + "account_name": String( + "guadalupe", + ), + "authority": Number( + 0, + ), + "created_at": String( + "2016-01-01T00:05:04Z", + ), + "del_flg": Number( + 0, + ), + "id": Number( + 304, + ), + "passhash": String( + "9609c5a3ff5ed3f8bc18b3779df3d483fcccf797e838fb298c69c2b796b040ce1213dd591a5aef373dd0086105113f8f5fa3f73fc1a28db3b860b07da38e3b42", + ), + }), + }), + Object({ + "comment_count": Number( + 5, + ), + "comments": Array([ + Object({ + "comment": Object({ + "comment": String( + "ε=(ノ\u{ff9f}▽\u{ff9f})ノスチャッ!タタ\u{ff9e}イマァ♪o(\u{ff9f}▽\u{ff9f})/", + ), + "created_at": String( + "2016-01-03T08:55:45Z", + ), + "id": Number( + 32145, + ), + "post_id": Number( + 9989, + ), + "user_id": Number( + 471, + ), + }), + "user": Object({ + "account_name": String( + "darla", + ), + "authority": Number( + 0, + ), + "created_at": String( + "2016-01-01T00:07:51Z", + ), + "del_flg": Number( + 0, + ), + "id": Number( + 471, + ), + "passhash": String( + "79b8d119bd95f996d395ee0e697361e33c1f54dabcceab631f848f4d254ba003d8e4298fd131642d9da3eaf112db295295b273b7f6f8e28cdb2dfa3177e35652", + ), + }), + }), + Object({ + "comment": Object({ + "comment": String( + "(〃⌒ー⌒)/どもっ♪", + ), + "created_at": String( + "2016-01-03T18:18:46Z", + ), + "id": Number( + 65926, + ), + "post_id": Number( + 9989, + ), + "user_id": Number( + 82, + ), + }), + "user": Object({ + "account_name": String( + "kathryn", + ), + "authority": Number( + 0, + ), + "created_at": String( + "2016-01-01T00:01:22Z", + ), + "del_flg": Number( + 0, + ), + "id": Number( + 82, + ), + "passhash": String( + "8df659a3a3cfe84099001300efa54ad95dc3f43a50a609a372e98c66f5a3457da8c715134744c33cec60435b7e626da5442a9e2482f635ee0c2d4d3c2948382c", + ), + }), + }), + Object({ + "comment": Object({ + "comment": String( + "( o ̄▽)o<※*:'\u{ff9f}。.お*:\u{ff9f}・め'\u{ff9f}\u{ff9f}:。で'・:+と\"。*・う':\u{ff9f}:*♪:'\u{ff9f}`。+:", + ), + "created_at": String( + "2016-01-04T03:04:36Z", + ), + "id": Number( + 97476, + ), + "post_id": Number( + 9989, + ), + "user_id": Number( + 979, + ), + }), + "user": Object({ + "account_name": String( + "alba", + ), + "authority": Number( + 0, + ), + "created_at": String( + "2016-01-01T00:16:19Z", + ), + "del_flg": Number( + 0, + ), + "id": Number( + 979, + ), + "passhash": String( + "474859ce5a6cef19066177e2d8562e17e2f9d9c138442e843f01cfb4e75b7fb7bbff5a5522b65e6a61805a0a5d82575d6f13b4f7da854aaf3fdfc151b7955be0", + ), + }), + }), + ]), + "csrf_token": String( + "", + ), + "post": Object({ + "body": String( + "川・ム・川ノハロー", + ), + "created_at": String( + "2016-01-02T02:46:29Z", + ), + "id": Number( + 9989, + ), + "imgdata": Null, + "mime": String( + "image/jpeg", + ), + "user_id": Number( + 775, + ), + }), + "user": Object({ + "account_name": String( + "allyson", + ), + "authority": Number( + 0, + ), + "created_at": String( + "2016-01-01T00:12:55Z", + ), + "del_flg": Number( + 0, + ), + "id": Number( + 775, + ), + "passhash": String( + "06f5d04dd7fef5f9d4f7ffd8190348bf57f3711ae5a325763faf3412502183dd6e44e2c47181d80ab2ba3d83d2ba5d726bdfa92bae20606717e93c0d608c6b3d", + ), + }), + }), + Object({ + "comment_count": Number( + 18, + ), + "comments": Array([ + Object({ + "comment": Object({ + "comment": String( + "( v^-\u{ff9f})Thanks♪", + ), + "created_at": String( + "2016-01-03T22:44:23Z", + ), + "id": Number( + 81863, + ), + "post_id": Number( + 9988, + ), + "user_id": Number( + 652, + ), + }), + "user": Object({ + "account_name": String( + "lily", + ), + "authority": Number( + 0, + ), + "created_at": String( + "2016-01-01T00:10:52Z", + ), + "del_flg": Number( + 0, + ), + "id": Number( + 652, + ), + "passhash": String( + "993705a18e45634cdf7f7d4eb82caa3c5eb7e3aa3ec129ecf01f74a51885330f1fa5811c0312e41cd35348a4eecf733ab11911186a1b84363e6bd65ac7b0bfaa", + ), + }), + }), + Object({ + "comment": Object({ + "comment": String( + "ヤァ \(⌒∇⌒(⌒∇⌒(⌒∇⌒)⌒∇⌒)⌒∇⌒)/ヤァ", + ), + "created_at": String( + "2016-01-04T01:17:33Z", + ), + "id": Number( + 91053, + ), + "post_id": Number( + 9988, + ), + "user_id": Number( + 701, + ), + }), + "user": Object({ + "account_name": String( + "luisa", + ), + "authority": Number( + 0, + ), + "created_at": String( + "2016-01-01T00:11:41Z", + ), + "del_flg": Number( + 0, + ), + "id": Number( + 701, + ), + "passhash": String( + "e2703c39d3a2a05a5c9dbdfa465ce48047d1ecc4a62075f8d228a325f655e234a7ce421c32c4c3783b6e8b822eb7c6bb0bfd6210b08b47da51edb5fb7a14d332", + ), + }), + }), + Object({ + "comment": Object({ + "comment": String( + "┃竹林┃_●)ノ゛\u{3000}ササっとさいなら~", + ), + "created_at": String( + "2016-01-04T02:46:35Z", + ), + "id": Number( + 96395, + ), + "post_id": Number( + 9988, + ), + "user_id": Number( + 961, + ), + }), + "user": Object({ + "account_name": String( + "marquita", + ), + "authority": Number( + 0, + ), + "created_at": String( + "2016-01-01T00:16:01Z", + ), + "del_flg": Number( + 0, + ), + "id": Number( + 961, + ), + "passhash": String( + "e14bb8174a2f0ee2561cba2508af50edc169f109953a3975e43521f6c7ef78bd8091e776f60908ca6541fcf3f89f56c0329b6e4f6c2c4e13318357146eb9db8b", + ), + }), + }), + ]), + "csrf_token": String( + "", + ), + "post": Object({ + "body": String( + "オイッス!!\(∇´) (`▽)/ケ\u{ff9e}ンキカ\u{ff9e}ナイソ\u{ff9e}-オイッス!!", + ), + "created_at": String( + "2016-01-02T02:46:28Z", + ), + "id": Number( + 9988, + ), + "imgdata": Null, + "mime": String( + "image/jpeg", + ), + "user_id": Number( + 878, + ), + }), + "user": Object({ + "account_name": String( + "deirdre", + ), + "authority": Number( + 0, + ), + "created_at": String( + "2016-01-01T00:14:38Z", + ), + "del_flg": Number( + 0, + ), + "id": Number( + 878, + ), + "passhash": String( + "d03a59272f2c76a6521a7d6056ed8d6bf4588e9417940b0b74cbe847947b0ce633e6ac98c4ae46b34bc85046c60ef65f10d701d7cbfb85d209c08f1e08895b81", + ), + }), + }), + Object({ + "comment_count": Number( + 8, + ), + "comments": Array([ + Object({ + "comment": Object({ + "comment": String( + "ヽ( ̄(エ) ̄)ノ イラッシャーイ♪ o(_^_)oヘ\u{ff9f}コッ", + ), + "created_at": String( + "2016-01-03T21:49:58Z", + ), + "id": Number( + 78598, + ), + "post_id": Number( + 9987, + ), + "user_id": Number( + 409, + ), + }), + "user": Object({ + "account_name": String( + "ernestine", + ), + "authority": Number( + 0, + ), + "created_at": String( + "2016-01-01T00:06:49Z", + ), + "del_flg": Number( + 0, + ), + "id": Number( + 409, + ), + "passhash": String( + "f841a590b28f9a3f655a45e40548128acd4e7c38e9c7f6d9bef158ab919420d96fe64e0bf33ca19b0339bf1964f10d27ff366ef933136c868e6458e8150030a9", + ), + }), + }), + Object({ + "comment": Object({ + "comment": String( + "オメットクシャミ!!(;\u{ff9f}Д\u{ff9f})ハッ!(\u{ff9f}口\u{ff9f};)ハッ!\u{3000}( >з<)=3 ハーーークシュン!!", + ), + "created_at": String( + "2016-01-03T22:25:58Z", + ), + "id": Number( + 80758, + ), + "post_id": Number( + 9987, + ), + "user_id": Number( + 714, + ), + }), + "user": Object({ + "account_name": String( + "virgie", + ), + "authority": Number( + 0, + ), + "created_at": String( + "2016-01-01T00:11:54Z", + ), + "del_flg": Number( + 0, + ), + "id": Number( + 714, + ), + "passhash": String( + "da34a3ef651f6a7711608f156697eccd66f4a86edae0be8dbfe05b7e82a1344b0d038ae023d9d2226f0c11c76507b6cec09baa6f958e2f2c566b81892a455d0e", + ), + }), + }), + Object({ + "comment": Object({ + "comment": String( + "オメテ\u{ff9e}トコーラス( \u{ff9f}o\u{ff9f})(\u{ff9f}o\u{ff9f})(\u{ff9f}o\u{ff9f} )どぅわ~♪", + ), + "created_at": String( + "2016-01-03T22:46:06Z", + ), + "id": Number( + 81966, + ), + "post_id": Number( + 9987, + ), + "user_id": Number( + 8, + ), + }), + "user": Object({ + "account_name": String( + "susan", + ), + "authority": Number( + 1, + ), + "created_at": String( + "2016-01-01T00:00:08Z", + ), + "del_flg": Number( + 0, + ), + "id": Number( + 8, + ), + "passhash": String( + "2a4a4d042136a6649e81a3a30b3d33e4b8c8958cf9071c3d8ea4e264e732296c89a7123eec7d1766260a7c589ce8b2ebe8190d11158add69b32cadfa45fca81a", + ), + }), + }), + ]), + "csrf_token": String( + "", + ), + "post": Object({ + "body": String( + "( ⌒o⌒)人(⌒-⌒ )v オヒサオヒサ", + ), + "created_at": String( + "2016-01-02T02:46:27Z", + ), + "id": Number( + 9987, + ), + "imgdata": Null, + "mime": String( + "image/jpeg", + ), + "user_id": Number( + 161, + ), + }), + "user": Object({ + "account_name": String( + "geraldine", + ), + "authority": Number( + 0, + ), + "created_at": String( + "2016-01-01T00:02:41Z", + ), + "del_flg": Number( + 0, + ), + "id": Number( + 161, + ), + "passhash": String( + "73ffff85ffbb8328a70ba6287e5889ad8e7cf6d0eb75aa69c1685d87826878982d6f8cb903a33429e98bc02e2184aacf412d64644e5a5afe5101bf2de66f4bd0", + ), + }), + }), + Object({ + "comment_count": Number( + 10, + ), + "comments": Array([ + Object({ + "comment": Object({ + "comment": String( + "ドゥモ.ドゥモ♪\( ̄ー ̄|電柱| ̄ー ̄)/ヨロシク♪", + ), + "created_at": String( + "2016-01-03T21:59:08Z", + ), + "id": Number( + 79148, + ), + "post_id": Number( + 9986, + ), + "user_id": Number( + 575, + ), + }), + "user": Object({ + "account_name": String( + "candy", + ), + "authority": Number( + 0, + ), + "created_at": String( + "2016-01-01T00:09:35Z", + ), + "del_flg": Number( + 0, + ), + "id": Number( + 575, + ), + "passhash": String( + "5be95e6e28a5ea9384dacf4de4645655f6196e3e128240d647168b4282b94fe232b2edbbbe67ebb73f583a7773e7d0a20e598607ccfebcab380790f0c437e52c", + ), + }), + }), + Object({ + "comment": Object({ + "comment": String( + "アリカ\u{ff9e}ト♪(*\u{ff9f} 3\u{ff9f})/~チュッ♪", + ), + "created_at": String( + "2016-01-04T02:18:06Z", + ), + "id": Number( + 94686, + ), + "post_id": Number( + 9986, + ), + "user_id": Number( + 86, + ), + }), + "user": Object({ + "account_name": String( + "jacqueline", + ), + "authority": Number( + 0, + ), + "created_at": String( + "2016-01-01T00:01:26Z", + ), + "del_flg": Number( + 0, + ), + "id": Number( + 86, + ), + "passhash": String( + "d39030b34ac20f31893665b98ba6a5e600267a57040777fb954c99f59602adff9f621d2701126809412fa1419c57d8118621a0650638d79f6336f69c1332fa69", + ), + }), + }), + Object({ + "comment": Object({ + "comment": String( + "才×〒\"├♪(⌒▽⌒) ノ☆・゜:*:゜", + ), + "created_at": String( + "2016-01-04T03:23:36Z", + ), + "id": Number( + 98616, + ), + "post_id": Number( + 9986, + ), + "user_id": Number( + 386, + ), + }), + "user": Object({ + "account_name": String( + "leticia", + ), + "authority": Number( + 0, + ), + "created_at": String( + "2016-01-01T00:06:26Z", + ), + "del_flg": Number( + 0, + ), + "id": Number( + 386, + ), + "passhash": String( + "33c0f1846272ae607ccb55c787a537fa4e6d778b6b9f380c38bd5d99734ce23c0eb37707a0a147cc8bcc2582c440afe403453e639a4ecdd857b4ef75759178d8", + ), + }), + }), + ]), + "csrf_token": String( + "", + ), + "post": Object({ + "body": String( + "オメットナケ\u{ff9e}キッスー♪(*^ω^)/チュッ♪ フヨフヨ~~コツン\u{ff9e}☆(。・_・。)ホ\u{ff9f}ッ", + ), + "created_at": String( + "2016-01-02T02:46:26Z", + ), + "id": Number( + 9986, + ), + "imgdata": Null, + "mime": String( + "image/jpeg", + ), + "user_id": Number( + 963, + ), + }), + "user": Object({ + "account_name": String( + "tisha", + ), + "authority": Number( + 0, + ), + "created_at": String( + "2016-01-01T00:16:03Z", + ), + "del_flg": Number( + 0, + ), + "id": Number( + 963, + ), + "passhash": String( + "ff9d8e340391af03ef532306d8c766738fe54fbbcf8a80059fdb7974a9213737c786242d2bd002a184afa1ef8cab20e80a314a4484c8c0c9ac8a4e74a17120e5", + ), + }), + }), + Object({ + "comment_count": Number( + 10, + ), + "comments": Array([ + Object({ + "comment": Object({ + "comment": String( + "ちわ~v( ̄∇ ̄)v", + ), + "created_at": String( + "2016-01-03T22:42:37Z", + ), + "id": Number( + 81757, + ), + "post_id": Number( + 9985, + ), + "user_id": Number( + 727, + ), + }), + "user": Object({ + "account_name": String( + "ila", + ), + "authority": Number( + 0, + ), + "created_at": String( + "2016-01-01T00:12:07Z", + ), + "del_flg": Number( + 0, + ), + "id": Number( + 727, + ), + "passhash": String( + "76ada11ad4275ec147859e5643e823d9f0f760fdacc2d5b2a3e76456f161a9401ddc819cad75e3809a1ebc650bb6b68ce23afa83b868178f620586bdc8d74f78", + ), + }), + }), + Object({ + "comment": Object({ + "comment": String( + "\_(^◇^)_/\(*^^*)/ 優勝オメデトウ!", + ), + "created_at": String( + "2016-01-03T23:27:04Z", + ), + "id": Number( + 84424, + ), + "post_id": Number( + 9985, + ), + "user_id": Number( + 631, + ), + }), + "user": Object({ + "account_name": String( + "lizzie", + ), + "authority": Number( + 0, + ), + "created_at": String( + "2016-01-01T00:10:31Z", + ), + "del_flg": Number( + 0, + ), + "id": Number( + 631, + ), + "passhash": String( + "7dddbfdfb0cc5c27689f6ec41ab84f97c7274b1a1f1576e4cb53a8084b6506329ac77bc3e967a6ecb7990e2761b5744eea3ff3b17da83783e54f92612cf5e813", + ), + }), + }), + Object({ + "comment": Object({ + "comment": String( + "(o^o^o)あ(o^-^o)り(o^o^o) が(o^O^o)と(o^.^o)う", + ), + "created_at": String( + "2016-01-04T01:01:26Z", + ), + "id": Number( + 90086, + ), + "post_id": Number( + 9985, + ), + "user_id": Number( + 750, + ), + }), + "user": Object({ + "account_name": String( + "sharron", + ), + "authority": Number( + 0, + ), + "created_at": String( + "2016-01-01T00:12:30Z", + ), + "del_flg": Number( + 1, + ), + "id": Number( + 750, + ), + "passhash": String( + "b89ab2450ed6ee59060fefb6ed2042b540f752b47c821f7838cbea41f795809baf01686752064233022ab4eb86cd3042b486dffb7be9fc05387cdb16f066a657", + ), + }), + }), + ]), + "csrf_token": String( + "", + ), + "post": Object({ + "body": String( + "♪(・_・)ノ●-●フ\u{ff9e}ラシ\u{ff9e}ャーフリフリハ\u{ff9e}イハ\u{ff9e}イ", + ), + "created_at": String( + "2016-01-02T02:46:25Z", + ), + "id": Number( + 9985, + ), + "imgdata": Null, + "mime": String( + "image/jpeg", + ), + "user_id": Number( + 649, + ), + }), + "user": Object({ + "account_name": String( + "sheena", + ), + "authority": Number( + 0, + ), + "created_at": String( + "2016-01-01T00:10:49Z", + ), + "del_flg": Number( + 0, + ), + "id": Number( + 649, + ), + "passhash": String( + "8c0e219fe69617a1056be63e0d05285f82b1ffbf74abca033e00e90d3c46503cf04a872106598dbee97c607ed31e0e096d0f1c2c61c1b06a23c539409926c777", + ), + }), + }), + Object({ + "comment_count": Number( + 6, + ), + "comments": Array([ + Object({ + "comment": Object({ + "comment": String( + "オ┤* ̄O ̄*├ヤ┤*-.-*├ス┤_ _├ミ", + ), + "created_at": String( + "2016-01-03T15:19:32Z", + ), + "id": Number( + 55172, + ), + "post_id": Number( + 9983, + ), + "user_id": Number( + 859, + ), + }), + "user": Object({ + "account_name": String( + "valeria", + ), + "authority": Number( + 0, + ), + "created_at": String( + "2016-01-01T00:14:19Z", + ), + "del_flg": Number( + 0, + ), + "id": Number( + 859, + ), + "passhash": String( + "daf03cf9fe3b680cb1dce3cd5da39e72932b91af5f57d035bda67fb300815504cfbe8f93cd4503ea8b431e2c031d5add6a6c4e575a53f2a77bf163f7c4562b90", + ), + }), + }), + Object({ + "comment": Object({ + "comment": String( + "バイバイッ♪ヾ(*'ー')*'ー')*'ー')/\"", + ), + "created_at": String( + "2016-01-03T18:58:19Z", + ), + "id": Number( + 68299, + ), + "post_id": Number( + 9983, + ), + "user_id": Number( + 362, + ), + }), + "user": Object({ + "account_name": String( + "candice", + ), + "authority": Number( + 0, + ), + "created_at": String( + "2016-01-01T00:06:02Z", + ), + "del_flg": Number( + 0, + ), + "id": Number( + 362, + ), + "passhash": String( + "706acbeef752cb39360f0f02c39aed28e371301041c21b36cb40f3d4745aaa83cb065272515fa6eb2885a0b90dfaa684e12c153401be39ab1aaecb4c7fd74403", + ), + }), + }), + Object({ + "comment": Object({ + "comment": String( + "(\u{3000})/!-ろは\u{3000}んっ( ^)\u{3000}こっちだ!(^-^)/はろ-!!", + ), + "created_at": String( + "2016-01-03T19:01:36Z", + ), + "id": Number( + 68496, + ), + "post_id": Number( + 9983, + ), + "user_id": Number( + 697, + ), + }), + "user": Object({ + "account_name": String( + "ivy", + ), + "authority": Number( + 0, + ), + "created_at": String( + "2016-01-01T00:11:37Z", + ), + "del_flg": Number( + 0, + ), + "id": Number( + 697, + ), + "passhash": String( + "d5104c98abc4de58849b9e625e2959c74a0586ba45fc3fa1e64623992416341327cb3aaa2858dc53c31dbfa600736953df0001953011a571cdd5ffc77d656860", + ), + }), + }), + ]), + "csrf_token": String( + "", + ), + "post": Object({ + "body": String( + "/_・)/_・)/_・)/_・)/_・)/_・)/_・)/_・) ティース", + ), + "created_at": String( + "2016-01-02T02:46:23Z", + ), + "id": Number( + 9983, + ), + "imgdata": Null, + "mime": String( + "image/jpeg", + ), + "user_id": Number( + 92, + ), + }), + "user": Object({ + "account_name": String( + "tina", + ), + "authority": Number( + 0, + ), + "created_at": String( + "2016-01-01T00:01:32Z", + ), + "del_flg": Number( + 0, + ), + "id": Number( + 92, + ), + "passhash": String( + "6d8598894bb156a7086f0d0d8eed2cc74529ec8fa4dc73f9b6e318dc06dec913fa0570fc6b21a89893605a71d8746c3b030d272a8889eb5712295fb1c1c3e444", + ), + }), + }), + Object({ + "comment_count": Number( + 6, + ), + "comments": Array([ + Object({ + "comment": Object({ + "comment": String( + "マッタニャーーーン(*^ー^*)・ ・‥…・・・★", + ), + "created_at": String( + "2016-01-03T17:45:44Z", + ), + "id": Number( + 63944, + ), + "post_id": Number( + 9982, + ), + "user_id": Number( + 736, + ), + }), + "user": Object({ + "account_name": String( + "estela", + ), + "authority": Number( + 0, + ), + "created_at": String( + "2016-01-01T00:12:16Z", + ), + "del_flg": Number( + 0, + ), + "id": Number( + 736, + ), + "passhash": String( + "62b864fba47d93bec9f593c1e150c99e25e5982d8bd68ec21df94459f10efff8a9f4af55a55babc6e0945364078c8eafd6c8d29a6f3c0fc507278667848820a5", + ), + }), + }), + Object({ + "comment": Object({ + "comment": String( + "ヾ(^-^;) コ\u{ff9e}メンコ\u{ff9e}メン", + ), + "created_at": String( + "2016-01-04T01:28:09Z", + ), + "id": Number( + 91689, + ), + "post_id": Number( + 9982, + ), + "user_id": Number( + 355, + ), + }), + "user": Object({ + "account_name": String( + "kristy", + ), + "authority": Number( + 0, + ), + "created_at": String( + "2016-01-01T00:05:55Z", + ), + "del_flg": Number( + 0, + ), + "id": Number( + 355, + ), + "passhash": String( + "92fb5a77a360379f6138e52f60b0e45fb7bdb745ec9906b7c11088a308bdd9e0901eebfbcd24c98fe1d4791fc1249035eba6159582de50b9fd2495b51670aaed", + ), + }), + }), + Object({ + "comment": Object({ + "comment": String( + "( ̄(オ) ̄)( ̄(メ) ̄)( ̄(デ) ̄)( ̄(ト) ̄)", + ), + "created_at": String( + "2016-01-04T03:42:13Z", + ), + "id": Number( + 99733, + ), + "post_id": Number( + 9982, + ), + "user_id": Number( + 311, + ), + }), + "user": Object({ + "account_name": String( + "natasha", + ), + "authority": Number( + 0, + ), + "created_at": String( + "2016-01-01T00:05:11Z", + ), + "del_flg": Number( + 0, + ), + "id": Number( + 311, + ), + "passhash": String( + "60e4879430b98d6790aed5bb86dd9d31c27180902a678fef861a1f8e6b4fa1de96984e9984d51c64e7c815a68f9d70b0a68e6e96b3ad5f0d6accce9126233dfc", + ), + }), + }), + ]), + "csrf_token": String( + "", + ), + "post": Object({ + "body": String( + "オメテ\u{ff9e}タファイヤー (*`□)<炎炎炎炎フ\u{ff9e}オォォオ*_*)/", + ), + "created_at": String( + "2016-01-02T02:46:22Z", + ), + "id": Number( + 9982, + ), + "imgdata": Null, + "mime": String( + "image/jpeg", + ), + "user_id": Number( + 544, + ), + }), + "user": Object({ + "account_name": String( + "tracie", + ), + "authority": Number( + 0, + ), + "created_at": String( + "2016-01-01T00:09:04Z", + ), + "del_flg": Number( + 0, + ), + "id": Number( + 544, + ), + "passhash": String( + "7f6c1c5044394f6ab5e5b50b11d4eaec839a75256e5d9b9ce8f00182c31c0ddb27054a0d09968b98570e9d4964c319c58b1df45fff2974e48a293bcaf1075fa6", + ), + }), + }), + Object({ + "comment_count": Number( + 13, + ), + "comments": Array([ + Object({ + "comment": Object({ + "comment": String( + "シ\u{ff9e}ャマスルヨ! ノ(・_・ヾ\", + ), + "created_at": String( + "2016-01-03T18:38:16Z", + ), + "id": Number( + 67096, + ), + "post_id": Number( + 9981, + ), + "user_id": Number( + 922, + ), + }), + "user": Object({ + "account_name": String( + "cherry", + ), + "authority": Number( + 0, + ), + "created_at": String( + "2016-01-01T00:15:22Z", + ), + "del_flg": Number( + 0, + ), + "id": Number( + 922, + ), + "passhash": String( + "2a03d833691146ee4772d48b7055432e6d69d726417b60b7fbd3ecc78363ff685c3b386f0e877b2e5fbeb97c5de320a0d5f29c69189123ec55ef4c950dc70007", + ), + }), + }), + Object({ + "comment": Object({ + "comment": String( + "(b*^0)d (ノ*^▽)ノ\u{3000}オッハー♪", + ), + "created_at": String( + "2016-01-03T20:06:06Z", + ), + "id": Number( + 72366, + ), + "post_id": Number( + 9981, + ), + "user_id": Number( + 14, + ), + }), + "user": Object({ + "account_name": String( + "betty", + ), + "authority": Number( + 0, + ), + "created_at": String( + "2016-01-01T00:00:14Z", + ), + "del_flg": Number( + 0, + ), + "id": Number( + 14, + ), + "passhash": String( + "1365fa1ad96358ac89069b4460865120bd19e5874be2b6f5972e4ba8adb61a4e56a68f48bc9354cefe1bc93aeae5afd656652e82da8faef31b1090468f3ec28b", + ), + }), + }), + Object({ + "comment": Object({ + "comment": String( + "ハイ、ヒソイリオメットチャ( ^-)_旦~~ (\u{ff9f}o\u{ff9f};)シヌシ\u{ff9e}ャン\u{ff9e}", + ), + "created_at": String( + "2016-01-03T22:45:37Z", + ), + "id": Number( + 81937, + ), + "post_id": Number( + 9981, + ), + "user_id": Number( + 314, + ), + }), + "user": Object({ + "account_name": String( + "marguerite", + ), + "authority": Number( + 0, + ), + "created_at": String( + "2016-01-01T00:05:14Z", + ), + "del_flg": Number( + 0, + ), + "id": Number( + 314, + ), + "passhash": String( + "fbb645554c3428c73e76a78e3f33b628e9d9a076ae86306740d606bd887f334f5627a274a05a4eccdb8c2b3062ba29a4f02b82c570774cc7efd08f8663668391", + ), + }), + }), + ]), + "csrf_token": String( + "", + ), + "post": Object({ + "body": String( + "~(=^‥^)ノ☆ おやすみニャ。", + ), + "created_at": String( + "2016-01-02T02:46:21Z", + ), + "id": Number( + 9981, + ), + "imgdata": Null, + "mime": String( + "image/jpeg", + ), + "user_id": Number( + 740, + ), + }), + "user": Object({ + "account_name": String( + "earline", + ), + "authority": Number( + 0, + ), + "created_at": String( + "2016-01-01T00:12:20Z", + ), + "del_flg": Number( + 0, + ), + "id": Number( + 740, + ), + "passhash": String( + "895aaf49df71bfd0d124f17d7d3e688b6aea4ff43aeb200eedb962ebae03bb67d0549a82348aa7a1d41e6eeadfc3adc1d23f6925cd4ad06bd1214b3460efc8a1", + ), + }), + }), + Object({ + "comment_count": Number( + 7, + ), + "comments": Array([ + Object({ + "comment": Object({ + "comment": String( + "ノー ̄)ノー ̄)ノー ̄)ノおいっす!", + ), + "created_at": String( + "2016-01-03T12:19:27Z", + ), + "id": Number( + 44367, + ), + "post_id": Number( + 9980, + ), + "user_id": Number( + 276, + ), + }), + "user": Object({ + "account_name": String( + "brandy", + ), + "authority": Number( + 0, + ), + "created_at": String( + "2016-01-01T00:04:36Z", + ), + "del_flg": Number( + 0, + ), + "id": Number( + 276, + ), + "passhash": String( + "3deb9bb3574ff147a08a0709ab811796d2dc8165344fa8c6978b9a93db3f2570ff62504a3450277ec0d0a87a32e60090f5f40b4ea53dcc4fb912c36e54b2e6c1", + ), + }), + }), + Object({ + "comment": Object({ + "comment": String( + "サンクスファイヤー( ・_・)r鹵~<火火炎炎炎゛【・ロ・】゛ヤケルヤケルー", + ), + "created_at": String( + "2016-01-03T15:15:48Z", + ), + "id": Number( + 54948, + ), + "post_id": Number( + 9980, + ), + "user_id": Number( + 722, + ), + }), + "user": Object({ + "account_name": String( + "haley", + ), + "authority": Number( + 0, + ), + "created_at": String( + "2016-01-01T00:12:02Z", + ), + "del_flg": Number( + 0, + ), + "id": Number( + 722, + ), + "passhash": String( + "a65c2e673df1697fb35faf81641be0a741cf7f031444d643374debd1ad3fdc2406ba8063728856b28857217e3e2c3f96e3705e339ca9a77a934cb1474055f13d", + ), + }), + }), + Object({ + "comment": Object({ + "comment": String( + "(/\u{ff9f}∇\u{ff9f})/\u{ff9f}∇\u{ff9f})o ティース♪", + ), + "created_at": String( + "2016-01-03T15:50:55Z", + ), + "id": Number( + 57055, + ), + "post_id": Number( + 9980, + ), + "user_id": Number( + 672, + ), + }), + "user": Object({ + "account_name": String( + "dominique", + ), + "authority": Number( + 0, + ), + "created_at": String( + "2016-01-01T00:11:12Z", + ), + "del_flg": Number( + 0, + ), + "id": Number( + 672, + ), + "passhash": String( + "481023fa797deb8cc5af70bdb28a0c04892fb1be01748de2af1ec77483da7736450e6e13146de99ee438294934623bfa5f4f550272c9e5b345c86589456a1579", + ), + }), + }), + ]), + "csrf_token": String( + "", + ), + "post": Object({ + "body": String( + "((((((((((((((((( ̄ー ̄)ノオイ~ッス", + ), + "created_at": String( + "2016-01-02T02:46:20Z", + ), + "id": Number( + 9980, + ), + "imgdata": Null, + "mime": String( + "image/jpeg", + ), + "user_id": Number( + 37, + ), + }), + "user": Object({ + "account_name": String( + "pamela", + ), + "authority": Number( + 0, + ), + "created_at": String( + "2016-01-01T00:00:37Z", + ), + "del_flg": Number( + 0, + ), + "id": Number( + 37, + ), + "passhash": String( + "60e5137c1867ee69f787e0d4ac63214209f6f8111538d102f6c7ae35c99e597dc05c3f41f150f503ab6b17dc3aa80f26ab4a6576daa7d2e6103c421d70f64f36", + ), + }), + }), + ]), + "posts_parent": String( + "index", + ), + "user": Object({ + "account_name": String( + "", + ), + "authority": Number( + 0, + ), + "created_at": String( + "2022-06-14T09:27:57.270628900Z", + ), + "del_flg": Number( + 0, + ), + "id": Number( + 0, + ), + "passhash": String( + "", + ), + }), +} \ No newline at end of file diff --git a/webapp/rust/src/main.rs b/webapp/rust/src/main.rs index 94c71979e..2b575aace 100644 --- a/webapp/rust/src/main.rs +++ b/webapp/rust/src/main.rs @@ -1,4 +1,11 @@ -use std::{any, env, io, path::Path, time::Duration}; +use std::{ + any, + collections::HashMap, + env, + io::{self, Write}, + path::Path, + time::Duration, +}; use actix_cors::Cors; use actix_files::Files; @@ -17,7 +24,7 @@ use anyhow::{bail, Context}; use chrono::{DateTime, FixedOffset, Local, Utc}; use derive_more::Constructor; use duct::cmd; -use handlebars::{to_json, Handlebars}; +use handlebars::{handlebars_helper, to_json, Handlebars}; use log::LevelFilter; use once_cell::sync::Lazy; use rand::{ @@ -26,6 +33,7 @@ use rand::{ }; use regex::Regex; use serde::{Deserialize, Serialize}; +use serde_json::Map; use simplelog::{ ColorChoice, CombinedLogger, ConfigBuilder, SharedLogger, TermLogger, TerminalMode, WriteLogger, }; @@ -243,7 +251,7 @@ async fn make_post( .context("Failed to query comment_count")? .count; - let mut comments = if !all_comments { + let mut comments = if all_comments { sqlx::query_as!( Comment, "SELECT * FROM `comments` WHERE `post_id` = ? ORDER BY `created_at` DESC", @@ -274,6 +282,7 @@ async fn make_post( .await .context("Failed to query user")? .context("Not found user")?; + log::debug!("comment user {:?}", &user); granted_comments.push(GrantedUserComment::new(comment, user)); } @@ -285,6 +294,7 @@ async fn make_post( .await .context("Failed to query user")? .context("Not found user")?; + log::debug!("user {:?}", &user); if user.del_flg == 0 { granted_info_posts.push(GrantedInfoPost::new( @@ -303,16 +313,31 @@ async fn make_post( Ok(granted_info_posts) } -fn image_url(p: &GrantedInfoPost) -> String { +// fn image_url(p: &GrantedInfoPost) -> String { +// let ext = match p.post.mime.as_str() { +// "image/jpeg" => ".jpg", +// "image/png" => ".png", +// "image/gif" => ".gif", +// _ => "", +// }; + +// format!("/image/{}{}", p.post.id, ext) +// } + +handlebars_helper!(image_url: |p: GrantedInfoPost| { let ext = match p.post.mime.as_str() { - "image/jpeg" => ".jpg", - "image/png" => ".png", - "image/gif" => ".gif", - _ => "", - }; + "image/jpeg" => ".jpg", + "image/png" => ".png", + "image/gif" => ".gif", + _ => "", + }; format!("/image/{}{}", p.post.id, ext) -} +}); + +handlebars_helper!(date_time_format: |create_at: DateTime| { + create_at.format("%Y-%m-%dT%H:%M:%S-07:00").to_string() +}); fn is_login(u: Option<&User>) -> bool { match u { @@ -563,6 +588,14 @@ async fn get_index( pool: Data>, handlebars: Data>, ) -> Result { + let me = match get_session_user(&session, pool.as_ref()).await { + Ok(user) => user.unwrap_or_default(), + Err(e) => { + log::error!("{:?}", &e); + return Ok(HttpResponse::InternalServerError().body(e.to_string())); + } + }; + let results = match sqlx::query_as_unchecked!(Post,"SELECT `id`, `user_id`, `body`, `mime`, `created_at`, NULL AS imgdata FROM `posts` ORDER BY `created_at` DESC").fetch_all(pool.as_ref()).await { Ok(results) => results, Err(e) => { @@ -571,12 +604,13 @@ async fn get_index( } }; - let csrf_token = if let Some(token) = get_csrf_token(&session) { - token - } else { - log::error!("token is None"); - return Ok(HttpResponse::InternalServerError().finish()); - }; + let csrf_token = get_csrf_token(&session).unwrap_or_default(); + // let csrf_token = if let Some(token) = get_csrf_token(&session) { + // token + // } else { + // log::error!("token is None"); + // return Ok(HttpResponse::InternalServerError().finish()); + // }; let posts = match make_post(results, csrf_token, false, pool.as_ref()).await { Ok(posts) => posts, Err(e) => { @@ -585,8 +619,30 @@ async fn get_index( } }; + let body = { + let mut map = Map::new(); + let json = serde_json::to_value(posts).unwrap(); + // let map = json.as_object_mut().unwrap(); + map.insert("posts".to_string(), to_json(json.as_array())); + map.insert("user".to_string(), to_json(me)); + map.insert( + "csrf_token".to_string(), + to_json(get_csrf_token(&session).unwrap_or_default()), + ); + map.insert("flash".to_string(), to_json(get_flash(&session, "notice"))); + + map.insert("post_parent".to_string(), to_json("posts")); + map.insert("posts_parent".to_string(), to_json("index")); + map.insert("content_parent".to_string(), to_json("layout")); + + let mut file = std::fs::File::create("map.json")?; + write!(file, "{:#?}", &map)?; + file.flush().unwrap(); + + handlebars.render("post", &map).unwrap() + }; // TODO: after golang 406 line - Ok(HttpResponse::Ok().finish()) + Ok(HttpResponse::Ok().body(body)) } async fn get_posts() -> Result { @@ -691,6 +747,8 @@ async fn main() -> io::Result<()> { HttpServer::new(move || { let mut handlebars = Handlebars::new(); + handlebars.register_helper("image_url_helper", Box::new(image_url)); + handlebars.register_helper("date_time_format", Box::new(date_time_format)); handlebars .register_templates_directory(".html", "./static") .unwrap(); @@ -721,12 +779,6 @@ async fn main() -> io::Result<()> { _ => HttpResponse::NotFound(), }), ) - .service(web::resource("/").to(|| async { - error::InternalError::new( - io::Error::new(io::ErrorKind::Other, "test"), - StatusCode::INTERNAL_SERVER_ERROR, - ) - })) }) .bind(("0.0.0.0", 8080))? .run() diff --git a/webapp/rust/static/post.html b/webapp/rust/static/post.html index 1e177e5d7..87ea58242 100644 --- a/webapp/rust/static/post.html +++ b/webapp/rust/static/post.html @@ -1,15 +1,16 @@ -
+{{#*inline "post_html"}} +
- - - + + +
- +
- + {{body}}
@@ -19,17 +20,19 @@ {{#each comments}} {{/each}}
- +
-
\ No newline at end of file +
+{{/inline}} +{{> (lookup this "post_parent")}} \ No newline at end of file diff --git a/webapp/rust/static/posts.html b/webapp/rust/static/posts.html index dfe2c8549..f282dbe28 100644 --- a/webapp/rust/static/posts.html +++ b/webapp/rust/static/posts.html @@ -1,5 +1,8 @@ +{{#*inline "posts_html"}}
- {{#each post}} + {{#each posts}} {{> post_html}} {{/each}} -
\ No newline at end of file +
+{{/inline}} +{{> (lookup this "posts_parent")}} \ No newline at end of file From 8358f04ddd40b1f3e4e1d2745222a0a8dfc5561a Mon Sep 17 00:00:00 2001 From: Romira915 <40430090+Romira915@users.noreply.github.com> Date: Tue, 14 Jun 2022 19:36:06 +0900 Subject: [PATCH 25/64] fix: origin --- webapp/docker-compose.yml | 5 +++-- webapp/rust/src/main.rs | 4 +++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/webapp/docker-compose.yml b/webapp/docker-compose.yml index 940536331..94c81813f 100644 --- a/webapp/docker-compose.yml +++ b/webapp/docker-compose.yml @@ -14,7 +14,7 @@ services: cpus: 1 mem_limit: 1g # Go実装の場合は golang/ PHP実装の場合は php/ - build: rust/ + build: golang/ environment: ISUCONP_DB_HOST: mysql ISUCONP_DB_PORT: 3306 @@ -28,7 +28,8 @@ services: volumes: - ./public:/home/public init: true - depends_on: mysql + depends_on: + - mysql mysql: cpus: 1 diff --git a/webapp/rust/src/main.rs b/webapp/rust/src/main.rs index 2b575aace..7c4f26e23 100644 --- a/webapp/rust/src/main.rs +++ b/webapp/rust/src/main.rs @@ -758,7 +758,9 @@ async fn main() -> io::Result<()> { .wrap(if cfg!(debug_assertions) { Cors::permissive() } else { - Cors::default().supports_credentials() + Cors::default() + .supports_credentials() + .allowed_origin("http://localhost") }) .wrap(RedisSession::new(redis_url.clone(), private_key.master())) .app_data(Data::new(db.clone())) From e476067590d1f823368a82e7b0982bcb9f7a241a Mon Sep 17 00:00:00 2001 From: Romira915 <40430090+Romira915@users.noreply.github.com> Date: Wed, 15 Jun 2022 03:09:27 +0900 Subject: [PATCH 26/64] features: get_image --- webapp/docker-compose.yml | 10 +- webapp/rust/.gitignore | 3 +- webapp/rust/Cargo.toml | 2 +- webapp/rust/Dockerfile | 15 +- webapp/rust/map.json | 332 ++++++++++++++++++++++++++------- webapp/rust/src/main.rs | 80 ++++++-- webapp/rust/static/layout.html | 4 +- 7 files changed, 354 insertions(+), 92 deletions(-) diff --git a/webapp/docker-compose.yml b/webapp/docker-compose.yml index 94c81813f..2ffdf8281 100644 --- a/webapp/docker-compose.yml +++ b/webapp/docker-compose.yml @@ -22,6 +22,7 @@ services: ISUCONP_DB_PASSWORD: root ISUCONP_DB_NAME: isuconp ISUCONP_MEMCACHED_ADDRESS: memcached:11211 + ISUCONP_REDIS_URL: redis:6379 links: - mysql - memcached @@ -29,7 +30,8 @@ services: - ./public:/home/public init: true depends_on: - - mysql + mysql: + condition: service_healthy mysql: cpus: 1 @@ -45,6 +47,12 @@ services: - ./sql:/docker-entrypoint-initdb.d ports: - "3306:3306" + healthcheck: + test: mysqladmin ping -h 127.0.0.1 -u$$MYSQL_USER -p$$MYSQL_PASSWORD + interval: 5s + timeout: 5s + retries: 10 + start_period: 5s memcached: image: memcached:1.6 diff --git a/webapp/rust/.gitignore b/webapp/rust/.gitignore index a1835db1d..64836335f 100644 --- a/webapp/rust/.gitignore +++ b/webapp/rust/.gitignore @@ -13,4 +13,5 @@ Cargo.lock # MSVC Windows builds of rustc generate these, which store debugging information *.pdb -.env \ No newline at end of file +.env +.tmp \ No newline at end of file diff --git a/webapp/rust/Cargo.toml b/webapp/rust/Cargo.toml index 2606d3def..7552aa808 100644 --- a/webapp/rust/Cargo.toml +++ b/webapp/rust/Cargo.toml @@ -23,7 +23,7 @@ log = "0.4.17" num_cpus = "1.13.1" once_cell = "1.10.0" rand = "0.8.5" -regex = "1" +regex = "1.5.6" serde = {version = "1.0.137", features = ["derive"]} serde_json = "1.0.81" simplelog = "0.12.0" diff --git a/webapp/rust/Dockerfile b/webapp/rust/Dockerfile index b580cdb4f..89d53bd2c 100644 --- a/webapp/rust/Dockerfile +++ b/webapp/rust/Dockerfile @@ -1,7 +1,14 @@ FROM rust:1.61.0 -RUN mkdir -p /home/webapp -COPY . /home/webapp WORKDIR /home/webapp -RUN cargo build --release -CMD ./target/release/rust + +COPY Cargo.toml Cargo.toml +RUN mkdir src \ + && echo "fn main(){}" > src/main.rs \ + && echo "DATABASE_URL=mysql://root:root@mysql:3306/isuconp" > .env \ + && cargo build --release + +COPY src src +COPY static static +RUN rm -f target/release/deps/rust* +CMD cargo run --release diff --git a/webapp/rust/map.json b/webapp/rust/map.json index 2e34bdccd..037e0ae47 100644 --- a/webapp/rust/map.json +++ b/webapp/rust/map.json @@ -10,53 +10,6 @@ "posts", ), "posts": Array([ - Object({ - "comment_count": Number( - 0, - ), - "comments": Array([]), - "csrf_token": String( - "", - ), - "post": Object({ - "body": String( - "てsってst", - ), - "created_at": String( - "2022-06-14T08:24:48Z", - ), - "id": Number( - 10001, - ), - "imgdata": Null, - "mime": String( - "image/jpeg", - ), - "user_id": Number( - 1005, - ), - }), - "user": Object({ - "account_name": String( - "testtest", - ), - "authority": Number( - 0, - ), - "created_at": String( - "2022-06-14T08:23:28Z", - ), - "del_flg": Number( - 0, - ), - "id": Number( - 1005, - ), - "passhash": String( - "e1df2715a909d3ed434b95223f96a5e87974c8a6101f05d83c16aa86d2ac487951dcbfc33730a29230a375fdc2f4b8c12cfbd92ac3bb6c16dbe36617996dc2c9", - ), - }), - }), Object({ "comment_count": Number( 11, @@ -193,7 +146,11 @@ "id": Number( 10000, ), - "imgdata": Null, + "imgdata": Array([ + Number( + 0, + ), + ]), "mime": String( "image/png", ), @@ -358,7 +315,11 @@ "id": Number( 9999, ), - "imgdata": Null, + "imgdata": Array([ + Number( + 0, + ), + ]), "mime": String( "image/jpeg", ), @@ -523,7 +484,11 @@ "id": Number( 9998, ), - "imgdata": Null, + "imgdata": Array([ + Number( + 0, + ), + ]), "mime": String( "image/jpeg", ), @@ -688,7 +653,11 @@ "id": Number( 9997, ), - "imgdata": Null, + "imgdata": Array([ + Number( + 0, + ), + ]), "mime": String( "image/jpeg", ), @@ -853,7 +822,11 @@ "id": Number( 9996, ), - "imgdata": Null, + "imgdata": Array([ + Number( + 0, + ), + ]), "mime": String( "image/jpeg", ), @@ -1018,7 +991,11 @@ "id": Number( 9995, ), - "imgdata": Null, + "imgdata": Array([ + Number( + 0, + ), + ]), "mime": String( "image/jpeg", ), @@ -1183,7 +1160,11 @@ "id": Number( 9994, ), - "imgdata": Null, + "imgdata": Array([ + Number( + 0, + ), + ]), "mime": String( "image/jpeg", ), @@ -1348,7 +1329,11 @@ "id": Number( 9993, ), - "imgdata": Null, + "imgdata": Array([ + Number( + 0, + ), + ]), "mime": String( "image/jpeg", ), @@ -1513,7 +1498,11 @@ "id": Number( 9991, ), - "imgdata": Null, + "imgdata": Array([ + Number( + 0, + ), + ]), "mime": String( "image/jpeg", ), @@ -1678,7 +1667,11 @@ "id": Number( 9990, ), - "imgdata": Null, + "imgdata": Array([ + Number( + 0, + ), + ]), "mime": String( "image/jpeg", ), @@ -1843,7 +1836,11 @@ "id": Number( 9989, ), - "imgdata": Null, + "imgdata": Array([ + Number( + 0, + ), + ]), "mime": String( "image/jpeg", ), @@ -2008,7 +2005,11 @@ "id": Number( 9988, ), - "imgdata": Null, + "imgdata": Array([ + Number( + 0, + ), + ]), "mime": String( "image/jpeg", ), @@ -2173,7 +2174,11 @@ "id": Number( 9987, ), - "imgdata": Null, + "imgdata": Array([ + Number( + 0, + ), + ]), "mime": String( "image/jpeg", ), @@ -2338,7 +2343,11 @@ "id": Number( 9986, ), - "imgdata": Null, + "imgdata": Array([ + Number( + 0, + ), + ]), "mime": String( "image/jpeg", ), @@ -2503,7 +2512,11 @@ "id": Number( 9985, ), - "imgdata": Null, + "imgdata": Array([ + Number( + 0, + ), + ]), "mime": String( "image/jpeg", ), @@ -2668,7 +2681,11 @@ "id": Number( 9983, ), - "imgdata": Null, + "imgdata": Array([ + Number( + 0, + ), + ]), "mime": String( "image/jpeg", ), @@ -2833,7 +2850,11 @@ "id": Number( 9982, ), - "imgdata": Null, + "imgdata": Array([ + Number( + 0, + ), + ]), "mime": String( "image/jpeg", ), @@ -2998,7 +3019,11 @@ "id": Number( 9981, ), - "imgdata": Null, + "imgdata": Array([ + Number( + 0, + ), + ]), "mime": String( "image/jpeg", ), @@ -3163,7 +3188,11 @@ "id": Number( 9980, ), - "imgdata": Null, + "imgdata": Array([ + Number( + 0, + ), + ]), "mime": String( "image/jpeg", ), @@ -3192,6 +3221,175 @@ ), }), }), + Object({ + "comment_count": Number( + 5, + ), + "comments": Array([ + Object({ + "comment": Object({ + "comment": String( + "オメテ\u{ff9e}チョーク( -.-)ノ・・・-=≡≡≡/((((((((((- チョーク☆ ̄(>。☆", + ), + "created_at": String( + "2016-01-03T23:38:54Z", + ), + "id": Number( + 85134, + ), + "post_id": Number( + 9979, + ), + "user_id": Number( + 566, + ), + }), + "user": Object({ + "account_name": String( + "cassie", + ), + "authority": Number( + 0, + ), + "created_at": String( + "2016-01-01T00:09:26Z", + ), + "del_flg": Number( + 0, + ), + "id": Number( + 566, + ), + "passhash": String( + "a3a858a3cf5972414501734297d3f88e74a20d15180c606b97975b16d3b970909f156494ad9436c810e622cc0b265849d0eb9d7b98ef0c98fa2bc8f6ad500950", + ), + }), + }), + Object({ + "comment": Object({ + "comment": String( + "(=^ー^)ノ彡☆゜・。・゜★ハ\u{ff9e}イハ\u{ff9e}イ", + ), + "created_at": String( + "2016-01-04T01:18:37Z", + ), + "id": Number( + 91117, + ), + "post_id": Number( + 9979, + ), + "user_id": Number( + 383, + ), + }), + "user": Object({ + "account_name": String( + "erma", + ), + "authority": Number( + 0, + ), + "created_at": String( + "2016-01-01T00:06:23Z", + ), + "del_flg": Number( + 0, + ), + "id": Number( + 383, + ), + "passhash": String( + "d82ef4f04eb11da50b32ebe5c01faf40e124d06519a201da1411124cdfd7cffd389db58a05257bd7ba419aa4095102717c30d623a13896a0fd219b55205817a3", + ), + }), + }), + Object({ + "comment": Object({ + "comment": String( + "アリカ\u{ff9e}トタ\u{ff9e}フ\u{ff9e}ルハ\u{ff9f}ンチ!!o( \u{ff9f}o\u{ff9f})=○)\u{ff9f}δ\u{ff9f}(○=(\u{ff9f}o\u{ff9f} )oハ\u{ff9e}キッx2", + ), + "created_at": String( + "2016-01-04T03:14:34Z", + ), + "id": Number( + 98074, + ), + "post_id": Number( + 9979, + ), + "user_id": Number( + 509, + ), + }), + "user": Object({ + "account_name": String( + "bonita", + ), + "authority": Number( + 0, + ), + "created_at": String( + "2016-01-01T00:08:29Z", + ), + "del_flg": Number( + 0, + ), + "id": Number( + 509, + ), + "passhash": String( + "de7aab6d183080949a41d4d72659692e45b7dabd3d221e1bcd26c6e284f3ea1ea0056f5f47709fd1d5e5e0b14ab032ae2cc56bc6d7f14afb566c2ad911c8b436", + ), + }), + }), + ]), + "csrf_token": String( + "", + ), + "post": Object({ + "body": String( + "ヾ(;ω;)Byeヾ(;ω;)Bye", + ), + "created_at": String( + "2016-01-02T02:46:19Z", + ), + "id": Number( + 9979, + ), + "imgdata": Array([ + Number( + 0, + ), + ]), + "mime": String( + "image/jpeg", + ), + "user_id": Number( + 476, + ), + }), + "user": Object({ + "account_name": String( + "lorene", + ), + "authority": Number( + 0, + ), + "created_at": String( + "2016-01-01T00:07:56Z", + ), + "del_flg": Number( + 0, + ), + "id": Number( + 476, + ), + "passhash": String( + "94093914fb98e389374b0e175ff1ee83a3921aae34c96951ef09adc5e91a75a008f23f40ccd4a1ce6a7513abe4e883b07e5bf4524c68024fed01233ad72a72da", + ), + }), + }), ]), "posts_parent": String( "index", @@ -3204,7 +3402,7 @@ 0, ), "created_at": String( - "2022-06-14T09:27:57.270628900Z", + "2022-06-14T18:07:33.858477550Z", ), "del_flg": Number( 0, diff --git a/webapp/rust/src/main.rs b/webapp/rust/src/main.rs index 7c4f26e23..9ed76b211 100644 --- a/webapp/rust/src/main.rs +++ b/webapp/rust/src/main.rs @@ -15,7 +15,10 @@ use actix_web::{ cookie::time::UtcOffset, dev::ResourceDef, error, get, - http::{header, Method, StatusCode}, + http::{ + header::{self, ContentType}, + Method, StatusCode, + }, middleware, post, web::{self, Data, Form}, App, HttpRequest, HttpResponse, HttpServer, Result, @@ -79,7 +82,7 @@ impl Default for User { struct Post { id: i32, user_id: i32, - imgdata: Option>, + imgdata: Vec, body: String, mime: String, created_at: chrono::DateTime, @@ -391,13 +394,14 @@ async fn get_login( }; let body = { - let mut json = serde_json::to_value(user).unwrap(); - let map = json.as_object_mut().unwrap(); + let mut map = Map::new(); + + map.insert("user".to_string(), to_json(user)); map.insert("flash".to_string(), to_json(get_flash(&session, "notice"))); map.insert("parent".to_string(), to_json("layout")); log::debug!("{:?}", &map); - handlebars.render("login", map).unwrap() + handlebars.render("login", &map).unwrap() }; log::debug!("{:?}", &body); @@ -465,13 +469,14 @@ async fn get_register( let body = { let user = User::default(); - let mut json = serde_json::to_value(user).unwrap(); - let map = json.as_object_mut().unwrap(); + let mut map = Map::new(); + + map.insert("user".to_string(), to_json(user)); map.insert("flash".to_string(), to_json(get_flash(&session, "notice"))); map.insert("parent".to_string(), to_json("layout")); log::debug!("map {:?}", &map); - handlebars.render("register", map).unwrap() + handlebars.render("register", &map).unwrap() }; log::debug!("return ok"); @@ -596,7 +601,7 @@ async fn get_index( } }; - let results = match sqlx::query_as_unchecked!(Post,"SELECT `id`, `user_id`, `body`, `mime`, `created_at`, NULL AS imgdata FROM `posts` ORDER BY `created_at` DESC").fetch_all(pool.as_ref()).await { + let results = match sqlx::query_as!(Post,"SELECT `id`, `user_id`, `body`, `mime`, `created_at`, b'0' AS imgdata FROM `posts` ORDER BY `created_at` DESC").fetch_all(pool.as_ref()).await { Ok(results) => results, Err(e) => { log::error!("{:?}",&e); @@ -621,9 +626,9 @@ async fn get_index( let body = { let mut map = Map::new(); - let json = serde_json::to_value(posts).unwrap(); + // let posts = serde_json::to_value(posts).unwrap(); // let map = json.as_object_mut().unwrap(); - map.insert("posts".to_string(), to_json(json.as_array())); + map.insert("posts".to_string(), to_json(posts)); map.insert("user".to_string(), to_json(me)); map.insert( "csrf_token".to_string(), @@ -657,8 +662,53 @@ async fn post_index() -> Result { todo!() } -async fn get_image() -> Result { - todo!() +#[get("/image/{path}")] +async fn get_image(path: web::Path<(String,)>, pool: Data>) -> Result { + let (pid, ext) = match path.0.rsplit_once(".") { + Some((pid, ext)) => { + let pid = match pid.parse::() { + Ok(pid) => pid, + Err(e) => { + log::warn!("{:?}", &e); + return Ok(HttpResponse::InternalServerError().body(e.to_string())); + } + }; + (pid, ext) + } + None => { + let e = "Invalid path"; + log::warn!("{}", e); + return Ok(HttpResponse::InternalServerError().body(e)); + } + }; + + let post = match sqlx::query_as!(Post, "SELECT * FROM `posts` WHERE `id` = ?", pid) + .fetch_optional(pool.as_ref()) + .await + { + Ok(Some(post)) => post, + Err(e) => { + log::warn!("{:?}", &e); + return Ok(HttpResponse::InternalServerError().body(e.to_string())); + } + _ => { + return Ok(HttpResponse::InternalServerError().finish()); + } + }; + + if ext == "jpg" && post.mime == "image/jpeg" + || ext == "png" && post.mime == "image/png" + || ext == "gif" && post.mime == "image/gif" + {} + + let content_type = match (ext, post.mime.as_str()) { + ("jpg", "image/jpeg") | ("png", "image/png") | ("gif", "image/gif") => post.mime.as_str(), + _ => return Ok(HttpResponse::InternalServerError().finish()), + }; + + Ok(HttpResponse::Ok() + .content_type(content_type) + .body(post.imgdata)) } async fn post_comment() -> Result { @@ -772,6 +822,7 @@ async fn main() -> io::Result<()> { .service(post_register) .service(get_logout) .service(get_index) + .service(get_image) // .service(ResourceDef::new("/{tail}*").) .service(Files::new("/", "../public")) .service( @@ -786,6 +837,3 @@ async fn main() -> io::Result<()> { .run() .await } - -static LAYOUT: &str = include_str!("../templates/layout.html"); -static LOGIN: &str = include_str!("../templates/login.html"); diff --git a/webapp/rust/static/layout.html b/webapp/rust/static/layout.html index c1bb124bb..dd271a2e9 100644 --- a/webapp/rust/static/layout.html +++ b/webapp/rust/static/layout.html @@ -14,11 +14,11 @@

Iscogram

- {{#if (eq id 0)}} + {{#if (eq user.id 0)}} {{else}} - {{#if (eq authority 1)}} + {{#if (eq user.authority 1)}} {{/if}} From db9c368452de6819b2e3e4a69fe17072124e7186 Mon Sep 17 00:00:00 2001 From: Romira915 <40430090+Romira915@users.noreply.github.com> Date: Wed, 15 Jun 2022 13:13:20 +0900 Subject: [PATCH 27/64] features: get_post_id --- webapp/rust/map.json | 3417 ------------------------------- webapp/rust/src/main.rs | 78 +- webapp/rust/static/post_id.html | 4 + 3 files changed, 75 insertions(+), 3424 deletions(-) delete mode 100644 webapp/rust/map.json create mode 100644 webapp/rust/static/post_id.html diff --git a/webapp/rust/map.json b/webapp/rust/map.json deleted file mode 100644 index 037e0ae47..000000000 --- a/webapp/rust/map.json +++ /dev/null @@ -1,3417 +0,0 @@ -{ - "content_parent": String( - "layout", - ), - "csrf_token": String( - "", - ), - "flash": Null, - "post_parent": String( - "posts", - ), - "posts": Array([ - Object({ - "comment_count": Number( - 11, - ), - "comments": Array([ - Object({ - "comment": Object({ - "comment": String( - "ヽ(^▽^@)ノ\u{3000}やぁ~", - ), - "created_at": String( - "2016-01-03T17:37:42Z", - ), - "id": Number( - 63462, - ), - "post_id": Number( - 10000, - ), - "user_id": Number( - 804, - ), - }), - "user": Object({ - "account_name": String( - "carmella", - ), - "authority": Number( - 0, - ), - "created_at": String( - "2016-01-01T00:13:24Z", - ), - "del_flg": Number( - 0, - ), - "id": Number( - 804, - ), - "passhash": String( - "a66b8705963efdbc8c4c9227cf98fd2497c96c5db8c05bf3e260e59d922f89eec771e049a9cec736278045e0afde96c3abbf8c535b4b9d677625f830b40cfa9b", - ), - }), - }), - Object({ - "comment": Object({ - "comment": String( - "(ノ^^)ノ―――――――※※☆★congratulations!!★☆", - ), - "created_at": String( - "2016-01-03T17:40:51Z", - ), - "id": Number( - 63651, - ), - "post_id": Number( - 10000, - ), - "user_id": Number( - 296, - ), - }), - "user": Object({ - "account_name": String( - "ramona", - ), - "authority": Number( - 0, - ), - "created_at": String( - "2016-01-01T00:04:56Z", - ), - "del_flg": Number( - 0, - ), - "id": Number( - 296, - ), - "passhash": String( - "e4d20709f5afad55a2685d586132dcbdd223d35a70e322ca08f929463205965f14dc3fd5873f0d4946e4df5190890bfc929120999fb4f0581b91a3a7d4ce4140", - ), - }), - }), - Object({ - "comment": Object({ - "comment": String( - "[壁]=\u{ff9f}▽\u{ff9f})ノ ヤァ♪", - ), - "created_at": String( - "2016-01-04T03:08:37Z", - ), - "id": Number( - 97717, - ), - "post_id": Number( - 10000, - ), - "user_id": Number( - 41, - ), - }), - "user": Object({ - "account_name": String( - "stephanie", - ), - "authority": Number( - 0, - ), - "created_at": String( - "2016-01-01T00:00:41Z", - ), - "del_flg": Number( - 0, - ), - "id": Number( - 41, - ), - "passhash": String( - "27a3a4ec313fcf9c85adb1e3811bfe8e217b4b7c6c62cd62f3e1f5d9cfbbed9c874d6a7f9847e282a60786344343f6d2c15ba6481f898367a9c026e59bd112d5", - ), - }), - }), - ]), - "csrf_token": String( - "", - ), - "post": Object({ - "body": String( - "ト\u{ff9e}モト\u{ff9e}モ\(^_^ ) ( ^_^)/ト\u{ff9e}モト\u{ff9e}モ", - ), - "created_at": String( - "2016-01-02T02:46:40Z", - ), - "id": Number( - 10000, - ), - "imgdata": Array([ - Number( - 0, - ), - ]), - "mime": String( - "image/png", - ), - "user_id": Number( - 112, - ), - }), - "user": Object({ - "account_name": String( - "rosa", - ), - "authority": Number( - 0, - ), - "created_at": String( - "2016-01-01T00:01:52Z", - ), - "del_flg": Number( - 0, - ), - "id": Number( - 112, - ), - "passhash": String( - "7ee7581f856795775c4f864ac6bbc1d687b6035f0560d3436a1d0e0138b07a6b9033f899a690c8ce3d46547a18a7a611ba80557a67f71ae50b48159b9f873dd8", - ), - }), - }), - Object({ - "comment_count": Number( - 11, - ), - "comments": Array([ - Object({ - "comment": Object({ - "comment": String( - "ハイ オメテ\u{ff9e}トネ( ゜σ ゜)Ξ(\u{3000}・_<)σ…----- ・ヒ\u{ff9f}ンッ! (^ ^ ;)ヤナカンシ\u{ff9e}", - ), - "created_at": String( - "2016-01-03T19:09:50Z", - ), - "id": Number( - 68990, - ), - "post_id": Number( - 9999, - ), - "user_id": Number( - 248, - ), - }), - "user": Object({ - "account_name": String( - "caroline", - ), - "authority": Number( - 0, - ), - "created_at": String( - "2016-01-01T00:04:08Z", - ), - "del_flg": Number( - 0, - ), - "id": Number( - 248, - ), - "passhash": String( - "2ac4e01921cab4bec906ca0171a69d8cad539d08501c8c209066e26781410f3ee1e177689d14aafdcd3736f8f4d3510173e22ef6910d6ae49076fab59d7ee017", - ), - }), - }), - Object({ - "comment": Object({ - "comment": String( - "睡魔→Ψ(`∀´#)ノ\_(T◇T)ノ\")),,,,,,,,,オヤスミー", - ), - "created_at": String( - "2016-01-03T23:09:36Z", - ), - "id": Number( - 83376, - ), - "post_id": Number( - 9999, - ), - "user_id": Number( - 410, - ), - }), - "user": Object({ - "account_name": String( - "muriel", - ), - "authority": Number( - 0, - ), - "created_at": String( - "2016-01-01T00:06:50Z", - ), - "del_flg": Number( - 0, - ), - "id": Number( - 410, - ), - "passhash": String( - "56fa35d0d22e863cecb79cb3fb0ff6eb2d073a682f1b5b21dbd0591e3c4fadc8544f9648c9d4c94ce113e39040e647225f1113ef9cde30ddc8ce71b81a44446b", - ), - }), - }), - Object({ - "comment": Object({ - "comment": String( - "v( ̄、 ̄)ノ\"ヨォッ!!ヒサシフ\u{ff9e}リ!!", - ), - "created_at": String( - "2016-01-04T02:36:31Z", - ), - "id": Number( - 95791, - ), - "post_id": Number( - 9999, - ), - "user_id": Number( - 357, - ), - }), - "user": Object({ - "account_name": String( - "lula", - ), - "authority": Number( - 0, - ), - "created_at": String( - "2016-01-01T00:05:57Z", - ), - "del_flg": Number( - 0, - ), - "id": Number( - 357, - ), - "passhash": String( - "e517cf650ffd37efc7106918e395f5f6f1b11fb1e2838a23ad58c1e7809708e4f63f431dfb941617ae94c7929c8ef2fdef6fc4213dd0dd40dbbedb22466890c5", - ), - }), - }), - ]), - "csrf_token": String( - "", - ), - "post": Object({ - "body": String( - "★*♪。☆*★*♪。☆*★*♪。☆*(^∇\u{ff9f}*)ノ\" オヤスミィ♪", - ), - "created_at": String( - "2016-01-02T02:46:39Z", - ), - "id": Number( - 9999, - ), - "imgdata": Array([ - Number( - 0, - ), - ]), - "mime": String( - "image/jpeg", - ), - "user_id": Number( - 792, - ), - }), - "user": Object({ - "account_name": String( - "jordan", - ), - "authority": Number( - 0, - ), - "created_at": String( - "2016-01-01T00:13:12Z", - ), - "del_flg": Number( - 0, - ), - "id": Number( - 792, - ), - "passhash": String( - "6530cd2f245b286042c5dfef368e23305475578c372bb56ddd4cb9e9303026ac3051976dd9bb10eb22a3b0a66fc892820411bc874a846fe9f59378104864342d", - ), - }), - }), - Object({ - "comment_count": Number( - 10, - ), - "comments": Array([ - Object({ - "comment": Object({ - "comment": String( - "オヒサ!((( ^^)爻(^^ )))オヒサ!", - ), - "created_at": String( - "2016-01-04T00:21:37Z", - ), - "id": Number( - 87697, - ), - "post_id": Number( - 9998, - ), - "user_id": Number( - 925, - ), - }), - "user": Object({ - "account_name": String( - "mai", - ), - "authority": Number( - 0, - ), - "created_at": String( - "2016-01-01T00:15:25Z", - ), - "del_flg": Number( - 0, - ), - "id": Number( - 925, - ), - "passhash": String( - "6733654598f5921dd8713cc3c7a1b05424d0171c54d5e1cbcb139496ef302ee3506d8e1d5fa931d916dc7560b05051f99f2b478720fdcbcdb84e5e0fb37272da", - ), - }), - }), - Object({ - "comment": Object({ - "comment": String( - "see you agein.....(/_・、)/~~", - ), - "created_at": String( - "2016-01-04T01:09:56Z", - ), - "id": Number( - 90596, - ), - "post_id": Number( - 9998, - ), - "user_id": Number( - 273, - ), - }), - "user": Object({ - "account_name": String( - "priscilla", - ), - "authority": Number( - 0, - ), - "created_at": String( - "2016-01-01T00:04:33Z", - ), - "del_flg": Number( - 0, - ), - "id": Number( - 273, - ), - "passhash": String( - "8a874793eb65c1b6aea4d66baab9b8803f2e00b5aaa0412be5f2d55a1c7125fc4468e2e004aab614a5b19252246a96a05958d424cd9e1e2ab282dd96c859a853", - ), - }), - }), - Object({ - "comment": Object({ - "comment": String( - "オメットマシ\u{ff9e}ックハント\u{ff9e}o((=\u{ff9f}エ\u{ff9f}=))oノXXXXXXXXXXXXX>C( )\u{ff9f}0\u{ff9f})ノノ", - ), - "created_at": String( - "2016-01-04T03:33:45Z", - ), - "id": Number( - 99225, - ), - "post_id": Number( - 9998, - ), - "user_id": Number( - 648, - ), - }), - "user": Object({ - "account_name": String( - "jeanine", - ), - "authority": Number( - 0, - ), - "created_at": String( - "2016-01-01T00:10:48Z", - ), - "del_flg": Number( - 0, - ), - "id": Number( - 648, - ), - "passhash": String( - "265f9c06fc79988e8dcfe3a27e68b98fd9c0694e5e79914f5ec97abb689ddb64e169354d4e0ce8367aad8b300713f4a67658dc4c79a96447614497d3e7aeacf9", - ), - }), - }), - ]), - "csrf_token": String( - "", - ), - "post": Object({ - "body": String( - "(^-^)ノ~~マタネー☆’.・*.・:★’.・*.・:☆’.・*.・:★", - ), - "created_at": String( - "2016-01-02T02:46:38Z", - ), - "id": Number( - 9998, - ), - "imgdata": Array([ - Number( - 0, - ), - ]), - "mime": String( - "image/jpeg", - ), - "user_id": Number( - 149, - ), - }), - "user": Object({ - "account_name": String( - "valerie", - ), - "authority": Number( - 0, - ), - "created_at": String( - "2016-01-01T00:02:29Z", - ), - "del_flg": Number( - 0, - ), - "id": Number( - 149, - ), - "passhash": String( - "8da0a01cb7ba509dbd29c0d03531659234ac08af0a90d86d72a37efad2a827a95359b28f6ef5a468edf346dd655dcfa2d465471b1f0dcdb9bb0ace7c77c79275", - ), - }), - }), - Object({ - "comment_count": Number( - 14, - ), - "comments": Array([ - Object({ - "comment": Object({ - "comment": String( - "(▼▼メ)/●~*【祝】*~●\(▼▼メ)", - ), - "created_at": String( - "2016-01-04T02:00:39Z", - ), - "id": Number( - 93639, - ), - "post_id": Number( - 9997, - ), - "user_id": Number( - 266, - ), - }), - "user": Object({ - "account_name": String( - "nora", - ), - "authority": Number( - 0, - ), - "created_at": String( - "2016-01-01T00:04:26Z", - ), - "del_flg": Number( - 0, - ), - "id": Number( - 266, - ), - "passhash": String( - "47fab786c3f1978cef77600a37c0db24d3a2ea582dfbafdb919f574c5669afceb9bc0ab07850c9f2d95a40957be7ad7c21df9e9b8122e3e69aedac650ece6ea3", - ), - }), - }), - Object({ - "comment": Object({ - "comment": String( - "(○\u{ff9f}▽\u{ff9f}○)/ ヨッ!!", - ), - "created_at": String( - "2016-01-04T02:04:50Z", - ), - "id": Number( - 93890, - ), - "post_id": Number( - 9997, - ), - "user_id": Number( - 838, - ), - }), - "user": Object({ - "account_name": String( - "jerry", - ), - "authority": Number( - 0, - ), - "created_at": String( - "2016-01-01T00:13:58Z", - ), - "del_flg": Number( - 0, - ), - "id": Number( - 838, - ), - "passhash": String( - "e025ec3ba311af1e6fa284dbaa8f94b95a54d4ec1ffc40158188bdaf00604be27bd6468fd1cb3352b122c9488f47cd292bd4146afb2eb2f13ca8c3cf1e2874fc", - ), - }), - }), - Object({ - "comment": Object({ - "comment": String( - "オメットナカ\u{ff9e}レホ\u{ff9e}シ(*'▽')ノ^---==ΞΞΞ☆", - ), - "created_at": String( - "2016-01-04T02:55:03Z", - ), - "id": Number( - 96903, - ), - "post_id": Number( - 9997, - ), - "user_id": Number( - 363, - ), - }), - "user": Object({ - "account_name": String( - "juana", - ), - "authority": Number( - 0, - ), - "created_at": String( - "2016-01-01T00:06:03Z", - ), - "del_flg": Number( - 0, - ), - "id": Number( - 363, - ), - "passhash": String( - "b2474ac1b1794af95b57e3fb1e7893a6975269f7290935ea728718d4ff8bfe618f6fee8498841ab3c6cde78576c0d8d2636d6c49db0f17195d481dee1c76b925", - ), - }), - }), - ]), - "csrf_token": String( - "", - ), - "post": Object({ - "body": String( - "ハ\u{ff9e}ヾ(*'O'*)イヾ(*'◇'*)ハ\u{ff9e}ヾ(*'□'*)ーヾ(*'□'*)イヾ(*'-'*)", - ), - "created_at": String( - "2016-01-02T02:46:37Z", - ), - "id": Number( - 9997, - ), - "imgdata": Array([ - Number( - 0, - ), - ]), - "mime": String( - "image/jpeg", - ), - "user_id": Number( - 89, - ), - }), - "user": Object({ - "account_name": String( - "julia", - ), - "authority": Number( - 0, - ), - "created_at": String( - "2016-01-01T00:01:29Z", - ), - "del_flg": Number( - 0, - ), - "id": Number( - 89, - ), - "passhash": String( - "1c80db58ddaa659bda70d61954231d8ef1dd33f3bc5817e9b02fdce0642be5a86c6582c78de0256b94d79856d0e5893854b5b11a677e3f361092f757ae4d849e", - ), - }), - }), - Object({ - "comment_count": Number( - 12, - ), - "comments": Array([ - Object({ - "comment": Object({ - "comment": String( - "電柱|・ω・`)ノ ヤァ", - ), - "created_at": String( - "2016-01-03T19:23:18Z", - ), - "id": Number( - 69798, - ), - "post_id": Number( - 9996, - ), - "user_id": Number( - 646, - ), - }), - "user": Object({ - "account_name": String( - "marisol", - ), - "authority": Number( - 0, - ), - "created_at": String( - "2016-01-01T00:10:46Z", - ), - "del_flg": Number( - 0, - ), - "id": Number( - 646, - ), - "passhash": String( - "a5c525e5dd29a1f9385feb91a28cf471f1e34374b228e4aec529c39484a2d4a6ac7fd6bf70ea38714294faee44cf919c7054be489cf265cffe4f40717d18b142", - ), - }), - }), - Object({ - "comment": Object({ - "comment": String( - "(キ▼⊿▼)ノ ヨォ!", - ), - "created_at": String( - "2016-01-03T21:30:50Z", - ), - "id": Number( - 77450, - ), - "post_id": Number( - 9996, - ), - "user_id": Number( - 573, - ), - }), - "user": Object({ - "account_name": String( - "janette", - ), - "authority": Number( - 0, - ), - "created_at": String( - "2016-01-01T00:09:33Z", - ), - "del_flg": Number( - 0, - ), - "id": Number( - 573, - ), - "passhash": String( - "7fba215169b327e4f914b75d7694f4c58beb71576c6ec7e683d9a03e27a1c87e281980a0a59ee1c2b525ccf6d83938dcd6f719be8f8e0718e012ed3597275bb6", - ), - }), - }), - Object({ - "comment": Object({ - "comment": String( - "(ノ`Д´)ノ^・:*:・\u{ff9f}'((●~*チチチ,。・:*:・\u{ff9f}'☆オメテ\u{ff9e}トォー!!", - ), - "created_at": String( - "2016-01-04T00:38:01Z", - ), - "id": Number( - 88681, - ), - "post_id": Number( - 9996, - ), - "user_id": Number( - 969, - ), - }), - "user": Object({ - "account_name": String( - "lolita", - ), - "authority": Number( - 0, - ), - "created_at": String( - "2016-01-01T00:16:09Z", - ), - "del_flg": Number( - 0, - ), - "id": Number( - 969, - ), - "passhash": String( - "327e0bedf08b755dd3f0981442e59da2ff725570279c5f8a53aa0a0d4203319eedb797a8b3f13e3425e3edcc4be08d20513bb6d41566c2eee20645265405aad3", - ), - }), - }), - ]), - "csrf_token": String( - "", - ), - "post": Object({ - "body": String( - "o( ̄∇ ̄o)ク\u{ff9e}ッ!!(∇ ̄ )クル(\u{3000}\u{3000})クル(  ̄∇)クル(o ̄∇ ̄)ノハ\u{ff9e}ーイ", - ), - "created_at": String( - "2016-01-02T02:46:36Z", - ), - "id": Number( - 9996, - ), - "imgdata": Array([ - Number( - 0, - ), - ]), - "mime": String( - "image/jpeg", - ), - "user_id": Number( - 876, - ), - }), - "user": Object({ - "account_name": String( - "elvia", - ), - "authority": Number( - 0, - ), - "created_at": String( - "2016-01-01T00:14:36Z", - ), - "del_flg": Number( - 0, - ), - "id": Number( - 876, - ), - "passhash": String( - "6d7bfe25c4afc7a05b03c5dcf5d202669536c59086b14019724eb1e33b83f3a0644c456d4ff4d5fedb3848d9847df7763096f13326c66d1fc80374eaa90e9401", - ), - }), - }), - Object({ - "comment_count": Number( - 6, - ), - "comments": Array([ - Object({ - "comment": Object({ - "comment": String( - "フ\u{ff9f}ンフ\u{ff9f}ン( ̄^ ̄メ)\(_ _ ;)ハンセイ…", - ), - "created_at": String( - "2016-01-03T17:33:32Z", - ), - "id": Number( - 63212, - ), - "post_id": Number( - 9995, - ), - "user_id": Number( - 395, - ), - }), - "user": Object({ - "account_name": String( - "rosalie", - ), - "authority": Number( - 0, - ), - "created_at": String( - "2016-01-01T00:06:35Z", - ), - "del_flg": Number( - 0, - ), - "id": Number( - 395, - ), - "passhash": String( - "f5f3b0940b8fca79d465ddb8179dbe136370260484d9c4c471d0e47fbb151f20d1a45aa2c6399e170a434cffa1496d8532b440383dbd6187027089d14eb4596d", - ), - }), - }), - Object({ - "comment": Object({ - "comment": String( - "(ノ_・。)/\u{ff9f}・:*【祝】*:・\u{ff9f}\(・_・、)", - ), - "created_at": String( - "2016-01-03T20:41:31Z", - ), - "id": Number( - 74491, - ), - "post_id": Number( - 9995, - ), - "user_id": Number( - 549, - ), - }), - "user": Object({ - "account_name": String( - "lourdes", - ), - "authority": Number( - 0, - ), - "created_at": String( - "2016-01-01T00:09:09Z", - ), - "del_flg": Number( - 0, - ), - "id": Number( - 549, - ), - "passhash": String( - "36b56a416cc99fd3d61dabef1f16910daec5772ea69c82db8ee3153f14350720cad1cac01c61df61acf4b4b72e35c011bae289a416e46d10a5491ad7329866bc", - ), - }), - }), - Object({ - "comment": Object({ - "comment": String( - "どもども( ^-^)∠※.。・:*:・°`☆、。・:*:・°`★", - ), - "created_at": String( - "2016-01-04T01:05:18Z", - ), - "id": Number( - 90318, - ), - "post_id": Number( - 9995, - ), - "user_id": Number( - 974, - ), - }), - "user": Object({ - "account_name": String( - "fanny", - ), - "authority": Number( - 0, - ), - "created_at": String( - "2016-01-01T00:16:14Z", - ), - "del_flg": Number( - 0, - ), - "id": Number( - 974, - ), - "passhash": String( - "379f797910aa9e1bc1e5190acd64b9c2b07b7932a7167965c159787161f1ec95f35258385adff53bb9712795f362e4a80b3b06ad1327b45045a9099457bb0db2", - ), - }), - }), - ]), - "csrf_token": String( - "", - ), - "post": Object({ - "body": String( - "ネシ\u{ff9e}ネシ\u{ff9e}ッ 8-(--)カタカタカタ-。。。。8-(^▽^)ノオメット!", - ), - "created_at": String( - "2016-01-02T02:46:35Z", - ), - "id": Number( - 9995, - ), - "imgdata": Array([ - Number( - 0, - ), - ]), - "mime": String( - "image/jpeg", - ), - "user_id": Number( - 517, - ), - }), - "user": Object({ - "account_name": String( - "adriana", - ), - "authority": Number( - 0, - ), - "created_at": String( - "2016-01-01T00:08:37Z", - ), - "del_flg": Number( - 0, - ), - "id": Number( - 517, - ), - "passhash": String( - "ecbacf7ca01829905ec159b691bebc4b0c1f20a81f7f4bea7d438ec24450e86166563d448a9dbb260e59e6de3a44c4a219d358781e26369a1405a588be1f07da", - ), - }), - }), - Object({ - "comment_count": Number( - 8, - ), - "comments": Array([ - Object({ - "comment": Object({ - "comment": String( - "オメットストーカー │電柱│_・) シ\u{ff9e}ィィ。。。 §;\u{ff9f}ロ\u{ff9f}§ ツケラレテイルワ!!", - ), - "created_at": String( - "2016-01-03T12:32:33Z", - ), - "id": Number( - 45153, - ), - "post_id": Number( - 9994, - ), - "user_id": Number( - 37, - ), - }), - "user": Object({ - "account_name": String( - "pamela", - ), - "authority": Number( - 0, - ), - "created_at": String( - "2016-01-01T00:00:37Z", - ), - "del_flg": Number( - 0, - ), - "id": Number( - 37, - ), - "passhash": String( - "60e5137c1867ee69f787e0d4ac63214209f6f8111538d102f6c7ae35c99e597dc05c3f41f150f503ab6b17dc3aa80f26ab4a6576daa7d2e6103c421d70f64f36", - ), - }), - }), - Object({ - "comment": Object({ - "comment": String( - "m(._.*)mヘ\u{ff9f}コッ", - ), - "created_at": String( - "2016-01-03T13:19:42Z", - ), - "id": Number( - 47982, - ), - "post_id": Number( - 9994, - ), - "user_id": Number( - 75, - ), - }), - "user": Object({ - "account_name": String( - "tammy", - ), - "authority": Number( - 0, - ), - "created_at": String( - "2016-01-01T00:01:15Z", - ), - "del_flg": Number( - 0, - ), - "id": Number( - 75, - ), - "passhash": String( - "8d0156ec5933427ff2df01865bf9eec613cda8a8fecddb57103b6983e8dec7d72133584906987962fd74e7dde69d08aebf136fd2ddf898a47489604e8038ac9e", - ), - }), - }), - Object({ - "comment": Object({ - "comment": String( - "ヾ@(o・ェ・)Uo・ェ・)\u{ff9f}Θ\u{ff9f})^・x・)ノ~~~ハ\u{ff9e}ハ\u{ff9e}~イ♪", - ), - "created_at": String( - "2016-01-03T22:24:03Z", - ), - "id": Number( - 80643, - ), - "post_id": Number( - 9994, - ), - "user_id": Number( - 395, - ), - }), - "user": Object({ - "account_name": String( - "rosalie", - ), - "authority": Number( - 0, - ), - "created_at": String( - "2016-01-01T00:06:35Z", - ), - "del_flg": Number( - 0, - ), - "id": Number( - 395, - ), - "passhash": String( - "f5f3b0940b8fca79d465ddb8179dbe136370260484d9c4c471d0e47fbb151f20d1a45aa2c6399e170a434cffa1496d8532b440383dbd6187027089d14eb4596d", - ), - }), - }), - ]), - "csrf_token": String( - "", - ), - "post": Object({ - "body": String( - "あ( ̄○ ̄)り( ̄◇ ̄)が( ̄△ ̄)と( ̄0 ̄)う", - ), - "created_at": String( - "2016-01-02T02:46:34Z", - ), - "id": Number( - 9994, - ), - "imgdata": Array([ - Number( - 0, - ), - ]), - "mime": String( - "image/jpeg", - ), - "user_id": Number( - 455, - ), - }), - "user": Object({ - "account_name": String( - "laverne", - ), - "authority": Number( - 0, - ), - "created_at": String( - "2016-01-01T00:07:35Z", - ), - "del_flg": Number( - 0, - ), - "id": Number( - 455, - ), - "passhash": String( - "b079c3079b1796e1ad545bab038578b510e3f94b228bbcc11102851aefd0b4a1b8acf58f04e0f32ef4e761c96cf83c931999735deb6f2206da62d171dfcc6569", - ), - }), - }), - Object({ - "comment_count": Number( - 9, - ), - "comments": Array([ - Object({ - "comment": Object({ - "comment": String( - "(・⊥・)/ ヤァ", - ), - "created_at": String( - "2016-01-03T18:59:01Z", - ), - "id": Number( - 68341, - ), - "post_id": Number( - 9993, - ), - "user_id": Number( - 230, - ), - }), - "user": Object({ - "account_name": String( - "joy", - ), - "authority": Number( - 0, - ), - "created_at": String( - "2016-01-01T00:03:50Z", - ), - "del_flg": Number( - 0, - ), - "id": Number( - 230, - ), - "passhash": String( - "69b3a18528fd3f9282694c84e05cd57ea0cca1fce1b0cb77b3315cdd3d36e74c4f89415888238bcf2beb307245fa80de239e523339b07a8a1b7106eacf572a3e", - ), - }), - }), - Object({ - "comment": Object({ - "comment": String( - "オメットフィッシンク\u{ff9e}!!( ・_・)ノシュッ~~~~~~くコ:彡", - ), - "created_at": String( - "2016-01-03T21:24:54Z", - ), - "id": Number( - 77094, - ), - "post_id": Number( - 9993, - ), - "user_id": Number( - 362, - ), - }), - "user": Object({ - "account_name": String( - "candice", - ), - "authority": Number( - 0, - ), - "created_at": String( - "2016-01-01T00:06:02Z", - ), - "del_flg": Number( - 0, - ), - "id": Number( - 362, - ), - "passhash": String( - "706acbeef752cb39360f0f02c39aed28e371301041c21b36cb40f3d4745aaa83cb065272515fa6eb2885a0b90dfaa684e12c153401be39ab1aaecb4c7fd74403", - ), - }), - }), - Object({ - "comment": Object({ - "comment": String( - "ハ\u{ff9e}イハ\u{ff9e}イノハ\u{ff9e}ーイ!!-=Ξヾ(ヾ(ヾ(ヾ(ヾ(ヾ(*´▽`)ツ", - ), - "created_at": String( - "2016-01-03T21:26:32Z", - ), - "id": Number( - 77192, - ), - "post_id": Number( - 9993, - ), - "user_id": Number( - 112, - ), - }), - "user": Object({ - "account_name": String( - "rosa", - ), - "authority": Number( - 0, - ), - "created_at": String( - "2016-01-01T00:01:52Z", - ), - "del_flg": Number( - 0, - ), - "id": Number( - 112, - ), - "passhash": String( - "7ee7581f856795775c4f864ac6bbc1d687b6035f0560d3436a1d0e0138b07a6b9033f899a690c8ce3d46547a18a7a611ba80557a67f71ae50b48159b9f873dd8", - ), - }), - }), - ]), - "csrf_token": String( - "", - ), - "post": Object({ - "body": String( - "サイナラ ~~~ヽ(`◇´;))))))) サササッ", - ), - "created_at": String( - "2016-01-02T02:46:33Z", - ), - "id": Number( - 9993, - ), - "imgdata": Array([ - Number( - 0, - ), - ]), - "mime": String( - "image/jpeg", - ), - "user_id": Number( - 945, - ), - }), - "user": Object({ - "account_name": String( - "dionne", - ), - "authority": Number( - 0, - ), - "created_at": String( - "2016-01-01T00:15:45Z", - ), - "del_flg": Number( - 0, - ), - "id": Number( - 945, - ), - "passhash": String( - "82c74b3684dfb07d905d62b0a809c746a9aeadbab292da1029ab6eb1e4614a1fe5e54d7ab7dba51bbb2d7a55512fd160c1ab4b747736f66c6e107b9b5f1b6ac2", - ), - }), - }), - Object({ - "comment_count": Number( - 12, - ), - "comments": Array([ - Object({ - "comment": Object({ - "comment": String( - "オメテ\u{ff9e}タ フフ\u{ff9e}キ ヒュゥゥウウ (*`◇)<氷氷氷氷≧∇≦) ヒヤッ!", - ), - "created_at": String( - "2016-01-03T23:28:25Z", - ), - "id": Number( - 84505, - ), - "post_id": Number( - 9991, - ), - "user_id": Number( - 487, - ), - }), - "user": Object({ - "account_name": String( - "shari", - ), - "authority": Number( - 0, - ), - "created_at": String( - "2016-01-01T00:08:07Z", - ), - "del_flg": Number( - 0, - ), - "id": Number( - 487, - ), - "passhash": String( - "cf098b2f40b21dd2ee05a5f25daa0b16e8c82724dd17853b656882106224b1f04d7623f8fe97e6ff029f74d0a08631eeefaec00f45df63b42e87cfff3fb63414", - ), - }), - }), - Object({ - "comment": Object({ - "comment": String( - "(*^^)/。・:*:・\u{ff9f}'★,。・:*:・\u{ff9f}'☆ Congratulations!!", - ), - "created_at": String( - "2016-01-04T01:28:59Z", - ), - "id": Number( - 91739, - ), - "post_id": Number( - 9991, - ), - "user_id": Number( - 598, - ), - }), - "user": Object({ - "account_name": String( - "rosario", - ), - "authority": Number( - 0, - ), - "created_at": String( - "2016-01-01T00:09:58Z", - ), - "del_flg": Number( - 0, - ), - "id": Number( - 598, - ), - "passhash": String( - "e345b3902bd221e11d7622c41df8dd21b629d77678fd353087b4756a1594ed94d349952d641a73ae84045cbd0775b4b83f148a0b17dda4d2d6a857904ad3bd07", - ), - }), - }), - Object({ - "comment": Object({ - "comment": String( - "ヾ(*'0'*)マ!!ヾ(*'O'*)タ!!ヾ(*'。'*)ネ!!", - ), - "created_at": String( - "2016-01-04T02:37:20Z", - ), - "id": Number( - 95840, - ), - "post_id": Number( - 9991, - ), - "user_id": Number( - 896, - ), - }), - "user": Object({ - "account_name": String( - "juliette", - ), - "authority": Number( - 0, - ), - "created_at": String( - "2016-01-01T00:14:56Z", - ), - "del_flg": Number( - 0, - ), - "id": Number( - 896, - ), - "passhash": String( - "4b7c5cc835698153a2a0899b1bfbfe228bad5730d19a80ef44e0429f6f9855c7facd14a812aa011876912baa1979025e10734c18f7cbb4d6208b97376494b7a7", - ), - }), - }), - ]), - "csrf_token": String( - "", - ), - "post": Object({ - "body": String( - "(*^o^*)サ(*^_^*)ヨ(*^O^*)ウ(*^_^*)ナ(*^O^*)ラ", - ), - "created_at": String( - "2016-01-02T02:46:31Z", - ), - "id": Number( - 9991, - ), - "imgdata": Array([ - Number( - 0, - ), - ]), - "mime": String( - "image/jpeg", - ), - "user_id": Number( - 618, - ), - }), - "user": Object({ - "account_name": String( - "daphne", - ), - "authority": Number( - 0, - ), - "created_at": String( - "2016-01-01T00:10:18Z", - ), - "del_flg": Number( - 0, - ), - "id": Number( - 618, - ), - "passhash": String( - "96449c36fd8d993f5c5df6d47cb7791fef9ea4332f5c9238228bef5c4925fc5938ca724ceac63a65e26bd790ad0dbc91159ebba2004ee7c83427fb14ec2a9530", - ), - }), - }), - Object({ - "comment_count": Number( - 11, - ), - "comments": Array([ - Object({ - "comment": Object({ - "comment": String( - "♪(*・д・)ノ●-●ぶらじゃぁフリフリばいばい~!", - ), - "created_at": String( - "2016-01-03T19:07:31Z", - ), - "id": Number( - 68851, - ), - "post_id": Number( - 9990, - ), - "user_id": Number( - 117, - ), - }), - "user": Object({ - "account_name": String( - "edith", - ), - "authority": Number( - 0, - ), - "created_at": String( - "2016-01-01T00:01:57Z", - ), - "del_flg": Number( - 0, - ), - "id": Number( - 117, - ), - "passhash": String( - "839f5986980bcf627420f1b8ab32d8236d8fd1d9975520e80b0cb24397f61ea90cef9c6d1ecf433a85cce478f9a1bcd3250844f684f02a258d877afc43b752c4", - ), - }), - }), - Object({ - "comment": Object({ - "comment": String( - "(TωT)ノ~~~ ハ\u{ff9e}イハ\u{ff9e}イ", - ), - "created_at": String( - "2016-01-03T20:49:21Z", - ), - "id": Number( - 74961, - ), - "post_id": Number( - 9990, - ), - "user_id": Number( - 342, - ), - }), - "user": Object({ - "account_name": String( - "kristine", - ), - "authority": Number( - 0, - ), - "created_at": String( - "2016-01-01T00:05:42Z", - ), - "del_flg": Number( - 0, - ), - "id": Number( - 342, - ), - "passhash": String( - "8986e52c35f185c4beebb28febe9d6b2430d65e728578db29d33125ef46f90fa9887c4c3d8589b1299a2f80111e4256fceb87791d96ee2e28f169a45ff4780e5", - ), - }), - }), - Object({ - "comment": Object({ - "comment": String( - "オメテ\u{ff9e}トーσ(⌒▽⌒)丿ワタシカ\u{ff9e}フリマシタ", - ), - "created_at": String( - "2016-01-04T03:41:42Z", - ), - "id": Number( - 99702, - ), - "post_id": Number( - 9990, - ), - "user_id": Number( - 442, - ), - }), - "user": Object({ - "account_name": String( - "eloise", - ), - "authority": Number( - 0, - ), - "created_at": String( - "2016-01-01T00:07:22Z", - ), - "del_flg": Number( - 0, - ), - "id": Number( - 442, - ), - "passhash": String( - "601fef1964b57f5a29b9d80ef39ed05cc18db76cee62d1fcc015b99e0641223e3d3cf32e0837bf5288d7ad34f63e28f4fdde3530cb7fd620b00029e4447dfa38", - ), - }), - }), - ]), - "csrf_token": String( - "", - ), - "post": Object({ - "body": String( - "(/*^^)/ハッロ-!!", - ), - "created_at": String( - "2016-01-02T02:46:30Z", - ), - "id": Number( - 9990, - ), - "imgdata": Array([ - Number( - 0, - ), - ]), - "mime": String( - "image/jpeg", - ), - "user_id": Number( - 304, - ), - }), - "user": Object({ - "account_name": String( - "guadalupe", - ), - "authority": Number( - 0, - ), - "created_at": String( - "2016-01-01T00:05:04Z", - ), - "del_flg": Number( - 0, - ), - "id": Number( - 304, - ), - "passhash": String( - "9609c5a3ff5ed3f8bc18b3779df3d483fcccf797e838fb298c69c2b796b040ce1213dd591a5aef373dd0086105113f8f5fa3f73fc1a28db3b860b07da38e3b42", - ), - }), - }), - Object({ - "comment_count": Number( - 5, - ), - "comments": Array([ - Object({ - "comment": Object({ - "comment": String( - "ε=(ノ\u{ff9f}▽\u{ff9f})ノスチャッ!タタ\u{ff9e}イマァ♪o(\u{ff9f}▽\u{ff9f})/", - ), - "created_at": String( - "2016-01-03T08:55:45Z", - ), - "id": Number( - 32145, - ), - "post_id": Number( - 9989, - ), - "user_id": Number( - 471, - ), - }), - "user": Object({ - "account_name": String( - "darla", - ), - "authority": Number( - 0, - ), - "created_at": String( - "2016-01-01T00:07:51Z", - ), - "del_flg": Number( - 0, - ), - "id": Number( - 471, - ), - "passhash": String( - "79b8d119bd95f996d395ee0e697361e33c1f54dabcceab631f848f4d254ba003d8e4298fd131642d9da3eaf112db295295b273b7f6f8e28cdb2dfa3177e35652", - ), - }), - }), - Object({ - "comment": Object({ - "comment": String( - "(〃⌒ー⌒)/どもっ♪", - ), - "created_at": String( - "2016-01-03T18:18:46Z", - ), - "id": Number( - 65926, - ), - "post_id": Number( - 9989, - ), - "user_id": Number( - 82, - ), - }), - "user": Object({ - "account_name": String( - "kathryn", - ), - "authority": Number( - 0, - ), - "created_at": String( - "2016-01-01T00:01:22Z", - ), - "del_flg": Number( - 0, - ), - "id": Number( - 82, - ), - "passhash": String( - "8df659a3a3cfe84099001300efa54ad95dc3f43a50a609a372e98c66f5a3457da8c715134744c33cec60435b7e626da5442a9e2482f635ee0c2d4d3c2948382c", - ), - }), - }), - Object({ - "comment": Object({ - "comment": String( - "( o ̄▽)o<※*:'\u{ff9f}。.お*:\u{ff9f}・め'\u{ff9f}\u{ff9f}:。で'・:+と\"。*・う':\u{ff9f}:*♪:'\u{ff9f}`。+:", - ), - "created_at": String( - "2016-01-04T03:04:36Z", - ), - "id": Number( - 97476, - ), - "post_id": Number( - 9989, - ), - "user_id": Number( - 979, - ), - }), - "user": Object({ - "account_name": String( - "alba", - ), - "authority": Number( - 0, - ), - "created_at": String( - "2016-01-01T00:16:19Z", - ), - "del_flg": Number( - 0, - ), - "id": Number( - 979, - ), - "passhash": String( - "474859ce5a6cef19066177e2d8562e17e2f9d9c138442e843f01cfb4e75b7fb7bbff5a5522b65e6a61805a0a5d82575d6f13b4f7da854aaf3fdfc151b7955be0", - ), - }), - }), - ]), - "csrf_token": String( - "", - ), - "post": Object({ - "body": String( - "川・ム・川ノハロー", - ), - "created_at": String( - "2016-01-02T02:46:29Z", - ), - "id": Number( - 9989, - ), - "imgdata": Array([ - Number( - 0, - ), - ]), - "mime": String( - "image/jpeg", - ), - "user_id": Number( - 775, - ), - }), - "user": Object({ - "account_name": String( - "allyson", - ), - "authority": Number( - 0, - ), - "created_at": String( - "2016-01-01T00:12:55Z", - ), - "del_flg": Number( - 0, - ), - "id": Number( - 775, - ), - "passhash": String( - "06f5d04dd7fef5f9d4f7ffd8190348bf57f3711ae5a325763faf3412502183dd6e44e2c47181d80ab2ba3d83d2ba5d726bdfa92bae20606717e93c0d608c6b3d", - ), - }), - }), - Object({ - "comment_count": Number( - 18, - ), - "comments": Array([ - Object({ - "comment": Object({ - "comment": String( - "( v^-\u{ff9f})Thanks♪", - ), - "created_at": String( - "2016-01-03T22:44:23Z", - ), - "id": Number( - 81863, - ), - "post_id": Number( - 9988, - ), - "user_id": Number( - 652, - ), - }), - "user": Object({ - "account_name": String( - "lily", - ), - "authority": Number( - 0, - ), - "created_at": String( - "2016-01-01T00:10:52Z", - ), - "del_flg": Number( - 0, - ), - "id": Number( - 652, - ), - "passhash": String( - "993705a18e45634cdf7f7d4eb82caa3c5eb7e3aa3ec129ecf01f74a51885330f1fa5811c0312e41cd35348a4eecf733ab11911186a1b84363e6bd65ac7b0bfaa", - ), - }), - }), - Object({ - "comment": Object({ - "comment": String( - "ヤァ \(⌒∇⌒(⌒∇⌒(⌒∇⌒)⌒∇⌒)⌒∇⌒)/ヤァ", - ), - "created_at": String( - "2016-01-04T01:17:33Z", - ), - "id": Number( - 91053, - ), - "post_id": Number( - 9988, - ), - "user_id": Number( - 701, - ), - }), - "user": Object({ - "account_name": String( - "luisa", - ), - "authority": Number( - 0, - ), - "created_at": String( - "2016-01-01T00:11:41Z", - ), - "del_flg": Number( - 0, - ), - "id": Number( - 701, - ), - "passhash": String( - "e2703c39d3a2a05a5c9dbdfa465ce48047d1ecc4a62075f8d228a325f655e234a7ce421c32c4c3783b6e8b822eb7c6bb0bfd6210b08b47da51edb5fb7a14d332", - ), - }), - }), - Object({ - "comment": Object({ - "comment": String( - "┃竹林┃_●)ノ゛\u{3000}ササっとさいなら~", - ), - "created_at": String( - "2016-01-04T02:46:35Z", - ), - "id": Number( - 96395, - ), - "post_id": Number( - 9988, - ), - "user_id": Number( - 961, - ), - }), - "user": Object({ - "account_name": String( - "marquita", - ), - "authority": Number( - 0, - ), - "created_at": String( - "2016-01-01T00:16:01Z", - ), - "del_flg": Number( - 0, - ), - "id": Number( - 961, - ), - "passhash": String( - "e14bb8174a2f0ee2561cba2508af50edc169f109953a3975e43521f6c7ef78bd8091e776f60908ca6541fcf3f89f56c0329b6e4f6c2c4e13318357146eb9db8b", - ), - }), - }), - ]), - "csrf_token": String( - "", - ), - "post": Object({ - "body": String( - "オイッス!!\(∇´) (`▽)/ケ\u{ff9e}ンキカ\u{ff9e}ナイソ\u{ff9e}-オイッス!!", - ), - "created_at": String( - "2016-01-02T02:46:28Z", - ), - "id": Number( - 9988, - ), - "imgdata": Array([ - Number( - 0, - ), - ]), - "mime": String( - "image/jpeg", - ), - "user_id": Number( - 878, - ), - }), - "user": Object({ - "account_name": String( - "deirdre", - ), - "authority": Number( - 0, - ), - "created_at": String( - "2016-01-01T00:14:38Z", - ), - "del_flg": Number( - 0, - ), - "id": Number( - 878, - ), - "passhash": String( - "d03a59272f2c76a6521a7d6056ed8d6bf4588e9417940b0b74cbe847947b0ce633e6ac98c4ae46b34bc85046c60ef65f10d701d7cbfb85d209c08f1e08895b81", - ), - }), - }), - Object({ - "comment_count": Number( - 8, - ), - "comments": Array([ - Object({ - "comment": Object({ - "comment": String( - "ヽ( ̄(エ) ̄)ノ イラッシャーイ♪ o(_^_)oヘ\u{ff9f}コッ", - ), - "created_at": String( - "2016-01-03T21:49:58Z", - ), - "id": Number( - 78598, - ), - "post_id": Number( - 9987, - ), - "user_id": Number( - 409, - ), - }), - "user": Object({ - "account_name": String( - "ernestine", - ), - "authority": Number( - 0, - ), - "created_at": String( - "2016-01-01T00:06:49Z", - ), - "del_flg": Number( - 0, - ), - "id": Number( - 409, - ), - "passhash": String( - "f841a590b28f9a3f655a45e40548128acd4e7c38e9c7f6d9bef158ab919420d96fe64e0bf33ca19b0339bf1964f10d27ff366ef933136c868e6458e8150030a9", - ), - }), - }), - Object({ - "comment": Object({ - "comment": String( - "オメットクシャミ!!(;\u{ff9f}Д\u{ff9f})ハッ!(\u{ff9f}口\u{ff9f};)ハッ!\u{3000}( >з<)=3 ハーーークシュン!!", - ), - "created_at": String( - "2016-01-03T22:25:58Z", - ), - "id": Number( - 80758, - ), - "post_id": Number( - 9987, - ), - "user_id": Number( - 714, - ), - }), - "user": Object({ - "account_name": String( - "virgie", - ), - "authority": Number( - 0, - ), - "created_at": String( - "2016-01-01T00:11:54Z", - ), - "del_flg": Number( - 0, - ), - "id": Number( - 714, - ), - "passhash": String( - "da34a3ef651f6a7711608f156697eccd66f4a86edae0be8dbfe05b7e82a1344b0d038ae023d9d2226f0c11c76507b6cec09baa6f958e2f2c566b81892a455d0e", - ), - }), - }), - Object({ - "comment": Object({ - "comment": String( - "オメテ\u{ff9e}トコーラス( \u{ff9f}o\u{ff9f})(\u{ff9f}o\u{ff9f})(\u{ff9f}o\u{ff9f} )どぅわ~♪", - ), - "created_at": String( - "2016-01-03T22:46:06Z", - ), - "id": Number( - 81966, - ), - "post_id": Number( - 9987, - ), - "user_id": Number( - 8, - ), - }), - "user": Object({ - "account_name": String( - "susan", - ), - "authority": Number( - 1, - ), - "created_at": String( - "2016-01-01T00:00:08Z", - ), - "del_flg": Number( - 0, - ), - "id": Number( - 8, - ), - "passhash": String( - "2a4a4d042136a6649e81a3a30b3d33e4b8c8958cf9071c3d8ea4e264e732296c89a7123eec7d1766260a7c589ce8b2ebe8190d11158add69b32cadfa45fca81a", - ), - }), - }), - ]), - "csrf_token": String( - "", - ), - "post": Object({ - "body": String( - "( ⌒o⌒)人(⌒-⌒ )v オヒサオヒサ", - ), - "created_at": String( - "2016-01-02T02:46:27Z", - ), - "id": Number( - 9987, - ), - "imgdata": Array([ - Number( - 0, - ), - ]), - "mime": String( - "image/jpeg", - ), - "user_id": Number( - 161, - ), - }), - "user": Object({ - "account_name": String( - "geraldine", - ), - "authority": Number( - 0, - ), - "created_at": String( - "2016-01-01T00:02:41Z", - ), - "del_flg": Number( - 0, - ), - "id": Number( - 161, - ), - "passhash": String( - "73ffff85ffbb8328a70ba6287e5889ad8e7cf6d0eb75aa69c1685d87826878982d6f8cb903a33429e98bc02e2184aacf412d64644e5a5afe5101bf2de66f4bd0", - ), - }), - }), - Object({ - "comment_count": Number( - 10, - ), - "comments": Array([ - Object({ - "comment": Object({ - "comment": String( - "ドゥモ.ドゥモ♪\( ̄ー ̄|電柱| ̄ー ̄)/ヨロシク♪", - ), - "created_at": String( - "2016-01-03T21:59:08Z", - ), - "id": Number( - 79148, - ), - "post_id": Number( - 9986, - ), - "user_id": Number( - 575, - ), - }), - "user": Object({ - "account_name": String( - "candy", - ), - "authority": Number( - 0, - ), - "created_at": String( - "2016-01-01T00:09:35Z", - ), - "del_flg": Number( - 0, - ), - "id": Number( - 575, - ), - "passhash": String( - "5be95e6e28a5ea9384dacf4de4645655f6196e3e128240d647168b4282b94fe232b2edbbbe67ebb73f583a7773e7d0a20e598607ccfebcab380790f0c437e52c", - ), - }), - }), - Object({ - "comment": Object({ - "comment": String( - "アリカ\u{ff9e}ト♪(*\u{ff9f} 3\u{ff9f})/~チュッ♪", - ), - "created_at": String( - "2016-01-04T02:18:06Z", - ), - "id": Number( - 94686, - ), - "post_id": Number( - 9986, - ), - "user_id": Number( - 86, - ), - }), - "user": Object({ - "account_name": String( - "jacqueline", - ), - "authority": Number( - 0, - ), - "created_at": String( - "2016-01-01T00:01:26Z", - ), - "del_flg": Number( - 0, - ), - "id": Number( - 86, - ), - "passhash": String( - "d39030b34ac20f31893665b98ba6a5e600267a57040777fb954c99f59602adff9f621d2701126809412fa1419c57d8118621a0650638d79f6336f69c1332fa69", - ), - }), - }), - Object({ - "comment": Object({ - "comment": String( - "才×〒\"├♪(⌒▽⌒) ノ☆・゜:*:゜", - ), - "created_at": String( - "2016-01-04T03:23:36Z", - ), - "id": Number( - 98616, - ), - "post_id": Number( - 9986, - ), - "user_id": Number( - 386, - ), - }), - "user": Object({ - "account_name": String( - "leticia", - ), - "authority": Number( - 0, - ), - "created_at": String( - "2016-01-01T00:06:26Z", - ), - "del_flg": Number( - 0, - ), - "id": Number( - 386, - ), - "passhash": String( - "33c0f1846272ae607ccb55c787a537fa4e6d778b6b9f380c38bd5d99734ce23c0eb37707a0a147cc8bcc2582c440afe403453e639a4ecdd857b4ef75759178d8", - ), - }), - }), - ]), - "csrf_token": String( - "", - ), - "post": Object({ - "body": String( - "オメットナケ\u{ff9e}キッスー♪(*^ω^)/チュッ♪ フヨフヨ~~コツン\u{ff9e}☆(。・_・。)ホ\u{ff9f}ッ", - ), - "created_at": String( - "2016-01-02T02:46:26Z", - ), - "id": Number( - 9986, - ), - "imgdata": Array([ - Number( - 0, - ), - ]), - "mime": String( - "image/jpeg", - ), - "user_id": Number( - 963, - ), - }), - "user": Object({ - "account_name": String( - "tisha", - ), - "authority": Number( - 0, - ), - "created_at": String( - "2016-01-01T00:16:03Z", - ), - "del_flg": Number( - 0, - ), - "id": Number( - 963, - ), - "passhash": String( - "ff9d8e340391af03ef532306d8c766738fe54fbbcf8a80059fdb7974a9213737c786242d2bd002a184afa1ef8cab20e80a314a4484c8c0c9ac8a4e74a17120e5", - ), - }), - }), - Object({ - "comment_count": Number( - 10, - ), - "comments": Array([ - Object({ - "comment": Object({ - "comment": String( - "ちわ~v( ̄∇ ̄)v", - ), - "created_at": String( - "2016-01-03T22:42:37Z", - ), - "id": Number( - 81757, - ), - "post_id": Number( - 9985, - ), - "user_id": Number( - 727, - ), - }), - "user": Object({ - "account_name": String( - "ila", - ), - "authority": Number( - 0, - ), - "created_at": String( - "2016-01-01T00:12:07Z", - ), - "del_flg": Number( - 0, - ), - "id": Number( - 727, - ), - "passhash": String( - "76ada11ad4275ec147859e5643e823d9f0f760fdacc2d5b2a3e76456f161a9401ddc819cad75e3809a1ebc650bb6b68ce23afa83b868178f620586bdc8d74f78", - ), - }), - }), - Object({ - "comment": Object({ - "comment": String( - "\_(^◇^)_/\(*^^*)/ 優勝オメデトウ!", - ), - "created_at": String( - "2016-01-03T23:27:04Z", - ), - "id": Number( - 84424, - ), - "post_id": Number( - 9985, - ), - "user_id": Number( - 631, - ), - }), - "user": Object({ - "account_name": String( - "lizzie", - ), - "authority": Number( - 0, - ), - "created_at": String( - "2016-01-01T00:10:31Z", - ), - "del_flg": Number( - 0, - ), - "id": Number( - 631, - ), - "passhash": String( - "7dddbfdfb0cc5c27689f6ec41ab84f97c7274b1a1f1576e4cb53a8084b6506329ac77bc3e967a6ecb7990e2761b5744eea3ff3b17da83783e54f92612cf5e813", - ), - }), - }), - Object({ - "comment": Object({ - "comment": String( - "(o^o^o)あ(o^-^o)り(o^o^o) が(o^O^o)と(o^.^o)う", - ), - "created_at": String( - "2016-01-04T01:01:26Z", - ), - "id": Number( - 90086, - ), - "post_id": Number( - 9985, - ), - "user_id": Number( - 750, - ), - }), - "user": Object({ - "account_name": String( - "sharron", - ), - "authority": Number( - 0, - ), - "created_at": String( - "2016-01-01T00:12:30Z", - ), - "del_flg": Number( - 1, - ), - "id": Number( - 750, - ), - "passhash": String( - "b89ab2450ed6ee59060fefb6ed2042b540f752b47c821f7838cbea41f795809baf01686752064233022ab4eb86cd3042b486dffb7be9fc05387cdb16f066a657", - ), - }), - }), - ]), - "csrf_token": String( - "", - ), - "post": Object({ - "body": String( - "♪(・_・)ノ●-●フ\u{ff9e}ラシ\u{ff9e}ャーフリフリハ\u{ff9e}イハ\u{ff9e}イ", - ), - "created_at": String( - "2016-01-02T02:46:25Z", - ), - "id": Number( - 9985, - ), - "imgdata": Array([ - Number( - 0, - ), - ]), - "mime": String( - "image/jpeg", - ), - "user_id": Number( - 649, - ), - }), - "user": Object({ - "account_name": String( - "sheena", - ), - "authority": Number( - 0, - ), - "created_at": String( - "2016-01-01T00:10:49Z", - ), - "del_flg": Number( - 0, - ), - "id": Number( - 649, - ), - "passhash": String( - "8c0e219fe69617a1056be63e0d05285f82b1ffbf74abca033e00e90d3c46503cf04a872106598dbee97c607ed31e0e096d0f1c2c61c1b06a23c539409926c777", - ), - }), - }), - Object({ - "comment_count": Number( - 6, - ), - "comments": Array([ - Object({ - "comment": Object({ - "comment": String( - "オ┤* ̄O ̄*├ヤ┤*-.-*├ス┤_ _├ミ", - ), - "created_at": String( - "2016-01-03T15:19:32Z", - ), - "id": Number( - 55172, - ), - "post_id": Number( - 9983, - ), - "user_id": Number( - 859, - ), - }), - "user": Object({ - "account_name": String( - "valeria", - ), - "authority": Number( - 0, - ), - "created_at": String( - "2016-01-01T00:14:19Z", - ), - "del_flg": Number( - 0, - ), - "id": Number( - 859, - ), - "passhash": String( - "daf03cf9fe3b680cb1dce3cd5da39e72932b91af5f57d035bda67fb300815504cfbe8f93cd4503ea8b431e2c031d5add6a6c4e575a53f2a77bf163f7c4562b90", - ), - }), - }), - Object({ - "comment": Object({ - "comment": String( - "バイバイッ♪ヾ(*'ー')*'ー')*'ー')/\"", - ), - "created_at": String( - "2016-01-03T18:58:19Z", - ), - "id": Number( - 68299, - ), - "post_id": Number( - 9983, - ), - "user_id": Number( - 362, - ), - }), - "user": Object({ - "account_name": String( - "candice", - ), - "authority": Number( - 0, - ), - "created_at": String( - "2016-01-01T00:06:02Z", - ), - "del_flg": Number( - 0, - ), - "id": Number( - 362, - ), - "passhash": String( - "706acbeef752cb39360f0f02c39aed28e371301041c21b36cb40f3d4745aaa83cb065272515fa6eb2885a0b90dfaa684e12c153401be39ab1aaecb4c7fd74403", - ), - }), - }), - Object({ - "comment": Object({ - "comment": String( - "(\u{3000})/!-ろは\u{3000}んっ( ^)\u{3000}こっちだ!(^-^)/はろ-!!", - ), - "created_at": String( - "2016-01-03T19:01:36Z", - ), - "id": Number( - 68496, - ), - "post_id": Number( - 9983, - ), - "user_id": Number( - 697, - ), - }), - "user": Object({ - "account_name": String( - "ivy", - ), - "authority": Number( - 0, - ), - "created_at": String( - "2016-01-01T00:11:37Z", - ), - "del_flg": Number( - 0, - ), - "id": Number( - 697, - ), - "passhash": String( - "d5104c98abc4de58849b9e625e2959c74a0586ba45fc3fa1e64623992416341327cb3aaa2858dc53c31dbfa600736953df0001953011a571cdd5ffc77d656860", - ), - }), - }), - ]), - "csrf_token": String( - "", - ), - "post": Object({ - "body": String( - "/_・)/_・)/_・)/_・)/_・)/_・)/_・)/_・) ティース", - ), - "created_at": String( - "2016-01-02T02:46:23Z", - ), - "id": Number( - 9983, - ), - "imgdata": Array([ - Number( - 0, - ), - ]), - "mime": String( - "image/jpeg", - ), - "user_id": Number( - 92, - ), - }), - "user": Object({ - "account_name": String( - "tina", - ), - "authority": Number( - 0, - ), - "created_at": String( - "2016-01-01T00:01:32Z", - ), - "del_flg": Number( - 0, - ), - "id": Number( - 92, - ), - "passhash": String( - "6d8598894bb156a7086f0d0d8eed2cc74529ec8fa4dc73f9b6e318dc06dec913fa0570fc6b21a89893605a71d8746c3b030d272a8889eb5712295fb1c1c3e444", - ), - }), - }), - Object({ - "comment_count": Number( - 6, - ), - "comments": Array([ - Object({ - "comment": Object({ - "comment": String( - "マッタニャーーーン(*^ー^*)・ ・‥…・・・★", - ), - "created_at": String( - "2016-01-03T17:45:44Z", - ), - "id": Number( - 63944, - ), - "post_id": Number( - 9982, - ), - "user_id": Number( - 736, - ), - }), - "user": Object({ - "account_name": String( - "estela", - ), - "authority": Number( - 0, - ), - "created_at": String( - "2016-01-01T00:12:16Z", - ), - "del_flg": Number( - 0, - ), - "id": Number( - 736, - ), - "passhash": String( - "62b864fba47d93bec9f593c1e150c99e25e5982d8bd68ec21df94459f10efff8a9f4af55a55babc6e0945364078c8eafd6c8d29a6f3c0fc507278667848820a5", - ), - }), - }), - Object({ - "comment": Object({ - "comment": String( - "ヾ(^-^;) コ\u{ff9e}メンコ\u{ff9e}メン", - ), - "created_at": String( - "2016-01-04T01:28:09Z", - ), - "id": Number( - 91689, - ), - "post_id": Number( - 9982, - ), - "user_id": Number( - 355, - ), - }), - "user": Object({ - "account_name": String( - "kristy", - ), - "authority": Number( - 0, - ), - "created_at": String( - "2016-01-01T00:05:55Z", - ), - "del_flg": Number( - 0, - ), - "id": Number( - 355, - ), - "passhash": String( - "92fb5a77a360379f6138e52f60b0e45fb7bdb745ec9906b7c11088a308bdd9e0901eebfbcd24c98fe1d4791fc1249035eba6159582de50b9fd2495b51670aaed", - ), - }), - }), - Object({ - "comment": Object({ - "comment": String( - "( ̄(オ) ̄)( ̄(メ) ̄)( ̄(デ) ̄)( ̄(ト) ̄)", - ), - "created_at": String( - "2016-01-04T03:42:13Z", - ), - "id": Number( - 99733, - ), - "post_id": Number( - 9982, - ), - "user_id": Number( - 311, - ), - }), - "user": Object({ - "account_name": String( - "natasha", - ), - "authority": Number( - 0, - ), - "created_at": String( - "2016-01-01T00:05:11Z", - ), - "del_flg": Number( - 0, - ), - "id": Number( - 311, - ), - "passhash": String( - "60e4879430b98d6790aed5bb86dd9d31c27180902a678fef861a1f8e6b4fa1de96984e9984d51c64e7c815a68f9d70b0a68e6e96b3ad5f0d6accce9126233dfc", - ), - }), - }), - ]), - "csrf_token": String( - "", - ), - "post": Object({ - "body": String( - "オメテ\u{ff9e}タファイヤー (*`□)<炎炎炎炎フ\u{ff9e}オォォオ*_*)/", - ), - "created_at": String( - "2016-01-02T02:46:22Z", - ), - "id": Number( - 9982, - ), - "imgdata": Array([ - Number( - 0, - ), - ]), - "mime": String( - "image/jpeg", - ), - "user_id": Number( - 544, - ), - }), - "user": Object({ - "account_name": String( - "tracie", - ), - "authority": Number( - 0, - ), - "created_at": String( - "2016-01-01T00:09:04Z", - ), - "del_flg": Number( - 0, - ), - "id": Number( - 544, - ), - "passhash": String( - "7f6c1c5044394f6ab5e5b50b11d4eaec839a75256e5d9b9ce8f00182c31c0ddb27054a0d09968b98570e9d4964c319c58b1df45fff2974e48a293bcaf1075fa6", - ), - }), - }), - Object({ - "comment_count": Number( - 13, - ), - "comments": Array([ - Object({ - "comment": Object({ - "comment": String( - "シ\u{ff9e}ャマスルヨ! ノ(・_・ヾ\", - ), - "created_at": String( - "2016-01-03T18:38:16Z", - ), - "id": Number( - 67096, - ), - "post_id": Number( - 9981, - ), - "user_id": Number( - 922, - ), - }), - "user": Object({ - "account_name": String( - "cherry", - ), - "authority": Number( - 0, - ), - "created_at": String( - "2016-01-01T00:15:22Z", - ), - "del_flg": Number( - 0, - ), - "id": Number( - 922, - ), - "passhash": String( - "2a03d833691146ee4772d48b7055432e6d69d726417b60b7fbd3ecc78363ff685c3b386f0e877b2e5fbeb97c5de320a0d5f29c69189123ec55ef4c950dc70007", - ), - }), - }), - Object({ - "comment": Object({ - "comment": String( - "(b*^0)d (ノ*^▽)ノ\u{3000}オッハー♪", - ), - "created_at": String( - "2016-01-03T20:06:06Z", - ), - "id": Number( - 72366, - ), - "post_id": Number( - 9981, - ), - "user_id": Number( - 14, - ), - }), - "user": Object({ - "account_name": String( - "betty", - ), - "authority": Number( - 0, - ), - "created_at": String( - "2016-01-01T00:00:14Z", - ), - "del_flg": Number( - 0, - ), - "id": Number( - 14, - ), - "passhash": String( - "1365fa1ad96358ac89069b4460865120bd19e5874be2b6f5972e4ba8adb61a4e56a68f48bc9354cefe1bc93aeae5afd656652e82da8faef31b1090468f3ec28b", - ), - }), - }), - Object({ - "comment": Object({ - "comment": String( - "ハイ、ヒソイリオメットチャ( ^-)_旦~~ (\u{ff9f}o\u{ff9f};)シヌシ\u{ff9e}ャン\u{ff9e}", - ), - "created_at": String( - "2016-01-03T22:45:37Z", - ), - "id": Number( - 81937, - ), - "post_id": Number( - 9981, - ), - "user_id": Number( - 314, - ), - }), - "user": Object({ - "account_name": String( - "marguerite", - ), - "authority": Number( - 0, - ), - "created_at": String( - "2016-01-01T00:05:14Z", - ), - "del_flg": Number( - 0, - ), - "id": Number( - 314, - ), - "passhash": String( - "fbb645554c3428c73e76a78e3f33b628e9d9a076ae86306740d606bd887f334f5627a274a05a4eccdb8c2b3062ba29a4f02b82c570774cc7efd08f8663668391", - ), - }), - }), - ]), - "csrf_token": String( - "", - ), - "post": Object({ - "body": String( - "~(=^‥^)ノ☆ おやすみニャ。", - ), - "created_at": String( - "2016-01-02T02:46:21Z", - ), - "id": Number( - 9981, - ), - "imgdata": Array([ - Number( - 0, - ), - ]), - "mime": String( - "image/jpeg", - ), - "user_id": Number( - 740, - ), - }), - "user": Object({ - "account_name": String( - "earline", - ), - "authority": Number( - 0, - ), - "created_at": String( - "2016-01-01T00:12:20Z", - ), - "del_flg": Number( - 0, - ), - "id": Number( - 740, - ), - "passhash": String( - "895aaf49df71bfd0d124f17d7d3e688b6aea4ff43aeb200eedb962ebae03bb67d0549a82348aa7a1d41e6eeadfc3adc1d23f6925cd4ad06bd1214b3460efc8a1", - ), - }), - }), - Object({ - "comment_count": Number( - 7, - ), - "comments": Array([ - Object({ - "comment": Object({ - "comment": String( - "ノー ̄)ノー ̄)ノー ̄)ノおいっす!", - ), - "created_at": String( - "2016-01-03T12:19:27Z", - ), - "id": Number( - 44367, - ), - "post_id": Number( - 9980, - ), - "user_id": Number( - 276, - ), - }), - "user": Object({ - "account_name": String( - "brandy", - ), - "authority": Number( - 0, - ), - "created_at": String( - "2016-01-01T00:04:36Z", - ), - "del_flg": Number( - 0, - ), - "id": Number( - 276, - ), - "passhash": String( - "3deb9bb3574ff147a08a0709ab811796d2dc8165344fa8c6978b9a93db3f2570ff62504a3450277ec0d0a87a32e60090f5f40b4ea53dcc4fb912c36e54b2e6c1", - ), - }), - }), - Object({ - "comment": Object({ - "comment": String( - "サンクスファイヤー( ・_・)r鹵~<火火炎炎炎゛【・ロ・】゛ヤケルヤケルー", - ), - "created_at": String( - "2016-01-03T15:15:48Z", - ), - "id": Number( - 54948, - ), - "post_id": Number( - 9980, - ), - "user_id": Number( - 722, - ), - }), - "user": Object({ - "account_name": String( - "haley", - ), - "authority": Number( - 0, - ), - "created_at": String( - "2016-01-01T00:12:02Z", - ), - "del_flg": Number( - 0, - ), - "id": Number( - 722, - ), - "passhash": String( - "a65c2e673df1697fb35faf81641be0a741cf7f031444d643374debd1ad3fdc2406ba8063728856b28857217e3e2c3f96e3705e339ca9a77a934cb1474055f13d", - ), - }), - }), - Object({ - "comment": Object({ - "comment": String( - "(/\u{ff9f}∇\u{ff9f})/\u{ff9f}∇\u{ff9f})o ティース♪", - ), - "created_at": String( - "2016-01-03T15:50:55Z", - ), - "id": Number( - 57055, - ), - "post_id": Number( - 9980, - ), - "user_id": Number( - 672, - ), - }), - "user": Object({ - "account_name": String( - "dominique", - ), - "authority": Number( - 0, - ), - "created_at": String( - "2016-01-01T00:11:12Z", - ), - "del_flg": Number( - 0, - ), - "id": Number( - 672, - ), - "passhash": String( - "481023fa797deb8cc5af70bdb28a0c04892fb1be01748de2af1ec77483da7736450e6e13146de99ee438294934623bfa5f4f550272c9e5b345c86589456a1579", - ), - }), - }), - ]), - "csrf_token": String( - "", - ), - "post": Object({ - "body": String( - "((((((((((((((((( ̄ー ̄)ノオイ~ッス", - ), - "created_at": String( - "2016-01-02T02:46:20Z", - ), - "id": Number( - 9980, - ), - "imgdata": Array([ - Number( - 0, - ), - ]), - "mime": String( - "image/jpeg", - ), - "user_id": Number( - 37, - ), - }), - "user": Object({ - "account_name": String( - "pamela", - ), - "authority": Number( - 0, - ), - "created_at": String( - "2016-01-01T00:00:37Z", - ), - "del_flg": Number( - 0, - ), - "id": Number( - 37, - ), - "passhash": String( - "60e5137c1867ee69f787e0d4ac63214209f6f8111538d102f6c7ae35c99e597dc05c3f41f150f503ab6b17dc3aa80f26ab4a6576daa7d2e6103c421d70f64f36", - ), - }), - }), - Object({ - "comment_count": Number( - 5, - ), - "comments": Array([ - Object({ - "comment": Object({ - "comment": String( - "オメテ\u{ff9e}チョーク( -.-)ノ・・・-=≡≡≡/((((((((((- チョーク☆ ̄(>。☆", - ), - "created_at": String( - "2016-01-03T23:38:54Z", - ), - "id": Number( - 85134, - ), - "post_id": Number( - 9979, - ), - "user_id": Number( - 566, - ), - }), - "user": Object({ - "account_name": String( - "cassie", - ), - "authority": Number( - 0, - ), - "created_at": String( - "2016-01-01T00:09:26Z", - ), - "del_flg": Number( - 0, - ), - "id": Number( - 566, - ), - "passhash": String( - "a3a858a3cf5972414501734297d3f88e74a20d15180c606b97975b16d3b970909f156494ad9436c810e622cc0b265849d0eb9d7b98ef0c98fa2bc8f6ad500950", - ), - }), - }), - Object({ - "comment": Object({ - "comment": String( - "(=^ー^)ノ彡☆゜・。・゜★ハ\u{ff9e}イハ\u{ff9e}イ", - ), - "created_at": String( - "2016-01-04T01:18:37Z", - ), - "id": Number( - 91117, - ), - "post_id": Number( - 9979, - ), - "user_id": Number( - 383, - ), - }), - "user": Object({ - "account_name": String( - "erma", - ), - "authority": Number( - 0, - ), - "created_at": String( - "2016-01-01T00:06:23Z", - ), - "del_flg": Number( - 0, - ), - "id": Number( - 383, - ), - "passhash": String( - "d82ef4f04eb11da50b32ebe5c01faf40e124d06519a201da1411124cdfd7cffd389db58a05257bd7ba419aa4095102717c30d623a13896a0fd219b55205817a3", - ), - }), - }), - Object({ - "comment": Object({ - "comment": String( - "アリカ\u{ff9e}トタ\u{ff9e}フ\u{ff9e}ルハ\u{ff9f}ンチ!!o( \u{ff9f}o\u{ff9f})=○)\u{ff9f}δ\u{ff9f}(○=(\u{ff9f}o\u{ff9f} )oハ\u{ff9e}キッx2", - ), - "created_at": String( - "2016-01-04T03:14:34Z", - ), - "id": Number( - 98074, - ), - "post_id": Number( - 9979, - ), - "user_id": Number( - 509, - ), - }), - "user": Object({ - "account_name": String( - "bonita", - ), - "authority": Number( - 0, - ), - "created_at": String( - "2016-01-01T00:08:29Z", - ), - "del_flg": Number( - 0, - ), - "id": Number( - 509, - ), - "passhash": String( - "de7aab6d183080949a41d4d72659692e45b7dabd3d221e1bcd26c6e284f3ea1ea0056f5f47709fd1d5e5e0b14ab032ae2cc56bc6d7f14afb566c2ad911c8b436", - ), - }), - }), - ]), - "csrf_token": String( - "", - ), - "post": Object({ - "body": String( - "ヾ(;ω;)Byeヾ(;ω;)Bye", - ), - "created_at": String( - "2016-01-02T02:46:19Z", - ), - "id": Number( - 9979, - ), - "imgdata": Array([ - Number( - 0, - ), - ]), - "mime": String( - "image/jpeg", - ), - "user_id": Number( - 476, - ), - }), - "user": Object({ - "account_name": String( - "lorene", - ), - "authority": Number( - 0, - ), - "created_at": String( - "2016-01-01T00:07:56Z", - ), - "del_flg": Number( - 0, - ), - "id": Number( - 476, - ), - "passhash": String( - "94093914fb98e389374b0e175ff1ee83a3921aae34c96951ef09adc5e91a75a008f23f40ccd4a1ce6a7513abe4e883b07e5bf4524c68024fed01233ad72a72da", - ), - }), - }), - ]), - "posts_parent": String( - "index", - ), - "user": Object({ - "account_name": String( - "", - ), - "authority": Number( - 0, - ), - "created_at": String( - "2022-06-14T18:07:33.858477550Z", - ), - "del_flg": Number( - 0, - ), - "id": Number( - 0, - ), - "passhash": String( - "", - ), - }), -} \ No newline at end of file diff --git a/webapp/rust/src/main.rs b/webapp/rust/src/main.rs index 9ed76b211..32bd49ad3 100644 --- a/webapp/rust/src/main.rs +++ b/webapp/rust/src/main.rs @@ -640,22 +640,84 @@ async fn get_index( map.insert("posts_parent".to_string(), to_json("index")); map.insert("content_parent".to_string(), to_json("layout")); - let mut file = std::fs::File::create("map.json")?; - write!(file, "{:#?}", &map)?; - file.flush().unwrap(); - handlebars.render("post", &map).unwrap() }; - // TODO: after golang 406 line + Ok(HttpResponse::Ok().body(body)) } +#[get("/posts")] async fn get_posts() -> Result { todo!() } -async fn get_posts_id() -> Result { - todo!() +#[get("/posts/{id}")] +async fn get_posts_id( + pid: web::Path<(u64,)>, + session: Session, + pool: Data>, + handlebars: Data>, +) -> Result { + let results = match sqlx::query_as!(Post, "SELECT * FROM `posts` WHERE `id` = ?", pid.0) + .fetch_all(pool.as_ref()) + .await + { + Ok(r) => r, + Err(e) => { + log::error!("{:?}", &e); + return Ok(HttpResponse::InternalServerError().body(e.to_string())); + } + }; + + let posts = match make_post( + results, + get_csrf_token(&session).unwrap_or_default(), + true, + pool.as_ref(), + ) + .await + { + Ok(p) => p, + Err(e) => { + log::error!("{:?}", &e); + return Ok(HttpResponse::InternalServerError().body(e.to_string())); + } + }; + + if posts.is_empty() { + return Ok(HttpResponse::NotFound().finish()); + } + + let p = &posts[0]; + + let me = match get_session_user(&session, pool.as_ref()).await { + Ok(u) => u.unwrap_or_default(), + Err(e) => { + log::error!("{:?}", &e); + return Ok(HttpResponse::InternalServerError().body(e.to_string())); + } + }; + + let body = { + // let mut map = Map::new(); + // let posts = serde_json::to_value(posts).unwrap(); + // let map = json.as_object_mut().unwrap(); + // map.insert("post".to_string(), to_json(p)); + + let mut post = serde_json::to_value(p).unwrap(); + let map = post.as_object_mut().unwrap(); + map.insert("user".to_string(), to_json(me)); + + map.insert("post_parent".to_string(), to_json("post_id")); + map.insert("content_parent".to_string(), to_json("layout")); + + // let mut file = std::fs::File::create(".tmp/get_posts_id.json").unwrap(); + // write!(file, "{:#?}", &map).unwrap(); + + handlebars.render("post", &map).unwrap() + }; + + Ok(HttpResponse::Ok().body(body)) } async fn post_index() -> Result { @@ -822,6 +884,8 @@ async fn main() -> io::Result<()> { .service(post_register) .service(get_logout) .service(get_index) + .service(get_posts) + .service(get_posts_id) .service(get_image) // .service(ResourceDef::new("/{tail}*").) .service(Files::new("/", "../public")) diff --git a/webapp/rust/static/post_id.html b/webapp/rust/static/post_id.html new file mode 100644 index 000000000..d9c0ddf32 --- /dev/null +++ b/webapp/rust/static/post_id.html @@ -0,0 +1,4 @@ +{{#*inline "content"}} +{{> post_html}} +{{/inline}} +{{> (lookup this "content_parent")}} \ No newline at end of file From 6673833664af7ce9fe77e32b8ff5a6cd9c003902 Mon Sep 17 00:00:00 2001 From: Romira915 <40430090+Romira915@users.noreply.github.com> Date: Thu, 16 Jun 2022 00:55:50 +0900 Subject: [PATCH 28/64] features: post_index --- webapp/rust/Cargo.toml | 2 + webapp/rust/src/main.rs | 138 +++++++++++++++++++++++++++++++++++++++- 2 files changed, 137 insertions(+), 3 deletions(-) diff --git a/webapp/rust/Cargo.toml b/webapp/rust/Cargo.toml index 7552aa808..8ae36ee24 100644 --- a/webapp/rust/Cargo.toml +++ b/webapp/rust/Cargo.toml @@ -8,6 +8,7 @@ version = "0.1.0" [dependencies] actix-cors = "0.6.1" actix-files = "0.6.0" +actix-multipart = "0.4.0" actix-redis = "0.10.0" actix-session = "0.5.0" actix-web = "4.0.1" @@ -19,6 +20,7 @@ anyhow = "1.0.57" chrono = {version = "0.4.19", features = ["serde"]} derive_more = "0.99.17" duct = "0.13.5" +futures-util = {version = "0.3.21", default-features = false, features = ["std"]} log = "0.4.17" num_cpus = "1.13.1" once_cell = "1.10.0" diff --git a/webapp/rust/src/main.rs b/webapp/rust/src/main.rs index 32bd49ad3..8409bf8b8 100644 --- a/webapp/rust/src/main.rs +++ b/webapp/rust/src/main.rs @@ -9,6 +9,7 @@ use std::{ use actix_cors::Cors; use actix_files::Files; +use actix_multipart::{Field, Multipart, MultipartError}; use actix_redis::RedisSession; use actix_session::Session; use actix_web::{ @@ -20,13 +21,14 @@ use actix_web::{ Method, StatusCode, }, middleware, post, - web::{self, Data, Form}, + web::{self, Bytes, Data, Form}, App, HttpRequest, HttpResponse, HttpServer, Result, }; use anyhow::{bail, Context}; use chrono::{DateTime, FixedOffset, Local, Utc}; use derive_more::Constructor; use duct::cmd; +use futures_util::TryStreamExt; use handlebars::{handlebars_helper, to_json, Handlebars}; use log::LevelFilter; use once_cell::sync::Lazy; @@ -43,6 +45,7 @@ use simplelog::{ use sqlx::{MySql, Pool}; const POSTS_PER_PAGE: usize = 20; +const UPLOAD_LIMIT: usize = 10 * 1024 * 1024; static AGGREGATION_LOWER_CASE_NUM: Lazy> = Lazy::new(|| { let mut az09 = Vec::new(); for az in 'a' as u32..('z' as u32 + 1) { @@ -118,6 +121,22 @@ struct LoginRegisterParams { password: String, } +#[derive(Debug, Serialize, Deserialize)] +struct IndexParams { + file: Vec, + body: String, + csrf_token: String, +} + +async fn field_to_vec(field: &mut Field) -> anyhow::Result> { + let mut b = Vec::new(); + while let Some(chunk) = field.try_next().await? { + b.append(&mut chunk.to_vec()); + } + + Ok(b) +} + async fn db_initialize(pool: &Pool) -> anyhow::Result<()> { sqlx::query!("DELETE FROM users WHERE id > 1000") .execute(pool) @@ -720,8 +739,120 @@ async fn get_posts_id( Ok(HttpResponse::Ok().body(body)) } -async fn post_index() -> Result { - todo!() +// golang版と処理順が異なる +#[post("/")] +async fn post_index( + session: Session, + pool: Data>, + mut payload: Multipart, +) -> Result { + let me = match get_session_user(&session, pool.as_ref()).await { + Ok(me) => { + if !is_login(me.as_ref()) { + return Ok(HttpResponse::Found() + .insert_header((header::LOCATION, "/login")) + .finish()); + } + me.unwrap_or_default() + } + Err(e) => { + log::error!("{:?}", &e); + return Ok(HttpResponse::InternalServerError().body(e.to_string())); + } + }; + + let mut file = Vec::new(); + let mut mime = String::new(); + let mut body = String::new(); + let mut csrf_token = String::new(); + + while let Some(mut field) = payload.try_next().await? { + log::debug!("{}", field.name()); + log::debug!("{:#?}", field.content_type()); + log::debug!("{:#?}", field.content_disposition()); + log::debug!("{:#?}", field.headers()); + match field.name() { + "file" => { + let content_type = field.content_type().to_string(); + log::debug!("content_type {}", &content_type); + if content_type.starts_with("image/") { + if let "image/jpeg" | "image/png" | "image/gif" = field.content_type().as_ref() + { + log::debug!("This is image"); + mime = content_type; + file = field_to_vec(&mut field).await.unwrap_or_default(); + } else { + if let Err(e) = + session.insert("notice", "投稿できる画像形式はjpgとpngとgifだけです") + { + log::error!("{:?}", &e); + return Ok(HttpResponse::InternalServerError().body(e.to_string())); + } else { + return Ok(HttpResponse::Found() + .insert_header((header::LOCATION, "/")) + .finish()); + } + } + } else { + if let Err(e) = session.insert("notice", "画像が必須です") { + log::error!("{:?}", &e); + return Ok(HttpResponse::InternalServerError().body(e.to_string())); + } else { + return Ok(HttpResponse::Found() + .insert_header((header::LOCATION, "/")) + .finish()); + } + } + } + "body" => { + // 例外処理入れたほうがいい? + let bytes = field_to_vec(&mut field).await.unwrap_or_default(); + body = String::from_utf8(bytes).unwrap_or_default(); + } + "csrf_token" => { + // 例外処理入れたほうがいい? + let bytes = field_to_vec(&mut field).await.unwrap_or_default(); + csrf_token = String::from_utf8(bytes).unwrap_or_default(); + } + _ => log::debug!("other"), + } + } + + if csrf_token != get_csrf_token(&session).unwrap_or_default() { + return Ok(HttpResponse::UnprocessableEntity().finish()); + } + + if file.len() > UPLOAD_LIMIT { + if let Err(e) = session.insert("notice", "ファイルサイズが大きすぎます") { + log::error!("{:?}", &e); + return Ok(HttpResponse::InternalServerError().body(e.to_string())); + } else { + return Ok(HttpResponse::Found() + .insert_header((header::LOCATION, "/")) + .finish()); + } + } + + let pid = match sqlx::query!( + "INSERT INTO `posts` (`user_id`, `mime`, `imgdata`, `body`) VALUES (?,?,?,?)", + me.id, + &mime, + &file, + &body + ) + .execute(pool.as_ref()) + .await + { + Ok(result) => result.last_insert_id(), + Err(e) => { + log::error!("{:?}", &e); + return Ok(HttpResponse::InternalServerError().body(e.to_string())); + } + }; + + Ok(HttpResponse::Found() + .insert_header((header::LOCATION, format!("/posts/{}", pid))) + .finish()) } #[get("/image/{path}")] @@ -886,6 +1017,7 @@ async fn main() -> io::Result<()> { .service(get_index) .service(get_posts) .service(get_posts_id) + .service(post_index) .service(get_image) // .service(ResourceDef::new("/{tail}*").) .service(Files::new("/", "../public")) From ced1035ffde2a2b67c3b0ed144166c6e630e2532 Mon Sep 17 00:00:00 2001 From: Romira915 <40430090+Romira915@users.noreply.github.com> Date: Thu, 16 Jun 2022 01:21:46 +0900 Subject: [PATCH 29/64] fix: show user name --- webapp/rust/src/main.rs | 4 ++-- webapp/rust/static/layout.html | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/webapp/rust/src/main.rs b/webapp/rust/src/main.rs index 8409bf8b8..f75d0cd92 100644 --- a/webapp/rust/src/main.rs +++ b/webapp/rust/src/main.rs @@ -739,7 +739,7 @@ async fn get_posts_id( Ok(HttpResponse::Ok().body(body)) } -// golang版と処理順が異なる +// NOTE: golang版と処理順が異なる #[post("/")] async fn post_index( session: Session, @@ -805,7 +805,7 @@ async fn post_index( } } "body" => { - // 例外処理入れたほうがいい? + // NOTE: 例外処理入れたほうがいい? let bytes = field_to_vec(&mut field).await.unwrap_or_default(); body = String::from_utf8(bytes).unwrap_or_default(); } diff --git a/webapp/rust/static/layout.html b/webapp/rust/static/layout.html index dd271a2e9..eac6dbe3e 100644 --- a/webapp/rust/static/layout.html +++ b/webapp/rust/static/layout.html @@ -17,7 +17,7 @@

Iscogram

{{#if (eq user.id 0)}} {{else}} - + {{#if (eq user.authority 1)}} {{/if}} From 09f32512a5992db9ad5910567e91c2db3ba34cb8 Mon Sep 17 00:00:00 2001 From: Romira915 <40430090+Romira915@users.noreply.github.com> Date: Thu, 16 Jun 2022 01:28:07 +0900 Subject: [PATCH 30/64] fix: log level --- webapp/rust/src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/webapp/rust/src/main.rs b/webapp/rust/src/main.rs index f75d0cd92..926bb66e7 100644 --- a/webapp/rust/src/main.rs +++ b/webapp/rust/src/main.rs @@ -935,7 +935,7 @@ fn init_logger>(log_path: Option

) { if cfg!(debug_assertions) { LevelFilter::Debug } else { - LevelFilter::Info + LevelFilter::Warn }, config.build(), TerminalMode::Mixed, From c2e67d7c162344b7c58fe2c2e0114c7c5a370838 Mon Sep 17 00:00:00 2001 From: Romira915 <40430090+Romira915@users.noreply.github.com> Date: Thu, 16 Jun 2022 01:31:47 +0900 Subject: [PATCH 31/64] fix: ref user page --- webapp/rust/src/main.rs | 4 ++++ webapp/rust/static/post.html | 6 +++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/webapp/rust/src/main.rs b/webapp/rust/src/main.rs index 926bb66e7..269e08f48 100644 --- a/webapp/rust/src/main.rs +++ b/webapp/rust/src/main.rs @@ -665,6 +665,10 @@ async fn get_index( Ok(HttpResponse::Ok().body(body)) } +async fn get_account_name() { + todo!() +} + #[get("/posts")] async fn get_posts() -> Result { todo!() diff --git a/webapp/rust/static/post.html b/webapp/rust/static/post.html index 87ea58242..40458f5d2 100644 --- a/webapp/rust/static/post.html +++ b/webapp/rust/static/post.html @@ -1,7 +1,7 @@ {{#*inline "post_html"}}

- + @@ -10,7 +10,7 @@
- + {{body}}
@@ -20,7 +20,7 @@ {{#each comments}} {{/each}} From dc0e2378d3dd820b363003bb8227ae6f11540e90 Mon Sep 17 00:00:00 2001 From: Romira915 <40430090+Romira915@users.noreply.github.com> Date: Thu, 16 Jun 2022 22:53:56 +0900 Subject: [PATCH 32/64] =?UTF-8?q?fix:=20=E4=B8=8D=E8=A6=81=E3=81=AA?= =?UTF-8?q?=E3=82=B3=E3=83=BC=E3=83=89=E3=82=92=E5=89=8A=E9=99=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- webapp/rust/src/main.rs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/webapp/rust/src/main.rs b/webapp/rust/src/main.rs index 269e08f48..1cd2983f4 100644 --- a/webapp/rust/src/main.rs +++ b/webapp/rust/src/main.rs @@ -893,11 +893,6 @@ async fn get_image(path: web::Path<(String,)>, pool: Data>) -> Resul } }; - if ext == "jpg" && post.mime == "image/jpeg" - || ext == "png" && post.mime == "image/png" - || ext == "gif" && post.mime == "image/gif" - {} - let content_type = match (ext, post.mime.as_str()) { ("jpg", "image/jpeg") | ("png", "image/png") | ("gif", "image/gif") => post.mime.as_str(), _ => return Ok(HttpResponse::InternalServerError().finish()), From a8f9ce5102114fe44c1def014591a5edb78b431d Mon Sep 17 00:00:00 2001 From: Romira915 <40430090+Romira915@users.noreply.github.com> Date: Fri, 17 Jun 2022 00:10:27 +0900 Subject: [PATCH 33/64] features: post_comment --- webapp/rust/src/main.rs | 49 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 47 insertions(+), 2 deletions(-) diff --git a/webapp/rust/src/main.rs b/webapp/rust/src/main.rs index 1cd2983f4..9faf2a373 100644 --- a/webapp/rust/src/main.rs +++ b/webapp/rust/src/main.rs @@ -128,6 +128,13 @@ struct IndexParams { csrf_token: String, } +#[derive(Debug, Serialize, Deserialize)] +struct CommentParams { + comment: String, + post_id: u64, + csrf_token: String, +} + async fn field_to_vec(field: &mut Field) -> anyhow::Result> { let mut b = Vec::new(); while let Some(chunk) = field.try_next().await? { @@ -903,8 +910,46 @@ async fn get_image(path: web::Path<(String,)>, pool: Data>) -> Resul .body(post.imgdata)) } -async fn post_comment() -> Result { - todo!() +async fn post_comment( + session: Session, + pool: Data>, + params: Form, +) -> Result { + let me = match get_session_user(&session, pool.as_ref()).await { + Ok(me) => { + if !is_login(me.as_ref()) { + return Ok(HttpResponse::Found() + .insert_header((header::LOCATION, "/login")) + .finish()); + } + me.unwrap_or_default() + } + Err(e) => { + log::warn!("{:?}", &e); + return Ok(HttpResponse::InternalServerError().body(e.to_string())); + } + }; + + if params.csrf_token != get_csrf_token(&session).unwrap_or_default() { + return Ok(HttpResponse::UnprocessableEntity().finish()); + } + + if let Err(e) = sqlx::query!( + "INSERT INTO `comments` (`post_id`, `user_id`, `comment`) VALUES (?,?,?)", + params.post_id, + me.id, + ¶ms.comment + ) + .execute(pool.as_ref()) + .await + { + log::warn!("{:?}", &e); + return Ok(HttpResponse::InternalServerError().body(e.to_string())); + } + + Ok(HttpResponse::Found() + .insert_header((header::LOCATION, format!("/posts/{}", params.post_id))) + .finish()) } async fn get_admin_banned() -> Result { From 882a50b01641a4e16c8e4d2215fbab789f722024 Mon Sep 17 00:00:00 2001 From: Romira915 <40430090+Romira915@users.noreply.github.com> Date: Fri, 17 Jun 2022 00:33:35 +0900 Subject: [PATCH 34/64] =?UTF-8?q?features:=20get=5Fadmin=5Fbanned=E3=82=92?= =?UTF-8?q?=E5=AE=9F=E8=A3=85=E3=81=97=E3=81=9F=E3=83=BB=E3=83=BB=E3=83=BB?= =?UTF-8?q?=E3=81=A0=E3=81=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- webapp/rust/src/main.rs | 61 ++++++++++++++++++++++++++++++++-- webapp/rust/static/banned.html | 17 ++++++++++ 2 files changed, 76 insertions(+), 2 deletions(-) create mode 100644 webapp/rust/static/banned.html diff --git a/webapp/rust/src/main.rs b/webapp/rust/src/main.rs index 9faf2a373..27f3d5792 100644 --- a/webapp/rust/src/main.rs +++ b/webapp/rust/src/main.rs @@ -910,6 +910,7 @@ async fn get_image(path: web::Path<(String,)>, pool: Data>) -> Resul .body(post.imgdata)) } +#[post("/comment")] async fn post_comment( session: Session, pool: Data>, @@ -952,8 +953,62 @@ async fn post_comment( .finish()) } -async fn get_admin_banned() -> Result { - todo!() +// NOTE: adminアカウントがわからないので検証できてない +#[get("/admin/banned")] +async fn get_admin_banned( + session: Session, + pool: Data>, + handlebars: Data>, +) -> Result { + let me = match get_session_user(&session, pool.as_ref()).await { + Ok(me) => { + if !is_login(me.as_ref()) { + return Ok(HttpResponse::Found() + .insert_header((header::LOCATION, "/")) + .finish()); + } + me.unwrap_or_default() + } + Err(e) => { + log::warn!("{:?}", &e); + return Ok(HttpResponse::InternalServerError().body(e.to_string())); + } + }; + + if me.authority == 0 { + return Ok(HttpResponse::Forbidden().finish()); + } + + let users = match sqlx::query_as!( + User, + "SELECT * FROM `users` WHERE `authority` = 0 AND `del_flg` = 0 ORDER BY `created_at` DESC" + ) + .fetch_all(pool.as_ref()) + .await + { + Ok(users) => users, + Err(e) => { + log::warn!("{:?}", &e); + return Ok(HttpResponse::InternalServerError().body(e.to_string())); + } + }; + + let body = { + let mut map = Map::new(); + + map.insert("users".to_string(), to_json(users)); + map.insert("user".to_string(), to_json(me)); + map.insert( + "csrf_token".to_string(), + to_json(get_csrf_token(&session).unwrap_or_default()), + ); + + map.insert("content_parent".to_string(), to_json("layout")); + + handlebars.render("banned", &map).unwrap() + }; + + Ok(HttpResponse::Ok().body(body)) } async fn post_admin_banned() -> Result { @@ -1063,6 +1118,8 @@ async fn main() -> io::Result<()> { .service(get_posts_id) .service(post_index) .service(get_image) + .service(post_comment) + .service(get_admin_banned) // .service(ResourceDef::new("/{tail}*").) .service(Files::new("/", "../public")) .service( diff --git a/webapp/rust/static/banned.html b/webapp/rust/static/banned.html new file mode 100644 index 000000000..e6760d76a --- /dev/null +++ b/webapp/rust/static/banned.html @@ -0,0 +1,17 @@ +{{#*inline "content"}} +
+
+ {{#each users}} +
+ + +
+ {{/each}} +
+ + +
+
+
+{{/inline}} +{{> (lookup this "content_parent")}} \ No newline at end of file From 63859dbb0f6382fde43e8ff651c3b21c924c80d2 Mon Sep 17 00:00:00 2001 From: Romira915 <40430090+Romira915@users.noreply.github.com> Date: Fri, 17 Jun 2022 01:34:43 +0900 Subject: [PATCH 35/64] =?UTF-8?q?fix:=20passhash=E3=81=AE=E4=B8=8D?= =?UTF-8?q?=E5=85=B7=E5=90=88=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- webapp/rust/src/main.rs | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/webapp/rust/src/main.rs b/webapp/rust/src/main.rs index 27f3d5792..3778b5a78 100644 --- a/webapp/rust/src/main.rs +++ b/webapp/rust/src/main.rs @@ -199,7 +199,7 @@ fn digest(src: &str) -> anyhow::Result { "/bin/bash", "-c", format!( - r#"printf "%s" "+{}+" | openssl dgst -sha512 | sed 's/^.*= //'"#, + r#"printf "%s" {} | openssl dgst -sha512 | sed 's/^.*= //'"#, escapeshellarg(src) ) ) @@ -1011,7 +1011,26 @@ async fn get_admin_banned( Ok(HttpResponse::Ok().body(body)) } -async fn post_admin_banned() -> Result { +#[post("/admin/banned")] +async fn post_admin_banned(session: Session, pool: Data>) -> Result { + let me = match get_session_user(&session, pool.as_ref()).await { + Ok(me) => { + if !is_login(me.as_ref()) { + return Ok(HttpResponse::Found() + .insert_header((header::LOCATION, "/")) + .finish()); + } + me.unwrap_or_default() + } + Err(e) => { + log::warn!("{:?}", &e); + return Ok(HttpResponse::InternalServerError().body(e.to_string())); + } + }; + + if me.authority == 0 { + return Ok(HttpResponse::Forbidden().finish()); + } todo!() } @@ -1120,6 +1139,7 @@ async fn main() -> io::Result<()> { .service(get_image) .service(post_comment) .service(get_admin_banned) + .service(post_admin_banned) // .service(ResourceDef::new("/{tail}*").) .service(Files::new("/", "../public")) .service( From 45874492f2bfaba1527d7ae08d9241e26a14223c Mon Sep 17 00:00:00 2001 From: Romira915 <40430090+Romira915@users.noreply.github.com> Date: Fri, 17 Jun 2022 01:58:51 +0900 Subject: [PATCH 36/64] =?UTF-8?q?fix:=20=E3=82=AF=E3=82=A8=E3=83=AA?= =?UTF-8?q?=E3=83=91=E3=83=A9=E3=83=A1=E3=83=BC=E3=82=BF=E3=82=92payload?= =?UTF-8?q?=E3=81=A7=E5=8F=97=E3=81=91=E5=8F=96=E3=82=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- webapp/rust/src/main.rs | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/webapp/rust/src/main.rs b/webapp/rust/src/main.rs index 3778b5a78..2a416d3d6 100644 --- a/webapp/rust/src/main.rs +++ b/webapp/rust/src/main.rs @@ -21,7 +21,7 @@ use actix_web::{ Method, StatusCode, }, middleware, post, - web::{self, Bytes, Data, Form}, + web::{self, Bytes, Data, Form, Payload}, App, HttpRequest, HttpResponse, HttpServer, Result, }; use anyhow::{bail, Context}; @@ -135,6 +135,12 @@ struct CommentParams { csrf_token: String, } +#[derive(Debug, Serialize, Deserialize)] +struct BannedParams { + uid: Vec, + csrf_token: String, +} + async fn field_to_vec(field: &mut Field) -> anyhow::Result> { let mut b = Vec::new(); while let Some(chunk) = field.try_next().await? { @@ -1012,7 +1018,18 @@ async fn get_admin_banned( } #[post("/admin/banned")] -async fn post_admin_banned(session: Session, pool: Data>) -> Result { +async fn post_admin_banned( + session: Session, + pool: Data>, + mut payload: Payload, +) -> Result { + let mut bytes = Vec::new(); + while let Some(field) = payload.try_next().await? { + bytes.append(&mut field.to_vec()); + } + let body = String::from_utf8(bytes).unwrap(); + log::debug!("{}", body); + let me = match get_session_user(&session, pool.as_ref()).await { Ok(me) => { if !is_login(me.as_ref()) { @@ -1031,7 +1048,8 @@ async fn post_admin_banned(session: Session, pool: Data>) -> Result< if me.authority == 0 { return Ok(HttpResponse::Forbidden().finish()); } - todo!() + + Ok(HttpResponse::Ok().body("Ok")) } fn init_logger>(log_path: Option

) { From 6001fde4910735fd9e9d9eef40994a30803bfee3 Mon Sep 17 00:00:00 2001 From: Romira915 <40430090+Romira915@users.noreply.github.com> Date: Fri, 17 Jun 2022 12:57:53 +0900 Subject: [PATCH 37/64] fix: post admin banned --- webapp/rust/Cargo.toml | 1 + webapp/rust/src/main.rs | 13 +++++++++++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/webapp/rust/Cargo.toml b/webapp/rust/Cargo.toml index 8ae36ee24..6fe50029a 100644 --- a/webapp/rust/Cargo.toml +++ b/webapp/rust/Cargo.toml @@ -28,4 +28,5 @@ rand = "0.8.5" regex = "1.5.6" serde = {version = "1.0.137", features = ["derive"]} serde_json = "1.0.81" +serde_qs = "0.9.2" simplelog = "0.12.0" diff --git a/webapp/rust/src/main.rs b/webapp/rust/src/main.rs index 2a416d3d6..1ad719dc8 100644 --- a/webapp/rust/src/main.rs +++ b/webapp/rust/src/main.rs @@ -135,7 +135,7 @@ struct CommentParams { csrf_token: String, } -#[derive(Debug, Serialize, Deserialize)] +#[derive(Debug, Default, Serialize, Deserialize)] struct BannedParams { uid: Vec, csrf_token: String, @@ -1023,12 +1023,21 @@ async fn post_admin_banned( pool: Data>, mut payload: Payload, ) -> Result { + // NOTE: field_to_vecにまとめたいなぁ let mut bytes = Vec::new(); while let Some(field) = payload.try_next().await? { bytes.append(&mut field.to_vec()); } let body = String::from_utf8(bytes).unwrap(); - log::debug!("{}", body); + let query = + match serde_qs::from_str::(&body.replace("%5B", "[").replace("%5D", "]")) { + Ok(q) => q, + Err(e) => { + log::error!("{:#?}", &e); + BannedParams::default() + } + }; + log::debug!("admin banned {:?}", query); let me = match get_session_user(&session, pool.as_ref()).await { Ok(me) => { From 499e1db6a37ad0a28d5761cfca6dc644ababe3e0 Mon Sep 17 00:00:00 2001 From: Romira915 <40430090+Romira915@users.noreply.github.com> Date: Fri, 17 Jun 2022 13:24:38 +0900 Subject: [PATCH 38/64] =?UTF-8?q?features:=20post=5Fadmin=5Fbanned=20?= =?UTF-8?q?=E5=AE=9F=E8=A3=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- webapp/rust/src/main.rs | 48 +++++++++++++++++++++++++++-------------- 1 file changed, 32 insertions(+), 16 deletions(-) diff --git a/webapp/rust/src/main.rs b/webapp/rust/src/main.rs index 1ad719dc8..5b4899876 100644 --- a/webapp/rust/src/main.rs +++ b/webapp/rust/src/main.rs @@ -1023,6 +1023,25 @@ async fn post_admin_banned( pool: Data>, mut payload: Payload, ) -> Result { + let me = match get_session_user(&session, pool.as_ref()).await { + Ok(me) => { + if !is_login(me.as_ref()) { + return Ok(HttpResponse::Found() + .insert_header((header::LOCATION, "/")) + .finish()); + } + me.unwrap_or_default() + } + Err(e) => { + log::warn!("{:?}", &e); + return Ok(HttpResponse::InternalServerError().body(e.to_string())); + } + }; + + if me.authority == 0 { + return Ok(HttpResponse::Forbidden().finish()); + } + // NOTE: field_to_vecにまとめたいなぁ let mut bytes = Vec::new(); while let Some(field) = payload.try_next().await? { @@ -1034,31 +1053,28 @@ async fn post_admin_banned( Ok(q) => q, Err(e) => { log::error!("{:#?}", &e); - BannedParams::default() + return Ok(HttpResponse::InternalServerError().body(e.to_string())); } }; log::debug!("admin banned {:?}", query); - let me = match get_session_user(&session, pool.as_ref()).await { - Ok(me) => { - if !is_login(me.as_ref()) { - return Ok(HttpResponse::Found() - .insert_header((header::LOCATION, "/")) - .finish()); - } - me.unwrap_or_default() - } - Err(e) => { + if query.csrf_token != get_csrf_token(&session).unwrap_or_default() { + return Ok(HttpResponse::UnprocessableEntity().finish()); + } + + for uid in &query.uid { + if let Err(e) = sqlx::query!("UPDATE `users` SET `del_flg` = ? WHERE `id` = ?", 1, &uid) + .execute(pool.as_ref()) + .await + { log::warn!("{:?}", &e); return Ok(HttpResponse::InternalServerError().body(e.to_string())); } - }; - - if me.authority == 0 { - return Ok(HttpResponse::Forbidden().finish()); } - Ok(HttpResponse::Ok().body("Ok")) + Ok(HttpResponse::Found() + .insert_header((header::LOCATION, "/admin/banned")) + .finish()) } fn init_logger>(log_path: Option

) { From f2e74f271db712efc5d78b8dfd6f41e8538e73fd Mon Sep 17 00:00:00 2001 From: Romira915 <40430090+Romira915@users.noreply.github.com> Date: Fri, 17 Jun 2022 18:30:34 +0900 Subject: [PATCH 39/64] =?UTF-8?q?features:=20get=5Faccount=5Fname=20?= =?UTF-8?q?=E5=AE=9F=E8=A3=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- webapp/rust/src/main.rs | 133 ++++++++++++++++++++++++++++++++++- webapp/rust/static/user.html | 11 +++ 2 files changed, 142 insertions(+), 2 deletions(-) create mode 100644 webapp/rust/static/user.html diff --git a/webapp/rust/src/main.rs b/webapp/rust/src/main.rs index 5b4899876..a7e8c9e90 100644 --- a/webapp/rust/src/main.rs +++ b/webapp/rust/src/main.rs @@ -374,6 +374,7 @@ handlebars_helper!(date_time_format: |create_at: DateTime| { create_at.format("%Y-%m-%dT%H:%M:%S-07:00").to_string() }); +// NOTE: idが0ならみたいなことしてるけどせっかくOptionがあるからこっちで判定したい fn is_login(u: Option<&User>) -> bool { match u { Some(u) => u.id != 0, @@ -678,8 +679,134 @@ async fn get_index( Ok(HttpResponse::Ok().body(body)) } -async fn get_account_name() { - todo!() +#[get("/@{account_name}")] +async fn get_account_name( + path: web::Path<(String,)>, + session: Session, + pool: Data>, + handlebars: Data>, +) -> Result { + let account_name = path.into_inner().0; + + let user = match sqlx::query_as!( + User, + "SELECT * FROM `users` WHERE `account_name` = ? AND `del_flg` = 0", + account_name + ) + .fetch_optional(pool.as_ref()) + .await + { + Ok(Some(user)) => user, + Ok(None) => return Ok(HttpResponse::NotFound().finish()), + Err(e) => { + log::error!("{:?}", &e); + return Ok(HttpResponse::InternalServerError().body(e.to_string())); + } + }; + + let results =match sqlx::query_as!(Post,"SELECT `id`, `user_id`, `body`, `mime`, `created_at`, b'0' AS imgdata FROM `posts` WHERE `user_id` = ? ORDER BY `created_at` DESC",user.id).fetch_all(pool.as_ref()).await{ + Ok(r) => r, + Err(e)=>{ + log::error!("{:?}", &e); + return Ok(HttpResponse::InternalServerError().body(e.to_string())); + } + }; + + let posts = match make_post( + results, + get_csrf_token(&session).unwrap_or_default(), + false, + pool.as_ref(), + ) + .await + { + Ok(p) => p, + Err(e) => { + log::error!("{:?}", &e); + return Ok(HttpResponse::InternalServerError().body(e.to_string())); + } + }; + + let comment_count = match sqlx::query!( + "SELECT COUNT(*) AS count FROM `comments` WHERE `user_id` = ?", + user.id + ) + .fetch_one(pool.as_ref()) + .await + { + Ok(r) => r.count, + Err(e) => { + log::error!("{:?}", &e); + return Ok(HttpResponse::InternalServerError().body(e.to_string())); + } + }; + + let post_ids = match sqlx::query!("SELECT `id` FROM `posts` WHERE `user_id` = ?", user.id) + .fetch_all(pool.as_ref()) + .await + { + Ok(records) => records.iter().map(|r| r.id).collect::>(), + Err(e) => { + log::error!("{:?}", &e); + return Ok(HttpResponse::InternalServerError().body(e.to_string())); + } + }; + let post_count = post_ids.len(); + + let commented_count = if post_count > 0 { + let mut s = Vec::new(); + for _pid in post_ids { + s.push("?".to_string()); + } + let place_holder = s.join(", "); + + let commented_count = match sqlx::query!( + "SELECT COUNT(*) AS count FROM `comments` WHERE `post_id` IN (?)", + place_holder + ) + .fetch_one(pool.as_ref()) + .await + { + Ok(r) => r.count, + Err(e) => { + log::error!("{:?}", &e); + return Ok(HttpResponse::InternalServerError().body(e.to_string())); + } + }; + log::debug!("{}", commented_count); + + commented_count + } else { + 0 + }; + + let me = match get_session_user(&session, pool.as_ref()).await { + Ok(me) => me.unwrap_or_default(), + Err(e) => { + log::error!("{:?}", &e); + return Ok(HttpResponse::InternalServerError().body(e.to_string())); + } + }; + + let body = { + let mut map = Map::new(); + // let posts = serde_json::to_value(posts).unwrap(); + // let map = json.as_object_mut().unwrap(); + map.insert("posts".to_string(), to_json(posts)); + map.insert("user".to_string(), to_json(user)); + map.insert("post_count".to_string(), to_json(post_count)); + map.insert("comment_count".to_string(), to_json(comment_count)); + map.insert("commented_count".to_string(), to_json(commented_count)); + map.insert("me".to_string(), to_json(me)); + + map.insert("post_parent".to_string(), to_json("posts")); + map.insert("posts_parent".to_string(), to_json("user")); + map.insert("content_parent".to_string(), to_json("layout")); + + handlebars.render("post", &map).unwrap() + }; + + Ok(HttpResponse::Ok().body(body)) } #[get("/posts")] @@ -872,6 +999,7 @@ async fn post_index( .finish()) } +// TODO: idと拡張子分離できそうなので分離する #[get("/image/{path}")] async fn get_image(path: web::Path<(String,)>, pool: Data>) -> Result { let (pid, ext) = match path.0.rsplit_once(".") { @@ -1183,6 +1311,7 @@ async fn main() -> io::Result<()> { .service(post_comment) .service(get_admin_banned) .service(post_admin_banned) + .service(get_account_name) // .service(ResourceDef::new("/{tail}*").) .service(Files::new("/", "../public")) .service( diff --git a/webapp/rust/static/user.html b/webapp/rust/static/user.html new file mode 100644 index 000000000..4a44ae171 --- /dev/null +++ b/webapp/rust/static/user.html @@ -0,0 +1,11 @@ +{{#*inline "content"}} +

+
のページ
+
投稿数 {{post_count }}
+
コメント数 {{comment_count }}
+
被コメント数 {{commented_count }}
+
+ +{{> posts_html}} +{{/inline}} +{{> (lookup this "content_parent")}} \ No newline at end of file From be2d762d8506f4c32da0c83479e20fbbfe58d804 Mon Sep 17 00:00:00 2001 From: Romira915 <40430090+Romira915@users.noreply.github.com> Date: Fri, 17 Jun 2022 18:34:55 +0900 Subject: [PATCH 40/64] =?UTF-8?q?fix:=20=E8=A1=A8=E7=A4=BA=E3=83=A6?= =?UTF-8?q?=E3=83=BC=E3=82=B6=E3=81=8C=E3=83=AD=E3=82=B0=E3=82=A4=E3=83=B3?= =?UTF-8?q?=E3=83=A6=E3=83=BC=E3=82=B6=E3=81=A8=E3=81=97=E3=81=A6=E8=A1=A8?= =?UTF-8?q?=E7=A4=BA=E3=81=95=E3=82=8C=E3=82=8B=E4=B8=8D=E5=85=B7=E5=90=88?= =?UTF-8?q?=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- webapp/rust/src/main.rs | 10 +++++----- webapp/rust/static/layout.html | 6 +++--- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/webapp/rust/src/main.rs b/webapp/rust/src/main.rs index a7e8c9e90..0301d27ee 100644 --- a/webapp/rust/src/main.rs +++ b/webapp/rust/src/main.rs @@ -429,7 +429,7 @@ async fn get_login( let body = { let mut map = Map::new(); - map.insert("user".to_string(), to_json(user)); + map.insert("me".to_string(), to_json(user)); map.insert("flash".to_string(), to_json(get_flash(&session, "notice"))); map.insert("parent".to_string(), to_json("layout")); log::debug!("{:?}", &map); @@ -504,7 +504,7 @@ async fn get_register( let mut map = Map::new(); - map.insert("user".to_string(), to_json(user)); + map.insert("me".to_string(), to_json(user)); map.insert("flash".to_string(), to_json(get_flash(&session, "notice"))); map.insert("parent".to_string(), to_json("layout")); log::debug!("map {:?}", &map); @@ -662,7 +662,7 @@ async fn get_index( // let posts = serde_json::to_value(posts).unwrap(); // let map = json.as_object_mut().unwrap(); map.insert("posts".to_string(), to_json(posts)); - map.insert("user".to_string(), to_json(me)); + map.insert("me".to_string(), to_json(me)); map.insert( "csrf_token".to_string(), to_json(get_csrf_token(&session).unwrap_or_default()), @@ -869,7 +869,7 @@ async fn get_posts_id( let mut post = serde_json::to_value(p).unwrap(); let map = post.as_object_mut().unwrap(); - map.insert("user".to_string(), to_json(me)); + map.insert("me".to_string(), to_json(me)); map.insert("post_parent".to_string(), to_json("post_id")); map.insert("content_parent".to_string(), to_json("layout")); @@ -1131,7 +1131,7 @@ async fn get_admin_banned( let mut map = Map::new(); map.insert("users".to_string(), to_json(users)); - map.insert("user".to_string(), to_json(me)); + map.insert("me".to_string(), to_json(me)); map.insert( "csrf_token".to_string(), to_json(get_csrf_token(&session).unwrap_or_default()), diff --git a/webapp/rust/static/layout.html b/webapp/rust/static/layout.html index eac6dbe3e..5af88c5a6 100644 --- a/webapp/rust/static/layout.html +++ b/webapp/rust/static/layout.html @@ -14,11 +14,11 @@

Iscogram

- {{#if (eq user.id 0)}} + {{#if (eq me.id 0)}} {{else}} - - {{#if (eq user.authority 1)}} + + {{#if (eq me.authority 1)}} {{/if}} From e719f0f70cec498f134b50949341294b3b8e8105 Mon Sep 17 00:00:00 2001 From: Romira915 <40430090+Romira915@users.noreply.github.com> Date: Fri, 17 Jun 2022 18:35:46 +0900 Subject: [PATCH 41/64] =?UTF-8?q?fix:=20bug=E3=82=92=E7=A2=BA=E8=AA=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- webapp/rust/src/main.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/webapp/rust/src/main.rs b/webapp/rust/src/main.rs index 0301d27ee..721eb4c30 100644 --- a/webapp/rust/src/main.rs +++ b/webapp/rust/src/main.rs @@ -760,6 +760,7 @@ async fn get_account_name( } let place_holder = s.join(", "); + // BUG: このクエリは意図した動作をしていない let commented_count = match sqlx::query!( "SELECT COUNT(*) AS count FROM `comments` WHERE `post_id` IN (?)", place_holder From 693cca2dde91573a5b24286b3fa30cf1c2cdc2a6 Mon Sep 17 00:00:00 2001 From: Romira915 <40430090+Romira915@users.noreply.github.com> Date: Fri, 17 Jun 2022 18:57:22 +0900 Subject: [PATCH 42/64] =?UTF-8?q?bugfix:=20commented=5Fcount=E3=81=8C?= =?UTF-8?q?=E6=AD=A3=E3=81=97=E3=81=8F=E3=81=AA=E3=81=84=E4=B8=8D=E5=85=B7?= =?UTF-8?q?=E5=90=88=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- webapp/rust/src/main.rs | 41 ++++++++++++++++++++++-------------- webapp/rust/static/user.html | 6 +++--- 2 files changed, 28 insertions(+), 19 deletions(-) diff --git a/webapp/rust/src/main.rs b/webapp/rust/src/main.rs index 721eb4c30..c3606563e 100644 --- a/webapp/rust/src/main.rs +++ b/webapp/rust/src/main.rs @@ -755,28 +755,37 @@ async fn get_account_name( let commented_count = if post_count > 0 { let mut s = Vec::new(); - for _pid in post_ids { + for _pid in &post_ids { s.push("?".to_string()); } let place_holder = s.join(", "); - // BUG: このクエリは意図した動作をしていない - let commented_count = match sqlx::query!( - "SELECT COUNT(*) AS count FROM `comments` WHERE `post_id` IN (?)", + #[derive(sqlx::FromRow)] + struct CommentedCount { + count: i64, + } + let q = format!( + "SELECT COUNT(*) AS count FROM `comments` WHERE `post_id` IN ({})", place_holder - ) - .fetch_one(pool.as_ref()) - .await - { - Ok(r) => r.count, - Err(e) => { - log::error!("{:?}", &e); - return Ok(HttpResponse::InternalServerError().body(e.to_string())); - } - }; - log::debug!("{}", commented_count); + ); + // NOTE: もっといい記述ないかな + let mut query = sqlx::query_as::<_, CommentedCount>(q.as_str()); + + for pid in &post_ids { + query = query.bind(pid); + } - commented_count + let commented_count = query.fetch_one(pool.as_ref()).await.unwrap(); + // { + // Ok(r) => r, + // Err(e) => { + // log::error!("{:?}", &e); + // return Ok(HttpResponse::InternalServerError().body(e.to_string())); + // } + // }; + // log::debug!("commented_count {}", commented_count); + // commented_count + commented_count.count } else { 0 }; diff --git a/webapp/rust/static/user.html b/webapp/rust/static/user.html index 4a44ae171..5ebcc8f8d 100644 --- a/webapp/rust/static/user.html +++ b/webapp/rust/static/user.html @@ -1,9 +1,9 @@ {{#*inline "content"}}
のページ
-
投稿数 {{post_count }}
-
コメント数 {{comment_count }}
-
被コメント数 {{commented_count }}
+
投稿数 {{post_count}}
+
コメント数 {{comment_count}}
+
被コメント数 {{commented_count}}
{{> posts_html}} From f4bf4bc1dce1eb9fb730cb2468407656d8b8bfc7 Mon Sep 17 00:00:00 2001 From: Romira915 <40430090+Romira915@users.noreply.github.com> Date: Fri, 17 Jun 2022 18:59:08 +0900 Subject: [PATCH 43/64] =?UTF-8?q?fix:=20=E4=BE=8B=E5=A4=96=E5=87=A6?= =?UTF-8?q?=E7=90=86=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- webapp/rust/src/main.rs | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/webapp/rust/src/main.rs b/webapp/rust/src/main.rs index c3606563e..e00c8615a 100644 --- a/webapp/rust/src/main.rs +++ b/webapp/rust/src/main.rs @@ -775,16 +775,14 @@ async fn get_account_name( query = query.bind(pid); } - let commented_count = query.fetch_one(pool.as_ref()).await.unwrap(); - // { - // Ok(r) => r, - // Err(e) => { - // log::error!("{:?}", &e); - // return Ok(HttpResponse::InternalServerError().body(e.to_string())); - // } - // }; - // log::debug!("commented_count {}", commented_count); - // commented_count + let commented_count = match query.fetch_one(pool.as_ref()).await { + Ok(c) => c, + Err(e) => { + log::error!("{:?}", &e); + return Ok(HttpResponse::InternalServerError().body(e.to_string())); + } + }; + commented_count.count } else { 0 From 8dc87ffe372eb68cb77457d237d16b7b07afa312 Mon Sep 17 00:00:00 2001 From: Romira915 <40430090+Romira915@users.noreply.github.com> Date: Fri, 17 Jun 2022 22:37:23 +0900 Subject: [PATCH 44/64] fix: add NOTE --- webapp/rust/src/main.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/webapp/rust/src/main.rs b/webapp/rust/src/main.rs index e00c8615a..a22d1c883 100644 --- a/webapp/rust/src/main.rs +++ b/webapp/rust/src/main.rs @@ -817,9 +817,10 @@ async fn get_account_name( Ok(HttpResponse::Ok().body(body)) } +// NOTE: クエリパラメータがわからないのでどうしようもない #[get("/posts")] async fn get_posts() -> Result { - todo!() + Ok(HttpResponse::Ok().finish()) } #[get("/posts/{id}")] @@ -1095,7 +1096,6 @@ async fn post_comment( .finish()) } -// NOTE: adminアカウントがわからないので検証できてない #[get("/admin/banned")] async fn get_admin_banned( session: Session, @@ -1262,17 +1262,17 @@ async fn main() -> io::Result<()> { .unwrap(); let user = env::var("ISUCONP_DB_USER").unwrap_or("root".to_string()); - // let password = env::var("ISUCONP_DB_PASSWORD").expect("Failed to ISUCONP_DB_PASSWORD"); - let password = env::var("ISUCONP_DB_PASSWORD").unwrap_or("root".to_string()); + let password = env::var("ISUCONP_DB_PASSWORD").expect("Failed to ISUCONP_DB_PASSWORD"); + // let password = env::var("ISUCONP_DB_PASSWORD").unwrap_or("root".to_string()); let dbname = env::var("ISUCONP_DB_NAME").unwrap_or("isuconp".to_string()); let redis_url = env::var("ISUCONP_REDIS_URL").unwrap_or("localhost:6379".to_string()); let dsn = format!( - "{}:{}@tcp({}:{})/{}?charset=utf8mb4&parseTime=true&loc=Local", + "mysql://{}:{}@{}:{}/{}", &user, &password, &host, &port, &dbname ); - let dsn = "mysql://root:root@localhost:3306/isuconp".to_string(); + // let dsn = "mysql://root:root@localhost:3306/isuconp".to_string(); let num_cpus = num_cpus::get(); From 330bec686628d8cd08876f2ca2e6509cc805f052 Mon Sep 17 00:00:00 2001 From: Romira915 <40430090+Romira915@users.noreply.github.com> Date: Sat, 18 Jun 2022 00:33:52 +0900 Subject: [PATCH 45/64] add: query param --- webapp/docker-compose.yml | 2 +- webapp/rust/.gitignore | 3 ++- webapp/rust/src/main.rs | 25 +++++++++++++++++++------ 3 files changed, 22 insertions(+), 8 deletions(-) diff --git a/webapp/docker-compose.yml b/webapp/docker-compose.yml index 2ffdf8281..7f2ac36be 100644 --- a/webapp/docker-compose.yml +++ b/webapp/docker-compose.yml @@ -14,7 +14,7 @@ services: cpus: 1 mem_limit: 1g # Go実装の場合は golang/ PHP実装の場合は php/ - build: golang/ + build: rust/ environment: ISUCONP_DB_HOST: mysql ISUCONP_DB_PORT: 3306 diff --git a/webapp/rust/.gitignore b/webapp/rust/.gitignore index 64836335f..000662fdf 100644 --- a/webapp/rust/.gitignore +++ b/webapp/rust/.gitignore @@ -14,4 +14,5 @@ Cargo.lock *.pdb .env -.tmp \ No newline at end of file +.tmp +*.log \ No newline at end of file diff --git a/webapp/rust/src/main.rs b/webapp/rust/src/main.rs index a22d1c883..53ae9bab3 100644 --- a/webapp/rust/src/main.rs +++ b/webapp/rust/src/main.rs @@ -141,6 +141,11 @@ struct BannedParams { csrf_token: String, } +#[derive(Debug, Serialize, Deserialize)] +struct PostsQuery { + max_created_at: String, +} + async fn field_to_vec(field: &mut Field) -> anyhow::Result> { let mut b = Vec::new(); while let Some(chunk) = field.try_next().await? { @@ -817,9 +822,17 @@ async fn get_account_name( Ok(HttpResponse::Ok().body(body)) } -// NOTE: クエリパラメータがわからないのでどうしようもない #[get("/posts")] -async fn get_posts() -> Result { +async fn get_posts(query: web::Query) -> Result { + log::error!("/posts {:?}", query.max_created_at); + // let mut bytes = Vec::new(); + // while let Some(field) = payload.try_next().await? { + // bytes.append(&mut field.to_vec()); + // } + // let body = String::from_utf8(bytes).unwrap(); + // let body = body.replace("%5B", "[").replace("%5D", "]"); + // log::error!("/posts {}", body); + Ok(HttpResponse::Ok().finish()) } @@ -1213,7 +1226,7 @@ async fn post_admin_banned( .finish()) } -fn init_logger>(log_path: Option

) { +fn init_logger>(log_dir: Option

) { const JST_UTCOFFSET_SECS: i32 = 9 * 3600; let jst_now = { @@ -1239,11 +1252,11 @@ fn init_logger>(log_path: Option

) { ColorChoice::Always, ), ]; - if let Some(log_path) = log_path { + if let Some(log_path) = log_dir { let log_path = log_path.as_ref(); std::fs::create_dir_all(&log_path).unwrap(); logger.push(WriteLogger::new( - LevelFilter::Info, + LevelFilter::Warn, config.build(), std::fs::File::create(log_path.join(format!("{}.log", jst_now))).unwrap(), )); @@ -1253,7 +1266,7 @@ fn init_logger>(log_path: Option

) { #[actix_web::main] async fn main() -> io::Result<()> { - init_logger::<&str>(None); + init_logger::<&str>(Some("/home/webapp/log")); let host = env::var("ISUCONP_DB_HOST").unwrap_or("localhost".to_string()); let port: u32 = env::var("ISUCONP_DB_PORT") From 751e87637d10549f9a17173eaa5f0a936a3df59d Mon Sep 17 00:00:00 2001 From: Romira915 <40430090+Romira915@users.noreply.github.com> Date: Sat, 18 Jun 2022 02:35:46 +0900 Subject: [PATCH 46/64] =?UTF-8?q?features:=20get=5Fposts=20=E5=AE=9F?= =?UTF-8?q?=E8=A3=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- webapp/rust/src/main.rs | 92 ++++++++++++++++++----- webapp/rust/static/posts_stand_alone.html | 15 ++++ 2 files changed, 89 insertions(+), 18 deletions(-) create mode 100644 webapp/rust/static/posts_stand_alone.html diff --git a/webapp/rust/src/main.rs b/webapp/rust/src/main.rs index 53ae9bab3..1940f521a 100644 --- a/webapp/rust/src/main.rs +++ b/webapp/rust/src/main.rs @@ -2,6 +2,7 @@ use std::{ any, collections::HashMap, env, + f32::consts::E, io::{self, Write}, path::Path, time::Duration, @@ -823,17 +824,66 @@ async fn get_account_name( } #[get("/posts")] -async fn get_posts(query: web::Query) -> Result { - log::error!("/posts {:?}", query.max_created_at); - // let mut bytes = Vec::new(); - // while let Some(field) = payload.try_next().await? { - // bytes.append(&mut field.to_vec()); - // } - // let body = String::from_utf8(bytes).unwrap(); - // let body = body.replace("%5B", "[").replace("%5D", "]"); - // log::error!("/posts {}", body); +async fn get_posts( + query: web::Query, + session: Session, + pool: Data>, + handlebars: Data>, +) -> Result { + // NOTE: example max_created_at "2016-01-02T11:46:23+09:00" + let max_create_at = query.into_inner().max_created_at; - Ok(HttpResponse::Ok().finish()) + if max_create_at.is_empty() { + return Ok(HttpResponse::InternalServerError().finish()); + } + + let t = match DateTime::parse_from_rfc3339(&max_create_at) { + Ok(t) => t, + Err(e) => { + log::error!("{:?}", &e); + return Ok(HttpResponse::InternalServerError().body(e.to_string())); + } + }; + + let results = match sqlx::query_as!(Post,"SELECT `id`, `user_id`, `body`, `mime`, `created_at`, b'0' AS imgdata FROM `posts` WHERE `created_at` <= ? ORDER BY `created_at` DESC",&t.to_rfc3339()).fetch_all(pool.as_ref()).await{ + Ok(r)=> r, + Err(e)=> { + log::error!("{:?}", &e); + return Ok(HttpResponse::InternalServerError().body(e.to_string())); + } + }; + + let posts = match make_post( + results, + get_csrf_token(&session).unwrap_or_default(), + false, + pool.as_ref(), + ) + .await + { + Ok(p) => p, + Err(e) => { + log::error!("{:?}", &e); + return Ok(HttpResponse::InternalServerError().body(e.to_string())); + } + }; + + if posts.is_empty() { + return Ok(HttpResponse::NotFound().finish()); + } + + log::debug!("posts len {}", posts.len()); + + let body = { + let mut map = Map::new(); + map.insert("posts".to_string(), to_json(posts)); + + map.insert("post_parent".to_string(), to_json("posts_stand_alone")); + + handlebars.render("post", &map).unwrap() + }; + + Ok(HttpResponse::Ok().body(body)) } #[get("/posts/{id}")] @@ -1266,7 +1316,7 @@ fn init_logger>(log_dir: Option

) { #[actix_web::main] async fn main() -> io::Result<()> { - init_logger::<&str>(Some("/home/webapp/log")); + init_logger::<&str>(None); let host = env::var("ISUCONP_DB_HOST").unwrap_or("localhost".to_string()); let port: u32 = env::var("ISUCONP_DB_PORT") @@ -1275,17 +1325,23 @@ async fn main() -> io::Result<()> { .unwrap(); let user = env::var("ISUCONP_DB_USER").unwrap_or("root".to_string()); - let password = env::var("ISUCONP_DB_PASSWORD").expect("Failed to ISUCONP_DB_PASSWORD"); - // let password = env::var("ISUCONP_DB_PASSWORD").unwrap_or("root".to_string()); + let password = if cfg!(debug_assertions) { + env::var("ISUCONP_DB_PASSWORD").unwrap_or("root".to_string()) + } else { + env::var("ISUCONP_DB_PASSWORD").expect("Failed to ISUCONP_DB_PASSWORD") + }; let dbname = env::var("ISUCONP_DB_NAME").unwrap_or("isuconp".to_string()); let redis_url = env::var("ISUCONP_REDIS_URL").unwrap_or("localhost:6379".to_string()); - let dsn = format!( - "mysql://{}:{}@{}:{}/{}", - &user, &password, &host, &port, &dbname - ); - // let dsn = "mysql://root:root@localhost:3306/isuconp".to_string(); + let dsn = if cfg!(debug_assertions) { + "mysql://root:root@localhost:3306/isuconp".to_string() + } else { + format!( + "mysql://{}:{}@{}:{}/{}", + &user, &password, &host, &port, &dbname + ) + }; let num_cpus = num_cpus::get(); diff --git a/webapp/rust/static/posts_stand_alone.html b/webapp/rust/static/posts_stand_alone.html new file mode 100644 index 000000000..0e9cf3ecc --- /dev/null +++ b/webapp/rust/static/posts_stand_alone.html @@ -0,0 +1,15 @@ + + + + + + Iscogram + + +

+ {{#each posts}} + {{> post_html}} + {{/each}} +
+ + \ No newline at end of file From 7354b967e9a7d4d928b3258df4413fb2723af6ed Mon Sep 17 00:00:00 2001 From: Romira915 <40430090+Romira915@users.noreply.github.com> Date: Sat, 18 Jun 2022 11:59:07 +0900 Subject: [PATCH 47/64] =?UTF-8?q?fix:=20=E4=B8=8D=E8=A6=81=E3=81=AAhandle?= =?UTF-8?q?=E3=82=92=E5=89=8A=E9=99=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- webapp/rust/src/main.rs | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/webapp/rust/src/main.rs b/webapp/rust/src/main.rs index 1940f521a..4ef153002 100644 --- a/webapp/rust/src/main.rs +++ b/webapp/rust/src/main.rs @@ -1335,7 +1335,8 @@ async fn main() -> io::Result<()> { let redis_url = env::var("ISUCONP_REDIS_URL").unwrap_or("localhost:6379".to_string()); let dsn = if cfg!(debug_assertions) { - "mysql://root:root@localhost:3306/isuconp".to_string() + "mysql://root:root@tcp(localhost:3306)/isuconp?charset=utf8mb4&parseTime=true&loc=Local" + .to_string() } else { format!( "mysql://{}:{}@{}:{}/{}", @@ -1391,13 +1392,6 @@ async fn main() -> io::Result<()> { .service(get_account_name) // .service(ResourceDef::new("/{tail}*").) .service(Files::new("/", "../public")) - .service( - web::resource("/test").to(|req: HttpRequest| match *req.method() { - Method::GET => HttpResponse::Ok(), - Method::POST => HttpResponse::MethodNotAllowed(), - _ => HttpResponse::NotFound(), - }), - ) }) .bind(("0.0.0.0", 8080))? .run() From 87b8fd3952cce68d4c0c1561d078bb100b417bdb Mon Sep 17 00:00:00 2001 From: Romira915 <40430090+Romira915@users.noreply.github.com> Date: Sat, 18 Jun 2022 16:07:49 +0900 Subject: [PATCH 48/64] =?UTF-8?q?fix:=20=E5=88=86=E9=9B=A2=20pid=20ext?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- webapp/rust/src/main.rs | 31 ++++++++----------------------- 1 file changed, 8 insertions(+), 23 deletions(-) diff --git a/webapp/rust/src/main.rs b/webapp/rust/src/main.rs index 4ef153002..155ed4547 100644 --- a/webapp/rust/src/main.rs +++ b/webapp/rust/src/main.rs @@ -1071,26 +1071,12 @@ async fn post_index( .finish()) } -// TODO: idと拡張子分離できそうなので分離する -#[get("/image/{path}")] -async fn get_image(path: web::Path<(String,)>, pool: Data>) -> Result { - let (pid, ext) = match path.0.rsplit_once(".") { - Some((pid, ext)) => { - let pid = match pid.parse::() { - Ok(pid) => pid, - Err(e) => { - log::warn!("{:?}", &e); - return Ok(HttpResponse::InternalServerError().body(e.to_string())); - } - }; - (pid, ext) - } - None => { - let e = "Invalid path"; - log::warn!("{}", e); - return Ok(HttpResponse::InternalServerError().body(e)); - } - }; +#[get("/image/{pid}.{ext}")] +async fn get_image( + path: web::Path<(String, String)>, + pool: Data>, +) -> Result { + let (pid, ext) = path.into_inner(); let post = match sqlx::query_as!(Post, "SELECT * FROM `posts` WHERE `id` = ?", pid) .fetch_optional(pool.as_ref()) @@ -1106,7 +1092,7 @@ async fn get_image(path: web::Path<(String,)>, pool: Data>) -> Resul } }; - let content_type = match (ext, post.mime.as_str()) { + let content_type = match (ext.as_str(), post.mime.as_str()) { ("jpg", "image/jpeg") | ("png", "image/png") | ("gif", "image/gif") => post.mime.as_str(), _ => return Ok(HttpResponse::InternalServerError().finish()), }; @@ -1335,8 +1321,7 @@ async fn main() -> io::Result<()> { let redis_url = env::var("ISUCONP_REDIS_URL").unwrap_or("localhost:6379".to_string()); let dsn = if cfg!(debug_assertions) { - "mysql://root:root@tcp(localhost:3306)/isuconp?charset=utf8mb4&parseTime=true&loc=Local" - .to_string() + "mysql://root:root@localhost:3306/isuconp".to_string() } else { format!( "mysql://{}:{}@{}:{}/{}", From 363a9455a4127c65af2919453fb4da219df985f8 Mon Sep 17 00:00:00 2001 From: Romira915 <40430090+Romira915@users.noreply.github.com> Date: Sat, 18 Jun 2022 21:46:44 +0900 Subject: [PATCH 49/64] =?UTF-8?q?fix:=20cookiesession=E3=81=A7=E3=81=AE?= =?UTF-8?q?=E3=83=99=E3=83=B3=E3=83=81=E3=83=9E=E3=83=BC=E3=82=AF=E3=82=92?= =?UTF-8?q?=E7=A2=BA=E8=AA=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- webapp/rust/src/main.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/webapp/rust/src/main.rs b/webapp/rust/src/main.rs index 155ed4547..55f796b2d 100644 --- a/webapp/rust/src/main.rs +++ b/webapp/rust/src/main.rs @@ -12,7 +12,7 @@ use actix_cors::Cors; use actix_files::Files; use actix_multipart::{Field, Multipart, MultipartError}; use actix_redis::RedisSession; -use actix_session::Session; +use actix_session::{CookieSession, Session}; use actix_web::{ cookie::time::UtcOffset, dev::ResourceDef, @@ -1357,7 +1357,7 @@ async fn main() -> io::Result<()> { .supports_credentials() .allowed_origin("http://localhost") }) - .wrap(RedisSession::new(redis_url.clone(), private_key.master())) + .wrap(CookieSession::signed(&[0; 32]).secure(false)) .app_data(Data::new(db.clone())) .app_data(Data::new(handlebars)) .service(get_initialize) From af1d0a56d7e918b70f0b248a1fc1feb992fe8654 Mon Sep 17 00:00:00 2001 From: Romira915 <40430090+Romira915@users.noreply.github.com> Date: Sat, 18 Jun 2022 23:04:57 +0900 Subject: [PATCH 50/64] rm: template dir --- webapp/rust/templates/banned.html | 15 ------------- webapp/rust/templates/index.html | 28 ----------------------- webapp/rust/templates/layout.html | 35 ----------------------------- webapp/rust/templates/login.html | 31 ------------------------- webapp/rust/templates/post.html | 35 ----------------------------- webapp/rust/templates/post_id.html | 3 --- webapp/rust/templates/posts.html | 5 ----- webapp/rust/templates/register.html | 27 ---------------------- webapp/rust/templates/user.html | 10 --------- 9 files changed, 189 deletions(-) delete mode 100644 webapp/rust/templates/banned.html delete mode 100644 webapp/rust/templates/index.html delete mode 100644 webapp/rust/templates/layout.html delete mode 100644 webapp/rust/templates/login.html delete mode 100644 webapp/rust/templates/post.html delete mode 100644 webapp/rust/templates/post_id.html delete mode 100644 webapp/rust/templates/posts.html delete mode 100644 webapp/rust/templates/register.html delete mode 100644 webapp/rust/templates/user.html diff --git a/webapp/rust/templates/banned.html b/webapp/rust/templates/banned.html deleted file mode 100644 index ef7141992..000000000 --- a/webapp/rust/templates/banned.html +++ /dev/null @@ -1,15 +0,0 @@ -{{ define "content" }} -
-
- {{ range .Users }} -
- -
- {{ end }} -
- - -
-
-
-{{ end }} diff --git a/webapp/rust/templates/index.html b/webapp/rust/templates/index.html deleted file mode 100644 index 22ff9c254..000000000 --- a/webapp/rust/templates/index.html +++ /dev/null @@ -1,28 +0,0 @@ -{{ define "content" }} -
-
-
- -
-
- -
-
- - -
- {{if .Flash}} -
- {{.Flash}} -
- {{end}} -
-
- -{{ template "posts.html" .Posts }} - -
- - -
-{{ end }} diff --git a/webapp/rust/templates/layout.html b/webapp/rust/templates/layout.html deleted file mode 100644 index 846b50e5d..000000000 --- a/webapp/rust/templates/layout.html +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - Iscogram - - - - -
-
-
-

Iscogram

-
-
- {{ if eq .Me.ID 0}} - - {{ else }} - - {{ if eq .Me.Authority 1 }} - - {{ end }} - - {{ end }} -
-
- - {{ template "content" . }} -
- - - - - \ No newline at end of file diff --git a/webapp/rust/templates/login.html b/webapp/rust/templates/login.html deleted file mode 100644 index aad60e47d..000000000 --- a/webapp/rust/templates/login.html +++ /dev/null @@ -1,31 +0,0 @@ -{{ define "content" }} -
-

ログイン

-
- -{{if .Flash}} -
- {{.Flash}} -
-{{end}} - -
-
- -
- パスワード - -
-
- -
-
-
- - -{{ end }} diff --git a/webapp/rust/templates/post.html b/webapp/rust/templates/post.html deleted file mode 100644 index d7279d6a8..000000000 --- a/webapp/rust/templates/post.html +++ /dev/null @@ -1,35 +0,0 @@ -
-
- - - - -
-
- -
-
- - {{ .Body }} -
-
-
- comments: {{ .CommentCount }} -
- - {{ range .Comments }} -
- - {{.Comment}} -
- {{ end }} -
-
- - - - -
-
-
-
diff --git a/webapp/rust/templates/post_id.html b/webapp/rust/templates/post_id.html deleted file mode 100644 index 939948530..000000000 --- a/webapp/rust/templates/post_id.html +++ /dev/null @@ -1,3 +0,0 @@ -{{ define "content" }} -{{ template "post.html" .Post }} -{{ end }} diff --git a/webapp/rust/templates/posts.html b/webapp/rust/templates/posts.html deleted file mode 100644 index 1e27b8959..000000000 --- a/webapp/rust/templates/posts.html +++ /dev/null @@ -1,5 +0,0 @@ -
- {{ range . }} - {{ template "post.html" . }} - {{ end }} -
diff --git a/webapp/rust/templates/register.html b/webapp/rust/templates/register.html deleted file mode 100644 index 6becf9da3..000000000 --- a/webapp/rust/templates/register.html +++ /dev/null @@ -1,27 +0,0 @@ -{{ define "content" }} -
-

ユーザー登録

-
- -{{if .Flash}} -
- {{.Flash}} -
-{{end}} - -
-
- -
- パスワード - -
-
- -
-
-
-{{ end }} diff --git a/webapp/rust/templates/user.html b/webapp/rust/templates/user.html deleted file mode 100644 index 6e9a100ab..000000000 --- a/webapp/rust/templates/user.html +++ /dev/null @@ -1,10 +0,0 @@ -{{ define "content" }} -
-
のページ
-
投稿数 {{ .PostCount }}
-
コメント数 {{ .CommentCount }}
-
被コメント数 {{ .CommentedCount }}
-
- -{{ template "posts.html" .Posts }} -{{ end }} From 72165e51088fbdd4a4dcca9cd3361acc0dd89836 Mon Sep 17 00:00:00 2001 From: Romira915 <40430090+Romira915@users.noreply.github.com> Date: Sat, 18 Jun 2022 23:50:04 +0900 Subject: [PATCH 51/64] =?UTF-8?q?fix:=20redis=E3=81=B8=E3=81=AE=E4=BE=9D?= =?UTF-8?q?=E5=AD=98=E3=82=92=E5=89=8A=E9=99=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- webapp/docker-compose.yml | 7 ------- webapp/rust/src/main.rs | 3 --- 2 files changed, 10 deletions(-) diff --git a/webapp/docker-compose.yml b/webapp/docker-compose.yml index 917d3a696..277b8dd03 100644 --- a/webapp/docker-compose.yml +++ b/webapp/docker-compose.yml @@ -19,7 +19,6 @@ services: ISUCONP_DB_PASSWORD: root ISUCONP_DB_NAME: isuconp ISUCONP_MEMCACHED_ADDRESS: memcached:11211 - ISUCONP_REDIS_URL: redis:6379 links: - mysql - memcached @@ -62,11 +61,5 @@ services: memcached: image: memcached:1.6 - redis: - image: redis:7.0.0 - restart: always - ports: - - 6379:6379 - volumes: mysql: diff --git a/webapp/rust/src/main.rs b/webapp/rust/src/main.rs index 55f796b2d..9eb15cd61 100644 --- a/webapp/rust/src/main.rs +++ b/webapp/rust/src/main.rs @@ -1338,8 +1338,6 @@ async fn main() -> io::Result<()> { .await .unwrap(); - let private_key = actix_web::cookie::Key::generate(); - HttpServer::new(move || { let mut handlebars = Handlebars::new(); handlebars.register_helper("image_url_helper", Box::new(image_url)); @@ -1375,7 +1373,6 @@ async fn main() -> io::Result<()> { .service(get_admin_banned) .service(post_admin_banned) .service(get_account_name) - // .service(ResourceDef::new("/{tail}*").) .service(Files::new("/", "../public")) }) .bind(("0.0.0.0", 8080))? From e3f67db7cd2779bb306a0d0921744d95e1c870d4 Mon Sep 17 00:00:00 2001 From: Romira915 <40430090+Romira915@users.noreply.github.com> Date: Sun, 19 Jun 2022 00:03:56 +0900 Subject: [PATCH 52/64] exec: cargo fix --- webapp/rust/src/main.rs | 27 +++++++++------------------ 1 file changed, 9 insertions(+), 18 deletions(-) diff --git a/webapp/rust/src/main.rs b/webapp/rust/src/main.rs index 9eb15cd61..abca15814 100644 --- a/webapp/rust/src/main.rs +++ b/webapp/rust/src/main.rs @@ -1,32 +1,25 @@ use std::{ - any, - collections::HashMap, env, - f32::consts::E, - io::{self, Write}, + io::{self}, path::Path, time::Duration, }; use actix_cors::Cors; use actix_files::Files; -use actix_multipart::{Field, Multipart, MultipartError}; -use actix_redis::RedisSession; +use actix_multipart::{Field, Multipart}; + use actix_session::{CookieSession, Session}; use actix_web::{ cookie::time::UtcOffset, - dev::ResourceDef, - error, get, - http::{ - header::{self, ContentType}, - Method, StatusCode, - }, + get, + http::header::{self}, middleware, post, - web::{self, Bytes, Data, Form, Payload}, - App, HttpRequest, HttpResponse, HttpServer, Result, + web::{self, Data, Form, Payload}, + App, HttpResponse, HttpServer, Result, }; use anyhow::{bail, Context}; -use chrono::{DateTime, FixedOffset, Local, Utc}; +use chrono::{DateTime, FixedOffset, Utc}; use derive_more::Constructor; use duct::cmd; use futures_util::TryStreamExt; @@ -292,7 +285,7 @@ async fn make_post( .context("Failed to query comment_count")? .count; - let mut comments = if all_comments { + let comments = if all_comments { sqlx::query_as!( Comment, "SELECT * FROM `comments` WHERE `post_id` = ? ORDER BY `created_at` DESC", @@ -1318,8 +1311,6 @@ async fn main() -> io::Result<()> { }; let dbname = env::var("ISUCONP_DB_NAME").unwrap_or("isuconp".to_string()); - let redis_url = env::var("ISUCONP_REDIS_URL").unwrap_or("localhost:6379".to_string()); - let dsn = if cfg!(debug_assertions) { "mysql://root:root@localhost:3306/isuconp".to_string() } else { From 8808e105d4d12d5c8336ee8e1ca1399567706ff8 Mon Sep 17 00:00:00 2001 From: Romira915 <40430090+Romira915@users.noreply.github.com> Date: Sun, 19 Jun 2022 00:12:03 +0900 Subject: [PATCH 53/64] =?UTF-8?q?fix:=20cargo=20clippy=E3=81=AB=E5=89=87?= =?UTF-8?q?=E3=81=A3=E3=81=9F=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- webapp/rust/src/main.rs | 42 +++++++++++++++++++---------------------- 1 file changed, 19 insertions(+), 23 deletions(-) diff --git a/webapp/rust/src/main.rs b/webapp/rust/src/main.rs index abca15814..a6da5b743 100644 --- a/webapp/rust/src/main.rs +++ b/webapp/rust/src/main.rs @@ -196,7 +196,7 @@ async fn try_login(account_name: &str, password: &str, pool: &Pool) -> an } fn escapeshellarg(arg: &str) -> String { - format!("'{}'", arg.replace("'", "'\\''")) + format!("'{}'", arg.replace('\'', "'\\''")) } fn digest(src: &str) -> anyhow::Result { @@ -211,7 +211,7 @@ fn digest(src: &str) -> anyhow::Result { .read() .context("Failed to cmd")?; - Ok(output.trim_end_matches("\n").to_string()) + Ok(output.trim_end_matches('\n').to_string()) } fn validate_user(account_name: &str, password: &str) -> bool { @@ -394,7 +394,7 @@ fn secure_random_str(b: u32) -> String { rnd_str.push(AGGREGATION_LOWER_CASE_NUM.choose(&mut rng).unwrap()); } - let rnd_str = rnd_str.iter().map(|c| *c).collect(); + let rnd_str = rnd_str.iter().copied().collect(); rnd_str } @@ -561,7 +561,7 @@ async fn post_register( } }; - if let Some(_) = exists { + if exists.is_some() { if let Err(e) = session.insert("notice", "アカウント名がすでに使われています") { log::error!("{:?}", &e); @@ -990,20 +990,9 @@ async fn post_index( log::debug!("This is image"); mime = content_type; file = field_to_vec(&mut field).await.unwrap_or_default(); - } else { - if let Err(e) = - session.insert("notice", "投稿できる画像形式はjpgとpngとgifだけです") - { - log::error!("{:?}", &e); - return Ok(HttpResponse::InternalServerError().body(e.to_string())); - } else { - return Ok(HttpResponse::Found() - .insert_header((header::LOCATION, "/")) - .finish()); - } - } - } else { - if let Err(e) = session.insert("notice", "画像が必須です") { + } else if let Err(e) = + session.insert("notice", "投稿できる画像形式はjpgとpngとgifだけです") + { log::error!("{:?}", &e); return Ok(HttpResponse::InternalServerError().body(e.to_string())); } else { @@ -1011,6 +1000,13 @@ async fn post_index( .insert_header((header::LOCATION, "/")) .finish()); } + } else if let Err(e) = session.insert("notice", "画像が必須です") { + log::error!("{:?}", &e); + return Ok(HttpResponse::InternalServerError().body(e.to_string())); + } else { + return Ok(HttpResponse::Found() + .insert_header((header::LOCATION, "/")) + .finish()); } } "body" => { @@ -1297,19 +1293,19 @@ fn init_logger>(log_dir: Option

) { async fn main() -> io::Result<()> { init_logger::<&str>(None); - let host = env::var("ISUCONP_DB_HOST").unwrap_or("localhost".to_string()); + let host = env::var("ISUCONP_DB_HOST").unwrap_or_else(|_| "localhost".to_string()); let port: u32 = env::var("ISUCONP_DB_PORT") - .unwrap_or("3306".to_string()) + .unwrap_or_else(|_| "3306".to_string()) .parse() .unwrap(); - let user = env::var("ISUCONP_DB_USER").unwrap_or("root".to_string()); + let user = env::var("ISUCONP_DB_USER").unwrap_or_else(|_| "root".to_string()); let password = if cfg!(debug_assertions) { - env::var("ISUCONP_DB_PASSWORD").unwrap_or("root".to_string()) + env::var("ISUCONP_DB_PASSWORD").unwrap_or_else(|_| "root".to_string()) } else { env::var("ISUCONP_DB_PASSWORD").expect("Failed to ISUCONP_DB_PASSWORD") }; - let dbname = env::var("ISUCONP_DB_NAME").unwrap_or("isuconp".to_string()); + let dbname = env::var("ISUCONP_DB_NAME").unwrap_or_else(|_| "isuconp".to_string()); let dsn = if cfg!(debug_assertions) { "mysql://root:root@localhost:3306/isuconp".to_string() From 9bd48cc2114a4727d31928db19a1abd1c83f48da Mon Sep 17 00:00:00 2001 From: Romira915 <40430090+Romira915@users.noreply.github.com> Date: Sun, 19 Jun 2022 00:17:34 +0900 Subject: [PATCH 54/64] =?UTF-8?q?rm:=20=E4=B8=8D=E8=A6=81=E3=81=AA?= =?UTF-8?q?=E3=82=B3=E3=83=A1=E3=83=B3=E3=83=88=E5=89=8A=E9=99=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- webapp/rust/src/main.rs | 32 +++----------------------------- 1 file changed, 3 insertions(+), 29 deletions(-) diff --git a/webapp/rust/src/main.rs b/webapp/rust/src/main.rs index a6da5b743..51e2135a9 100644 --- a/webapp/rust/src/main.rs +++ b/webapp/rust/src/main.rs @@ -347,17 +347,6 @@ async fn make_post( Ok(granted_info_posts) } -// fn image_url(p: &GrantedInfoPost) -> String { -// let ext = match p.post.mime.as_str() { -// "image/jpeg" => ".jpg", -// "image/png" => ".png", -// "image/gif" => ".gif", -// _ => "", -// }; - -// format!("/image/{}{}", p.post.id, ext) -// } - handlebars_helper!(image_url: |p: GrantedInfoPost| { let ext = match p.post.mime.as_str() { "image/jpeg" => ".jpg", @@ -642,12 +631,7 @@ async fn get_index( }; let csrf_token = get_csrf_token(&session).unwrap_or_default(); - // let csrf_token = if let Some(token) = get_csrf_token(&session) { - // token - // } else { - // log::error!("token is None"); - // return Ok(HttpResponse::InternalServerError().finish()); - // }; + let posts = match make_post(results, csrf_token, false, pool.as_ref()).await { Ok(posts) => posts, Err(e) => { @@ -658,8 +642,7 @@ async fn get_index( let body = { let mut map = Map::new(); - // let posts = serde_json::to_value(posts).unwrap(); - // let map = json.as_object_mut().unwrap(); + map.insert("posts".to_string(), to_json(posts)); map.insert("me".to_string(), to_json(me)); map.insert( @@ -797,8 +780,7 @@ async fn get_account_name( let body = { let mut map = Map::new(); - // let posts = serde_json::to_value(posts).unwrap(); - // let map = json.as_object_mut().unwrap(); + map.insert("posts".to_string(), to_json(posts)); map.insert("user".to_string(), to_json(user)); map.insert("post_count".to_string(), to_json(post_count)); @@ -927,11 +909,6 @@ async fn get_posts_id( }; let body = { - // let mut map = Map::new(); - // let posts = serde_json::to_value(posts).unwrap(); - // let map = json.as_object_mut().unwrap(); - // map.insert("post".to_string(), to_json(p)); - let mut post = serde_json::to_value(p).unwrap(); let map = post.as_object_mut().unwrap(); map.insert("me".to_string(), to_json(me)); @@ -939,9 +916,6 @@ async fn get_posts_id( map.insert("post_parent".to_string(), to_json("post_id")); map.insert("content_parent".to_string(), to_json("layout")); - // let mut file = std::fs::File::create(".tmp/get_posts_id.json").unwrap(); - // write!(file, "{:#?}", &map).unwrap(); - handlebars.render("post", &map).unwrap() }; From 262f96b106fade107c3af6debb768cece0024df1 Mon Sep 17 00:00:00 2001 From: Romira915 <40430090+Romira915@users.noreply.github.com> Date: Sun, 19 Jun 2022 00:24:59 +0900 Subject: [PATCH 55/64] fix: log level --- webapp/rust/src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/webapp/rust/src/main.rs b/webapp/rust/src/main.rs index 51e2135a9..6f510b256 100644 --- a/webapp/rust/src/main.rs +++ b/webapp/rust/src/main.rs @@ -456,7 +456,7 @@ async fn post_login( .finish()) } Err(e) => { - log::error!("{:?}", &e); + log::info!("{:?}", &e); session .insert("notice", "アカウント名かパスワードが間違っています") .unwrap(); From 4cee458d57ca5d02b66e8dfbf30a9fada2d8bdea Mon Sep 17 00:00:00 2001 From: Romira915 <40430090+Romira915@users.noreply.github.com> Date: Sun, 19 Jun 2022 02:21:01 +0900 Subject: [PATCH 56/64] =?UTF-8?q?fix:=20golang=E3=81=AE=E5=87=A6=E7=90=86?= =?UTF-8?q?=E3=81=AB=E6=BA=96=E6=8B=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- webapp/rust/src/main.rs | 48 ++++++++++++++++++++--------------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/webapp/rust/src/main.rs b/webapp/rust/src/main.rs index 6f510b256..e6676e4df 100644 --- a/webapp/rust/src/main.rs +++ b/webapp/rust/src/main.rs @@ -580,18 +580,18 @@ async fn post_register( Ok(r) => r.last_insert_id(), Err(e) => { log::error!("{:?}", &e); - return Ok(HttpResponse::InternalServerError().body(e.to_string())); + return Ok(HttpResponse::Ok().body(e.to_string())); } }; log::debug!("last insert id {}", &uid); if let Err(e) = session.insert("user_id", uid) { log::error!("{:?}", &e); - return Ok(HttpResponse::InternalServerError().body(e.to_string())); + return Ok(HttpResponse::Ok().body(e.to_string())); } if let Err(e) = session.insert("csrf_token", secure_random_str(32)) { log::error!("{:?}", &e); - return Ok(HttpResponse::InternalServerError().body(e.to_string())); + return Ok(HttpResponse::Ok().body(e.to_string())); } Ok(HttpResponse::Found() @@ -626,7 +626,7 @@ async fn get_index( Ok(results) => results, Err(e) => { log::error!("{:?}",&e); - return Ok(HttpResponse::InternalServerError().body(e.to_string())); + return Ok(HttpResponse::Ok().body(e.to_string())); } }; @@ -636,7 +636,7 @@ async fn get_index( Ok(posts) => posts, Err(e) => { log::error!("{:?}", &e); - return Ok(HttpResponse::InternalServerError().body(e.to_string())); + return Ok(HttpResponse::Ok().body(e.to_string())); } }; @@ -682,7 +682,7 @@ async fn get_account_name( Ok(None) => return Ok(HttpResponse::NotFound().finish()), Err(e) => { log::error!("{:?}", &e); - return Ok(HttpResponse::InternalServerError().body(e.to_string())); + return Ok(HttpResponse::Ok().body(e.to_string())); } }; @@ -690,7 +690,7 @@ async fn get_account_name( Ok(r) => r, Err(e)=>{ log::error!("{:?}", &e); - return Ok(HttpResponse::InternalServerError().body(e.to_string())); + return Ok(HttpResponse::Ok().body(e.to_string())); } }; @@ -705,7 +705,7 @@ async fn get_account_name( Ok(p) => p, Err(e) => { log::error!("{:?}", &e); - return Ok(HttpResponse::InternalServerError().body(e.to_string())); + return Ok(HttpResponse::Ok().body(e.to_string())); } }; @@ -719,7 +719,7 @@ async fn get_account_name( Ok(r) => r.count, Err(e) => { log::error!("{:?}", &e); - return Ok(HttpResponse::InternalServerError().body(e.to_string())); + return Ok(HttpResponse::Ok().body(e.to_string())); } }; @@ -730,7 +730,7 @@ async fn get_account_name( Ok(records) => records.iter().map(|r| r.id).collect::>(), Err(e) => { log::error!("{:?}", &e); - return Ok(HttpResponse::InternalServerError().body(e.to_string())); + return Ok(HttpResponse::Ok().body(e.to_string())); } }; let post_count = post_ids.len(); @@ -761,7 +761,7 @@ async fn get_account_name( Ok(c) => c, Err(e) => { log::error!("{:?}", &e); - return Ok(HttpResponse::InternalServerError().body(e.to_string())); + return Ok(HttpResponse::Ok().body(e.to_string())); } }; @@ -809,14 +809,14 @@ async fn get_posts( let max_create_at = query.into_inner().max_created_at; if max_create_at.is_empty() { - return Ok(HttpResponse::InternalServerError().finish()); + return Ok(HttpResponse::Ok().finish()); } let t = match DateTime::parse_from_rfc3339(&max_create_at) { Ok(t) => t, Err(e) => { log::error!("{:?}", &e); - return Ok(HttpResponse::InternalServerError().body(e.to_string())); + return Ok(HttpResponse::Ok().body(e.to_string())); } }; @@ -824,7 +824,7 @@ async fn get_posts( Ok(r)=> r, Err(e)=> { log::error!("{:?}", &e); - return Ok(HttpResponse::InternalServerError().body(e.to_string())); + return Ok(HttpResponse::Ok().body(e.to_string())); } }; @@ -839,7 +839,7 @@ async fn get_posts( Ok(p) => p, Err(e) => { log::error!("{:?}", &e); - return Ok(HttpResponse::InternalServerError().body(e.to_string())); + return Ok(HttpResponse::Ok().body(e.to_string())); } }; @@ -875,7 +875,7 @@ async fn get_posts_id( Ok(r) => r, Err(e) => { log::error!("{:?}", &e); - return Ok(HttpResponse::InternalServerError().body(e.to_string())); + return Ok(HttpResponse::Ok().body(e.to_string())); } }; @@ -890,7 +890,7 @@ async fn get_posts_id( Ok(p) => p, Err(e) => { log::error!("{:?}", &e); - return Ok(HttpResponse::InternalServerError().body(e.to_string())); + return Ok(HttpResponse::Ok().body(e.to_string())); } }; @@ -1025,7 +1025,7 @@ async fn post_index( Ok(result) => result.last_insert_id(), Err(e) => { log::error!("{:?}", &e); - return Ok(HttpResponse::InternalServerError().body(e.to_string())); + return Ok(HttpResponse::Ok().body(e.to_string())); } }; @@ -1048,16 +1048,16 @@ async fn get_image( Ok(Some(post)) => post, Err(e) => { log::warn!("{:?}", &e); - return Ok(HttpResponse::InternalServerError().body(e.to_string())); + return Ok(HttpResponse::Ok().body(e.to_string())); } _ => { - return Ok(HttpResponse::InternalServerError().finish()); + return Ok(HttpResponse::Ok().finish()); } }; let content_type = match (ext.as_str(), post.mime.as_str()) { ("jpg", "image/jpeg") | ("png", "image/png") | ("gif", "image/gif") => post.mime.as_str(), - _ => return Ok(HttpResponse::InternalServerError().finish()), + _ => return Ok(HttpResponse::Ok().finish()), }; Ok(HttpResponse::Ok() @@ -1100,7 +1100,7 @@ async fn post_comment( .await { log::warn!("{:?}", &e); - return Ok(HttpResponse::InternalServerError().body(e.to_string())); + return Ok(HttpResponse::Ok().body(e.to_string())); } Ok(HttpResponse::Found() @@ -1143,7 +1143,7 @@ async fn get_admin_banned( Ok(users) => users, Err(e) => { log::warn!("{:?}", &e); - return Ok(HttpResponse::InternalServerError().body(e.to_string())); + return Ok(HttpResponse::Ok().body(e.to_string())); } }; @@ -1201,7 +1201,7 @@ async fn post_admin_banned( Ok(q) => q, Err(e) => { log::error!("{:#?}", &e); - return Ok(HttpResponse::InternalServerError().body(e.to_string())); + return Ok(HttpResponse::Ok().body(e.to_string())); } }; log::debug!("admin banned {:?}", query); From b3ba129587d29c92b3b47ca8141b3d8c2226abee Mon Sep 17 00:00:00 2001 From: Romira915 <40430090+Romira915@users.noreply.github.com> Date: Sun, 19 Jun 2022 11:44:34 +0900 Subject: [PATCH 57/64] fix: cargo fix --- webapp/rust/src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/webapp/rust/src/main.rs b/webapp/rust/src/main.rs index e6676e4df..e2168b580 100644 --- a/webapp/rust/src/main.rs +++ b/webapp/rust/src/main.rs @@ -686,7 +686,7 @@ async fn get_account_name( } }; - let results =match sqlx::query_as!(Post,"SELECT `id`, `user_id`, `body`, `mime`, `created_at`, b'0' AS imgdata FROM `posts` WHERE `user_id` = ? ORDER BY `created_at` DESC",user.id).fetch_all(pool.as_ref()).await{ + let results = match sqlx::query_as!(Post,"SELECT `id`, `user_id`, `body`, `mime`, `created_at`, b'0' AS imgdata FROM `posts` WHERE `user_id` = ? ORDER BY `created_at` DESC",user.id).fetch_all(pool.as_ref()).await{ Ok(r) => r, Err(e)=>{ log::error!("{:?}", &e); From f65cefca84c07293d04e944e8bf1cc87069df853 Mon Sep 17 00:00:00 2001 From: Romira915 <40430090+Romira915@users.noreply.github.com> Date: Sun, 19 Jun 2022 11:59:53 +0900 Subject: [PATCH 58/64] rm : .vscode --- webapp/rust/.vscode/settings.json | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 webapp/rust/.vscode/settings.json diff --git a/webapp/rust/.vscode/settings.json b/webapp/rust/.vscode/settings.json deleted file mode 100644 index 6378977b1..000000000 --- a/webapp/rust/.vscode/settings.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "codic.case": "snake_case" -} From 9cb1397c4dccd2e588ca2793c32fb9b45779ea49 Mon Sep 17 00:00:00 2001 From: Romira915 <40430090+Romira915@users.noreply.github.com> Date: Sun, 19 Jun 2022 12:35:17 +0900 Subject: [PATCH 59/64] =?UTF-8?q?fix:=20=E3=83=AA=E3=83=B3=E3=82=AF?= =?UTF-8?q?=E3=83=9F=E3=82=B9=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- webapp/rust/src/main.rs | 13 +++++-------- webapp/rust/static/layout.html | 2 +- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/webapp/rust/src/main.rs b/webapp/rust/src/main.rs index e2168b580..ad4e090b3 100644 --- a/webapp/rust/src/main.rs +++ b/webapp/rust/src/main.rs @@ -1,9 +1,4 @@ -use std::{ - env, - io::{self}, - path::Path, - time::Duration, -}; +use std::{env, io, path::Path, time::Duration}; use actix_cors::Cors; use actix_files::Files; @@ -13,7 +8,7 @@ use actix_session::{CookieSession, Session}; use actix_web::{ cookie::time::UtcOffset, get, - http::header::{self}, + http::header, middleware, post, web::{self, Data, Form, Payload}, App, HttpResponse, HttpServer, Result, @@ -1299,6 +1294,8 @@ async fn main() -> io::Result<()> { .await .unwrap(); + let private_key = actix_web::cookie::Key::generate(); + HttpServer::new(move || { let mut handlebars = Handlebars::new(); handlebars.register_helper("image_url_helper", Box::new(image_url)); @@ -1316,7 +1313,7 @@ async fn main() -> io::Result<()> { .supports_credentials() .allowed_origin("http://localhost") }) - .wrap(CookieSession::signed(&[0; 32]).secure(false)) + .wrap(CookieSession::signed(private_key.encryption()).secure(false)) .app_data(Data::new(db.clone())) .app_data(Data::new(handlebars)) .service(get_initialize) diff --git a/webapp/rust/static/layout.html b/webapp/rust/static/layout.html index 5af88c5a6..288dfdfb4 100644 --- a/webapp/rust/static/layout.html +++ b/webapp/rust/static/layout.html @@ -17,7 +17,7 @@

Iscogram

{{#if (eq me.id 0)}} {{else}} - + {{#if (eq me.authority 1)}} {{/if}} From c08215d29b17a84a4570ba05983cdd08a92887c5 Mon Sep 17 00:00:00 2001 From: Romira915 <40430090+Romira915@users.noreply.github.com> Date: Sun, 19 Jun 2022 13:27:33 +0900 Subject: [PATCH 60/64] fix: default app --- webapp/docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/webapp/docker-compose.yml b/webapp/docker-compose.yml index 277b8dd03..ce96d98c3 100644 --- a/webapp/docker-compose.yml +++ b/webapp/docker-compose.yml @@ -11,7 +11,7 @@ services: app: # Go実装の場合は golang/ PHP実装の場合は php/ - build: rust/ + build: ruby/ environment: ISUCONP_DB_HOST: mysql ISUCONP_DB_PORT: 3306 From fd26f9121fb2017f1cf521abd9653f4b66f878be Mon Sep 17 00:00:00 2001 From: Romira915 <40430090+Romira915@users.noreply.github.com> Date: Sun, 19 Jun 2022 14:35:38 +0900 Subject: [PATCH 61/64] =?UTF-8?q?fix:=20golang=E3=81=AE=E6=84=8F=E5=9B=B3?= =?UTF-8?q?=E3=81=97=E3=81=A6=E3=81=84=E3=81=AA=E3=81=84=E7=B7=A8=E9=9B=86?= =?UTF-8?q?=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- webapp/golang/app.go | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/webapp/golang/app.go b/webapp/golang/app.go index 63edcd1b2..719285367 100644 --- a/webapp/golang/app.go +++ b/webapp/golang/app.go @@ -369,9 +369,7 @@ func postRegister(w http.ResponseWriter, r *http.Request) { return } session.Values["user_id"] = uid - rstr := secureRandomStr(16) - log.Print(rstr) - session.Values["csrf_token"] = rstr + session.Values["csrf_token"] = secureRandomStr(16) session.Save(r, w) http.Redirect(w, r, "/", http.StatusFound) From 9838a225df759cc4132180a724249626541874b6 Mon Sep 17 00:00:00 2001 From: Romira915 <40430090+Romira915@users.noreply.github.com> Date: Sun, 19 Jun 2022 23:01:15 +0900 Subject: [PATCH 62/64] fix: cmd! to duct_sh --- webapp/rust/Cargo.toml | 1 + webapp/rust/src/main.rs | 14 ++++---------- 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/webapp/rust/Cargo.toml b/webapp/rust/Cargo.toml index 6fe50029a..5d642a2b5 100644 --- a/webapp/rust/Cargo.toml +++ b/webapp/rust/Cargo.toml @@ -20,6 +20,7 @@ anyhow = "1.0.57" chrono = {version = "0.4.19", features = ["serde"]} derive_more = "0.99.17" duct = "0.13.5" +duct_sh = "0.13.5" futures-util = {version = "0.3.21", default-features = false, features = ["std"]} log = "0.4.17" num_cpus = "1.13.1" diff --git a/webapp/rust/src/main.rs b/webapp/rust/src/main.rs index ad4e090b3..62f986893 100644 --- a/webapp/rust/src/main.rs +++ b/webapp/rust/src/main.rs @@ -195,16 +195,10 @@ fn escapeshellarg(arg: &str) -> String { } fn digest(src: &str) -> anyhow::Result { - let output = cmd!( - "/bin/bash", - "-c", - format!( - r#"printf "%s" {} | openssl dgst -sha512 | sed 's/^.*= //'"#, - escapeshellarg(src) - ) - ) - .read() - .context("Failed to cmd")?; + let output = duct_sh::sh(r#"printf "%s" $SRC | openssl dgst -sha512 | sed 's/^.*= //'"#) + .env("SRC", src) + .read() + .context("Failed to cmd")?; Ok(output.trim_end_matches('\n').to_string()) } From 486a6e9b4e405297da03f54e16443cb966558d24 Mon Sep 17 00:00:00 2001 From: Romira915 <40430090+Romira915@users.noreply.github.com> Date: Mon, 20 Jun 2022 12:42:02 +0900 Subject: [PATCH 63/64] fix: append about rust --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index aa6446225..acb176f72 100644 --- a/README.md +++ b/README.md @@ -47,6 +47,7 @@ Ubuntu 20.04 / 22.04 * Ruby/Go/PHPの3言語が用意されており、デフォルトはRubyが起動する * Node.jsは現状メンテナンスされていない + * Rustは現在、Docker Composeでのみ用意されている * AMI・Vagrantで他の言語の実装を動かす場合は[manual.md](/manual.md)を参考にする * AMI・Docker Compose・Vagrantが用意されている * 手元で適当に動かすことも難しくない From 84467ae88ca2d4eac670ecef4d62140f781f0dda Mon Sep 17 00:00:00 2001 From: Romira915 <40430090+Romira915@users.noreply.github.com> Date: Mon, 20 Jun 2022 16:36:24 +0900 Subject: [PATCH 64/64] fix: escape shell arg --- webapp/rust/src/main.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/webapp/rust/src/main.rs b/webapp/rust/src/main.rs index 62f986893..0bf18df43 100644 --- a/webapp/rust/src/main.rs +++ b/webapp/rust/src/main.rs @@ -16,7 +16,6 @@ use actix_web::{ use anyhow::{bail, Context}; use chrono::{DateTime, FixedOffset, Utc}; use derive_more::Constructor; -use duct::cmd; use futures_util::TryStreamExt; use handlebars::{handlebars_helper, to_json, Handlebars}; use log::LevelFilter; @@ -190,12 +189,12 @@ async fn try_login(account_name: &str, password: &str, pool: &Pool) -> an } } -fn escapeshellarg(arg: &str) -> String { +fn _escapeshellarg(arg: &str) -> String { format!("'{}'", arg.replace('\'', "'\\''")) } fn digest(src: &str) -> anyhow::Result { - let output = duct_sh::sh(r#"printf "%s" $SRC | openssl dgst -sha512 | sed 's/^.*= //'"#) + let output = duct_sh::sh(r#"printf "%s" "$SRC" | openssl dgst -sha512 | sed 's/^.*= //'"#) .env("SRC", src) .read() .context("Failed to cmd")?;