Rust blog backend in Rocket and Diesel, lots of clones

I have a small blog backend in Rust with Rocket and Diesel on Postgres. It reads and writes to and from the database fine, but to get to where it is I used a lot of clone() calls on strings. I feel like it could be written more efficiently with lifetimes, but my grasp of lifetimes in Rust is quite tenuous and I get a lot of compiler complaints.

The blog is divided into collections called ‘atlases’ with sub pages in each atlas. Each page has properties including ancestors, content blocks, and user IDs and roles. Each request comes with a cookie containing a session ID. To get a page the program receives a POST request to an endpoint containing an atlas ID and a page ID. It uses the cookie to authenticate the request, then queries the database through a Diesel schema to get the content blocks, ancestors, and other bits and bobs belonging to the page, and returns them as JSON data.

The main.rs file is generally standard Rocket boilerplate. The relevant bits for the POST handler to get a page from an atlas:

mod atlas;
#(macro_use)
extern crate rocket;
#(macro_use)
extern crate rocket_contrib;
#(macro_use)
extern crate diesel;

use response::{ResponseJson, ResponsePublicMedia, ResponseStaticFile, STATIC_FILES};
use rocket::http::CookieJar;
use rocket::Data;

pub mod schema;

#(database("postgres_conn"))
pub struct Db(diesel::PgConnection);

... // various endpoints and handlers

#(post("/endpoint/atlas.page.get/<atlas_id>/<page_id>"))
async fn tel_atlas_page_get(
    conn: Db,
    cookies: &CookieJar<'_>,
    atlas_id: String,
    page_id: String,
) -> ResponseJson {
    atlas::page_get(conn, cookies, atlas_id, page_id).await
}

...

#(launch)
fn rocket() -> rocket::Rocket {
    rocket::ignite()
        .mount(
            "/",
            routes!(
                ...
                tel_atlas_page_get,
                ...
            ),
        )
        .attach(Db::fairing())
}

The handler internals file:

use crate::atlas;
use crate::response::ResponseJson;
use crate::users::auth;
use crate::utilities::ERR;
use crate::Db;

use rocket::http::CookieJar;
use rocket_contrib::databases::diesel::prelude::*;

pub async fn page_get(
    conn: Db,
    cookies: &CookieJar<'_>,
    atlas_id: String,
    page_id: String,
) -> ResponseJson {
    // Page data
    let a_clone_page = atlas_id.clone();
    let p_clone_page = page_id.clone();
    let page = match conn.run(|c| get_page(c, a_clone_page, p_clone_page)).await {
        Some(p) => p,
        None => return ResponseJson::message("page.404", ""),
    };

    // User ID
    let user_id = match cookies.get("token") {
        Some(cookie) => match auth::check(cookie).await {
            Some((_email, user_id, _name, _token)) => Some(user_id),
            None => None,
        },
        None => None,
    };

    // Atlas role
    let a_clone_role = atlas_id.clone();
    let role = match user_id.clone() {
        Some(u) => conn.run(|c| get_atlas_role(c, u, a_clone_role)).await,
        None => "none".to_owned(),
    };

    // Page users
    let a_clone_users = atlas_id.clone();
    let p_clone_users = page_id.clone();
    let users = match user_id.clone() {
        Some(u) => {
            conn.run(|c| get_users(c, u, a_clone_users, p_clone_users))
                .await
        }
        None => Vec::new(),
    };

    if page.public || role != "none" || (user_id.is_some() && !users.is_empty()) {
        // Page ancestors
        let a_clone_ancestors = atlas_id.clone();
        let p_clone_ancestors = page_id.clone();
        let ancestors = conn
            .run(|c| get_ancestors(c, a_clone_ancestors, p_clone_ancestors))
            .await;

        // Page children
        let a_clone_children = atlas_id.clone();
        let p_clone_children = page_id.clone();
        let children = conn
            .run(|c| get_children(c, a_clone_children, p_clone_children))
            .await;

        // Page blocks
        let timestamp_clone = page.timestamp.clone();
        let blocks = conn
            .run(|c| get_blocks(c, atlas_id, page_id, timestamp_clone))
            .await;

        // JSON encode
        let page_encoded = match serde_json::to_string(&page) {
            Ok(e) => e,
            Err(_) => return ResponseJson::error(ERR.generic),
        };
        let users_encoded = match serde_json::to_string(&users) {
            Ok(e) => e,
            Err(_) => return ResponseJson::error(ERR.generic),
        };
        let ancestors_encoded = match serde_json::to_string(&ancestors) {
            Ok(e) => e,
            Err(_) => return ResponseJson::error(ERR.generic),
        };
        let children_encoded = match serde_json::to_string(&children) {
            Ok(e) => e,
            Err(_) => return ResponseJson::error(ERR.generic),
        };
        let blocks_encoded = match serde_json::to_string(&blocks) {
            Ok(e) => e,
            Err(_) => return ResponseJson::error(ERR.generic),
        };
        ResponseJson::message(
            "atlas.page",
            &format!(
                "{{"page":{},"atlas_role":"{}","users":{},"ancestors":{},"blocks":{},"children":{}}}",
                page_encoded, role, users_encoded, ancestors_encoded, blocks_encoded, children_encoded
            ),
        )
    } else {
        ResponseJson::message("auth.forbidden", "")
    }
}

