Added defolt auth w/o ref token
This commit is contained in:
parent
aa4db89f97
commit
1577486736
1671
Cargo.lock
generated
Normal file
1671
Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
21
Cargo.toml
21
Cargo.toml
@ -1,8 +1,27 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "bitauth"
|
name = "BitAuth"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
bb8 = "0.8.1"
|
||||||
|
bcrypt = "0.15.0"
|
||||||
|
chrono = "0.4.31"
|
||||||
|
http-body-util = "0.1.0"
|
||||||
|
hyper = { version = "1.1.0", features = ["full"] }
|
||||||
|
hyper-util = { version = "0.1.2", features = ["full"] }
|
||||||
|
jsonwebtoken = "9.2.0"
|
||||||
|
rand = "0.8.5"
|
||||||
|
rsa = "0.9.6"
|
||||||
|
serde_json = "1.0.111"
|
||||||
|
skytable = "0.8.3"
|
||||||
|
tokio = { version = "1.35.1", features = ["full"] }
|
||||||
|
urlencoding = "2.1.3"
|
||||||
|
uuid = { version = "1.6.1", features = ["v4", "v5"] }
|
||||||
|
|
||||||
|
|
||||||
|
[[bin]]
|
||||||
|
name = "bitauth"
|
||||||
|
path = "src/main.rs"
|
||||||
|
475
src/main.rs
475
src/main.rs
@ -1,3 +1,474 @@
|
|||||||
fn main() {
|
use std::{
|
||||||
println!("Hello, world!");
|
sync::Arc,
|
||||||
|
net::SocketAddr,
|
||||||
|
collections::HashMap,
|
||||||
|
time::{SystemTime, UNIX_EPOCH},
|
||||||
|
};
|
||||||
|
use chrono::{
|
||||||
|
DateTime,
|
||||||
|
};
|
||||||
|
use http_body_util::{
|
||||||
|
Full,
|
||||||
|
BodyExt,
|
||||||
|
};
|
||||||
|
use hyper::{
|
||||||
|
StatusCode,
|
||||||
|
Request,
|
||||||
|
Response,
|
||||||
|
Method,
|
||||||
|
HeaderMap,
|
||||||
|
header::HeaderValue,
|
||||||
|
body::{Bytes, Incoming},
|
||||||
|
server::conn::http1 as Server,
|
||||||
|
service::service_fn,
|
||||||
|
};
|
||||||
|
use hyper_util::{
|
||||||
|
rt::TokioIo,
|
||||||
|
};
|
||||||
|
use tokio::{
|
||||||
|
net::TcpListener,
|
||||||
|
};
|
||||||
|
use rsa::{
|
||||||
|
pkcs1::{EncodeRsaPublicKey, EncodeRsaPrivateKey},
|
||||||
|
RsaPrivateKey,
|
||||||
|
RsaPublicKey,
|
||||||
|
};
|
||||||
|
use urlencoding::{
|
||||||
|
decode as url_decode,
|
||||||
|
};
|
||||||
|
use jsonwebtoken as jwt;
|
||||||
|
use jwt::{
|
||||||
|
Header,
|
||||||
|
Algorithm,
|
||||||
|
TokenData,
|
||||||
|
Validation,
|
||||||
|
EncodingKey,
|
||||||
|
DecodingKey,
|
||||||
|
encode as jwt_encode,
|
||||||
|
decode as jwt_decode,
|
||||||
|
};
|
||||||
|
use serde_json::{
|
||||||
|
Value as Json,
|
||||||
|
json,
|
||||||
|
};
|
||||||
|
use uuid::{
|
||||||
|
Uuid,
|
||||||
|
};
|
||||||
|
use skytable::{
|
||||||
|
Config,
|
||||||
|
pool::{self, ConnectionMgrTcp},
|
||||||
|
query,
|
||||||
|
};
|
||||||
|
use bb8::{
|
||||||
|
Pool,
|
||||||
|
};
|
||||||
|
mod type_users;
|
||||||
|
mod type_sites;
|
||||||
|
use crate::{
|
||||||
|
type_users::Users,
|
||||||
|
type_sites::Sites,
|
||||||
|
};
|
||||||
|
|
||||||
|
type Res<T, E> = std::result::Result<T, E>;
|
||||||
|
type Result<T> = std::result::Result<T, Box<dyn std::error::Error + Send + Sync>>;
|
||||||
|
|
||||||
|
|
||||||
|
const PORT: u16 = 8081;
|
||||||
|
|
||||||
|
const DB_POOL: u32 = 32;
|
||||||
|
const DB_ADDR: &str = "192.168.1.49";
|
||||||
|
const DB_PORT: u16 = 2003;
|
||||||
|
const DB_USER: &str = "root";
|
||||||
|
const DB_PASS: &str = "rootpass12345678";
|
||||||
|
|
||||||
|
const TOKEN_LIFETIME: u32 = 300;
|
||||||
|
const REFRESH_LIFETIME: u32 = 2_678_400;
|
||||||
|
|
||||||
|
const HEADER_HTML: &str = r#"
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head></head>
|
||||||
|
<body>
|
||||||
|
<header>
|
||||||
|
<a href="/">index</a>
|
||||||
|
<a href="/login">login</a>
|
||||||
|
<a href="/register">register</a>
|
||||||
|
<hr>
|
||||||
|
</header>
|
||||||
|
<main>
|
||||||
|
"#;
|
||||||
|
const FOOTER_HTML: &str = r#"
|
||||||
|
<footer>
|
||||||
|
<hr>
|
||||||
|
Made by BitHeaven.
|
||||||
|
</footer>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
"#;
|
||||||
|
const INDEX_HTML: &str = "<h1>main</h1>";
|
||||||
|
const LOGIN_HTML: &str = r#"
|
||||||
|
<h1>login</h1>
|
||||||
|
<form method="POST">
|
||||||
|
<input name="login" type="text" placeholder="login / email" required>
|
||||||
|
<br>
|
||||||
|
<input name="password" type="password" placeholder="password" required>
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
<button type="submit">login</button>
|
||||||
|
</form>
|
||||||
|
"#;
|
||||||
|
const REG_HTML: &str = r#"
|
||||||
|
<h1>register</h1>
|
||||||
|
<form method="POST">
|
||||||
|
<input name="login" type="text" placeholder="login" required>
|
||||||
|
<br>
|
||||||
|
<input name="email" type="email" placeholder="email (opt)">
|
||||||
|
<br>
|
||||||
|
<input name="password" type="password" placeholder="password" required>
|
||||||
|
<br>
|
||||||
|
<input name="password2" type="password" placeholder="password again" required>
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
<button type="submit">register</button>
|
||||||
|
</form>
|
||||||
|
"#;
|
||||||
|
const RECOVER_HTML: &str = "<h1>recover</h1>";
|
||||||
|
const NF_HTML: &str = "<h1>404</h1>think about it.";
|
||||||
|
const CSS3: &str = r#"<style>
|
||||||
|
:root { color-scheme: dark; }
|
||||||
|
</style>"#;
|
||||||
|
|
||||||
|
#[tokio::main]
|
||||||
|
async fn main() -> Result<()> {
|
||||||
|
let addr = SocketAddr::from(([0, 0, 0, 0], PORT));
|
||||||
|
let listener = TcpListener::bind(addr).await?;
|
||||||
|
|
||||||
|
let pool = Arc::new(pool::get_async(DB_POOL, Config::new(DB_ADDR, DB_PORT, DB_USER, DB_PASS)).await.unwrap());
|
||||||
|
init_tables(pool.clone()).await?;
|
||||||
|
|
||||||
|
println!("Server started on port: {}", PORT);
|
||||||
|
|
||||||
|
loop {
|
||||||
|
let (stream, _) = listener.accept().await?;
|
||||||
|
|
||||||
|
let ip = format!("{:?}", stream.peer_addr().unwrap().ip());
|
||||||
|
|
||||||
|
let io = TokioIo::new(stream);
|
||||||
|
|
||||||
|
let this_pool = pool.clone();
|
||||||
|
tokio::task::spawn(async move {
|
||||||
|
if let Err(err) = Server::Builder::new().serve_connection(
|
||||||
|
io, service_fn(move |req| handle_connection(req, this_pool.clone(), ip.clone()))
|
||||||
|
).await {
|
||||||
|
println!("Error serving connection: {:?}", err);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn handle_connection(req: Request<Incoming>, pool: Arc<Pool<ConnectionMgrTcp>>, ip: String) -> Result<Response<Full<Bytes>>> {
|
||||||
|
if ip == "1.1.1.1" {
|
||||||
|
}
|
||||||
|
|
||||||
|
// let mut con = pool.get().await?;
|
||||||
|
// let q = con.query_parse::<Forwards>(&query!("SELECT * FROM bitproxy.forwards WHERE domain = ?", host)).await;
|
||||||
|
// if !q.is_ok() {
|
||||||
|
// }
|
||||||
|
// let target_url = q.unwrap().address.to_owned()
|
||||||
|
// .parse::<hyper::Uri>().unwrap();
|
||||||
|
|
||||||
|
let res = Response::new(Full::new(Bytes::new()));
|
||||||
|
let (mut parts, _) = res.into_parts();
|
||||||
|
let body: String;
|
||||||
|
let restype: HeaderValue;
|
||||||
|
|
||||||
|
let mut headers = parts.headers.clone();
|
||||||
|
|
||||||
|
let cookies = get_cookies(req.headers().clone());
|
||||||
|
let token = cookies.get("token");
|
||||||
|
let token = match token.is_none() {
|
||||||
|
false => token.unwrap(),
|
||||||
|
_ => ""
|
||||||
|
};
|
||||||
|
|
||||||
|
if token != "" && jwt_verify(pool.clone(), token).await?.claims.as_object().unwrap().len() == 0 {
|
||||||
|
parts.status = StatusCode::FOUND;
|
||||||
|
set_cookie(&mut headers, "token", "");
|
||||||
|
set_location(&mut headers, "/");
|
||||||
|
parts.headers = headers;
|
||||||
|
return Ok(Response::from_parts(parts, Full::new(Bytes::new())));
|
||||||
|
}
|
||||||
|
|
||||||
|
(body, parts.status, restype) = match req.uri().path().as_ref() {
|
||||||
|
"/" => uri_index(),
|
||||||
|
"/cabinet" => uri_login(req, pool.clone(), &mut headers).await?,
|
||||||
|
"/login" => uri_login(req, pool.clone(), &mut headers).await?,
|
||||||
|
"/register" => uri_register(req, pool.clone()).await?,
|
||||||
|
"/recover" => uri_recover(),
|
||||||
|
x if x.starts_with("/api") => uri_api(req),
|
||||||
|
_ => uri_404()
|
||||||
|
};
|
||||||
|
|
||||||
|
headers.insert(hyper::header::CONTENT_TYPE, restype);
|
||||||
|
parts.headers = headers;
|
||||||
|
|
||||||
|
Ok(Response::from_parts(parts, Full::new(Bytes::from(body))))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn build_html(body: &str) -> String {
|
||||||
|
format!("{}{}{}{}", HEADER_HTML, CSS3, body, FOOTER_HTML)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_cookie(headers: &mut HeaderMap, key: &str, value: &str) {
|
||||||
|
let time = DateTime::from_timestamp((time() + REFRESH_LIFETIME) as i64, 0).expect("REASON").to_rfc2822();
|
||||||
|
let time = time.replace("+0000", "GMT");
|
||||||
|
headers.append(hyper::header::SET_COOKIE, HeaderValue::from_str(format!("{}={}; HttpOnly; Expires={}", key, value, time).as_str()).unwrap());
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_cookies(headers: HeaderMap) -> HashMap<String, String> {
|
||||||
|
let header = headers.get(hyper::header::COOKIE);
|
||||||
|
let cookies = match header.is_none() {
|
||||||
|
false => header.unwrap().to_str().unwrap(),
|
||||||
|
_ => ""
|
||||||
|
};
|
||||||
|
|
||||||
|
double_split(cookies.to_owned(), ";", "=")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_location(headers: &mut HeaderMap, location: &str) {
|
||||||
|
headers.append(hyper::header::LOCATION, HeaderValue::from_str(format!("{}", location).as_str()).unwrap());
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn uri_login(req: Request<Incoming>, pool: Arc<Pool<ConnectionMgrTcp>>, headers: &mut HeaderMap) -> Result<(String, StatusCode, HeaderValue)> {
|
||||||
|
let mut cookie: String = Default::default();
|
||||||
|
|
||||||
|
if *req.method() == Method::POST {
|
||||||
|
let body = get_body_from_request(req).await?;
|
||||||
|
let body = String::from_utf8(body).unwrap();
|
||||||
|
let body = double_split(body, "&", "=");
|
||||||
|
|
||||||
|
cookie = login_user(pool.clone(), body).await?;
|
||||||
|
}
|
||||||
|
|
||||||
|
set_cookie(headers, "token", &cookie);
|
||||||
|
|
||||||
|
let restype: HeaderValue = "text/html".parse().unwrap();
|
||||||
|
Ok((build_html(LOGIN_HTML), StatusCode::OK, restype))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn uri_index() -> (String, StatusCode, HeaderValue) {
|
||||||
|
let restype: HeaderValue = "text/html".parse().unwrap();
|
||||||
|
(build_html(INDEX_HTML), StatusCode::OK, restype)
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn uri_register(req: Request<Incoming>, pool: Arc<Pool<ConnectionMgrTcp>>) -> Result<(String, StatusCode, HeaderValue)> {
|
||||||
|
if *req.method() == Method::POST {
|
||||||
|
let body = get_body_from_request(req).await?;
|
||||||
|
let body = String::from_utf8(body).unwrap();
|
||||||
|
let body = double_split(body, "&", "=");
|
||||||
|
|
||||||
|
match create_user(pool.clone(), body).await? {
|
||||||
|
true => println!("Created"),
|
||||||
|
_ => println!("Failed")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let restype: HeaderValue = "text/html".parse().unwrap();
|
||||||
|
Ok((build_html(REG_HTML), StatusCode::OK, restype))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn uri_recover() -> (String, StatusCode, HeaderValue) {
|
||||||
|
let restype: HeaderValue = "text/html".parse().unwrap();
|
||||||
|
(build_html(RECOVER_HTML), StatusCode::OK, restype)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn uri_api(req: Request<Incoming>) -> (String, StatusCode, HeaderValue) {
|
||||||
|
let uri_api: &str = req.uri().path().as_ref();
|
||||||
|
let res: Json = match &uri_api[4..uri_api.len()] {
|
||||||
|
"/test" => json!({"error": false, "msg": "test"}),
|
||||||
|
_ => json!({"error": true, "msg": "No endpoint"})
|
||||||
|
};
|
||||||
|
|
||||||
|
let restype: HeaderValue = "application/json".parse().unwrap();
|
||||||
|
(res.to_string(), StatusCode::IM_A_TEAPOT, restype)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn uri_404() -> (String, StatusCode, HeaderValue) {
|
||||||
|
let restype: HeaderValue = "text/html".parse().unwrap();
|
||||||
|
(build_html(NF_HTML), StatusCode::NOT_FOUND, restype)
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn init_tables(pool: Arc<Pool<ConnectionMgrTcp>>) -> Res<(), skytable::error::Error> {
|
||||||
|
let mut con = pool.get().await.unwrap();
|
||||||
|
|
||||||
|
let _ = con.query_parse::<()>(&query!("CREATE SPACE IF NOT EXISTS bitauth")).await;
|
||||||
|
let _ = con.query_parse::<()>(&query!(
|
||||||
|
"CREATE MODEL IF NOT EXISTS bitauth.users(login: string, uuid: string, password: string, null email: string)"
|
||||||
|
)).await;
|
||||||
|
let _ = con.query_parse::<()>(&query!(
|
||||||
|
"CREATE MODEL IF NOT EXISTS bitauth.sites(uuid: string, uid: string, domain: string, pkey: binary, skey: binary)"
|
||||||
|
)).await;
|
||||||
|
let _ = con.query_parse::<()>(&query!(
|
||||||
|
"CREATE MODEL IF NOT EXISTS bitauth.tokens(uuid: string, uid: string, sid: string, ref: string, refend: uint32)"
|
||||||
|
)).await;
|
||||||
|
|
||||||
|
let q = con.query_parse::<Sites>(&query!("SELECT * FROM bitauth.sites WHERE uuid = 0")).await;
|
||||||
|
if q.is_err() {
|
||||||
|
let (skey, pkey) = rsa_gen();
|
||||||
|
let _ = con.query_parse::<()>(&query!(
|
||||||
|
"INSERT INTO bitauth.sites { uuid: ?, uid: ?, domain: ?, pkey: ?, skey: ? }",
|
||||||
|
"0", "0", "", pkey, skey
|
||||||
|
)).await;
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn login_user(pool: Arc<Pool<ConnectionMgrTcp>>, data: HashMap<String, String>) -> Res<String, skytable::error::Error> {
|
||||||
|
let mut err = false;
|
||||||
|
let mut ret: String = Default::default();
|
||||||
|
let mut con = pool.get().await.unwrap();
|
||||||
|
|
||||||
|
let login = data.get("login").unwrap();
|
||||||
|
let pass = data.get("password").unwrap().trim();
|
||||||
|
|
||||||
|
let q = con.query_parse::<Users>(&query!("SELECT * FROM bitauth.users WHERE login = ?", login)).await;
|
||||||
|
if q.is_err() { err = true };
|
||||||
|
|
||||||
|
if !err {
|
||||||
|
let q = q.unwrap();
|
||||||
|
if bcrypt::verify(pass, q.password.as_str()).unwrap() {
|
||||||
|
ret = jwt_sign(pool.clone(), json!({
|
||||||
|
"login": q.login,
|
||||||
|
"uuid": q.uuid,
|
||||||
|
// "refresh": q.ref,
|
||||||
|
// "refexp": q.refend,
|
||||||
|
"iat": time(),
|
||||||
|
"exp": time() + TOKEN_LIFETIME
|
||||||
|
})).await.unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn create_user(pool: Arc<Pool<ConnectionMgrTcp>>, data: HashMap<String, String>) -> Res<bool, skytable::error::Error> {
|
||||||
|
let mut ret = true;
|
||||||
|
let mut con = pool.get().await.unwrap();
|
||||||
|
|
||||||
|
let login = data.get("login").unwrap();
|
||||||
|
let email = data.get("email").unwrap();
|
||||||
|
let pass = data.get("password").unwrap();
|
||||||
|
let pass2 = data.get("password2").unwrap();
|
||||||
|
|
||||||
|
if pass != pass2 { ret = false };
|
||||||
|
if pass.len() < 8 { ret = false };
|
||||||
|
|
||||||
|
let q = con.query_parse::<(String,)>(&query!("SELECT uuid FROM bitauth.users WHERE login = ?", login)).await;
|
||||||
|
if q.is_ok() { ret = false };
|
||||||
|
|
||||||
|
if ret {
|
||||||
|
let uuid = format!("{}", uuid_v4().as_hyphenated());
|
||||||
|
let pass = bcrypt::hash(pass, 12).unwrap();
|
||||||
|
|
||||||
|
let q = con.query_parse::<()>(&query!(
|
||||||
|
r#"INSERT INTO bitauth.users {
|
||||||
|
uuid: ?,
|
||||||
|
login: ?,
|
||||||
|
password: ?,
|
||||||
|
email: ?
|
||||||
|
}"#,
|
||||||
|
uuid,
|
||||||
|
login,
|
||||||
|
pass,
|
||||||
|
email
|
||||||
|
)).await;
|
||||||
|
|
||||||
|
if q.is_err() { ret = false }
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn get_body_from_request(mut req: Request<Incoming>) -> Result<Vec<u8>> {
|
||||||
|
let mut body: Vec<u8> = vec![];
|
||||||
|
while let Some(next) = req.frame().await {
|
||||||
|
let frame = next?;
|
||||||
|
if let Some(chunk) = frame.data_ref() {
|
||||||
|
body.extend_from_slice(chunk);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(body)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn double_split(body: String, first: &str, second: &str) -> HashMap<String, String> {
|
||||||
|
body.split(first)
|
||||||
|
.filter_map(|c| {
|
||||||
|
c.split_once(second)
|
||||||
|
.map(|(l, r)| (l.trim().to_owned(), format!("{}", url_decode(r).expect("UTF-8")).trim().to_owned()))})
|
||||||
|
.collect::<HashMap<String, String>>()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn rsa_gen() -> (Vec<u8>, Vec<u8>) {
|
||||||
|
let mut rng = rand::thread_rng();
|
||||||
|
let bits = 2048;
|
||||||
|
let skey = RsaPrivateKey::new(&mut rng, bits).expect("RSA err");
|
||||||
|
let pkey = RsaPublicKey::from(&skey);
|
||||||
|
|
||||||
|
let skey = skey.to_pkcs1_der().unwrap().as_bytes().to_vec();
|
||||||
|
let pkey = pkey.to_pkcs1_der().unwrap().as_bytes().to_vec();
|
||||||
|
|
||||||
|
(skey, pkey)
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn jwt_sign(pool: Arc<Pool<ConnectionMgrTcp>>, data: Json) -> Result<String> {
|
||||||
|
let mut con = pool.get().await.unwrap();
|
||||||
|
|
||||||
|
let q = con.query_parse::<Sites>(&query!("SELECT * FROM bitauth.sites WHERE uuid = ?", "0")).await;
|
||||||
|
if q.is_err() { return Ok("".to_owned()) };
|
||||||
|
let skey = q.unwrap().skey;
|
||||||
|
|
||||||
|
let skey = EncodingKey::from_rsa_der(&skey);
|
||||||
|
let header = Header::new(Algorithm::RS512);
|
||||||
|
let token = jwt_encode(&header, &data, &skey)?;
|
||||||
|
|
||||||
|
Ok(token)
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn jwt_verify(pool: Arc<Pool<ConnectionMgrTcp>>, token: &str) -> Result<TokenData<Json>> {
|
||||||
|
let mut con = pool.get().await.unwrap();
|
||||||
|
let mut ret = TokenData { header: Header::new(Algorithm::RS512), claims: json![{}] };
|
||||||
|
|
||||||
|
let q = con.query_parse::<Sites>(&query!("SELECT * FROM bitauth.sites WHERE uuid = ?", "0")).await;
|
||||||
|
if q.is_err() { return Ok(ret) };
|
||||||
|
let pkey = q.unwrap().pkey;
|
||||||
|
|
||||||
|
let pkey = DecodingKey::from_rsa_der(&pkey);
|
||||||
|
let token = jwt_decode::<Json>(&token, &pkey, &Validation::new(Algorithm::RS512));
|
||||||
|
|
||||||
|
match token.is_ok() {
|
||||||
|
true => ret = token.clone().unwrap(),
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn uuid_v4() -> Uuid {
|
||||||
|
Uuid::new_v4()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn time() -> u32 {
|
||||||
|
SystemTime::now()
|
||||||
|
.duration_since(UNIX_EPOCH)
|
||||||
|
.unwrap()
|
||||||
|
.as_secs() as u32
|
||||||
|
}
|
||||||
|
|
||||||
|
/*fn time_ns() -> u128 {
|
||||||
|
SystemTime::now()
|
||||||
|
.duration_since(UNIX_EPOCH)
|
||||||
|
.unwrap()
|
||||||
|
.as_millis() as u128
|
||||||
|
}*/
|
||||||
|
40
src/type_sites.rs
Normal file
40
src/type_sites.rs
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
use skytable::{
|
||||||
|
query::SQParam,
|
||||||
|
response::{FromResponse, Response},
|
||||||
|
ClientResult,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
pub struct Sites {
|
||||||
|
pub uuid: String,
|
||||||
|
pub uid: String,
|
||||||
|
pub domain: String,
|
||||||
|
pub pkey: Vec<u8>,
|
||||||
|
pub skey: Vec<u8>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Sites {
|
||||||
|
pub fn new(uuid: String, uid: String, domain: String, pkey: Vec<u8>, skey: Vec<u8>) -> Self {
|
||||||
|
Self {
|
||||||
|
uuid,
|
||||||
|
uid,
|
||||||
|
domain,
|
||||||
|
pkey,
|
||||||
|
skey,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SQParam for Sites {
|
||||||
|
fn append_param(&self, q: &mut Vec<u8>) -> usize {
|
||||||
|
self.uuid.append_param(q)
|
||||||
|
+ self.domain.append_param(q)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromResponse for Sites {
|
||||||
|
fn from_response(resp: Response) -> ClientResult<Self> {
|
||||||
|
let (uuid, uid, domain, pkey, skey) = FromResponse::from_response(resp)?;
|
||||||
|
Ok(Self::new(uuid, uid, domain, pkey, skey))
|
||||||
|
}
|
||||||
|
}
|
38
src/type_users.rs
Normal file
38
src/type_users.rs
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
use skytable::{
|
||||||
|
query::SQParam,
|
||||||
|
response::{FromResponse, Response},
|
||||||
|
ClientResult,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
pub struct Users {
|
||||||
|
pub login: String,
|
||||||
|
pub uuid: String,
|
||||||
|
pub password: String,
|
||||||
|
pub email: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Users {
|
||||||
|
pub fn new(login: String, uuid: String, password: String, email: String) -> Self {
|
||||||
|
Self {
|
||||||
|
login,
|
||||||
|
uuid,
|
||||||
|
password,
|
||||||
|
email,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SQParam for Users {
|
||||||
|
fn append_param(&self, q: &mut Vec<u8>) -> usize {
|
||||||
|
self.login.append_param(q)
|
||||||
|
+ self.uuid.append_param(q)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromResponse for Users {
|
||||||
|
fn from_response(resp: Response) -> ClientResult<Self> {
|
||||||
|
let (login, uuid, password, email) = FromResponse::from_response(resp)?;
|
||||||
|
Ok(Self::new(login, uuid, password, email))
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user