1
0
mirror of https://github.com/haiwen/seafile-server.git synced 2025-04-28 03:20:10 +00:00

Merge branch '8.0'

This commit is contained in:
杨赫然 2021-12-14 17:45:05 +08:00
commit c158fd2767
2 changed files with 90 additions and 25 deletions

View File

@ -8,10 +8,11 @@ SETUP_DIR=${TESTS_DIR}/ci
cd $SETUP_DIR
sudo systemctl start mysql.service
sudo apt-get update
sudo apt-get install -y intltool libarchive-dev libcurl4-openssl-dev libevent-dev \
libfuse-dev libglib2.0-dev libjansson-dev libmysqlclient-dev libonig-dev \
sqlite3 libsqlite3-dev libtool net-tools uuid-dev valac mysql-client
sudo service mysql start
sqlite3 libsqlite3-dev libtool net-tools uuid-dev valac
sudo systemctl start mysql.service
pip install -r requirements.txt

View File

@ -95,8 +95,11 @@ typedef struct TokenInfo {
gint64 expire_time;
} TokenInfo;
// PermInfo caches the results from the last permission check for accessing a repo.
// They're cached in a hash table having "repo_Id:username:op" as key.
// The cached result is updated on the next call to get_check_permission_cb function, or when the cache expires.
// The result is only cached if the permission check passed.
typedef struct PermInfo {
char *perm;
gint64 expire_time;
} PermInfo;
@ -342,25 +345,31 @@ validate_token (HttpServer *htp_server, evhtp_request_t *req,
}
static PermInfo *
lookup_perm_cache (HttpServer *htp_server, const char *repo_id, const char *username)
lookup_perm_cache (HttpServer *htp_server, const char *repo_id, const char *username, const char *op)
{
PermInfo *ret = NULL;
char *key = g_strdup_printf ("%s:%s", repo_id, username);
PermInfo *perm = NULL;
char *key = g_strdup_printf ("%s:%s:%s", repo_id, username, op);
pthread_mutex_lock (&htp_server->perm_cache_lock);
ret = g_hash_table_lookup (htp_server->perm_cache, key);
if (ret) {
perm = g_new0 (PermInfo, 1);
perm->expire_time = ret->expire_time;
}
pthread_mutex_unlock (&htp_server->perm_cache_lock);
g_free (key);
return ret;
return perm;
}
static void
insert_perm_cache (HttpServer *htp_server,
const char *repo_id, const char *username,
const char *op,
PermInfo *perm)
{
char *key = g_strdup_printf ("%s:%s", repo_id, username);
char *key = g_strdup_printf ("%s:%s:%s", repo_id, username, op);
pthread_mutex_lock (&htp_server->perm_cache_lock);
g_hash_table_insert (htp_server->perm_cache, key, perm);
@ -369,9 +378,10 @@ insert_perm_cache (HttpServer *htp_server,
static void
remove_perm_cache (HttpServer *htp_server,
const char *repo_id, const char *username)
const char *repo_id, const char *username,
const char *op)
{
char *key = g_strdup_printf ("%s:%s", repo_id, username);
char *key = g_strdup_printf ("%s:%s:%s", repo_id, username, op);
pthread_mutex_lock (&htp_server->perm_cache_lock);
g_hash_table_remove (htp_server->perm_cache, key);
@ -380,6 +390,8 @@ remove_perm_cache (HttpServer *htp_server,
g_free (key);
}
static void perm_cache_value_free (gpointer data);
static int
check_permission (HttpServer *htp_server, const char *repo_id, const char *username,
const char *op, gboolean skip_cache)
@ -387,14 +399,15 @@ check_permission (HttpServer *htp_server, const char *repo_id, const char *usern
PermInfo *perm_info = NULL;
if (!skip_cache)
perm_info = lookup_perm_cache (htp_server, repo_id, username);
perm_info = lookup_perm_cache (htp_server, repo_id, username, op);
if (perm_info) {
if (strcmp(perm_info->perm, "r") == 0 && strcmp(op, "upload") == 0)
return EVHTP_RES_FORBIDDEN;
perm_cache_value_free (perm_info);
return EVHTP_RES_OK;
}
remove_perm_cache (htp_server, repo_id, username, op);
if (strcmp(op, "upload") == 0) {
int status = seaf_repo_manager_get_repo_status(seaf->repo_mgr, repo_id);
if (status != REPO_STATUS_NORMAL && status != -1)
@ -404,19 +417,20 @@ check_permission (HttpServer *htp_server, const char *repo_id, const char *usern
char *perm = seaf_repo_manager_check_permission (seaf->repo_mgr,
repo_id, username, NULL);
if (perm) {
if ((strcmp (perm, "r") == 0 && strcmp (op, "upload") == 0)) {
g_free (perm);
return EVHTP_RES_FORBIDDEN;
}
g_free (perm);
perm_info = g_new0 (PermInfo, 1);
/* Take the reference of perm. */
perm_info->perm = perm;
perm_info->expire_time = (gint64)time(NULL) + PERM_EXPIRE_TIME;
insert_perm_cache (htp_server, repo_id, username, perm_info);
if ((strcmp (perm, "r") == 0 && strcmp (op, "upload") == 0))
return EVHTP_RES_FORBIDDEN;
insert_perm_cache (htp_server, repo_id, username, op, perm_info);
return EVHTP_RES_OK;
}
/* Invalidate cache if perm not found in db. */
remove_perm_cache (htp_server, repo_id, username);
return EVHTP_RES_FORBIDDEN;
}
@ -1268,13 +1282,21 @@ get_commit_info_cb (evhtp_request_t *req, void *arg)
char **parts = g_strsplit (req->uri->path->full + 1, "/", 0);
char *repo_id = parts[1];
char *commit_id = parts[3];
char *username = NULL;
int token_status = validate_token (htp_server, req, repo_id, NULL, FALSE);
int token_status = validate_token (htp_server, req, repo_id, &username, FALSE);
if (token_status != EVHTP_RES_OK) {
evhtp_send_reply (req, token_status);
goto out;
}
int perm_status = check_permission (htp_server, repo_id, username,
"download", FALSE);
if (perm_status != EVHTP_RES_OK) {
evhtp_send_reply (req, EVHTP_RES_FORBIDDEN);
goto out;
}
char *data = NULL;
int len;
@ -1291,6 +1313,7 @@ get_commit_info_cb (evhtp_request_t *req, void *arg)
g_free (data);
out:
g_free (username);
g_strfreev (parts);
}
@ -1475,6 +1498,7 @@ get_fs_obj_id_cb (evhtp_request_t *req, void *arg)
char *repo_id;
SeafRepo *repo = NULL;
gboolean dir_only = FALSE;
char *username = NULL;
const char *server_head = evhtp_kv_find (req->uri->query, "server-head");
if (server_head == NULL || !is_object_id_valid (server_head)) {
@ -1501,12 +1525,19 @@ get_fs_obj_id_cb (evhtp_request_t *req, void *arg)
parts = g_strsplit (req->uri->path->full + 1, "/", 0);
repo_id = parts[1];
int token_status = validate_token (htp_server, req, repo_id, NULL, FALSE);
int token_status = validate_token (htp_server, req, repo_id, &username, FALSE);
if (token_status != EVHTP_RES_OK) {
evhtp_send_reply (req, token_status);
goto out;
}
int perm_status = check_permission (htp_server, repo_id, username,
"download", FALSE);
if (perm_status != EVHTP_RES_OK) {
evhtp_send_reply (req, EVHTP_RES_FORBIDDEN);
goto out;
}
GList *list = NULL, *ptr;
repo = seaf_repo_manager_get_repo (seaf->repo_mgr, repo_id);
@ -1537,6 +1568,7 @@ get_fs_obj_id_cb (evhtp_request_t *req, void *arg)
json_decref (obj_array);
out:
g_free (username);
g_strfreev (parts);
seaf_repo_unref (repo);
}
@ -1848,6 +1880,13 @@ get_block_cb (evhtp_request_t *req, void *arg)
goto out;
}
int perm_status = check_permission (htp_server, repo_id, username,
"download", FALSE);
if (perm_status != EVHTP_RES_OK) {
evhtp_send_reply (req, EVHTP_RES_FORBIDDEN);
goto out;
}
store_id = get_repo_store_id (htp_server, repo_id);
if (!store_id) {
evhtp_send_reply (req, EVHTP_RES_SERVERR);
@ -2015,13 +2054,21 @@ post_check_exist_cb (evhtp_request_t *req, void *arg, CheckExistType type)
char **parts = g_strsplit (req->uri->path->full + 1, "/", 0);
char *repo_id = parts[1];
char *store_id = NULL;
char *username = NULL;
int token_status = validate_token (htp_server, req, repo_id, NULL, FALSE);
int token_status = validate_token (htp_server, req, repo_id, &username, FALSE);
if (token_status != EVHTP_RES_OK) {
evhtp_send_reply (req, token_status);
goto out;
}
int perm_status = check_permission (htp_server, repo_id, username,
"download", FALSE);
if (perm_status != EVHTP_RES_OK) {
evhtp_send_reply (req, EVHTP_RES_FORBIDDEN);
goto out;
}
store_id = get_repo_store_id (htp_server, repo_id);
if (!store_id) {
evhtp_send_reply (req, EVHTP_RES_SERVERR);
@ -2088,6 +2135,7 @@ post_check_exist_cb (evhtp_request_t *req, void *arg, CheckExistType type)
json_decref (obj_array);
out:
g_free (username);
g_free (store_id);
g_strfreev (parts);
}
@ -2122,7 +2170,7 @@ post_recv_fs_cb (evhtp_request_t *req, void *arg)
int perm_status = check_permission (htp_server, repo_id, username,
"upload", FALSE);
if (perm_status == EVHTP_RES_FORBIDDEN) {
if (perm_status != EVHTP_RES_OK) {
evhtp_send_reply (req, EVHTP_RES_FORBIDDEN);
goto out;
}
@ -2208,13 +2256,20 @@ post_pack_fs_cb (evhtp_request_t *req, void *arg)
char **parts = g_strsplit (req->uri->path->full + 1, "/", 0);
const char *repo_id = parts[1];
char *store_id = NULL;
char *username = NULL;
int token_status = validate_token (htp_server, req, repo_id, NULL, FALSE);
int token_status = validate_token (htp_server, req, repo_id, &username, FALSE);
if (token_status != EVHTP_RES_OK) {
evhtp_send_reply (req, token_status);
goto out;
}
int perm_status = check_permission (htp_server, repo_id, username,
"download", FALSE);
if (perm_status != EVHTP_RES_OK) {
evhtp_send_reply (req, EVHTP_RES_FORBIDDEN);
goto out;
}
store_id = get_repo_store_id (htp_server, repo_id);
if (!store_id) {
evhtp_send_reply (req, EVHTP_RES_SERVERR);
@ -2290,6 +2345,7 @@ post_pack_fs_cb (evhtp_request_t *req, void *arg)
json_decref (fs_id_array);
out:
g_free (username);
g_free (store_id);
g_strfreev (parts);
}
@ -2306,17 +2362,25 @@ get_block_map_cb (evhtp_request_t *req, void *arg)
BlockMetadata *blk_meta = NULL;
json_t *array = NULL;
char *data = NULL;
char *username = NULL;
char **parts = g_strsplit (req->uri->path->full + 1, "/", 0);
repo_id = parts[1];
file_id = parts[3];
int token_status = validate_token (htp_server, req, repo_id, NULL, FALSE);
int token_status = validate_token (htp_server, req, repo_id, &username, FALSE);
if (token_status != EVHTP_RES_OK) {
evhtp_send_reply (req, token_status);
goto out;
}
int perm_status = check_permission (htp_server, repo_id, username,
"download", FALSE);
if (perm_status != EVHTP_RES_OK) {
evhtp_send_reply (req, EVHTP_RES_FORBIDDEN);
goto out;
}
store_id = get_repo_store_id (htp_server, repo_id);
if (!store_id) {
evhtp_send_reply (req, EVHTP_RES_SERVERR);
@ -2351,6 +2415,7 @@ get_block_map_cb (evhtp_request_t *req, void *arg)
evhtp_send_reply (req, EVHTP_RES_OK);
out:
g_free (username);
g_free (store_id);
seafile_unref (file);
if (array)
@ -2719,7 +2784,6 @@ static void
perm_cache_value_free (gpointer data)
{
PermInfo *perm_info = data;
g_free (perm_info->perm);
g_free (perm_info);
}