Compare commits
5 commits
926cf3fe08
...
58bb606879
Author | SHA1 | Date | |
---|---|---|---|
58bb606879 | |||
ed68b4570c | |||
30be3a293d | |||
dd38dd05d1 | |||
344cc85935 |
9 changed files with 997 additions and 56 deletions
|
@ -19,8 +19,7 @@ cookie_secret = "94b2b2732626fdb7736229a7c777cb451e6304c147c4549f30"
|
||||||
|
|
||||||
[page]
|
[page]
|
||||||
base_path = "/tmp/librepages-defualt-config/"
|
base_path = "/tmp/librepages-defualt-config/"
|
||||||
|
base_domain = "librepages.test" # domain where customer pages will be deployed.
|
||||||
|
|
||||||
|
|
||||||
[database]
|
[database]
|
||||||
# This section deals with the database location and how to access it
|
# This section deals with the database location and how to access it
|
||||||
|
|
|
@ -22,6 +22,8 @@ use crate::ctx::Ctx;
|
||||||
use crate::db::Site;
|
use crate::db::Site;
|
||||||
use crate::errors::*;
|
use crate::errors::*;
|
||||||
use crate::page::Page;
|
use crate::page::Page;
|
||||||
|
use crate::settings::Settings;
|
||||||
|
use crate::subdomains::get_random_subdomain;
|
||||||
use crate::utils::get_random;
|
use crate::utils::get_random;
|
||||||
|
|
||||||
#[derive(Clone, Debug, Deserialize, Serialize, Eq, PartialEq)]
|
#[derive(Clone, Debug, Deserialize, Serialize, Eq, PartialEq)]
|
||||||
|
@ -29,30 +31,30 @@ use crate::utils::get_random;
|
||||||
pub struct AddSite {
|
pub struct AddSite {
|
||||||
pub repo_url: String,
|
pub repo_url: String,
|
||||||
pub branch: String,
|
pub branch: String,
|
||||||
pub hostname: String,
|
|
||||||
pub owner: String,
|
pub owner: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AddSite {
|
impl AddSite {
|
||||||
fn to_site(self) -> Site {
|
fn to_site(self, s: &Settings) -> Site {
|
||||||
let site_secret = get_random(32);
|
let site_secret = get_random(32);
|
||||||
|
let hostname = get_random_subdomain(s);
|
||||||
Site {
|
Site {
|
||||||
site_secret,
|
site_secret,
|
||||||
repo_url: self.repo_url,
|
repo_url: self.repo_url,
|
||||||
branch: self.branch,
|
branch: self.branch,
|
||||||
hostname: self.hostname,
|
hostname,
|
||||||
owner: self.owner,
|
owner: self.owner,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Ctx {
|
impl Ctx {
|
||||||
pub async fn add_site(&self, site: AddSite) -> ServiceResult<()> {
|
pub async fn add_site(&self, site: AddSite) -> ServiceResult<Page> {
|
||||||
let db_site = site.to_site();
|
let db_site = site.to_site(&self.settings);
|
||||||
self.db.add_site(&db_site).await?;
|
self.db.add_site(&db_site).await?;
|
||||||
let page = Page::from_site(&self.settings, db_site);
|
let page = Page::from_site(&self.settings, db_site);
|
||||||
page.update(&page.branch)?;
|
page.update(&page.branch)?;
|
||||||
Ok(())
|
Ok(page)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn update_site(&self, secret: &str, branch: Option<String>) -> ServiceResult<()> {
|
pub async fn update_site(&self, secret: &str, branch: Option<String>) -> ServiceResult<()> {
|
||||||
|
|
|
@ -117,14 +117,11 @@ mod tests {
|
||||||
let (_dir, ctx) = tests::get_ctx().await;
|
let (_dir, ctx) = tests::get_ctx().await;
|
||||||
let _ = ctx.delete_user(NAME, PASSWORD).await;
|
let _ = ctx.delete_user(NAME, PASSWORD).await;
|
||||||
let (_, _signin_resp) = ctx.register_and_signin(NAME, EMAIL, PASSWORD).await;
|
let (_, _signin_resp) = ctx.register_and_signin(NAME, EMAIL, PASSWORD).await;
|
||||||
let hostname = ctx.get_test_hostname(NAME);
|
let page = ctx.add_test_site(NAME.into()).await;
|
||||||
ctx.add_test_site(NAME.into(), hostname.clone()).await;
|
|
||||||
let app = get_app!(ctx).await;
|
let app = get_app!(ctx).await;
|
||||||
|
|
||||||
let page = ctx.db.get_site(NAME, &hostname).await.unwrap();
|
|
||||||
|
|
||||||
let mut payload = DeployEvent {
|
let mut payload = DeployEvent {
|
||||||
secret: page.site_secret.clone(),
|
secret: page.secret.clone(),
|
||||||
branch: page.branch.clone(),
|
branch: page.branch.clone(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -154,13 +151,11 @@ mod tests {
|
||||||
let (_dir, ctx) = tests::get_ctx().await;
|
let (_dir, ctx) = tests::get_ctx().await;
|
||||||
let _ = ctx.delete_user(NAME, PASSWORD).await;
|
let _ = ctx.delete_user(NAME, PASSWORD).await;
|
||||||
let (_, _signin_resp) = ctx.register_and_signin(NAME, EMAIL, PASSWORD).await;
|
let (_, _signin_resp) = ctx.register_and_signin(NAME, EMAIL, PASSWORD).await;
|
||||||
let hostname = ctx.get_test_hostname(NAME);
|
let page = ctx.add_test_site(NAME.into()).await;
|
||||||
ctx.add_test_site(NAME.into(), hostname.clone()).await;
|
|
||||||
let app = get_app!(ctx).await;
|
let app = get_app!(ctx).await;
|
||||||
|
|
||||||
let page = ctx.db.get_site(NAME, &hostname).await.unwrap();
|
|
||||||
let mut payload = DeploySecret {
|
let mut payload = DeploySecret {
|
||||||
secret: page.site_secret.clone(),
|
secret: page.secret.clone(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let resp = test::call_service(
|
let resp = test::call_service(
|
||||||
|
@ -173,7 +168,7 @@ mod tests {
|
||||||
|
|
||||||
let response: DeployInfo = actix_web::test::read_body_json(resp).await;
|
let response: DeployInfo = actix_web::test::read_body_json(resp).await;
|
||||||
assert_eq!(response.head, page.branch);
|
assert_eq!(response.head, page.branch);
|
||||||
assert_eq!(response.remote, page.repo_url);
|
assert_eq!(response.remote, page.repo);
|
||||||
|
|
||||||
payload.secret = page.branch.clone();
|
payload.secret = page.branch.clone();
|
||||||
|
|
||||||
|
|
|
@ -38,6 +38,7 @@ mod preview;
|
||||||
mod serve;
|
mod serve;
|
||||||
mod settings;
|
mod settings;
|
||||||
mod static_assets;
|
mod static_assets;
|
||||||
|
mod subdomains;
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests;
|
mod tests;
|
||||||
mod utils;
|
mod utils;
|
||||||
|
|
|
@ -25,7 +25,7 @@ pub struct Preview<'a> {
|
||||||
impl<'a> Preview<'a> {
|
impl<'a> Preview<'a> {
|
||||||
pub fn new(ctx: &'a AppCtx) -> Self {
|
pub fn new(ctx: &'a AppCtx) -> Self {
|
||||||
Self {
|
Self {
|
||||||
base: &ctx.settings.server.domain,
|
base: &ctx.settings.page.base_domain,
|
||||||
delimiter: ".",
|
delimiter: ".",
|
||||||
prefix: "deploy-preview-",
|
prefix: "deploy-preview-",
|
||||||
}
|
}
|
||||||
|
|
10
src/serve.rs
10
src/serve.rs
|
@ -41,19 +41,17 @@ async fn index(req: HttpRequest, ctx: AppCtx) -> ServiceResult<impl Responder> {
|
||||||
host = host.split(':').next().unwrap();
|
host = host.split(':').next().unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// serve meta page
|
||||||
if host == ctx.settings.server.domain || host == "localhost" {
|
if host == ctx.settings.server.domain || host == "localhost" {
|
||||||
return Ok(HttpResponse::Ok()
|
return Ok(HttpResponse::Ok()
|
||||||
.content_type(ContentType::html())
|
.content_type(ContentType::html())
|
||||||
.body("Welcome to Librepages!"));
|
.body("Welcome to Librepages!"));
|
||||||
}
|
}
|
||||||
|
|
||||||
if host.contains(&ctx.settings.server.domain) {
|
// serve default hostname content
|
||||||
|
if host.contains(&ctx.settings.page.base_domain) {
|
||||||
let extractor = crate::preview::Preview::new(&ctx);
|
let extractor = crate::preview::Preview::new(&ctx);
|
||||||
if let Some(preview_branch) = extractor.extract(host) {
|
if let Some(preview_branch) = extractor.extract(host) {
|
||||||
unimplemented!(
|
|
||||||
"map a local subdomain on settings.server.domain and use it to fetch page"
|
|
||||||
);
|
|
||||||
|
|
||||||
let res = if ctx.db.hostname_exists(&host).await? {
|
let res = if ctx.db.hostname_exists(&host).await? {
|
||||||
let path = crate::utils::get_website_path(&ctx.settings, &host);
|
let path = crate::utils::get_website_path(&ctx.settings, &host);
|
||||||
let content =
|
let content =
|
||||||
|
@ -70,9 +68,11 @@ async fn index(req: HttpRequest, ctx: AppCtx) -> ServiceResult<impl Responder> {
|
||||||
} else {
|
} else {
|
||||||
Err(ServiceError::WebsiteNotFound)
|
Err(ServiceError::WebsiteNotFound)
|
||||||
};
|
};
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: custom domains.
|
||||||
if ctx.db.hostname_exists(host).await? {
|
if ctx.db.hostname_exists(host).await? {
|
||||||
let path = crate::utils::get_website_path(&ctx.settings, &host);
|
let path = crate::utils::get_website_path(&ctx.settings, &host);
|
||||||
let content = crate::git::read_file(&path, req.uri().path())?;
|
let content = crate::git::read_file(&path, req.uri().path())?;
|
||||||
|
|
|
@ -89,6 +89,7 @@ pub struct Settings {
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
pub struct PageConfig {
|
pub struct PageConfig {
|
||||||
pub base_path: String,
|
pub base_path: String,
|
||||||
|
pub base_domain: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(tarpaulin_include))]
|
#[cfg(not(tarpaulin_include))]
|
||||||
|
@ -181,31 +182,7 @@ impl Settings {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// create_dir_util(Path::new(&page.path));
|
|
||||||
create_dir_util(Path::new(&self.page.base_path));
|
create_dir_util(Path::new(&self.page.base_path));
|
||||||
|
|
||||||
// for (index, page) in self.pages.iter().enumerate() {
|
|
||||||
// Url::parse(&page.repo).unwrap();
|
|
||||||
//
|
|
||||||
// for (index2, page2) in self.pages.iter().enumerate() {
|
|
||||||
// if index2 == index {
|
|
||||||
// continue;
|
|
||||||
// }
|
|
||||||
// if page.secret == page2.secret {
|
|
||||||
// error!("{}", ServiceError::SecretTaken(page.clone(), page2.clone()));
|
|
||||||
// } else if page.repo == page2.repo {
|
|
||||||
// error!(
|
|
||||||
// "{}",
|
|
||||||
// ServiceError::DuplicateRepositoryURL(page.clone(), page2.clone(),)
|
|
||||||
// );
|
|
||||||
// } else if page.path == page2.path {
|
|
||||||
// error!("{}", ServiceError::PathTaken(page.clone(), page2.clone()));
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// if let Err(e) = page.update(&page.branch) {
|
|
||||||
// error!("{e}");
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(tarpaulin_include))]
|
#[cfg(not(tarpaulin_include))]
|
||||||
|
|
972
src/subdomains.rs
Normal file
972
src/subdomains.rs
Normal file
|
@ -0,0 +1,972 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2022 Aravinth Manivannan <realaravinth@batsense.net>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
* published by the Free Software Foundation, either version 3 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
use crate::settings::Settings;
|
||||||
|
|
||||||
|
// source: https://www.randomlists.com/data/nouns.json
|
||||||
|
const LEN: usize = 876;
|
||||||
|
const WORDLIST: [&str; LEN] = [
|
||||||
|
"account",
|
||||||
|
"achiever",
|
||||||
|
"acoustics",
|
||||||
|
"act",
|
||||||
|
"action",
|
||||||
|
"activity",
|
||||||
|
"actor",
|
||||||
|
"addition",
|
||||||
|
"adjustment",
|
||||||
|
"advertisement",
|
||||||
|
"advice",
|
||||||
|
"aftermath",
|
||||||
|
"afternoon",
|
||||||
|
"afterthought",
|
||||||
|
"agreement",
|
||||||
|
"air",
|
||||||
|
"airplane",
|
||||||
|
"airport",
|
||||||
|
"alarm",
|
||||||
|
"amount",
|
||||||
|
"amusement",
|
||||||
|
"anger",
|
||||||
|
"angle",
|
||||||
|
"animal",
|
||||||
|
"ants",
|
||||||
|
"apparatus",
|
||||||
|
"apparel",
|
||||||
|
"appliance",
|
||||||
|
"approval",
|
||||||
|
"arch",
|
||||||
|
"argument",
|
||||||
|
"arithmetic",
|
||||||
|
"arm",
|
||||||
|
"army",
|
||||||
|
"art",
|
||||||
|
"attack",
|
||||||
|
"attraction",
|
||||||
|
"aunt",
|
||||||
|
"authority",
|
||||||
|
"babies",
|
||||||
|
"baby",
|
||||||
|
"back",
|
||||||
|
"badge",
|
||||||
|
"bag",
|
||||||
|
"bait",
|
||||||
|
"balance",
|
||||||
|
"ball",
|
||||||
|
"base",
|
||||||
|
"baseball",
|
||||||
|
"basin",
|
||||||
|
"basket",
|
||||||
|
"basketball",
|
||||||
|
"bat",
|
||||||
|
"bath",
|
||||||
|
"battle",
|
||||||
|
"bead",
|
||||||
|
"bear",
|
||||||
|
"bed",
|
||||||
|
"bedroom",
|
||||||
|
"beds",
|
||||||
|
"bee",
|
||||||
|
"beef",
|
||||||
|
"beginner",
|
||||||
|
"behavior",
|
||||||
|
"belief",
|
||||||
|
"believe",
|
||||||
|
"bell",
|
||||||
|
"bells",
|
||||||
|
"berry",
|
||||||
|
"bike",
|
||||||
|
"bikes",
|
||||||
|
"bird",
|
||||||
|
"birds",
|
||||||
|
"birth",
|
||||||
|
"birthday",
|
||||||
|
"bit",
|
||||||
|
"bite",
|
||||||
|
"blade",
|
||||||
|
"blood",
|
||||||
|
"blow",
|
||||||
|
"board",
|
||||||
|
"boat",
|
||||||
|
"bomb",
|
||||||
|
"bone",
|
||||||
|
"book",
|
||||||
|
"books",
|
||||||
|
"boot",
|
||||||
|
"border",
|
||||||
|
"bottle",
|
||||||
|
"boundary",
|
||||||
|
"box",
|
||||||
|
"boy",
|
||||||
|
"brake",
|
||||||
|
"branch",
|
||||||
|
"brass",
|
||||||
|
"breath",
|
||||||
|
"brick",
|
||||||
|
"bridge",
|
||||||
|
"brother",
|
||||||
|
"bubble",
|
||||||
|
"bucket",
|
||||||
|
"building",
|
||||||
|
"bulb",
|
||||||
|
"burst",
|
||||||
|
"bushes",
|
||||||
|
"business",
|
||||||
|
"butter",
|
||||||
|
"button",
|
||||||
|
"cabbage",
|
||||||
|
"cable",
|
||||||
|
"cactus",
|
||||||
|
"cake",
|
||||||
|
"cakes",
|
||||||
|
"calculator",
|
||||||
|
"calendar",
|
||||||
|
"camera",
|
||||||
|
"camp",
|
||||||
|
"can",
|
||||||
|
"cannon",
|
||||||
|
"canvas",
|
||||||
|
"cap",
|
||||||
|
"caption",
|
||||||
|
"car",
|
||||||
|
"card",
|
||||||
|
"care",
|
||||||
|
"carpenter",
|
||||||
|
"carriage",
|
||||||
|
"cars",
|
||||||
|
"cart",
|
||||||
|
"cast",
|
||||||
|
"cat",
|
||||||
|
"cats",
|
||||||
|
"cattle",
|
||||||
|
"cause",
|
||||||
|
"cave",
|
||||||
|
"celery",
|
||||||
|
"cellar",
|
||||||
|
"cemetery",
|
||||||
|
"cent",
|
||||||
|
"chalk",
|
||||||
|
"chance",
|
||||||
|
"change",
|
||||||
|
"channel",
|
||||||
|
"cheese",
|
||||||
|
"cherries",
|
||||||
|
"cherry",
|
||||||
|
"chess",
|
||||||
|
"chicken",
|
||||||
|
"chickens",
|
||||||
|
"children",
|
||||||
|
"chin",
|
||||||
|
"church",
|
||||||
|
"circle",
|
||||||
|
"clam",
|
||||||
|
"class",
|
||||||
|
"cloth",
|
||||||
|
"clover",
|
||||||
|
"club",
|
||||||
|
"coach",
|
||||||
|
"coal",
|
||||||
|
"coast",
|
||||||
|
"coat",
|
||||||
|
"cobweb",
|
||||||
|
"coil",
|
||||||
|
"collar",
|
||||||
|
"color",
|
||||||
|
"committee",
|
||||||
|
"company",
|
||||||
|
"comparison",
|
||||||
|
"competition",
|
||||||
|
"condition",
|
||||||
|
"connection",
|
||||||
|
"control",
|
||||||
|
"cook",
|
||||||
|
"copper",
|
||||||
|
"corn",
|
||||||
|
"cough",
|
||||||
|
"country",
|
||||||
|
"cover",
|
||||||
|
"cow",
|
||||||
|
"cows",
|
||||||
|
"crack",
|
||||||
|
"cracker",
|
||||||
|
"crate",
|
||||||
|
"crayon",
|
||||||
|
"cream",
|
||||||
|
"creator",
|
||||||
|
"creature",
|
||||||
|
"credit",
|
||||||
|
"crib",
|
||||||
|
"crime",
|
||||||
|
"crook",
|
||||||
|
"crow",
|
||||||
|
"crowd",
|
||||||
|
"crown",
|
||||||
|
"cub",
|
||||||
|
"cup",
|
||||||
|
"current",
|
||||||
|
"curtain",
|
||||||
|
"curve",
|
||||||
|
"cushion",
|
||||||
|
"dad",
|
||||||
|
"daughter",
|
||||||
|
"day",
|
||||||
|
"death",
|
||||||
|
"debt",
|
||||||
|
"decision",
|
||||||
|
"deer",
|
||||||
|
"degree",
|
||||||
|
"design",
|
||||||
|
"desire",
|
||||||
|
"desk",
|
||||||
|
"destruction",
|
||||||
|
"detail",
|
||||||
|
"development",
|
||||||
|
"digestion",
|
||||||
|
"dime",
|
||||||
|
"dinner",
|
||||||
|
"dinosaurs",
|
||||||
|
"direction",
|
||||||
|
"dirt",
|
||||||
|
"discovery",
|
||||||
|
"discussion",
|
||||||
|
"distance",
|
||||||
|
"distribution",
|
||||||
|
"division",
|
||||||
|
"dock",
|
||||||
|
"doctor",
|
||||||
|
"dog",
|
||||||
|
"dogs",
|
||||||
|
"doll",
|
||||||
|
"dolls",
|
||||||
|
"donkey",
|
||||||
|
"door",
|
||||||
|
"downtown",
|
||||||
|
"drain",
|
||||||
|
"drawer",
|
||||||
|
"dress",
|
||||||
|
"drink",
|
||||||
|
"driving",
|
||||||
|
"drop",
|
||||||
|
"duck",
|
||||||
|
"ducks",
|
||||||
|
"dust",
|
||||||
|
"ear",
|
||||||
|
"earth",
|
||||||
|
"earthquake",
|
||||||
|
"edge",
|
||||||
|
"education",
|
||||||
|
"effect",
|
||||||
|
"egg",
|
||||||
|
"eggnog",
|
||||||
|
"eggs",
|
||||||
|
"elbow",
|
||||||
|
"end",
|
||||||
|
"engine",
|
||||||
|
"error",
|
||||||
|
"event",
|
||||||
|
"example",
|
||||||
|
"exchange",
|
||||||
|
"existence",
|
||||||
|
"expansion",
|
||||||
|
"experience",
|
||||||
|
"expert",
|
||||||
|
"eye",
|
||||||
|
"eyes",
|
||||||
|
"face",
|
||||||
|
"fact",
|
||||||
|
"fairies",
|
||||||
|
"fall",
|
||||||
|
"fang",
|
||||||
|
"farm",
|
||||||
|
"fear",
|
||||||
|
"feeling",
|
||||||
|
"field",
|
||||||
|
"finger",
|
||||||
|
"fire",
|
||||||
|
"fireman",
|
||||||
|
"fish",
|
||||||
|
"flag",
|
||||||
|
"flame",
|
||||||
|
"flavor",
|
||||||
|
"flesh",
|
||||||
|
"flight",
|
||||||
|
"flock",
|
||||||
|
"floor",
|
||||||
|
"flower",
|
||||||
|
"flowers",
|
||||||
|
"fly",
|
||||||
|
"fog",
|
||||||
|
"fold",
|
||||||
|
"food",
|
||||||
|
"foot",
|
||||||
|
"force",
|
||||||
|
"fork",
|
||||||
|
"form",
|
||||||
|
"fowl",
|
||||||
|
"frame",
|
||||||
|
"friction",
|
||||||
|
"friend",
|
||||||
|
"friends",
|
||||||
|
"frog",
|
||||||
|
"frogs",
|
||||||
|
"front",
|
||||||
|
"fruit",
|
||||||
|
"fuel",
|
||||||
|
"furniture",
|
||||||
|
"gate",
|
||||||
|
"geese",
|
||||||
|
"ghost",
|
||||||
|
"giants",
|
||||||
|
"giraffe",
|
||||||
|
"girl",
|
||||||
|
"girls",
|
||||||
|
"glass",
|
||||||
|
"glove",
|
||||||
|
"gold",
|
||||||
|
"government",
|
||||||
|
"governor",
|
||||||
|
"grade",
|
||||||
|
"grain",
|
||||||
|
"grandfather",
|
||||||
|
"grandmother",
|
||||||
|
"grape",
|
||||||
|
"grass",
|
||||||
|
"grip",
|
||||||
|
"ground",
|
||||||
|
"group",
|
||||||
|
"growth",
|
||||||
|
"guide",
|
||||||
|
"guitar",
|
||||||
|
"gun",
|
||||||
|
"hair",
|
||||||
|
"haircut",
|
||||||
|
"hall",
|
||||||
|
"hammer",
|
||||||
|
"hand",
|
||||||
|
"hands",
|
||||||
|
"harbor",
|
||||||
|
"harmony",
|
||||||
|
"hat",
|
||||||
|
"hate",
|
||||||
|
"head",
|
||||||
|
"health",
|
||||||
|
"heat",
|
||||||
|
"hill",
|
||||||
|
"history",
|
||||||
|
"hobbies",
|
||||||
|
"hole",
|
||||||
|
"holiday",
|
||||||
|
"home",
|
||||||
|
"honey",
|
||||||
|
"hook",
|
||||||
|
"hope",
|
||||||
|
"horn",
|
||||||
|
"horse",
|
||||||
|
"horses",
|
||||||
|
"hose",
|
||||||
|
"hospital",
|
||||||
|
"hot",
|
||||||
|
"hour",
|
||||||
|
"house",
|
||||||
|
"houses",
|
||||||
|
"humor",
|
||||||
|
"hydrant",
|
||||||
|
"ice",
|
||||||
|
"icicle",
|
||||||
|
"idea",
|
||||||
|
"impulse",
|
||||||
|
"income",
|
||||||
|
"increase",
|
||||||
|
"industry",
|
||||||
|
"ink",
|
||||||
|
"insect",
|
||||||
|
"instrument",
|
||||||
|
"insurance",
|
||||||
|
"interest",
|
||||||
|
"invention",
|
||||||
|
"iron",
|
||||||
|
"island",
|
||||||
|
"jail",
|
||||||
|
"jam",
|
||||||
|
"jar",
|
||||||
|
"jeans",
|
||||||
|
"jelly",
|
||||||
|
"jellyfish",
|
||||||
|
"jewel",
|
||||||
|
"join",
|
||||||
|
"judge",
|
||||||
|
"juice",
|
||||||
|
"jump",
|
||||||
|
"kettle",
|
||||||
|
"key",
|
||||||
|
"kick",
|
||||||
|
"kiss",
|
||||||
|
"kittens",
|
||||||
|
"kitty",
|
||||||
|
"knee",
|
||||||
|
"knife",
|
||||||
|
"knot",
|
||||||
|
"knowledge",
|
||||||
|
"laborer",
|
||||||
|
"lace",
|
||||||
|
"ladybug",
|
||||||
|
"lake",
|
||||||
|
"lamp",
|
||||||
|
"land",
|
||||||
|
"language",
|
||||||
|
"laugh",
|
||||||
|
"leather",
|
||||||
|
"leg",
|
||||||
|
"legs",
|
||||||
|
"letter",
|
||||||
|
"letters",
|
||||||
|
"lettuce",
|
||||||
|
"level",
|
||||||
|
"library",
|
||||||
|
"limit",
|
||||||
|
"line",
|
||||||
|
"linen",
|
||||||
|
"lip",
|
||||||
|
"liquid",
|
||||||
|
"loaf",
|
||||||
|
"lock",
|
||||||
|
"locket",
|
||||||
|
"look",
|
||||||
|
"loss",
|
||||||
|
"love",
|
||||||
|
"low",
|
||||||
|
"lumber",
|
||||||
|
"lunch",
|
||||||
|
"lunchroom",
|
||||||
|
"machine",
|
||||||
|
"magic",
|
||||||
|
"maid",
|
||||||
|
"mailbox",
|
||||||
|
"man",
|
||||||
|
"marble",
|
||||||
|
"mark",
|
||||||
|
"market",
|
||||||
|
"mask",
|
||||||
|
"mass",
|
||||||
|
"match",
|
||||||
|
"meal",
|
||||||
|
"measure",
|
||||||
|
"meat",
|
||||||
|
"meeting",
|
||||||
|
"memory",
|
||||||
|
"men",
|
||||||
|
"metal",
|
||||||
|
"mice",
|
||||||
|
"middle",
|
||||||
|
"milk",
|
||||||
|
"mind",
|
||||||
|
"mine",
|
||||||
|
"minister",
|
||||||
|
"mint",
|
||||||
|
"minute",
|
||||||
|
"mist",
|
||||||
|
"mitten",
|
||||||
|
"mom",
|
||||||
|
"money",
|
||||||
|
"monkey",
|
||||||
|
"month",
|
||||||
|
"moon",
|
||||||
|
"morning",
|
||||||
|
"mother",
|
||||||
|
"motion",
|
||||||
|
"mountain",
|
||||||
|
"mouth",
|
||||||
|
"move",
|
||||||
|
"muscle",
|
||||||
|
"name",
|
||||||
|
"nation",
|
||||||
|
"neck",
|
||||||
|
"need",
|
||||||
|
"needle",
|
||||||
|
"nerve",
|
||||||
|
"nest",
|
||||||
|
"night",
|
||||||
|
"noise",
|
||||||
|
"north",
|
||||||
|
"nose",
|
||||||
|
"note",
|
||||||
|
"notebook",
|
||||||
|
"number",
|
||||||
|
"nut",
|
||||||
|
"oatmeal",
|
||||||
|
"observation",
|
||||||
|
"ocean",
|
||||||
|
"offer",
|
||||||
|
"office",
|
||||||
|
"oil",
|
||||||
|
"orange",
|
||||||
|
"oranges",
|
||||||
|
"order",
|
||||||
|
"oven",
|
||||||
|
"page",
|
||||||
|
"pail",
|
||||||
|
"pan",
|
||||||
|
"pancake",
|
||||||
|
"paper",
|
||||||
|
"parcel",
|
||||||
|
"part",
|
||||||
|
"partner",
|
||||||
|
"party",
|
||||||
|
"passenger",
|
||||||
|
"payment",
|
||||||
|
"peace",
|
||||||
|
"pear",
|
||||||
|
"pen",
|
||||||
|
"pencil",
|
||||||
|
"person",
|
||||||
|
"pest",
|
||||||
|
"pet",
|
||||||
|
"pets",
|
||||||
|
"pickle",
|
||||||
|
"picture",
|
||||||
|
"pie",
|
||||||
|
"pies",
|
||||||
|
"pig",
|
||||||
|
"pigs",
|
||||||
|
"pin",
|
||||||
|
"pipe",
|
||||||
|
"pizzas",
|
||||||
|
"place",
|
||||||
|
"plane",
|
||||||
|
"planes",
|
||||||
|
"plant",
|
||||||
|
"plantation",
|
||||||
|
"plants",
|
||||||
|
"plastic",
|
||||||
|
"plate",
|
||||||
|
"play",
|
||||||
|
"playground",
|
||||||
|
"pleasure",
|
||||||
|
"plot",
|
||||||
|
"plough",
|
||||||
|
"pocket",
|
||||||
|
"point",
|
||||||
|
"poison",
|
||||||
|
"pollution",
|
||||||
|
"popcorn",
|
||||||
|
"porter",
|
||||||
|
"position",
|
||||||
|
"pot",
|
||||||
|
"potato",
|
||||||
|
"powder",
|
||||||
|
"power",
|
||||||
|
"price",
|
||||||
|
"produce",
|
||||||
|
"profit",
|
||||||
|
"property",
|
||||||
|
"prose",
|
||||||
|
"protest",
|
||||||
|
"pull",
|
||||||
|
"pump",
|
||||||
|
"punishment",
|
||||||
|
"purpose",
|
||||||
|
"push",
|
||||||
|
"quarter",
|
||||||
|
"quartz",
|
||||||
|
"queen",
|
||||||
|
"question",
|
||||||
|
"quicksand",
|
||||||
|
"quiet",
|
||||||
|
"quill",
|
||||||
|
"quilt",
|
||||||
|
"quince",
|
||||||
|
"quiver",
|
||||||
|
"rabbit",
|
||||||
|
"rabbits",
|
||||||
|
"rail",
|
||||||
|
"railway",
|
||||||
|
"rain",
|
||||||
|
"rainstorm",
|
||||||
|
"rake",
|
||||||
|
"range",
|
||||||
|
"rat",
|
||||||
|
"rate",
|
||||||
|
"ray",
|
||||||
|
"reaction",
|
||||||
|
"reading",
|
||||||
|
"reason",
|
||||||
|
"receipt",
|
||||||
|
"recess",
|
||||||
|
"record",
|
||||||
|
"regret",
|
||||||
|
"relation",
|
||||||
|
"religion",
|
||||||
|
"representative",
|
||||||
|
"request",
|
||||||
|
"respect",
|
||||||
|
"rest",
|
||||||
|
"reward",
|
||||||
|
"rhythm",
|
||||||
|
"rice",
|
||||||
|
"riddle",
|
||||||
|
"rifle",
|
||||||
|
"ring",
|
||||||
|
"rings",
|
||||||
|
"river",
|
||||||
|
"road",
|
||||||
|
"robin",
|
||||||
|
"rock",
|
||||||
|
"rod",
|
||||||
|
"roll",
|
||||||
|
"roof",
|
||||||
|
"room",
|
||||||
|
"root",
|
||||||
|
"rose",
|
||||||
|
"route",
|
||||||
|
"rub",
|
||||||
|
"rule",
|
||||||
|
"run",
|
||||||
|
"sack",
|
||||||
|
"sail",
|
||||||
|
"salt",
|
||||||
|
"sand",
|
||||||
|
"scale",
|
||||||
|
"scarecrow",
|
||||||
|
"scarf",
|
||||||
|
"scene",
|
||||||
|
"scent",
|
||||||
|
"school",
|
||||||
|
"science",
|
||||||
|
"scissors",
|
||||||
|
"screw",
|
||||||
|
"sea",
|
||||||
|
"seashore",
|
||||||
|
"seat",
|
||||||
|
"secretary",
|
||||||
|
"seed",
|
||||||
|
"selection",
|
||||||
|
"self",
|
||||||
|
"sense",
|
||||||
|
"servant",
|
||||||
|
"shade",
|
||||||
|
"shake",
|
||||||
|
"shame",
|
||||||
|
"shape",
|
||||||
|
"sheep",
|
||||||
|
"sheet",
|
||||||
|
"shelf",
|
||||||
|
"ship",
|
||||||
|
"shirt",
|
||||||
|
"shock",
|
||||||
|
"shoe",
|
||||||
|
"shoes",
|
||||||
|
"shop",
|
||||||
|
"show",
|
||||||
|
"side",
|
||||||
|
"sidewalk",
|
||||||
|
"sign",
|
||||||
|
"silk",
|
||||||
|
"silver",
|
||||||
|
"sink",
|
||||||
|
"sister",
|
||||||
|
"sisters",
|
||||||
|
"size",
|
||||||
|
"skate",
|
||||||
|
"skin",
|
||||||
|
"skirt",
|
||||||
|
"sky",
|
||||||
|
"slave",
|
||||||
|
"sleep",
|
||||||
|
"sleet",
|
||||||
|
"slip",
|
||||||
|
"slope",
|
||||||
|
"smash",
|
||||||
|
"smell",
|
||||||
|
"smile",
|
||||||
|
"smoke",
|
||||||
|
"snail",
|
||||||
|
"snails",
|
||||||
|
"snake",
|
||||||
|
"snakes",
|
||||||
|
"sneeze",
|
||||||
|
"snow",
|
||||||
|
"soap",
|
||||||
|
"society",
|
||||||
|
"sock",
|
||||||
|
"soda",
|
||||||
|
"sofa",
|
||||||
|
"son",
|
||||||
|
"song",
|
||||||
|
"songs",
|
||||||
|
"sort",
|
||||||
|
"sound",
|
||||||
|
"soup",
|
||||||
|
"space",
|
||||||
|
"spade",
|
||||||
|
"spark",
|
||||||
|
"spiders",
|
||||||
|
"sponge",
|
||||||
|
"spoon",
|
||||||
|
"spot",
|
||||||
|
"spring",
|
||||||
|
"spy",
|
||||||
|
"square",
|
||||||
|
"squirrel",
|
||||||
|
"stage",
|
||||||
|
"stamp",
|
||||||
|
"star",
|
||||||
|
"start",
|
||||||
|
"statement",
|
||||||
|
"station",
|
||||||
|
"steam",
|
||||||
|
"steel",
|
||||||
|
"stem",
|
||||||
|
"step",
|
||||||
|
"stew",
|
||||||
|
"stick",
|
||||||
|
"sticks",
|
||||||
|
"stitch",
|
||||||
|
"stocking",
|
||||||
|
"stomach",
|
||||||
|
"stone",
|
||||||
|
"stop",
|
||||||
|
"store",
|
||||||
|
"story",
|
||||||
|
"stove",
|
||||||
|
"stranger",
|
||||||
|
"straw",
|
||||||
|
"stream",
|
||||||
|
"street",
|
||||||
|
"stretch",
|
||||||
|
"string",
|
||||||
|
"structure",
|
||||||
|
"substance",
|
||||||
|
"sugar",
|
||||||
|
"suggestion",
|
||||||
|
"suit",
|
||||||
|
"summer",
|
||||||
|
"sun",
|
||||||
|
"support",
|
||||||
|
"surprise",
|
||||||
|
"sweater",
|
||||||
|
"swim",
|
||||||
|
"swing",
|
||||||
|
"system",
|
||||||
|
"table",
|
||||||
|
"tail",
|
||||||
|
"talk",
|
||||||
|
"tank",
|
||||||
|
"taste",
|
||||||
|
"tax",
|
||||||
|
"teaching",
|
||||||
|
"team",
|
||||||
|
"teeth",
|
||||||
|
"temper",
|
||||||
|
"tendency",
|
||||||
|
"tent",
|
||||||
|
"territory",
|
||||||
|
"test",
|
||||||
|
"texture",
|
||||||
|
"theory",
|
||||||
|
"thing",
|
||||||
|
"things",
|
||||||
|
"thought",
|
||||||
|
"thread",
|
||||||
|
"thrill",
|
||||||
|
"throat",
|
||||||
|
"throne",
|
||||||
|
"thumb",
|
||||||
|
"thunder",
|
||||||
|
"ticket",
|
||||||
|
"tiger",
|
||||||
|
"time",
|
||||||
|
"tin",
|
||||||
|
"title",
|
||||||
|
"toad",
|
||||||
|
"toe",
|
||||||
|
"toes",
|
||||||
|
"tomatoes",
|
||||||
|
"tongue",
|
||||||
|
"tooth",
|
||||||
|
"toothbrush",
|
||||||
|
"toothpaste",
|
||||||
|
"top",
|
||||||
|
"touch",
|
||||||
|
"town",
|
||||||
|
"toy",
|
||||||
|
"toys",
|
||||||
|
"trade",
|
||||||
|
"trail",
|
||||||
|
"train",
|
||||||
|
"trains",
|
||||||
|
"tramp",
|
||||||
|
"transport",
|
||||||
|
"tray",
|
||||||
|
"treatment",
|
||||||
|
"tree",
|
||||||
|
"trees",
|
||||||
|
"trick",
|
||||||
|
"trip",
|
||||||
|
"trouble",
|
||||||
|
"trousers",
|
||||||
|
"truck",
|
||||||
|
"trucks",
|
||||||
|
"tub",
|
||||||
|
"turkey",
|
||||||
|
"turn",
|
||||||
|
"twig",
|
||||||
|
"twist",
|
||||||
|
"umbrella",
|
||||||
|
"uncle",
|
||||||
|
"underwear",
|
||||||
|
"unit",
|
||||||
|
"use",
|
||||||
|
"vacation",
|
||||||
|
"value",
|
||||||
|
"van",
|
||||||
|
"vase",
|
||||||
|
"vegetable",
|
||||||
|
"veil",
|
||||||
|
"vein",
|
||||||
|
"verse",
|
||||||
|
"vessel",
|
||||||
|
"vest",
|
||||||
|
"view",
|
||||||
|
"visitor",
|
||||||
|
"voice",
|
||||||
|
"volcano",
|
||||||
|
"volleyball",
|
||||||
|
"voyage",
|
||||||
|
"walk",
|
||||||
|
"wall",
|
||||||
|
"war",
|
||||||
|
"wash",
|
||||||
|
"waste",
|
||||||
|
"watch",
|
||||||
|
"water",
|
||||||
|
"wave",
|
||||||
|
"waves",
|
||||||
|
"wax",
|
||||||
|
"way",
|
||||||
|
"wealth",
|
||||||
|
"weather",
|
||||||
|
"week",
|
||||||
|
"weight",
|
||||||
|
"wheel",
|
||||||
|
"whip",
|
||||||
|
"whistle",
|
||||||
|
"wilderness",
|
||||||
|
"wind",
|
||||||
|
"window",
|
||||||
|
"wine",
|
||||||
|
"wing",
|
||||||
|
"winter",
|
||||||
|
"wire",
|
||||||
|
"wish",
|
||||||
|
"woman",
|
||||||
|
"women",
|
||||||
|
"wood",
|
||||||
|
"wool",
|
||||||
|
"word",
|
||||||
|
"work",
|
||||||
|
"worm",
|
||||||
|
"wound",
|
||||||
|
"wren",
|
||||||
|
"wrench",
|
||||||
|
"wrist",
|
||||||
|
"writer",
|
||||||
|
"writing",
|
||||||
|
"yak",
|
||||||
|
"yam",
|
||||||
|
"yard",
|
||||||
|
"yarn",
|
||||||
|
"year",
|
||||||
|
"yoke",
|
||||||
|
"zebra",
|
||||||
|
"zephyr",
|
||||||
|
"zinc",
|
||||||
|
"zipper",
|
||||||
|
"zoo",
|
||||||
|
];
|
||||||
|
|
||||||
|
struct ID<'a> {
|
||||||
|
first: &'a str,
|
||||||
|
second: &'a str,
|
||||||
|
third: &'a str,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> ID<'a> {
|
||||||
|
fn hostname(&self, base_domain: &str) -> String {
|
||||||
|
format!(
|
||||||
|
"{}-{}-{}.{}",
|
||||||
|
self.first, self.second, self.third, base_domain
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_random_id() -> ID<'static> {
|
||||||
|
use rand::{rngs::ThreadRng, thread_rng, Rng};
|
||||||
|
|
||||||
|
let mut rng: ThreadRng = thread_rng();
|
||||||
|
let first: usize = rng.gen_range(0..LEN);
|
||||||
|
let mut second: usize;
|
||||||
|
let mut third: usize;
|
||||||
|
|
||||||
|
loop {
|
||||||
|
second = rng.gen_range(0..LEN);
|
||||||
|
if second != first {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
loop {
|
||||||
|
third = rng.gen_range(0..LEN);
|
||||||
|
if third != first && second != third {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let first = WORDLIST[first];
|
||||||
|
let second = WORDLIST[second];
|
||||||
|
let third = WORDLIST[third];
|
||||||
|
ID {
|
||||||
|
first,
|
||||||
|
second,
|
||||||
|
third,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_random_subdomain(s: &Settings) -> String {
|
||||||
|
let id = get_random_id();
|
||||||
|
id.hostname(&s.page.base_domain)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_subdomains() {
|
||||||
|
// test random ID
|
||||||
|
let id = get_random_id();
|
||||||
|
assert_ne!(id.first, id.second);
|
||||||
|
assert_ne!(id.first, id.third);
|
||||||
|
assert_ne!(id.third, id.second);
|
||||||
|
|
||||||
|
// test ID::hostname
|
||||||
|
let delimiter = "foobar21312";
|
||||||
|
assert_eq!(
|
||||||
|
id.hostname(delimiter),
|
||||||
|
format!("{}-{}-{}.{delimiter}", id.first, id.second, id.third,)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
11
src/tests.rs
11
src/tests.rs
|
@ -29,10 +29,10 @@ use crate::ctx::api::v1::auth::{Login, Register};
|
||||||
use crate::ctx::api::v1::pages::AddSite;
|
use crate::ctx::api::v1::pages::AddSite;
|
||||||
use crate::ctx::Ctx;
|
use crate::ctx::Ctx;
|
||||||
use crate::errors::*;
|
use crate::errors::*;
|
||||||
|
use crate::page::Page;
|
||||||
use crate::settings::Settings;
|
use crate::settings::Settings;
|
||||||
use crate::*;
|
use crate::*;
|
||||||
|
|
||||||
const HOSTNAME: &str = "example.org";
|
|
||||||
pub const REPO_URL: &str = "https://github.com/mCaptcha/website/";
|
pub const REPO_URL: &str = "https://github.com/mCaptcha/website/";
|
||||||
pub const BRANCH: &str = "gh-pages";
|
pub const BRANCH: &str = "gh-pages";
|
||||||
|
|
||||||
|
@ -268,17 +268,12 @@ impl Ctx {
|
||||||
assert_eq!(resp_err.error, format!("{}", err));
|
assert_eq!(resp_err.error, format!("{}", err));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn add_test_site(&self, owner: String, hostname: String) {
|
pub async fn add_test_site(&self, owner: String) -> Page {
|
||||||
let msg = AddSite {
|
let msg = AddSite {
|
||||||
repo_url: REPO_URL.into(),
|
repo_url: REPO_URL.into(),
|
||||||
branch: BRANCH.into(),
|
branch: BRANCH.into(),
|
||||||
hostname,
|
|
||||||
owner,
|
owner,
|
||||||
};
|
};
|
||||||
self.add_site(msg).await.unwrap();
|
self.add_site(msg).await.unwrap()
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_test_hostname(&self, unique: &str) -> String {
|
|
||||||
format!("{unique}.{HOSTNAME}")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue