mirror of
https://github.com/emqx/neuron.git
synced 2026-10-26 03:40:01 +08:00
feat: user management api -add user
This commit is contained in:
@@ -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,
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user