fn get_page(
    conn: &mut diesel::PgConnection,
    atlas_id: String,
    page_id: String,
) -> Option<atlas::Page> {
    use crate::schema::atlas_pages;

    if &page_id == "maps" || &page_id == "locations" {
        match atlas_pages::table
            .select((
                atlas_pages::page_id,
                atlas_pages::atlas_id,
                atlas_pages::title,
                atlas_pages::image,
                atlas_pages::public,
                atlas_pages::parent,
                atlas_pages::timestamp,
            ))
            .filter(atlas_pages::atlas_id.eq(&atlas_id))
            .filter(atlas_pages::page_id.eq("index"))
            .first::<atlas::Page>(conn)
        {
            Ok(a) => Some(atlas::Page {
                page_id,
                atlas_id,
                title: a.title,
                image: a.image,
                public: a.public,
                parent: "index".to_owned(),
                timestamp: a.timestamp,
            }),
            Err(_) => None,
        }
    } else {
        match atlas_pages::table
            .select((
                atlas_pages::page_id,
                atlas_pages::atlas_id,
                atlas_pages::title,
                atlas_pages::image,
                atlas_pages::public,
                atlas_pages::parent,
                atlas_pages::timestamp,
            ))
            .filter(atlas_pages::atlas_id.eq(&atlas_id))
            .filter(atlas_pages::page_id.eq(&page_id))
            .first::<atlas::Page>(conn)
        {
            Ok(a) => Some(a),
            Err(_) => None,
        }
    }
}

fn get_users(
    conn: &mut diesel::PgConnection,
    user_id: String,
    atlas_id: String,
    page_id: String,
) -> Vec<atlas::AtlasUser> {
    use crate::schema::page_users;

    let user = match page_users::table
        .select((page_users::user_id, page_users::user_type))
        .filter(page_users::user_id.eq(&user_id))
        .filter(page_users::atlas_id.eq(&atlas_id))
        .filter(page_users::page_id.eq(&page_id))
        .first::<atlas::AtlasUser>(conn)
    {
        Ok(a) => a,
        Err(_) => return Vec::new(),
    };

    if user.user_type == "owner" {
        match page_users::table
            .select((page_users::user_id, page_users::user_type))
            .filter(page_users::atlas_id.eq(&atlas_id))
            .filter(page_users::page_id.eq(&page_id))
            .load::<atlas::AtlasUser>(conn)
        {
            Ok(a) => a,
            Err(_) => Vec::new(),
        }
    } else {
        vec!(user)
    }
}

fn get_atlas_role(conn: &mut diesel::PgConnection, user_id: String, atlas_id: String) -> String {
    use crate::schema::page_users;

    match page_users::table
        .select((page_users::user_id, page_users::user_type))
        .filter(page_users::user_id.eq(&user_id))
        .filter(page_users::atlas_id.eq(&atlas_id))
        .filter(page_users::page_id.eq("index"))
        .first::<atlas::AtlasUser>(conn)
    {
        Ok(a) => a.user_type,
        Err(_) => "none".to_owned(),
    }
}

fn get_ancestors(
    conn: &mut diesel::PgConnection,
    atlas_id: String,
    page_id: String,
) -> Vec<atlas::Ancestors> {
    use crate::schema::page_ancestors;

    match page_ancestors::table
        .select((
            page_ancestors::page_id,
            page_ancestors::atlas_id,
            page_ancestors::title,
            page_ancestors::index,
            page_ancestors::ancestor,
        ))
        .filter(page_ancestors::atlas_id.eq(&atlas_id))
        .filter(page_ancestors::page_id.eq(&page_id))
        .order(page_ancestors::index.asc())
        .load::<atlas::Ancestors>(conn)
    {
        Ok(a) => a,
        Err(_) => Vec::new(),
    }
}

