mirror of
https://github.com/Mercantec-GHC/h4-projekt-gruppe-0-sm.git
synced 2025-04-27 16:24:07 +02:00
register
This commit is contained in:
parent
2b1b536172
commit
b3246c9a3e
1
backend/.gitignore
vendored
1
backend/.gitignore
vendored
@ -1,2 +1,3 @@
|
||||
build/
|
||||
database.db
|
||||
Session.vim
|
||||
|
@ -38,5 +38,7 @@ void route_post_user_register(HttpCtx* ctx);
|
||||
#define RESPOND_JSON(HTTP_CTX, STATUS, ...) \
|
||||
RESPOND(HTTP_CTX, STATUS, "application/json", __VA_ARGS__)
|
||||
|
||||
#define RESPOND_BAD_REQUEST(HTTP_CTX) \
|
||||
RESPOND_JSON(HTTP_CTX, 400, "{\"ok\":false}")
|
||||
#define RESPOND_BAD_REQUEST(HTTP_CTX, MSG) \
|
||||
RESPOND_JSON(HTTP_CTX, 400, "{\"ok\":false,\"msg\":\"%s\"}", (MSG))
|
||||
#define RESPOND_SERVER_ERROR(HTTP_CTX) \
|
||||
RESPOND_JSON(HTTP_CTX, 500, "{\"ok\":false,\"msg\":\"server error\"}")
|
||||
|
10
backend/src/controllers/auth.c
Normal file
10
backend/src/controllers/auth.c
Normal file
@ -0,0 +1,10 @@
|
||||
#include "../controllers.h"
|
||||
#include "../http_server.h"
|
||||
#include "../models_json.h"
|
||||
#include "../str_util.h"
|
||||
|
||||
void route_post_auth_login(HttpCtx* ctx)
|
||||
{
|
||||
|
||||
Cx* cx = http_ctx_user_ctx(ctx);
|
||||
}
|
48
backend/src/controllers/general.c
Normal file
48
backend/src/controllers/general.c
Normal file
@ -0,0 +1,48 @@
|
||||
#include "../controllers.h"
|
||||
#include "../http_server.h"
|
||||
#include "../models_json.h"
|
||||
|
||||
void route_get_index(HttpCtx* ctx)
|
||||
{
|
||||
Cx* cx = http_ctx_user_ctx(ctx);
|
||||
|
||||
RESPOND_HTML(ctx, 200,
|
||||
"<!DOCTYPE html><html><head><meta "
|
||||
"charset=\"utf-8\"></head><body><h1>Number = %d</h1></body></html>",
|
||||
cx->number);
|
||||
}
|
||||
|
||||
void route_post_set_number(HttpCtx* ctx)
|
||||
{
|
||||
Cx* cx = http_ctx_user_ctx(ctx);
|
||||
|
||||
const char* body_text = http_ctx_req_body(ctx);
|
||||
JsonParser parser;
|
||||
json_parser_construct(&parser, body_text, strlen(body_text));
|
||||
JsonValue* body = json_parser_parse(&parser);
|
||||
json_parser_destroy(&parser);
|
||||
|
||||
if (!json_object_has(body, "value")) {
|
||||
RESPOND_JSON(
|
||||
ctx, 200, "{\"ok\": false, \"msg\": \"no 'value' key\"}\r\n");
|
||||
goto l0_return;
|
||||
}
|
||||
|
||||
int64_t value = json_int(json_object_get(body, "value"));
|
||||
cx->number = (int)value;
|
||||
|
||||
RESPOND_JSON(ctx, 200, "{\"ok\": true}\r\n");
|
||||
|
||||
l0_return:
|
||||
json_free(body);
|
||||
}
|
||||
|
||||
void route_get_not_found(HttpCtx* ctx)
|
||||
{
|
||||
RESPOND_HTML(ctx, 404,
|
||||
"<!DOCTYPE html><html><head><meta "
|
||||
"charset=\"utf-8\"></head><body><center><h1>404 Not "
|
||||
"Found</h1><code style=\"font-size: 1rem;\">GET "
|
||||
"%s</code></center></body></html>",
|
||||
http_ctx_req_path(ctx));
|
||||
}
|
66
backend/src/controllers/users.c
Normal file
66
backend/src/controllers/users.c
Normal file
@ -0,0 +1,66 @@
|
||||
#include "../controllers.h"
|
||||
#include "../http_server.h"
|
||||
#include "../models_json.h"
|
||||
#include "../str_util.h"
|
||||
#include <string.h>
|
||||
|
||||
void route_post_user_register(HttpCtx* ctx)
|
||||
{
|
||||
Cx* cx = http_ctx_user_ctx(ctx);
|
||||
|
||||
const char* body_str = http_ctx_req_body(ctx);
|
||||
|
||||
JsonValue* body_json = json_parse(body_str, strlen(body_str));
|
||||
|
||||
UsersRegisterReq req;
|
||||
if (users_register_req_from_json(&req, body_json) != 0) {
|
||||
RESPOND_BAD_REQUEST(ctx, "bad request");
|
||||
json_free(body_json);
|
||||
return;
|
||||
}
|
||||
json_free(body_json);
|
||||
|
||||
if (strlen(req.name) == 0 || strlen(req.email) == 0
|
||||
|| strlen(req.password) > MAX_HASH_INPUT_LEN) {
|
||||
RESPOND_BAD_REQUEST(ctx, "bad request");
|
||||
users_register_req_free(&req);
|
||||
return;
|
||||
}
|
||||
|
||||
Ids ids;
|
||||
ids_construct(&ids);
|
||||
if (db_users_with_email(cx->db, &ids, req.email) != DbRes_Ok) {
|
||||
RESPOND_SERVER_ERROR(ctx);
|
||||
ids_destroy(&ids);
|
||||
users_register_req_free(&req);
|
||||
return;
|
||||
}
|
||||
if (ids.size > 0) {
|
||||
RESPOND_BAD_REQUEST(ctx, "email in use");
|
||||
ids_destroy(&ids);
|
||||
users_register_req_free(&req);
|
||||
return;
|
||||
}
|
||||
ids_destroy(&ids);
|
||||
|
||||
char* password_hash = str_hash(req.password);
|
||||
|
||||
if (db_user_insert(cx->db,
|
||||
&(User) {
|
||||
.id = 0,
|
||||
.name = req.name,
|
||||
.email = req.email,
|
||||
.password_hash = password_hash,
|
||||
.balance_dkk_cent = 0,
|
||||
})
|
||||
!= DbRes_Ok) {
|
||||
|
||||
RESPOND_SERVER_ERROR(ctx);
|
||||
free(password_hash);
|
||||
users_register_req_free(&req);
|
||||
return;
|
||||
}
|
||||
free(password_hash);
|
||||
users_register_req_free(&req);
|
||||
RESPOND_JSON(ctx, 200, "{\"ok\":true}");
|
||||
}
|
@ -15,7 +15,7 @@ typedef enum {
|
||||
typedef struct Db Db;
|
||||
|
||||
/// `user.id` field is ignored.
|
||||
DbRes db_user_insert(Db* db, User* user);
|
||||
DbRes db_user_insert(Db* db, const User* user);
|
||||
DbRes db_user_from_id(Db* db, User* user, int64_t id);
|
||||
/// Expects `ids` to be constructed.
|
||||
DbRes db_users_with_email(Db* db, Ids* ids, const char* email);
|
||||
|
@ -65,7 +65,7 @@ static inline void disconnect(sqlite3* connection)
|
||||
disconnect(connection); \
|
||||
}
|
||||
|
||||
DbRes db_user_insert(Db* db, User* user)
|
||||
DbRes db_user_insert(Db* db, const User* user)
|
||||
{
|
||||
static_assert(sizeof(User) == 40, "model has changed");
|
||||
|
||||
@ -76,7 +76,7 @@ DbRes db_user_insert(Db* db, User* user)
|
||||
sqlite3_stmt* stmt;
|
||||
sqlite3_prepare_v2(connection,
|
||||
"INSERT INTO users (name, email, password_hash, balance_dkk_cent) "
|
||||
"VALUES (?, ?, ?)",
|
||||
"VALUES (?, ?, ?, ?)",
|
||||
-1, &stmt, NULL);
|
||||
|
||||
sqlite3_bind_text(stmt, 1, user->name, -1, SQLITE_STATIC);
|
||||
|
@ -72,17 +72,27 @@ char* string_copy(const String* string)
|
||||
return copy;
|
||||
}
|
||||
|
||||
static inline StrHash str_hash_with_salt(const char* str, const uint8_t* salt)
|
||||
#define STR_HASH_SALT_SIZE 32
|
||||
#define STR_HASH_HASH_SIZE 32
|
||||
#define STR_HASH_STR_LEN 128
|
||||
|
||||
typedef struct {
|
||||
uint8_t salt[STR_HASH_SALT_SIZE];
|
||||
uint8_t hash[STR_HASH_HASH_SIZE];
|
||||
} HashData;
|
||||
|
||||
static inline HashData hashdata_from_str_and_salt(
|
||||
const char* str, const uint8_t* salt)
|
||||
{
|
||||
if (strlen(str) >= MAX_HASH_INPUT_LEN - 1) {
|
||||
if (strlen(str) >= MAX_HASH_INPUT_LEN) {
|
||||
fprintf(stderr, "error: tried to hash too long input\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
StrHash hash;
|
||||
HashData hash;
|
||||
memcpy(hash.salt, salt, STR_HASH_SALT_SIZE);
|
||||
|
||||
uint8_t input[MAX_HASH_INPUT_LEN + STR_HASH_SALT_SIZE] = { 0 };
|
||||
uint8_t input[MAX_HASH_INPUT_LEN + 1 + STR_HASH_SALT_SIZE] = { 0 };
|
||||
memcpy(input, hash.salt, STR_HASH_SALT_SIZE);
|
||||
memcpy(&input[STR_HASH_SALT_SIZE], str, strlen(str));
|
||||
|
||||
@ -90,20 +100,20 @@ static inline StrHash str_hash_with_salt(const char* str, const uint8_t* salt)
|
||||
return hash;
|
||||
}
|
||||
|
||||
StrHash str_hash(const char* str)
|
||||
static inline HashData hashdata_from_str(const char* str)
|
||||
{
|
||||
uint8_t salt[STR_HASH_SALT_SIZE];
|
||||
RAND_bytes(salt, STR_HASH_SALT_SIZE);
|
||||
return str_hash_with_salt(str, salt);
|
||||
return hashdata_from_str_and_salt(str, salt);
|
||||
}
|
||||
|
||||
bool str_hash_is_equal(StrHash hash, const char* str)
|
||||
static inline bool hashdata_is_equal(HashData hash, const char* str)
|
||||
{
|
||||
StrHash other = str_hash_with_salt(str, hash.salt);
|
||||
HashData other = hashdata_from_str_and_salt(str, hash.salt);
|
||||
return memcmp(hash.hash, other.hash, STR_HASH_HASH_SIZE) == 0;
|
||||
}
|
||||
|
||||
char* str_hash_to_string(StrHash hash)
|
||||
static inline char* hashdata_to_string(HashData hash)
|
||||
{
|
||||
char* result = calloc(STR_HASH_STR_LEN + 1, sizeof(char));
|
||||
for (size_t i = 0; i < STR_HASH_SALT_SIZE; ++i) {
|
||||
@ -121,7 +131,7 @@ char* str_hash_to_string(StrHash hash)
|
||||
return result;
|
||||
}
|
||||
|
||||
StrHash str_hash_from_string(const char* str)
|
||||
static inline HashData hashdata_from_hash_string(const char* str)
|
||||
{
|
||||
uint8_t result[64] = { 0 };
|
||||
size_t result_i = 0;
|
||||
@ -133,7 +143,7 @@ StrHash str_hash_from_string(const char* str)
|
||||
result_i += 1;
|
||||
}
|
||||
|
||||
StrHash hash;
|
||||
HashData hash;
|
||||
// memcpy((uint8_t*)&hash, result, sizeof(result));
|
||||
for (size_t i = 0; i < 32; ++i) {
|
||||
hash.salt[i] = result[i];
|
||||
@ -141,3 +151,15 @@ StrHash str_hash_from_string(const char* str)
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
char* str_hash(const char* input)
|
||||
{
|
||||
HashData data = hashdata_from_str(input);
|
||||
return hashdata_to_string(data);
|
||||
}
|
||||
|
||||
bool str_hash_equal(const char* hash, const char* input)
|
||||
{
|
||||
HashData data = hashdata_from_hash_string(hash);
|
||||
return hashdata_is_equal(data, input);
|
||||
}
|
||||
|
@ -33,18 +33,7 @@ char* string_copy(const String* string);
|
||||
|
||||
DEFINE_VEC(char*, RawStrVec, rawstr_vec, 8)
|
||||
|
||||
#define MAX_HASH_INPUT_LEN 256
|
||||
#define MAX_HASH_INPUT_LEN 256 - 1
|
||||
|
||||
#define STR_HASH_SALT_SIZE 32
|
||||
#define STR_HASH_HASH_SIZE 32
|
||||
#define STR_HASH_STR_LEN 128
|
||||
|
||||
typedef struct {
|
||||
uint8_t salt[STR_HASH_SALT_SIZE];
|
||||
uint8_t hash[STR_HASH_HASH_SIZE];
|
||||
} StrHash;
|
||||
|
||||
StrHash str_hash(const char* str);
|
||||
bool str_hash_is_equal(StrHash hash, const char* str);
|
||||
char* str_hash_to_string(StrHash hash);
|
||||
StrHash str_hash_from_string(const char* str);
|
||||
char* str_hash(const char* input);
|
||||
bool str_hash_equal(const char* hash, const char* input);
|
||||
|
Loading…
x
Reference in New Issue
Block a user