Use session_token for most actions, fail on NULL token

pull/5/head
~erin 2021-07-22 13:01:30 -04:00
parent 4c416cbee0
commit fe2a63afed
Signed by: erin
GPG Key ID: DA70E064A8C70F44
6 changed files with 106 additions and 10 deletions

19
CHANGELOG.md Normal file
View File

@ -0,0 +1,19 @@
## 0.5.0
- Most actions should now fail on a NULL token
- Cookie should now expire after a week
- Use sled database instead of json file to store users
## 0.4.0
- Serve frontend code
- Set cookie for token
- Basic messaging functionality
- Return JSON for all http requests
- License added (CNPLv6+)
## 0.3.0
- Add todo and other info to README
- Add chat core
## 0.2.0
- Basic functionality added
- Program is split into multiple files

View File

@ -1,6 +1,6 @@
[package]
name = "pogchat"
version = "0.4.0"
version = "0.5.0"
authors = ["Erin Nova <erin@the-system.eu.org>"]
edition = "2018"

View File

@ -26,7 +26,9 @@ or
},
}`
`GET /api/users/<name>/<pin>` Check if the user exists, and if the pin provided matches
`GET /api/token/<name>` Check if the current token matches the user provided
DEPRECATED `GET /api/users/<name>/<pin>` Check if the user exists, and if the pin provided matches
Returns status & reason json.
`POST /api/users/change {"name":"<username>","pin":"<pin>","changed_event":"name/pin/pronouns","new_event":"<new name/pin/pronouns>"` Change a users details via a json post.
@ -59,13 +61,18 @@ Whenever user sends a message, client will send message & token and backend will
- [x] Basic messaging system
- [x] Finish up `chat::create_message()`
- [x] Create `chat::fetch_messages()`
- [ ] Use unix timestamp for date
- [ ] Create `chat::delete_message()`
- [x] Switch to using sled database to store users
- [ ] Error handling
- [x] Token generation & storage
- [x] Sets cookie
- [x] Store token in json
- [x] Have cookie expire
- [x] Remove old cookie
- [x] Use token for most stuff
- [ ] Logout API
- [x] Fail on NULL token
- [x] Pronouns
- [x] Set pronouns
- [ ] Change pronouns

View File

@ -88,6 +88,50 @@ fn create_token(name: String, mut users: Vec<User>) -> String {
return "NULL".to_string();
}
// Check if user is properly logged in
#[get("/token/<name>")]
pub fn check_token(name: String, mut cookies: Cookies) -> JsonValue {
let users: Vec<User> = db_read();
for i in &users {
if i.name == name.to_lowercase() {
let token = match cookies.get_private("token") {
None => {
warn!("couldn't get token cookie!");
return json!({
"status": "fail",
"reason": "could not read cookie",
});
},
Some(token) => token,
};
if token.value() == "NULL" {
warn!("NULL token!");
return json!({
"status": "fail",
"reason": "NULL token",
});
} else if token.value() == i.session_token {
info!("user {} has correct session token", name);
return json!({
"status": "ok",
"reason": "correct token",
});
} else {
info!("user {} has incorrect token!", name);
return json!({
"status": "fail",
"reason": "incorrect token",
});
}
}
}
warn!("user {} not found", name);
return json!({
"status": "fail",
"reason": "user not found",
});
}
// Check if pin matches user
#[get("/users/<name>/<pin>")]
pub fn check_pin(mut cookies: Cookies, name: String, pin: i32) -> JsonValue {
@ -146,16 +190,35 @@ pub struct Event {
// Change info about a user
#[post("/users/change", format = "json", data = "<input>")]
pub fn change_info(input: Json<Event>) -> JsonValue {
pub fn change_info(input: Json<Event>, mut cookies: Cookies) -> JsonValue {
println!("{:?}", input);
// read in the users & hash the pin
let mut users: Vec<User> = db_read();
let hashed_pin = sha1::Sha1::from(&input.pin).digest().to_string();
// get token from cookie
let token = match cookies.get_private("token") {
None => {
warn!("couldn't get token cookie!");
return json!({
"status": "fail",
"reason": "could not read cookie",
});
},
Some(token) => token,
};
if token.value() == "NULL" {
warn!("NULL token!");
return json!({
"status": "fail",
"reason": "NULL token",
});
}
// loop through the users
for i in 0..users.len() {
if input.name.to_lowercase() == users[i].name { // if user found...
if hashed_pin == users[i].pin_hashed { // & if pin matches:
if token.value() == users[i].session_token { // & if token matches:
if input.changed_event == "name" {
// change the name
users[i].name = input.new_event.clone();
@ -212,8 +275,8 @@ pub fn change(name: String, pin: i32, new_name: String, new_pin: i32) -> JsonVal
for i in 0..users.len() {
if users[i].name == name.to_lowercase() {
// make sure name exists
if users[i].pin_hashed == hashed_pin_input {
// check if pin is correct
if hashed_pin_input == users[i].pin_hashed {
// check if token is correct
// Check wether to change name or name+pin
if users[i].name == new_name.to_lowercase() {
// check if new name already exists
@ -265,10 +328,10 @@ pub fn change(name: String, pin: i32, new_name: String, new_pin: i32) -> JsonVal
});
}
} else {
warn!("Incorrect pin given for user {}!", name.to_string());
warn!("Incorrect token for user {}!", name.to_string());
return json!({
"status": "fail",
"reason": "incorrect pin for user",
"reason": "incorrect token for user",
});
}
}

View File

@ -67,7 +67,13 @@ fn check_token(token: Cookie, message: Json<MessageInput<'_>>) -> JsonValue {
for i in &users {
// loop through elements
if i.name == message.name.to_lowercase() { // if it finds the user in the file
if i.session_token == token.value() { // if token matches
if token == "NULL" {
warn!("NULL token!");
return json!({
"status": "fail",
"reason": "NULL token",
});
} else if i.session_token == token.value() { // if token matches
info!("user exists and given token matches");
return create_message(message, "messages.json", i);
} else {

View File

@ -35,7 +35,8 @@ fn main() {
auth::change,
chat::send_message,
chat::fetch_messages,
auth::change_info
auth::change_info,
auth::check_token
],
)
.mount("/", StaticFiles::from("frontend"))