fn get_children(
    conn: &mut diesel::PgConnection,
    atlas_id: String,
    page_id: String,
) -> Vec<atlas::Page> {
    use crate::schema::atlas_pages;

    match atlas_pages::table
        .select((
            atlas_pages::page_id,
            atlas_pages::atlas_id,
            atlas_pages::title,
            atlas_pages::image,
            atlas_pages::public,
            atlas_pages::parent,
            atlas_pages::timestamp,
        ))
        .filter(atlas_pages::atlas_id.eq(&atlas_id))
        .filter(atlas_pages::parent.eq(&page_id))
        .order(atlas_pages::title.desc())
        .load::<atlas::Page>(conn)
    {
        Ok(a) => a,
        Err(_) => Vec::new(),
    }
}

fn get_blocks(
    conn: &mut diesel::PgConnection,
    atlas_id: String,
    page_id: String,
    timestamp: String,
) -> Vec<atlas::Block> {
    use crate::schema::page_blocks;

    match page_blocks::table
        .select((
            page_blocks::page_id,
            page_blocks::atlas_id,
            page_blocks::index,
            page_blocks::label,
            page_blocks::block,
            page_blocks::text,
            page_blocks::data,
            page_blocks::timestamp,
        ))
        .filter(page_blocks::atlas_id.eq(atlas_id))
        .filter(page_blocks::page_id.eq(page_id))
        .filter(page_blocks::timestamp.eq(timestamp))
        .order(page_blocks::index.asc())
        .load::<atlas::Block>(conn)
    {
        Ok(a) => a,
        Err(_) => Vec::new(),
    }
}

I will write & publish article on DA 56 Fashion, lifestyle and beauty Blog. for $10

I will write & publish article on DA 56 Fashion, lifestyle and beauty Blog.

I will write and publish post with DO-FOLLOW backlink on Fashion, lifestyle, and beauty Blog.

Niche:

Accepting only Fashion, lifestyle, and beauty related article.

Benefits:

Unique content

Article with a permanent DOFOLLOW backlink.

The post will be listed on the homepage of our site for a limited time until new posts are published

We will add internal and external links to improve SEO and to make the article look more natural.

100% Satisfaction

Please contact for more details

.

Casino blog posts on quality blog

Embed

HTML:

BBCode:

Link image:

i will provide 05 niche relevant dofollow blog comment backlinks for $5

i will provide 05 niche relevant dofollow blog comment backlinks

Are you looking for niche relevant do-follow links? Then you are at right place!

If you are looking for a way to drive traffic to your website,And want to rank your website, so try dofollow niche relevant dofollow blog comments service. really matter for the performance of very website. These powerful link will skyrocket your site on Google.

All Backlinks Will be Dofollow

OBL will be Low

All well indexed pages

Variety of different domains

100% SERP will be improved after using this service

All Comments will be made Manually,and relevant

No use of any auto approved software’s or tools

No spammed comments.

After completion i provide full detail with Excel report

Note: You can ask Before Place Order,

This Is Niche Relevant service not Keyword Relevant, Because google assume Niche relevant as Natural Link Building not keyword Relevant.

What are you waiting for? Hurry Up! Don’t wait and lose free traffic.

Order Now!

.

I will write & publish article on Fashion, lifestyle and beauty Blog. for $10

I will write & publish article on Fashion, lifestyle and beauty Blog.

I will write and publish post with DO-FOLLOW backlink on Fashion, lifestyle, and beauty Blog.

Niche:

Accepting only Fashion, lifestyle, and beauty related article.

Benefits:

Unique content

Article with a permanent DOFOLLOW backlink.

The post will be listed on the homepage of our site for a limited time until new posts are published

We will add internal and external links to improve SEO and to make the article look more natural.

100% Satisfaction

Please contact for more details

.

I will prepare 5 unique content for your website or blog. for $5

I will prepare 5 unique content for your website or blog.

An article is a bloodline for a website or blog. It keeps the website alive. So writing articles is the most important task to manage your website. I will provide you Unique and 100% error-free articles for your website. Here you will get 5 articles only at $5.

My article offers you:

  • A good research article
  • quality content to improve your traffic
  • Non-Plagiarized Content
  • 100% error-free

Being a professional, my clients’ satisfaction is a very important thing for me. Looking forward to your first order and a long-lasting business relationship.
If you need any information feel free to contact me. Thanks.

.

hacked – My WordPress Blog sends malicious traffic to other sites

I’m running a wordpress blog on a Compute Engine VM on Google Cloud. A few days ago, I received an email from Google telling me that a potential violation of our Acceptable Use Policy has been detected:

We have recently detected that your Google Cloud Project wordpress-blog (id: xxxxxx) IP XX.XXX.XXX.XXX has been performing intrusion attempts against a third-party and appears to be violating our Terms of Service. You can fix the problem by ensuring that your project traffic directed at third-parties is expected, and that your project has not been compromised. Please check the traffic originating from all your instances and fix any other instances that may be impacted by this.

