add user info events

This commit is contained in:
Bevan Hunt 2020-01-07 16:19:18 -08:00
parent cc642bd8b6
commit 6abd574034
4 changed files with 94 additions and 13 deletions

2
Cargo.lock generated
View File

@ -386,7 +386,7 @@ dependencies = [
[[package]]
name = "broker"
version = "0.7.1"
version = "0.8.0"
dependencies = [
"actix-cors 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"actix-rt 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",

View File

@ -1,6 +1,6 @@
[package]
name = "broker"
version = "0.7.1"
version = "0.8.0"
authors = ["Bevan Hunt <bevan@bevanhunt.com>"]
edition = "2018"
license = "MIT"

View File

@ -32,9 +32,9 @@ POST /users
- public endpoint
- POST JSON to create a user
```json
{"username":{...}, "password":{...}, "info":{...}}
{"username":{...}, "password":{...}, "collection_id":{...}}
```
- where {...} is for username and string, password a string, and info any JSON you want
- where {...} is for username and string, password a string, and collection_id is the uuid of the event collection for user info
will return
```json
@ -92,6 +92,13 @@ GET /events/collections/{collection_id}
- authenticated endpoint (Authorization: Bearer {jwt})
- do a GET request where {collection_id} is the uuid of the collection you want (sorted by ascending timestamp)
```html
GET /events/user
```
- authenticated endpoint (Authorization: Bearer {jwt})
- do a GET request to get the user info event collection (sorted by ascending timestamp)
```html
GET /events/{id}/cancel
```

View File

@ -39,14 +39,14 @@ struct User {
id: uuid::Uuid,
username: String,
password: String,
info: serde_json::Value,
collection_id: uuid::Uuid,
}
#[derive(Debug, Serialize, Deserialize, Clone)]
struct UserForm {
username: String,
password: String,
info: serde_json::Value,
collection_id: uuid::Uuid,
}
#[derive(Debug, Serialize, Deserialize, Clone)]
@ -83,6 +83,75 @@ struct Claims {
exp: usize,
}
async fn user_collection(data: web::Data<MyData>, req: HttpRequest) -> Result<HttpResponse, Error> {
// get origin env var
let config = envy::from_env::<Config>().unwrap();
let secret = config.secret;
let mut id = "".to_owned();
// verify jwt
let headers = req.headers();
let mut check : i32 = 0;
for (k, v) in headers {
if k == "Authorization" {
let token = v.to_str().unwrap().to_owned();
let parts = token.split(" ");
for part in parts {
if part != "Bearer" {
let _ = match decode::<Claims>(&part, secret.as_ref(), &Validation::default()) {
Ok(c) => {
check = check + 1;
id = c.claims.sub;
},
Err(err) => match *err.kind() {
_ => return Ok(HttpResponse::Unauthorized().json(""))
},
};
}
}
}
}
// if no auth header
if check == 0 {
return Ok(HttpResponse::Unauthorized().json(""))
}
let versioned = format!("_u_{}", id);
let g = data.db.get(&versioned.as_bytes()).unwrap().unwrap();
let v = std::str::from_utf8(&g).unwrap().to_owned();
let user : User = serde_json::from_str(&v).unwrap();
// turn iVec(s) to String(s) and make HashMap
let mut records: Vec<Event> = data.db.iter().into_iter().filter(|x| {
let p = x.as_ref().unwrap();
let k = std::str::from_utf8(&p.0).unwrap().to_owned();
if k.contains(&"_v_") {
let v = std::str::from_utf8(&p.1).unwrap().to_owned();
let j : Event = serde_json::from_str(&v).unwrap();
if j.collection_id.to_string() == user.collection_id.to_string() {
return true
} else {
return false
}
} else {
return false
}
}).map(|x| {
let p = x.unwrap();
let v = std::str::from_utf8(&p.1).unwrap().to_owned();
let j : Event = serde_json::from_str(&v).unwrap();
j
}).collect();
records.sort_by(|a, b| a.timestamp.cmp(&b.timestamp));
// return data to json response as 200
Ok(HttpResponse::Ok().json(records))
}
async fn collection(data: web::Data<MyData>, path: web::Path<Path>, req: HttpRequest) -> Result<HttpResponse, Error> {
// get origin env var
@ -304,9 +373,9 @@ async fn user_create(data: web::Data<MyData>, json: web::Json<UserForm>) -> Resu
} else {
// set as future value
let uuid = Uuid::new_v4();
let versioned = format!("user_u_{}", uuid.to_string());
let versioned = format!("_u_{}", uuid.to_string());
let hashed = hash(json.clone().password, DEFAULT_COST).unwrap();
let new_user = User{id: uuid, username: json.clone().username, password: hashed, info: json.clone().info};
let new_user = User{id: uuid, username: json.clone().username, password: hashed, collection_id: json.collection_id };
let _ = data.db.compare_and_swap(versioned.as_bytes(), None as Option<&[u8]>, Some(serde_json::to_string(&new_user).unwrap().as_bytes()));
let _ = web::block(move || { data.db.flush() }).await;
@ -332,12 +401,16 @@ async fn login(data: web::Data<MyData>, json: web::Json<Login>) -> Result<HttpRe
let records : HashMap<String, String> = data.db.iter().into_iter().filter(|x| {
let p = x.as_ref().unwrap();
let k = std::str::from_utf8(&p.0).unwrap().to_owned();
let v = std::str::from_utf8(&p.1).unwrap().to_owned();
let user : User = serde_json::from_str(&v).unwrap();
if k.contains(&"_u_") && user.username == json.username {
return true;
if k.contains(&"_u_") {
let v = std::str::from_utf8(&p.1).unwrap().to_owned();
let user : User = serde_json::from_str(&v).unwrap();
if user.username == json.username {
return true
} else {
return false
}
} else {
return false;
return false
}
}).map(|x| {
let p = x.unwrap();
@ -440,6 +513,7 @@ pub async fn broker_run(origin: String) -> std::result::Result<(), std::io::Erro
.route("/events", web::get().to(new_client))
.route("/events/collections/{id}", web::get().to(collection))
.route("/events/{id}/cancel", web::get().to(cancel))
.route("/events/user", web::get().to(user_collection))
.route("/users", web::post().to(user_create))
.route("/login", web::post().to(login))
})