feat: user management api -add user

This commit is contained in:
gc87
2024-12-16 08:01:00 +08:00
parent 8671b4baaa
commit 1b5c8528e2
8 changed files with 184 additions and 6 deletions
+18
View File
@@ -78,6 +78,24 @@
} \
}
#define NEU_VALIDATE_JWT_WITH_USER(aio, user) \
{ \
if (!disable_jwt) { \
char *jwt = \
(char *) neu_http_get_header(aio, (char *) "Authorization"); \
\
NEU_JSON_RESPONSE_ERROR(neu_jwt_validate(jwt), { \
if (error_code.error != NEU_ERR_SUCCESS) { \
neu_http_response(aio, error_code.error, result_error); \
free(result_error); \
return; \
} else { \
neu_jwt_decode_user(jwt, user); \
} \
}); \
} \
}
enum neu_http_method {
NEU_HTTP_METHOD_UNDEFINE = 0x0,
NEU_HTTP_METHOD_GET,
+2 -1
View File
@@ -26,9 +26,10 @@ extern "C" {
#include <stdbool.h>
int neu_jwt_init(const char *dir_path);
int neu_jwt_new(char **token);
int neu_jwt_new(char **token, const char *user);
int neu_jwt_validate(char *b_token);
void neu_jwt_destroy();
int neu_jwt_decode_user(char *token, char *user);
#ifdef __cplusplus
}
+57 -2
View File
@@ -73,7 +73,7 @@ void handle_login(nng_aio *aio)
char *token = NULL;
char *result = NULL;
int ret = neu_jwt_new(&token);
int ret = neu_jwt_new(&token, req->name);
if (ret != 0) {
NEU_JSON_RESPONSE_ERROR(NEU_ERR_NEED_TOKEN, {
neu_http_response(aio, error_code.error, result_error);
@@ -101,7 +101,62 @@ void handle_login(nng_aio *aio)
void handle_add_user(nng_aio *aio)
{
(void) aio;
char current_user[USER_NAME_LEN] = { 0 };
NEU_VALIDATE_JWT_WITH_USER(aio, current_user);
NEU_PROCESS_HTTP_REQUEST(
aio, neu_json_login_req_t, neu_json_decode_login_req, {
neu_json_login_resp_t login_resp = { 0 };
neu_user_t * user = neu_load_user(req->name);
int pass_len = strlen(req->pass);
if (0 == strlen(current_user)) {
nlog_error("check current user failed");
NEU_JSON_RESPONSE_ERROR(NEU_ERR_INVALID_USER_OR_PASSWORD, {
neu_http_response(aio, error_code.error, result_error);
});
}
if (NULL == user) {
nlog_error("could not find user `%s`", req->name);
NEU_JSON_RESPONSE_ERROR(NEU_ERR_INVALID_USER_OR_PASSWORD, {
neu_http_response(aio, error_code.error, result_error);
});
} else if (pass_len < NEU_USER_PASSWORD_MIN_LEN ||
pass_len > NEU_USER_PASSWORD_MAX_LEN) {
nlog_error("user `%s` password too short or too long",
req->name);
NEU_JSON_RESPONSE_ERROR(NEU_ERR_INVALID_PASSWORD_LEN, {
neu_http_response(aio, error_code.error, result_error);
});
} else if (neu_user_check_password(user, req->pass)) {
char *token = NULL;
char *result = NULL;
int ret = neu_jwt_new(&token, req->name);
if (ret != 0) {
NEU_JSON_RESPONSE_ERROR(NEU_ERR_NEED_TOKEN, {
neu_http_response(aio, error_code.error, result_error);
jwt_free_str(token);
});
}
login_resp.token = token;
neu_json_encode_by_fn(&login_resp, neu_json_encode_login_resp,
&result);
neu_http_ok(aio, result);
jwt_free_str(token);
free(result);
} else {
nlog_error("user `%s` password check fail", req->name);
NEU_JSON_RESPONSE_ERROR(NEU_ERR_INVALID_USER_OR_PASSWORD, {
neu_http_response(aio, error_code.error, result_error);
});
}
neu_user_free(user);
})
}
void handle_delete_user(nng_aio *aio)
+6
View File
@@ -28,6 +28,8 @@ extern "C" {
#include "persist/persist.h"
#define USER_NAME_LEN 32
typedef struct {
char *name;
char *hash;
@@ -41,6 +43,10 @@ int neu_user_update_password(neu_user_t *user, const char *new_password);
neu_user_t *neu_load_user(const char *name);
int neu_save_user(neu_user_t *user);
int neu_user_list();
int neu_user_add(const char *name, const char *password);
int neu_user_delete(const char *name);
#ifdef __cplusplus
}
#endif
+63
View File
@@ -129,3 +129,66 @@ int neu_json_encode_login_resp(void *json_object, void *param)
return ret;
}
int neu_json_decode_add_user_req(char *buf, neu_json_password_req_t **result)
{
int ret = 0;
neu_json_password_req_t *req = calloc(1, sizeof(neu_json_password_req_t));
neu_json_elem_t req_elems[] = {
{
.name = "name",
.t = NEU_JSON_STR,
},
{
.name = "old_pass",
.t = NEU_JSON_STR,
},
{
.name = "new_pass",
.t = NEU_JSON_STR,
},
};
ret = neu_json_decode(buf, NEU_JSON_ELEM_SIZE(req_elems), req_elems);
if (ret != 0) {
goto decode_fail;
}
req->name = req_elems[0].v.val_str;
req->old_pass = req_elems[1].v.val_str;
req->new_pass = req_elems[2].v.val_str;
*result = req;
return ret;
decode_fail:
free(req);
return -1;
}
void neu_json_decode_add_user_req_free(neu_json_password_req_t *req)
{
if (req) {
free(req->name);
free(req->old_pass);
free(req->new_pass);
free(req);
}
}
int neu_json_encode_add_user_resp(void *json_object, void *param)
{
int ret = 0;
neu_json_login_resp_t *resp = (neu_json_login_resp_t *) param;
neu_json_elem_t resp_elems[] = { {
.name = "token",
.t = NEU_JSON_STR,
.v.val_str = resp->token,
} };
ret = neu_json_encode_field(json_object, resp_elems,
NEU_JSON_ELEM_SIZE(resp_elems));
return ret;
}
+3
View File
@@ -54,6 +54,9 @@ typedef struct {
int neu_json_encode_login_resp(void *json_object, void *param);
int neu_json_decode_add_user_req(char *buf, neu_json_password_req_t **result);
void neu_json_decode_add_user_req_free(neu_json_password_req_t *req);
#ifdef __cplusplus
}
#endif
+33 -1
View File
@@ -145,7 +145,7 @@ int neu_jwt_init(const char *dir_path)
return 0;
}
int neu_jwt_new(char **token)
int neu_jwt_new(char **token, const char *user)
{
struct timeval tv = { 0 };
jwt_alg_t opt_alg = JWT_ALG_RS256;
@@ -185,6 +185,14 @@ int neu_jwt_new(char **token)
goto err_out;
}
// only normal user need to add user grant
// do not change the original logic
if (0 != strcmp(user, "admin")) {
if (0 != jwt_add_grant(jwt, "user", user)) {
goto err_out;
}
}
ret = jwt_set_alg(jwt, opt_alg, (const unsigned char *) neuron_private_key,
strlen(neuron_private_key));
if (ret != 0) {
@@ -214,6 +222,30 @@ err_out:
return -1;
}
int neu_jwt_decode_user(char *token, char *user)
{
jwt_t *jwt = NULL;
int ret = -1;
ret = jwt_decode(&jwt, token, NULL, 0);
if (ret != 0) {
zlog_error(neuron, "jwt decode error: %d", ret);
return -1;
}
const char *user_grant = jwt_get_grant(jwt, "user");
if (NULL == user_grant) {
zlog_error(neuron, "jwt get user grant error, the token is: %s", token);
jwt_free(jwt);
return -1;
}
strncpy(user, user_grant, strlen(user_grant));
jwt_free(jwt);
return 0;
}
static void *neu_jwt_decode(char *token)
{
jwt_t * jwt = NULL;
+2 -2
View File
@@ -14,7 +14,7 @@ TEST(JwtTest, SetJwt)
EXPECT_EQ(0, neu_jwt_init((char *) "./config"));
EXPECT_EQ(0, neu_jwt_new(&token));
EXPECT_EQ(0, neu_jwt_new(&token, "admin"));
EXPECT_GE(strlen(token), 400);
jwt_free_str(token);
@@ -26,7 +26,7 @@ TEST(JwtTest, JwtValidate)
char b_token[1024] = { 0 };
EXPECT_EQ(0, neu_jwt_init((char *) "./config"));
EXPECT_EQ(0, neu_jwt_new(&token));
EXPECT_EQ(0, neu_jwt_new(&token, "admin"));
snprintf(b_token, sizeof(b_token), "Bearer %s", token);