some work
This commit is contained in:
parent
c46bf75993
commit
a6aa68682e
3 changed files with 1459 additions and 0 deletions
1268
Cargo.lock
generated
Normal file
1268
Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load diff
11
Cargo.toml
Normal file
11
Cargo.toml
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
[package]
|
||||||
|
name = "abies"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
actix-web = "4"
|
||||||
|
serde = { version = "1", features = ["derive"] }
|
||||||
|
base64 = "0.21"
|
180
src/main.rs
Normal file
180
src/main.rs
Normal file
|
@ -0,0 +1,180 @@
|
||||||
|
use std::io;
|
||||||
|
use actix_web::{App, get, HttpRequest, HttpResponse, HttpServer, post, Responder};
|
||||||
|
use actix_web::web::{Form, Json, Path, Query, Redirect};
|
||||||
|
use base64::Engine;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
struct AuthorizeReq {
|
||||||
|
state: String,
|
||||||
|
redirect_uri: String,
|
||||||
|
client_id: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[get("/oauth/authorize")]
|
||||||
|
async fn authorize(req: Query<AuthorizeReq>) -> impl Responder {
|
||||||
|
// We will return a code that is just the base64 of the return information
|
||||||
|
// The client ID is the user info
|
||||||
|
Redirect::to(
|
||||||
|
format!("{}?code={}&state={}",
|
||||||
|
req.redirect_uri,
|
||||||
|
base64::engine::general_purpose::URL_SAFE.encode(&req.client_id),
|
||||||
|
req.state
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
struct TokenReq {
|
||||||
|
client_id: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize)]
|
||||||
|
struct TokenResp {
|
||||||
|
access_token: String,
|
||||||
|
expires_in: u64,
|
||||||
|
data: User,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize)]
|
||||||
|
struct User {
|
||||||
|
cid: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[post("/oauth/token")]
|
||||||
|
async fn token(req: Form<TokenReq>) -> Json<TokenResp> {
|
||||||
|
let parts = req.client_id.split(';').collect::<Vec<_>>();
|
||||||
|
Json(TokenResp {
|
||||||
|
access_token: req.client_id.clone(),
|
||||||
|
expires_in: u64::MAX,
|
||||||
|
data: User {
|
||||||
|
cid: parts[0].parse().unwrap()
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize)]
|
||||||
|
struct UserResp {
|
||||||
|
data: UserB,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize)]
|
||||||
|
struct UserB {
|
||||||
|
cid: u64,
|
||||||
|
oauth: UserBOauth,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize)]
|
||||||
|
struct UserBOauth {
|
||||||
|
token_valid: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[get("/api/user")]
|
||||||
|
async fn user(req: HttpRequest) -> Json<UserResp> {
|
||||||
|
let bearer = req.headers().get("Authorization").unwrap();
|
||||||
|
let bearer = bearer.to_str().unwrap().split(' ').nth(1).unwrap();
|
||||||
|
|
||||||
|
let parts = bearer.split(';').collect::<Vec<_>>();
|
||||||
|
Json(UserResp {
|
||||||
|
data: UserB {
|
||||||
|
cid: parts[0].parse().unwrap(),
|
||||||
|
oauth: UserBOauth { token_valid: "true".to_string() },
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
struct ApiKey {
|
||||||
|
apikey: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize)]
|
||||||
|
struct RosterResponse {
|
||||||
|
data: Vec<RosterUser>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize)]
|
||||||
|
struct RosterUser {
|
||||||
|
cid: u64,
|
||||||
|
fname: String,
|
||||||
|
lname: String,
|
||||||
|
rating: u64,
|
||||||
|
facility_join: String,
|
||||||
|
email: String,
|
||||||
|
flag_broadcastOptedIn: bool
|
||||||
|
}
|
||||||
|
|
||||||
|
#[get("/v2/facility/{_facility}/roster")]
|
||||||
|
async fn roster(_facility: Path<String>, info: Query<ApiKey>) -> Json<RosterResponse> {
|
||||||
|
// API KEY:
|
||||||
|
// cid;first;last;rating;date;email
|
||||||
|
let split = info.apikey.split(';').collect::<Vec<_>>();
|
||||||
|
let cid = split[0];
|
||||||
|
let first = split[1];
|
||||||
|
let last = split[2];
|
||||||
|
let rating = split[3];
|
||||||
|
let join = split[4];
|
||||||
|
let email = split[5];
|
||||||
|
|
||||||
|
Json(RosterResponse {
|
||||||
|
data: vec![
|
||||||
|
RosterUser {
|
||||||
|
cid: cid.parse().unwrap(),
|
||||||
|
fname: first.to_string(),
|
||||||
|
lname: last.to_string(),
|
||||||
|
rating: rating.parse().unwrap(),
|
||||||
|
facility_join: join.to_string(),
|
||||||
|
email: email.to_string(),
|
||||||
|
flag_broadcastOptedIn: false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize)]
|
||||||
|
struct RosterUserWithData {
|
||||||
|
data: RosterUser
|
||||||
|
}
|
||||||
|
|
||||||
|
#[get("/v2/user/{_user}")]
|
||||||
|
async fn user_vatusa(_user: Path<String>, info: Query<ApiKey>) -> Json<RosterUserWithData> {
|
||||||
|
// API KEY:
|
||||||
|
// cid;first;last;rating;date;email
|
||||||
|
let split = info.apikey.split(';').collect::<Vec<_>>();
|
||||||
|
let cid = split[0];
|
||||||
|
let first = split[1];
|
||||||
|
let last = split[2];
|
||||||
|
let rating = split[3];
|
||||||
|
let join = split[4];
|
||||||
|
let email = split[5];
|
||||||
|
|
||||||
|
Json(RosterUserWithData {
|
||||||
|
data: RosterUser {
|
||||||
|
cid: cid.parse().unwrap(),
|
||||||
|
fname: first.to_string(),
|
||||||
|
lname: last.to_string(),
|
||||||
|
rating: rating.parse().unwrap(),
|
||||||
|
facility_join: join.to_string(),
|
||||||
|
email: email.to_string(),
|
||||||
|
flag_broadcastOptedIn: false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
#[get("/v2/facility/ZTL")]
|
||||||
|
async fn facility_info() -> HttpResponse {
|
||||||
|
HttpResponse::Ok().content_type("application/json").body("{\"data\":{\"facility\":{\"info\":{\"id\":\"ZTL\",\"name\":\"Atlanta ARTCC\",\"url\":\"https://www.ztlartcc.org\",\"hosted_email_domain\":null,\"region\":7,\"atm\":1419831,\"datm\":1363076,\"ta\":0,\"ec\":1299471,\"fe\":1436006,\"wm\":1504635,\"uls_return\":\"https://www.ztlartcc.org/login\",\"uls_devreturn\":\"https://ztl-dev.team-stringer.com/login\",\"active\":1,\"ip\":\"62.232.184.170\",\"api_sandbox_ip\":\"\",\"ace\":0,\"url_dev\":\"https://dev.ztlartcc.org, http://localhost:8000\"},\"roles\":[{\"id\":3478260,\"cid\":1179253,\"facility\":\"ZTL\",\"role\":\"MTR\",\"created_at\":\"2020-07-21T15:06:06+00:00\"},{\"id\":4542083,\"cid\":1371112,\"facility\":\"ZTL\",\"role\":\"FACCBT\",\"created_at\":\"2021-08-16T16:48:09+00:00\"},{\"id\":4556123,\"cid\":1436006,\"facility\":\"ZTL\",\"role\":\"FACCBT\",\"created_at\":\"2021-08-21T17:57:27+00:00\"},{\"id\":4561585,\"cid\":1497213,\"facility\":\"ZTL\",\"role\":\"FACCBT\",\"created_at\":\"2021-08-23T17:35:53+00:00\"},{\"id\":4575631,\"cid\":1504635,\"facility\":\"ZTL\",\"role\":\"MTR\",\"created_at\":\"2021-08-28T17:51:37+00:00\"},{\"id\":4661286,\"cid\":1259390,\"facility\":\"ZTL\",\"role\":\"MTR\",\"created_at\":\"2021-09-28T21:01:00+00:00\"},{\"id\":4842798,\"cid\":1456808,\"facility\":\"ZTL\",\"role\":\"MTR\",\"created_at\":\"2021-12-03T01:05:21+00:00\"},{\"id\":5082406,\"cid\":1505957,\"facility\":\"ZTL\",\"role\":\"MTR\",\"created_at\":\"2022-02-25T16:20:00+00:00\"},{\"id\":5262130,\"cid\":1350969,\"facility\":\"ZTL\",\"role\":\"MTR\",\"created_at\":\"2022-04-29T19:50:25+00:00\"},{\"id\":5636024,\"cid\":1363076,\"facility\":\"ZTL\",\"role\":\"MTR\",\"created_at\":\"2022-09-13T03:00:04+00:00\"},{\"id\":5682489,\"cid\":1179253,\"facility\":\"ZTL\",\"role\":\"FACCBT\",\"created_at\":\"2022-09-29T22:42:40+00:00\"},{\"id\":5793538,\"cid\":1582574,\"facility\":\"ZTL\",\"role\":\"MTR\",\"created_at\":\"2022-11-07T02:41:26+00:00\"},{\"id\":6172122,\"cid\":1560654,\"facility\":\"ZTL\",\"role\":\"MTR\",\"created_at\":\"2023-03-14T02:44:31+00:00\"},{\"id\":6305725,\"cid\":1519217,\"facility\":\"ZTL\",\"role\":\"FACCBT\",\"created_at\":\"2023-04-28T19:23:11+00:00\"},{\"id\":6349612,\"cid\":1599592,\"facility\":\"ZTL\",\"role\":\"MTR\",\"created_at\":\"2023-05-13T03:23:40+00:00\"},{\"id\":6447106,\"cid\":1496415,\"facility\":\"ZTL\",\"role\":\"MTR\",\"created_at\":\"2023-06-15T03:44:08+00:00\"},{\"id\":6550011,\"cid\":1380859,\"facility\":\"ZTL\",\"role\":\"MTR\",\"created_at\":\"2023-07-20T02:54:03+00:00\"},{\"id\":6579168,\"cid\":1315134,\"facility\":\"ZTL\",\"role\":\"MTR\",\"created_at\":\"2023-07-30T03:49:25+00:00\"},{\"id\":6626465,\"cid\":1419831,\"facility\":\"ZTL\",\"role\":\"ATM\",\"created_at\":\"2023-08-14T16:45:06+00:00\"},{\"id\":6626466,\"cid\":1363076,\"facility\":\"ZTL\",\"role\":\"DATM\",\"created_at\":\"2023-08-14T16:45:06+00:00\"},{\"id\":6626467,\"cid\":1436006,\"facility\":\"ZTL\",\"role\":\"FE\",\"created_at\":\"2023-08-14T16:45:06+00:00\"},{\"id\":6626468,\"cid\":1299471,\"facility\":\"ZTL\",\"role\":\"EC\",\"created_at\":\"2023-08-14T16:45:06+00:00\"},{\"id\":6626469,\"cid\":1504635,\"facility\":\"ZTL\",\"role\":\"WM\",\"created_at\":\"2023-08-14T16:45:06+00:00\"}]},\"stats\":{\"controllers\":140,\"pendingTransfers\":0},\"notices\":[]},\"testing\":false}")
|
||||||
|
}
|
||||||
|
|
||||||
|
#[actix_web::main]
|
||||||
|
async fn main() -> io::Result<()> {
|
||||||
|
HttpServer::new(|| {
|
||||||
|
App::new()
|
||||||
|
.service(authorize)
|
||||||
|
.service(token)
|
||||||
|
.service(user)
|
||||||
|
.service(roster)
|
||||||
|
.service(user_vatusa)
|
||||||
|
.service(facility_info)
|
||||||
|
})
|
||||||
|
.bind(("127.0.0.1", 8080))?.run().await
|
||||||
|
}
|
Loading…
Reference in a new issue