some unfinished database work - /v1/signup works now
This commit is contained in:
parent
a6ea23c32d
commit
c3990486b8
|
@ -1,7 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="SqlDialectMappings">
|
||||
<file url="file://$PROJECT_DIR$/trifid-api/migrations/20230203025121_create_users.sql" dialect="GenericSQL" />
|
||||
<file url="PROJECT" dialect="PostgreSQL" />
|
||||
</component>
|
||||
</project>
|
|
@ -2,6 +2,12 @@
|
|||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "adler"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
|
||||
|
||||
[[package]]
|
||||
name = "aead"
|
||||
version = "0.5.1"
|
||||
|
@ -115,6 +121,12 @@ version = "1.1.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
||||
|
||||
[[package]]
|
||||
name = "base32"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "23ce669cd6c8588f79e15cf450314f9638f967fc5770ff1c7c1deb0925ea7cfa"
|
||||
|
||||
[[package]]
|
||||
name = "base64"
|
||||
version = "0.13.1"
|
||||
|
@ -160,6 +172,12 @@ version = "3.12.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535"
|
||||
|
||||
[[package]]
|
||||
name = "bytemuck"
|
||||
version = "1.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c041d3eab048880cb0b86b256447da3f18859a163c3b8d8893f4e6368abe6393"
|
||||
|
||||
[[package]]
|
||||
name = "byteorder"
|
||||
version = "1.4.3"
|
||||
|
@ -194,6 +212,18 @@ dependencies = [
|
|||
"inout",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "color_quant"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b"
|
||||
|
||||
[[package]]
|
||||
name = "constant_time_eq"
|
||||
version = "0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f3ad85c1f65dc7b37604eb0e89748faf0b9653065f2a8ef69f96a687ec1e9279"
|
||||
|
||||
[[package]]
|
||||
name = "cookie"
|
||||
version = "0.16.2"
|
||||
|
@ -252,6 +282,15 @@ version = "2.2.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9cace84e55f07e7301bae1c519df89cdad8cc3cd868413d3fdbdeca9ff3db484"
|
||||
|
||||
[[package]]
|
||||
name = "crc32fast"
|
||||
version = "1.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-queue"
|
||||
version = "0.3.8"
|
||||
|
@ -405,6 +444,16 @@ dependencies = [
|
|||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "flate2"
|
||||
version = "1.0.25"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a8a2db397cb1c8772f31494cb8917e48cd1e64f0fa7efac59fbd741a0a8ce841"
|
||||
dependencies = [
|
||||
"crc32fast",
|
||||
"miniz_oxide",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fnv"
|
||||
version = "1.0.7"
|
||||
|
@ -717,6 +766,20 @@ dependencies = [
|
|||
"unicode-normalization",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "image"
|
||||
version = "0.24.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "69b7ea949b537b0fd0af141fff8c77690f2ce96f4f41f042ccb6c69c6c965945"
|
||||
dependencies = [
|
||||
"bytemuck",
|
||||
"byteorder",
|
||||
"color_quant",
|
||||
"num-rational",
|
||||
"num-traits",
|
||||
"png",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "1.9.2"
|
||||
|
@ -858,6 +921,15 @@ version = "0.2.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
|
||||
|
||||
[[package]]
|
||||
name = "miniz_oxide"
|
||||
version = "0.6.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa"
|
||||
dependencies = [
|
||||
"adler",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mio"
|
||||
version = "0.8.5"
|
||||
|
@ -937,6 +1009,27 @@ dependencies = [
|
|||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-integer"
|
||||
version = "0.1.45"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-rational"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.15"
|
||||
|
@ -1120,6 +1213,18 @@ version = "0.3.26"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160"
|
||||
|
||||
[[package]]
|
||||
name = "png"
|
||||
version = "0.17.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5d708eaf860a19b19ce538740d2b4bdeeb8337fa53f7738455e706623ad5c638"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"crc32fast",
|
||||
"flate2",
|
||||
"miniz_oxide",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "polyval"
|
||||
version = "0.6.0"
|
||||
|
@ -1160,6 +1265,12 @@ dependencies = [
|
|||
"yansi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "qrcodegen"
|
||||
version = "1.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4339fc7a1021c9c1621d87f5e3505f2805c8c105420ba2f2a4df86814590c142"
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.23"
|
||||
|
@ -1866,6 +1977,25 @@ dependencies = [
|
|||
"toml_datetime",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "totp-rs"
|
||||
version = "4.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9fdd21080b6cf581e0c8fe849626ad627b42af1a0f71ce980244f2d6b1a47836"
|
||||
dependencies = [
|
||||
"base32",
|
||||
"base64 0.20.0",
|
||||
"constant_time_eq",
|
||||
"hmac",
|
||||
"image",
|
||||
"qrcodegen",
|
||||
"rand",
|
||||
"sha1",
|
||||
"sha2",
|
||||
"url",
|
||||
"urlencoding",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tower-service"
|
||||
version = "0.3.2"
|
||||
|
@ -1947,6 +2077,10 @@ dependencies = [
|
|||
"sqlx",
|
||||
"tokio",
|
||||
"toml 0.7.1",
|
||||
"totp-rs",
|
||||
"url",
|
||||
"urlencoding",
|
||||
"uuid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -2038,6 +2172,35 @@ dependencies = [
|
|||
"form_urlencoded",
|
||||
"idna",
|
||||
"percent-encoding",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "urlencoding"
|
||||
version = "2.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e8db7427f936968176eaa7cdf81b7f98b980b18495ec28f1b5791ac3bfe3eea9"
|
||||
|
||||
[[package]]
|
||||
name = "uuid"
|
||||
version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1674845326ee10d37ca60470760d4288a6f80f304007d92e5c53bab78c9cfd79"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
"rand",
|
||||
"uuid-macro-internal",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "uuid-macro-internal"
|
||||
version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c1b300a878652a387d2a0de915bdae8f1a548f0c6d45e072fe2688794b656cc9"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
POST /v1/auth/magic-link HTTP/2
|
||||
Host: api.defined.net
|
||||
Content-Length: 29
|
||||
Sec-Ch-Ua: "Chromium";v="109", "Not_A Brand";v="99"
|
||||
Accept: application/json
|
||||
Content-Type: application/json
|
||||
Sec-Ch-Ua-Mobile: ?0
|
||||
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.5414.75 Safari/537.36
|
||||
Sec-Ch-Ua-Platform: "Linux"
|
||||
Origin: https://admin.defined.net
|
||||
Sec-Fetch-Site: same-site
|
||||
Sec-Fetch-Mode: cors
|
||||
Sec-Fetch-Dest: empty
|
||||
Accept-Encoding: gzip, deflate
|
||||
Accept-Language: en-US,en;q=0.9
|
||||
|
||||
{"email":"core@coredoes.dev"}
|
||||
|
||||
HTTP/2 200 OK
|
||||
Access-Control-Allow-Credentials: true
|
||||
Access-Control-Allow-Origin: https://admin.defined.net
|
||||
Access-Control-Expose-Headers: X-Request-Id
|
||||
Cache-Control: no-store
|
||||
Content-Security-Policy: default-src 'none'
|
||||
Content-Type: application/json; charset=utf-8
|
||||
Strict-Transport-Security: max-age=31536000; includeSubdomains
|
||||
Vary: Origin
|
||||
X-Content-Type-Options: nosniff
|
||||
X-Frame-Options: DENY
|
||||
X-Request-Id: GI4RVV7JQIINE3DDPCYOBAT6TI
|
||||
Content-Length: 26
|
||||
Date: Sat, 04 Feb 2023 17:45:20 GMT
|
||||
|
||||
{"data":{},"metadata":{}}
|
|
@ -15,3 +15,7 @@ toml = "0.7.1"
|
|||
serde = "1.0.152"
|
||||
dotenvy = "0.15.6"
|
||||
paste = "1.0.11"
|
||||
totp-rs = { version = "4.2.0", features = ["qr", "otpauth", "gen_secret"]}
|
||||
uuid = { version = "1.3.0", features = ["v4", "fast-rng", "macro-diagnostics"]}
|
||||
url = { version = "2.3.1", features = ["serde"] }
|
||||
urlencoding = "2.1.2"
|
|
@ -1,2 +1,4 @@
|
|||
listen_port = 8000
|
||||
db_url = "postgres://postgres@localhost/trifidapi"
|
||||
base = "http://localhost:8000"
|
||||
magic_links_valid_for = 86400
|
|
@ -1,6 +0,0 @@
|
|||
CREATE TABLE organizations (
|
||||
id SERIAL NOT NULL PRIMARY KEY,
|
||||
network_range VARCHAR(18) NOT NULL, -- https://docs.defined.net/guides/choosing-a-cidr/
|
||||
org_name VARCHAR(258) NOT NULL
|
||||
);
|
||||
CREATE INDEX idx_organizations_name ON organizations(org_name);
|
|
@ -1,10 +0,0 @@
|
|||
CREATE TABLE users (
|
||||
id SERIAL NOT NULL PRIMARY KEY,
|
||||
email VARCHAR(320) NOT NULL,
|
||||
|
||||
totp_enabled INTEGER NOT NULL,
|
||||
totp_verified INTEGER NOT NULL,
|
||||
totp_base32 VARCHAR(1024) NOT NULL,
|
||||
totp_auth_url VARCHAR(1024) NOT NULL
|
||||
);
|
||||
CREATE INDEX idx_users_email ON users(email);
|
|
@ -1,10 +0,0 @@
|
|||
CREATE TABLE roles (
|
||||
id SERIAL NOT NULL PRIMARY KEY,
|
||||
|
||||
role_name VARCHAR(128) NOT NULL,
|
||||
role_desc VARCHAR(512) NOT NULL,
|
||||
|
||||
org_id SERIAL NOT NULL REFERENCES organizations(id)
|
||||
);
|
||||
CREATE INDEX idx_roles_org_id ON roles(org_id);
|
||||
-- every org should have an id=0 role which every node is a member of
|
|
@ -1,9 +0,0 @@
|
|||
CREATE TABLE firewall_rules (
|
||||
id SERIAL NOT NULL PRIMARY KEY,
|
||||
|
||||
allow_role_id SERIAL NOT NULL REFERENCES roles(id), -- all roles: use the organization role itself
|
||||
|
||||
protocol INTEGER NOT NULL, -- 0: any, 1: icmp, 2: udp, 3: tcp
|
||||
port VARCHAR(256) NOT NULL, -- port range (ignore if protocol==1)
|
||||
description VARCHAR(256) NOT NULL -- description
|
||||
)
|
|
@ -0,0 +1,13 @@
|
|||
CREATE TABLE users (
|
||||
id SERIAL NOT NULL PRIMARY KEY,
|
||||
email VARCHAR(320) NOT NULL UNIQUE,
|
||||
created_on INTEGER NOT NULL,
|
||||
|
||||
banned INTEGER NOT NULL,
|
||||
ban_reason VARCHAR(1024) NOT NULL,
|
||||
|
||||
totp_secret VARCHAR(128) NOT NULL,
|
||||
totp_verified INTEGER NOT NULL,
|
||||
totp_otpurl VARCHAR(3000) NOT NULL
|
||||
);
|
||||
CREATE INDEX idx_users_email ON users(email);
|
|
@ -0,0 +1,5 @@
|
|||
CREATE TABLE magic_links (
|
||||
id VARCHAR(36) NOT NULL PRIMARY KEY UNIQUE,
|
||||
user_id SERIAL NOT NULL REFERENCES users(id),
|
||||
expires_on INTEGER NOT NULL
|
||||
);
|
|
@ -1,7 +1,10 @@
|
|||
use serde::Deserialize;
|
||||
use url::Url;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct TFConfig {
|
||||
pub listen_port: u16,
|
||||
pub db_url: String
|
||||
pub db_url: String,
|
||||
pub base: Url,
|
||||
pub magic_links_valid_for: i64
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
use std::error::Error;
|
||||
use log::info;
|
||||
use sqlx::PgPool;
|
||||
use uuid::Uuid;
|
||||
use crate::config::TFConfig;
|
||||
// https://admin.defined.net/auth/magic-link?email=coredoescode%40gmail.com&token=ml-ckBsgw_5IdK5VYgseBYcoV_v_cQjtdq1re_RhDu_MKg
|
||||
pub async fn send_magic_link(id: i64, email: String, db: &PgPool, config: &TFConfig) -> Result<(), Box<dyn Error>> {
|
||||
let otp = Uuid::new_v4().to_string();
|
||||
let otp_url = format!("{}/{}", config.base, urlencoding::encode(&format!("/auth/magic-link?email={}&token={}", email.clone(), otp.clone())));
|
||||
sqlx::query!("INSERT INTO magic_links (id, user_id, expires_on) VALUES ($1, $2, $3) ON CONFLICT DO NOTHING;", otp, id, SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs() as i64 + config.config.magic_links_valid_for).await?;
|
||||
// TODO: send email
|
||||
info!("sent magic link {} to {}, valid for {} seconds", otp_url, email.clone(), config.magic_links_valid_for);
|
||||
Ok(())
|
||||
}
|
|
@ -12,7 +12,7 @@ pub mod format;
|
|||
pub mod util;
|
||||
pub mod db;
|
||||
pub mod config;
|
||||
|
||||
pub mod email;
|
||||
pub mod routes;
|
||||
|
||||
static MIGRATOR: Migrator = sqlx::migrate!();
|
||||
|
@ -75,29 +75,19 @@ async fn main() -> Result<(), Box<dyn Error>> {
|
|||
info!("[tfapi] building rocket config");
|
||||
|
||||
let figment = rocket::Config::figment().merge(("port", config.listen_port));
|
||||
/*
|
||||
error_handler!(400, "ERR_MALFORMED_REQUEST", "unable to parse the request body, is it properly formatted?");
|
||||
error_handler!(401, "ERR_AUTHENTICATION_REQUIRED", "this endpoint requires authentication but it was not provided");
|
||||
error_handler!(403, "ERR_UNAUTHORIZED", "authorization was provided but it is expired or invalid");
|
||||
error_handler!(404, "ERR_NOT_FOUND", "resource not found");
|
||||
error_handler!(405, "ERR_METHOD_NOT_ALLOWED", "method not allowed for this endpoint");
|
||||
error_handler!(500, "ERR_QL_QUERY_FAILED", "graphql query timed out");
|
||||
error_handler!(501, "ERR_NOT_IMPLEMENTED", "query not supported by this version of graphql");
|
||||
error_handler!(502, "ERR_PROXY_ERR", "servers under load, please try again later");
|
||||
error_handler!(503, "ERR_SERVER_OVERLOADED", "servers under load, please try again later");
|
||||
error_handler!(504, "ERR_PROXY_TIMEOUT", "servers under load, please try again later");
|
||||
error_handler!(505, "ERR_CLIENT_UNSUPPORTED", "your version of dnclient is out of date, please update");
|
||||
|
||||
*/
|
||||
let _ = rocket::custom(figment)
|
||||
.mount("/", routes![
|
||||
crate::routes::v1::auth::verify_magic_link::verify_magic_link
|
||||
//crate::routes::v1::auth::verify_magic_link::verify_magic_link
|
||||
crate::routes::v1::signup::signup_request
|
||||
])
|
||||
.register("/", catchers![
|
||||
crate::routes::handler_400,
|
||||
crate::routes::handler_401,
|
||||
crate::routes::handler_403,
|
||||
crate::routes::handler_404,
|
||||
crate::routes::handler_422,
|
||||
|
||||
crate::routes::handler_500,
|
||||
crate::routes::handler_501,
|
||||
crate::routes::handler_502,
|
||||
|
|
|
@ -35,6 +35,8 @@ error_handler!(401, "ERR_AUTHENTICATION_REQUIRED", "this endpoint requires authe
|
|||
error_handler!(403, "ERR_UNAUTHORIZED", "authorization was provided but it is expired or invalid");
|
||||
error_handler!(404, "ERR_NOT_FOUND", "resource not found");
|
||||
error_handler!(405, "ERR_METHOD_NOT_ALLOWED", "method not allowed for this endpoint");
|
||||
error_handler!(422, "ERR_MALFORMED_REQUEST", "unable to parse the request body, is it properly formatted?");
|
||||
|
||||
error_handler!(500, "ERR_QL_QUERY_FAILED", "graphql query timed out");
|
||||
error_handler!(501, "ERR_NOT_IMPLEMENTED", "query not supported by this version of graphql");
|
||||
error_handler!(502, "ERR_PROXY_ERR", "servers under load, please try again later");
|
||||
|
|
|
@ -1 +1,2 @@
|
|||
pub mod auth;
|
||||
//pub mod auth;
|
||||
pub mod signup;
|
|
@ -0,0 +1,55 @@
|
|||
use rocket::{post, State};
|
||||
use rocket::serde::json::Json;
|
||||
use serde::{Serialize, Deserialize};
|
||||
use std::time::{SystemTime, UNIX_EPOCH};
|
||||
use rocket::http::{ContentType, Status};
|
||||
use sqlx::PgPool;
|
||||
use crate::config::TFConfig;
|
||||
use crate::email::send_magic_link;
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(crate = "rocket::serde")]
|
||||
pub struct SignupRequest {
|
||||
pub email: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(crate = "rocket::serde")]
|
||||
pub struct SignupResponseMetadata {}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(crate = "rocket::serde")]
|
||||
pub struct SignupResponse {
|
||||
pub data: Option<String>,
|
||||
pub metadata: SignupResponseMetadata,
|
||||
}
|
||||
/*
|
||||
created_on TIMESTAMP NOT NULL,
|
||||
|
||||
banned INTEGER NOT NULL,
|
||||
ban_reason VARCHAR(1024) NOT NULL
|
||||
*/
|
||||
#[post("/v1/signup", data = "<req>")]
|
||||
pub async fn signup_request(req: Json<SignupRequest>, pool: &State<PgPool>, config: &State<TFConfig>) -> Result<(ContentType, Json<SignupResponse>), (Status, String)> {
|
||||
match sqlx::query!("INSERT INTO users (email, created_on, banned, ban_reason, totp_secret, totp_otpurl, totp_verified) VALUES ($1, $2, $3, $4, $5, $6, $7) RETURNING id ON CONFLICT DO NOTHING;", req.email, SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs() as i64, 0, "", "", "", 0).execute(pool.inner()).await {
|
||||
Ok(_) => (),
|
||||
Err(e) => {
|
||||
return Err((Status::InternalServerError, format!("{{\"errors\":[{{\"code\":\"{}\",\"message\":\"{} - {}\"}}]}}", "ERR_QL_QUERY_FAILED", "an error occurred while running the graphql query", e)))
|
||||
}
|
||||
};
|
||||
|
||||
// send magic link to email
|
||||
match send_magic_link(req.email.clone(), pool.inner(), config.inner()).await {
|
||||
Ok(_) => (),
|
||||
Err(e) => {
|
||||
return Err((Status::InternalServerError, format!("{{\"errors\":[{{\"code\":\"{}\",\"message\":\"{} - {}\"}}]}}", "ERR_QL_QUERY_FAILED", "an error occurred while running the graphql query", e)))
|
||||
}
|
||||
};
|
||||
|
||||
// this endpoint doesn't actually ever return an error? it will send you the magic link no matter what
|
||||
// this appears to do the exact same thing as /v1/auth/magic-link, but it doesn't check if you have an account (magic-link does)
|
||||
Ok((ContentType::JSON, Json(SignupResponse {
|
||||
data: None,
|
||||
metadata: SignupResponseMetadata {},
|
||||
})))
|
||||
}
|
|
@ -1,4 +1,11 @@
|
|||
use base64::Engine;
|
||||
use totp_rs::Algorithm;
|
||||
|
||||
pub const TOTP_ALGORITHM: Algorithm = Algorithm::SHA1;
|
||||
pub const TOTP_DIGITS: usize = 6;
|
||||
pub const TOTP_SKEW: u8 = 1;
|
||||
pub const TOTP_STEP: u64 = 30;
|
||||
pub const TOTP_ISSUER: &'static str = "trifidapi";
|
||||
|
||||
pub fn base64decode(val: &str) -> Result<Vec<u8>, base64::DecodeError> {
|
||||
base64::engine::general_purpose::STANDARD.decode(val)
|
||||
|
|
Loading…
Reference in New Issue