I submitted an appeal where I explained them that I was not aware of the situation and asked for more details. They gave me a log from BitNinja with the malicious attempts. Let me give a sample:

XXX.XXX.XXX.XXX – – (23/Aug/2020:15:20:43 +0200) “GET /wp-admin/admin-ajax.php?action=ave_publishPost&title=random&short=1&term=1&thumb=../wp-config.php
HTTP/1.0” 400 595 “-” “Mozilla” SenseLog id (80_1_013) Message
(ApacheWpConfig))

Url:
(in###ar.ru/wp-content/plugins/seo-by-rank-math/assets/front/js/rank-math.js)
Remote connection: (XXX.XXX.XXX.XXX:59662) Headers: (array ( ‘Host’
=> ‘in###ar.ru’, ‘User-Agent’ => ‘Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.125
Safari/537.36’, ‘Connection’ => ‘close’, ‘Content-Length’ => ‘0’,
‘Content-Type’ => ‘application/x-www-form-urlencoded’,
‘Accept-Encoding’ => ‘gzip’, ))

I tried to see my own logs but didn’t find anything suspicious. Could you please give me some advice on what steps could I follow to disinfect my machine? I’m running Ubuntu 20.04 LTS.

{Global Host IT Smart}Host Your Blog on WordPress|1-Click Installation|Only @ $1.50 – Hosting, VPN, Proxies

Select your WordPress hosting plan for your blogging website & go online today!

Host IT Smart a fantastic offer on WordPress Hosting plans that gears you up to sign up & share your content across the web. With affordable pricing, the plans’ features & services would be as best as you want for your website.

We have one of the best WordPress hosting plans. When you host with us, regular back up, uptime maintenance, speed, scalability, security, literally everything – is taken care of, while you put your efforts towards growing your business.

Let’s get into the pricing of WordPress Hosting Plans by Host IT Smart:

Starter plan – @ $1.50/mo

  • Unlimited webspace
  • Unlimited Bandwidth
  • 1 website
  • Free SSL Certificate
  • Unlimited Email IDs
  • 1 subdomain
  • 2 MYSQL space
  • 1 park domain
  • 1 FTP Accounts

Performance plan- @ $2.50/mo

  • Unlimited Webspace
  • Unlimited Bandwidth
  • 10 Websites
  • Free SSL Certificate
  • Unlimited Email IDs
  • 10 subdomains
  • 10 MYSQL space
  • 5 park domain
  • 10 FTP accounts

Business plan- @ $5.00/mo

  • Unlimited Webspace
  • Unlimited Bandwidth
  • Unlimited websites
  • Free SSL Certificate
  • Unlimited subdomains
  • Unlimited data space
  • Unlimited park domain
  • Unlimited FTP accounts

These are 50% discounted, but you can avail more discounts with the plans.

If you purchase WordPress hosting for 1 or 2 years, it avails you of an additional 20% discount.
By Applying code: HOSTITSMART20, You Get an Extra 20% Discount.

If you purchase WordPress hosting for more than 2 years, it avails you of an additional 30% discount.
By Applying code: HOSTITSMART30, You Get an Extra 30% Discount.

Check Our More Deals:
https://global.hostitsmart.com/deals

 

Our Support Team is prepared to help you in any circumstance and anytime to tackle any issue in the best possible manner. We additionally furnish Instant Talk administration to interact with you, virtually.

For Immediate Assistance or information, contact us: info@hostitsmart.com or visit our website for live chat. 
 

I will make 150 HQ backlinks using blog comments for $5

I will make 150 HQ backlinks using blog comments

Welcome to my service

Hi, I am Abdul Aziz. Are you looking for high quality and result oriented blog comments? We welcome you to go for our Blog Commenting Service with High DA PA backlinks. Blog Comments is the best place to promote the Website. These Backlinks are search engines that will follow the link and so the juice of the link will pass. The links that are counted as points help push the juice of SEO links and increase the page rank of the linked-site sites, resulting in further improvement in their SERPs.


What Will I Do?

This is the better SEO Technique to Rank your Website. Newest SEO Strategy 2020 to increase the Authority of your hard-earned money website with credible HIGH DA & Powerful Back-links. These powerful links will Skyrocket your Site on Google and provide you Maximum link juice!

My service

Free revision until customer’s satisfaction

All answers done by manually

No automated software

100% do-follow backlinks

UnlimitedUrl’s and Keywords

On-time delivery and it’s my target.

After Work full summary details

24/7 day support

Also, you will get a permanent backlink from Blog Comments. If you have any Questions? please, feel free to talk mine inbox.

.