added endpoints end refactor
This commit is contained in:
@@ -3,3 +3,4 @@
|
||||
.cache
|
||||
.idea
|
||||
build
|
||||
fmongoose
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
CC = gcc
|
||||
CFLAGS = -Wall -g -std=gnu23
|
||||
CFLAGS = -Wall -g -std=gnu2x
|
||||
LDFLAGS =
|
||||
LIBS = -lpthread -lcrypto
|
||||
INCLUDES = -I./src/lib -I./src
|
||||
|
||||
+10
-1
@@ -1,10 +1,19 @@
|
||||
project('fmongoose', 'c', default_options : ['c_std=gnu23'])
|
||||
project('fmongoose', 'c', default_options: ['c_std=gnu2x'])
|
||||
include_dirs = include_directories('src', 'src/lib')
|
||||
deps = dependency('openssl')
|
||||
executable(
|
||||
'fmongoose',
|
||||
'src/main.c',
|
||||
'src/user.c',
|
||||
'src/add_user.c',
|
||||
'src/change_password.c',
|
||||
'src/change_user.c',
|
||||
'src/delete_user.c',
|
||||
'src/get_all_users.c',
|
||||
'src/get_token.c',
|
||||
'src/get_user.c',
|
||||
'src/register_user.c',
|
||||
'src/verify_token.c',
|
||||
'src/utils.c',
|
||||
'src/jwt.c',
|
||||
'src/lib/mongoose.c',
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
#include "user.h"
|
||||
#include "jwt.h"
|
||||
#include "utils.h"
|
||||
|
||||
void add_user(struct mg_connection *c, struct mg_http_message *hm) {
|
||||
request_with_token *requestdata = check_body(hm);
|
||||
const bool valid = jwt_verifyJWT(requestdata->token, JWT_DEFAULT_SECRET);
|
||||
if (!valid) {
|
||||
mg_http_reply(c, 403, "", "{%m:%m}", MG_ESC("error"),
|
||||
MG_ESC("invalid token"));
|
||||
return;
|
||||
}
|
||||
char responsedata[2048] = {0};
|
||||
snprintf(
|
||||
responsedata,
|
||||
sizeof(responsedata),
|
||||
"{\"success\": true}"
|
||||
);
|
||||
|
||||
mg_http_reply(
|
||||
c,
|
||||
200,
|
||||
"Content-Type: application/json\r\n",
|
||||
responsedata
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
#include "user.h"
|
||||
#include "jwt.h"
|
||||
#include "utils.h"
|
||||
|
||||
void change_password(struct mg_connection *c, struct mg_http_message *hm) {
|
||||
request_with_token *requestdata = check_body(hm);
|
||||
const bool valid = jwt_verifyJWT(requestdata->token, JWT_DEFAULT_SECRET);
|
||||
if (!valid) {
|
||||
mg_http_reply(c, 403, "", "{%m:%m}", MG_ESC("error"),
|
||||
MG_ESC("invalid token"));
|
||||
return;
|
||||
}
|
||||
char responsedata[2048] = {0};
|
||||
snprintf(
|
||||
responsedata,
|
||||
sizeof(responsedata),
|
||||
"{\"success\": true}"
|
||||
);
|
||||
|
||||
mg_http_reply(
|
||||
c,
|
||||
200,
|
||||
"Content-Type: application/json\r\n",
|
||||
responsedata
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
#include "user.h"
|
||||
#include "jwt.h"
|
||||
#include "utils.h"
|
||||
|
||||
void change_user(struct mg_connection *c, struct mg_http_message *hm) {
|
||||
request_with_token *requestdata = check_body(hm);
|
||||
const bool valid = jwt_verifyJWT(requestdata->token, JWT_DEFAULT_SECRET);
|
||||
if (!valid) {
|
||||
mg_http_reply(c, 403, "", "{%m:%m}", MG_ESC("error"),
|
||||
MG_ESC("invalid token"));
|
||||
return;
|
||||
}
|
||||
char responsedata[2048] = {0};
|
||||
snprintf(
|
||||
responsedata,
|
||||
sizeof(responsedata),
|
||||
"{\"success\": true}"
|
||||
);
|
||||
|
||||
mg_http_reply(
|
||||
c,
|
||||
200,
|
||||
"Content-Type: application/json\r\n",
|
||||
responsedata
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
#include "user.h"
|
||||
#include "jwt.h"
|
||||
#include "utils.h"
|
||||
|
||||
void delete_user(struct mg_connection *c, struct mg_http_message *hm) {
|
||||
request_with_token *requestdata = check_body(hm);
|
||||
const bool valid = jwt_verifyJWT(requestdata->token, JWT_DEFAULT_SECRET);
|
||||
if (!valid) {
|
||||
mg_http_reply(c, 403, "", "{%m:%m}", MG_ESC("error"),
|
||||
MG_ESC("invalid token"));
|
||||
return;
|
||||
}
|
||||
char responsedata[2048] = {0};
|
||||
snprintf(
|
||||
responsedata,
|
||||
sizeof(responsedata),
|
||||
"{\"success\": true}"
|
||||
);
|
||||
|
||||
mg_http_reply(
|
||||
c,
|
||||
200,
|
||||
"Content-Type: application/json\r\n",
|
||||
responsedata
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
#include "user.h"
|
||||
#include "utils.h"
|
||||
|
||||
void get_all_users(struct mg_connection *c, struct mg_http_message *hm) {
|
||||
request_with_token *data = check_body(hm);
|
||||
if (data->error != NULL) {
|
||||
mg_http_reply(c, 403, "", "{%m:%m}", MG_ESC("error"), MG_ESC(data->error));
|
||||
return;
|
||||
}
|
||||
free_request_with_token(data);
|
||||
|
||||
User users[2] = {{.id = 1,
|
||||
.username = "tola",
|
||||
.email = "mail@example.com",
|
||||
.password = "passsword",
|
||||
.group = "root",
|
||||
.is_superuser = true},
|
||||
{.id = 2,
|
||||
.username = "lisa",
|
||||
.email = "mail@example.com",
|
||||
.password = "asdf",
|
||||
.group = "users",
|
||||
.is_superuser = false}};
|
||||
char msg[2048] = {0};
|
||||
strncpy(msg, "[", sizeof(msg));
|
||||
for (int i = 0; i < sizeof(users) / sizeof(User); i++) {
|
||||
snprintf(msg + strlen(msg), sizeof(msg) - strlen(msg),
|
||||
"{\"%s\":%d,\"%s\":\"%s\",\"%s\":\"%s\",\"%s\":\"%s\",\"%s\":\"%"
|
||||
"s\",\"%s\":%d}",
|
||||
"id", users[i].id, "username", users[i].username, "email",
|
||||
users[i].email, "password", users[i].password, "group",
|
||||
users[i].group, "is_superuser", users[i].is_superuser);
|
||||
if (i < sizeof(users) / sizeof(User) - 1) {
|
||||
strncat(msg, ",", strlen(msg));
|
||||
}
|
||||
}
|
||||
strncat(msg, "]\n", strlen(msg));
|
||||
mg_http_reply(c, 200, "Content-type: application/json\r\n", msg);
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
#include "user.h"
|
||||
#include "jwt.h"
|
||||
|
||||
void get_token(struct mg_connection *c, struct mg_http_message *hm) {
|
||||
if (hm->body.len == 0) {
|
||||
mg_http_reply(c, 400, "", "{%m:%m}", MG_ESC("error"),
|
||||
MG_ESC("must have username and password"));
|
||||
return;
|
||||
}
|
||||
cJSON *jsonbody = cJSON_Parse(hm->body.buf);
|
||||
cJSON *username = cJSON_GetObjectItem(jsonbody, "username");
|
||||
cJSON *password = cJSON_GetObjectItem(jsonbody, "password");
|
||||
if (username == NULL || password == NULL) {
|
||||
const char *error_ptr = cJSON_GetErrorPtr();
|
||||
if (error_ptr != NULL) {
|
||||
mg_http_reply(c, 400, "", "{%m:%m}", MG_ESC("error"), MG_ESC(error_ptr));
|
||||
return;
|
||||
}
|
||||
mg_http_reply(c, 400, "", "{%m:%m}", MG_ESC("error"),
|
||||
MG_ESC("must have username and password"));
|
||||
return;
|
||||
}
|
||||
const char *header = "{\"alg\":\"HS256\",\"typ\":\"JWT\"}";
|
||||
const char *payload = "{\"sub\": \"1234567890\",\"username\": "
|
||||
"\"tola\",\"is_superuser\": true,\"iat\": 1516239022}";
|
||||
char *token = jwt_createJWT(header, payload, JWT_DEFAULT_SECRET);
|
||||
mg_http_reply(c, 200, "", "{%m:%m}", MG_ESC("token"), MG_ESC(token));
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
#include "user.h"
|
||||
#include "jwt.h"
|
||||
#include "utils.h"
|
||||
|
||||
void get_user(struct mg_connection *c, struct mg_http_message *hm) {
|
||||
request_with_token *requestdata = check_body(hm);
|
||||
const bool valid = jwt_verifyJWT(requestdata->token, JWT_DEFAULT_SECRET);
|
||||
if (!valid) {
|
||||
mg_http_reply(c, 403, "", "{%m:%m}", MG_ESC("error"),
|
||||
MG_ESC("invalid token"));
|
||||
return;
|
||||
}
|
||||
const User *user = new_user("username", "", "mail@example.com", "root", true);
|
||||
if (user == NULL) {
|
||||
mg_http_reply(c, 404, "", "{%m:%m}", MG_ESC("error"), MG_ESC("user not found"));
|
||||
return;
|
||||
}
|
||||
char responsedata[2048] = {0};
|
||||
snprintf(
|
||||
responsedata,
|
||||
sizeof(responsedata),
|
||||
"{\"id\": %d, \"username\": \"%s\", \"email\": \"%s\", \"group\": \"%s\", \"is_superuser\": %s}",
|
||||
user->id,
|
||||
user->username,
|
||||
user->email,
|
||||
user->group,
|
||||
user->is_superuser ? "true" : "false"
|
||||
);
|
||||
|
||||
mg_http_reply(
|
||||
c,
|
||||
200,
|
||||
"Content-Type: application/json\r\n",
|
||||
responsedata
|
||||
);
|
||||
}
|
||||
@@ -12,6 +12,12 @@ static const struct route routes[] = {
|
||||
{"POST", "/api/token", get_token},
|
||||
{"POST", "/api/token/verify", verify_token},
|
||||
{"POST", "/api/users", get_all_users},
|
||||
{"POST", "/api/users/user", get_user},
|
||||
{"POST", "/api/users/delete", delete_user},
|
||||
{"POST", "/api/users/password", change_password},
|
||||
{"POST", "/api/users/change", change_password},
|
||||
{"POST", "/api/users/add", add_user},
|
||||
{"POST", "/api/register", register_user},
|
||||
{nullptr, nullptr, nullptr}
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
#include "user.h"
|
||||
|
||||
void register_user(struct mg_connection *c, struct mg_http_message *hm) {
|
||||
if (hm->body.len == 0) {
|
||||
mg_http_reply(c, 400, "", "{%m:%m}", MG_ESC("error"),
|
||||
MG_ESC("must have <username>, <password>, <email>, <group, optional>, <is_superuser, optional>"));
|
||||
return;
|
||||
}
|
||||
cJSON *jsonbody = cJSON_Parse(hm->body.buf);
|
||||
cJSON *username = cJSON_GetObjectItem(jsonbody, "username");
|
||||
cJSON *password = cJSON_GetObjectItem(jsonbody, "password");
|
||||
cJSON *email = cJSON_GetObjectItem(jsonbody, "email");
|
||||
cJSON *group = cJSON_GetObjectItem(jsonbody, "group");
|
||||
cJSON *is_superuser = cJSON_GetObjectItem(jsonbody, "is_superuser");
|
||||
if (username == nullptr || password == nullptr || email == nullptr) {
|
||||
mg_http_reply(c, 400, "", "{%m:%m}", MG_ESC("error"),
|
||||
MG_ESC("must have <username>, <password>, <email>, <group, optional>, <is_superuser, optional>"));
|
||||
return;
|
||||
}
|
||||
if (group == nullptr) {
|
||||
group = cJSON_CreateString("users");
|
||||
}
|
||||
if (is_superuser == nullptr) {
|
||||
is_superuser = cJSON_CreateBool(false);
|
||||
}
|
||||
const User *new_user_data = new_user(
|
||||
username->valuestring,
|
||||
password->valuestring,
|
||||
email->valuestring,
|
||||
group->valuestring,
|
||||
is_superuser->valueint
|
||||
);
|
||||
if (new_user_data == nullptr) {
|
||||
mg_http_reply(c, 500, "", "{%m:%m}", MG_ESC("error"), MG_ESC("failed to create user"));
|
||||
return;
|
||||
}
|
||||
char responsedata[2048] = {0};
|
||||
snprintf(
|
||||
responsedata,
|
||||
sizeof(responsedata),
|
||||
"{\"id\": %d, \"username\": \"%s\", \"email\": \"%s\", \"group\": \"%s\", \"is_superuser\": %d}",
|
||||
new_user_data->id,
|
||||
new_user_data->username,
|
||||
new_user_data->email,
|
||||
new_user_data->group,
|
||||
new_user_data->is_superuser
|
||||
);
|
||||
|
||||
mg_http_reply(
|
||||
c,
|
||||
200,
|
||||
"Content-Type: application/json\r\n",
|
||||
responsedata
|
||||
);
|
||||
}
|
||||
+13
-80
@@ -4,86 +4,6 @@
|
||||
#include <cJSON.h>
|
||||
#include <mongoose.h>
|
||||
|
||||
#define JWT_SECRET_KEY "secret"
|
||||
|
||||
void get_all_users(struct mg_connection *c, struct mg_http_message *hm) {
|
||||
request_with_token *data = check_body(hm);
|
||||
if (data->error != NULL) {
|
||||
mg_http_reply(c, 403, "", "{%m:%m}", MG_ESC("error"), MG_ESC(data->error));
|
||||
return;
|
||||
}
|
||||
free_request_with_token(data);
|
||||
|
||||
User users[2] = {{.id = 1,
|
||||
.username = "tola",
|
||||
.email = "mail@example.com",
|
||||
.password = "passsword",
|
||||
.group = "root",
|
||||
.is_superuser = 1},
|
||||
{.id = 2,
|
||||
.username = "lisa",
|
||||
.email = "mail@example.com",
|
||||
.password = "asdf",
|
||||
.group = "users",
|
||||
.is_superuser = 0}};
|
||||
char msg[2048] = {0};
|
||||
strncpy(msg, "[", sizeof(msg));
|
||||
for (int i = 0; i < sizeof(users) / sizeof(User); i++) {
|
||||
snprintf(msg + strlen(msg), sizeof(msg) - strlen(msg),
|
||||
"{\"%s\":%d,\"%s\":\"%s\",\"%s\":\"%s\",\"%s\":\"%s\",\"%s\":\"%"
|
||||
"s\",\"%s\":%d}",
|
||||
"id", users[i].id, "username", users[i].username, "email",
|
||||
users[i].email, "password", users[i].password, "group",
|
||||
users[i].group, "is_superuser", users[i].is_superuser);
|
||||
if (i < sizeof(users) / sizeof(User) - 1) {
|
||||
strncat(msg, ",", strlen(msg));
|
||||
}
|
||||
}
|
||||
strncat(msg, "]\n", strlen(msg));
|
||||
mg_http_reply(c, 200, "Content-type: application/json\r\n", msg);
|
||||
}
|
||||
|
||||
void get_token(struct mg_connection *c, struct mg_http_message *hm) {
|
||||
if (hm->body.len == 0) {
|
||||
mg_http_reply(c, 400, "", "{%m:%m}", MG_ESC("error"),
|
||||
MG_ESC("must have username and password"));
|
||||
return;
|
||||
}
|
||||
cJSON *jsonbody = cJSON_Parse(hm->body.buf);
|
||||
cJSON *username = cJSON_GetObjectItem(jsonbody, "username");
|
||||
cJSON *password = cJSON_GetObjectItem(jsonbody, "password");
|
||||
if (username == NULL || password == NULL) {
|
||||
const char *error_ptr = cJSON_GetErrorPtr();
|
||||
if (error_ptr != NULL) {
|
||||
mg_http_reply(c, 400, "", "{%m:%m}", MG_ESC("error"), MG_ESC(error_ptr));
|
||||
return;
|
||||
}
|
||||
mg_http_reply(c, 400, "", "{%m:%m}", MG_ESC("error"),
|
||||
MG_ESC("must have username and password"));
|
||||
return;
|
||||
}
|
||||
const char *header = "{\"alg\":\"HS256\",\"typ\":\"JWT\"}";
|
||||
const char *payload = "{\"sub\": \"1234567890\",\"username\": "
|
||||
"\"tola\",\"is_superuser\": true,\"iat\": 1516239022}";
|
||||
char *token = jwt_createJWT(header, payload, JWT_SECRET_KEY);
|
||||
mg_http_reply(c, 200, "", "{%m:%m}", MG_ESC("token"), MG_ESC(token));
|
||||
}
|
||||
|
||||
void verify_token(struct mg_connection *c, struct mg_http_message *hm) {
|
||||
const request_with_token *data = check_body(hm);
|
||||
if (data->error != nullptr) {
|
||||
mg_http_reply(c, 403, "", "{%m:%m}", MG_ESC("error"), MG_ESC(data->error));
|
||||
return;
|
||||
}
|
||||
const bool valid = jwt_verifyJWT(data->token, JWT_SECRET_KEY);
|
||||
if (!valid) {
|
||||
mg_http_reply(c, 403, "", "{%m:%m}", MG_ESC("error"),
|
||||
MG_ESC("invalid token"));
|
||||
return;
|
||||
}
|
||||
mg_http_reply(c, 200, "", "{%m:%m}", MG_ESC("valid"), MG_ESC("true"));
|
||||
}
|
||||
|
||||
request_with_token *new_request_with_token(char *token, cJSON *body,
|
||||
char *error) {
|
||||
request_with_token *data = malloc(sizeof(request_with_token));
|
||||
@@ -105,3 +25,16 @@ void free_request_with_token(request_with_token *data) {
|
||||
}
|
||||
free(data);
|
||||
}
|
||||
|
||||
User *new_user(const char *username, const char *password, const char *email, const char *group, bool is_superuser) {
|
||||
User *user = malloc(sizeof(User));
|
||||
if (user == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
user->username = strdup(username);
|
||||
user->password = strdup(password);
|
||||
user->email = strdup(email);
|
||||
user->group = strdup(group);
|
||||
user->is_superuser = is_superuser;
|
||||
return user;
|
||||
}
|
||||
|
||||
+22
-5
@@ -5,13 +5,24 @@
|
||||
|
||||
typedef struct User {
|
||||
int id;
|
||||
char username[256];
|
||||
char email[256];
|
||||
char password[256];
|
||||
char group[256];
|
||||
int is_superuser;
|
||||
char *username;
|
||||
char *email;
|
||||
char *password;
|
||||
char *group;
|
||||
bool is_superuser;
|
||||
} User;
|
||||
|
||||
User *new_user(const char *username, const char *password, const char *email, const char *group, bool is_superuser);
|
||||
|
||||
typedef struct register_request {
|
||||
char *username;
|
||||
char *email;
|
||||
char *password;
|
||||
char *group;
|
||||
bool is_superuser;
|
||||
char *error;
|
||||
} register_request;
|
||||
|
||||
typedef struct request_with_token {
|
||||
char *token;
|
||||
cJSON *body;
|
||||
@@ -29,5 +40,11 @@ request_with_token *new_request_with_token(char *token, cJSON *body,
|
||||
void free_request_with_token(request_with_token *data);
|
||||
|
||||
void get_all_users(struct mg_connection *c, struct mg_http_message *hm);
|
||||
void get_user(struct mg_connection *c, struct mg_http_message *hm);
|
||||
void delete_user(struct mg_connection *c, struct mg_http_message *hm);
|
||||
void add_user(struct mg_connection *c, struct mg_http_message *hm);
|
||||
void change_user(struct mg_connection *c, struct mg_http_message *hm);
|
||||
void change_password(struct mg_connection *c, struct mg_http_message *hm);
|
||||
void register_user(struct mg_connection *c, struct mg_http_message *hm);
|
||||
void get_token(struct mg_connection *c, struct mg_http_message *hm);
|
||||
void verify_token(struct mg_connection *c, struct mg_http_message *hm);
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
#include "user.h"
|
||||
#include "jwt.h"
|
||||
#include "utils.h"
|
||||
|
||||
void verify_token(struct mg_connection *c, struct mg_http_message *hm) {
|
||||
const request_with_token *data = check_body(hm);
|
||||
if (data->error != nullptr) {
|
||||
mg_http_reply(c, 403, "", "{%m:%m}", MG_ESC("error"), MG_ESC(data->error));
|
||||
return;
|
||||
}
|
||||
const bool valid = jwt_verifyJWT(data->token, JWT_DEFAULT_SECRET);
|
||||
if (!valid) {
|
||||
mg_http_reply(c, 403, "", "{%m:%m}", MG_ESC("error"),
|
||||
MG_ESC("invalid token"));
|
||||
return;
|
||||
}
|
||||
mg_http_reply(c, 200, "", "{%m:%m}", MG_ESC("valid"), MG_ESC("true"));
|
||||
}
|
||||
Reference in New Issue
Block a user