mirror of
https://github.com/haiwen/seafile-server.git
synced 2025-09-19 18:16:25 +00:00
Merge branch '8.0'
This commit is contained in:
@@ -8,10 +8,11 @@ SETUP_DIR=${TESTS_DIR}/ci
|
|||||||
|
|
||||||
cd $SETUP_DIR
|
cd $SETUP_DIR
|
||||||
|
|
||||||
|
sudo systemctl start mysql.service
|
||||||
sudo apt-get update
|
sudo apt-get update
|
||||||
sudo apt-get install -y intltool libarchive-dev libcurl4-openssl-dev libevent-dev \
|
sudo apt-get install -y intltool libarchive-dev libcurl4-openssl-dev libevent-dev \
|
||||||
libfuse-dev libglib2.0-dev libjansson-dev libmysqlclient-dev libonig-dev \
|
libfuse-dev libglib2.0-dev libjansson-dev libmysqlclient-dev libonig-dev \
|
||||||
sqlite3 libsqlite3-dev libtool net-tools uuid-dev valac mysql-client
|
sqlite3 libsqlite3-dev libtool net-tools uuid-dev valac
|
||||||
sudo service mysql start
|
sudo systemctl start mysql.service
|
||||||
|
|
||||||
pip install -r requirements.txt
|
pip install -r requirements.txt
|
||||||
|
@@ -95,8 +95,11 @@ typedef struct TokenInfo {
|
|||||||
gint64 expire_time;
|
gint64 expire_time;
|
||||||
} TokenInfo;
|
} 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 {
|
typedef struct PermInfo {
|
||||||
char *perm;
|
|
||||||
gint64 expire_time;
|
gint64 expire_time;
|
||||||
} PermInfo;
|
} PermInfo;
|
||||||
|
|
||||||
@@ -342,25 +345,31 @@ validate_token (HttpServer *htp_server, evhtp_request_t *req,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static PermInfo *
|
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;
|
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);
|
pthread_mutex_lock (&htp_server->perm_cache_lock);
|
||||||
ret = g_hash_table_lookup (htp_server->perm_cache, key);
|
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);
|
pthread_mutex_unlock (&htp_server->perm_cache_lock);
|
||||||
g_free (key);
|
g_free (key);
|
||||||
|
|
||||||
return ret;
|
return perm;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
insert_perm_cache (HttpServer *htp_server,
|
insert_perm_cache (HttpServer *htp_server,
|
||||||
const char *repo_id, const char *username,
|
const char *repo_id, const char *username,
|
||||||
|
const char *op,
|
||||||
PermInfo *perm)
|
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);
|
pthread_mutex_lock (&htp_server->perm_cache_lock);
|
||||||
g_hash_table_insert (htp_server->perm_cache, key, perm);
|
g_hash_table_insert (htp_server->perm_cache, key, perm);
|
||||||
@@ -369,9 +378,10 @@ insert_perm_cache (HttpServer *htp_server,
|
|||||||
|
|
||||||
static void
|
static void
|
||||||
remove_perm_cache (HttpServer *htp_server,
|
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);
|
pthread_mutex_lock (&htp_server->perm_cache_lock);
|
||||||
g_hash_table_remove (htp_server->perm_cache, key);
|
g_hash_table_remove (htp_server->perm_cache, key);
|
||||||
@@ -380,6 +390,8 @@ remove_perm_cache (HttpServer *htp_server,
|
|||||||
g_free (key);
|
g_free (key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void perm_cache_value_free (gpointer data);
|
||||||
|
|
||||||
static int
|
static int
|
||||||
check_permission (HttpServer *htp_server, const char *repo_id, const char *username,
|
check_permission (HttpServer *htp_server, const char *repo_id, const char *username,
|
||||||
const char *op, gboolean skip_cache)
|
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;
|
PermInfo *perm_info = NULL;
|
||||||
|
|
||||||
if (!skip_cache)
|
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 (perm_info) {
|
||||||
if (strcmp(perm_info->perm, "r") == 0 && strcmp(op, "upload") == 0)
|
perm_cache_value_free (perm_info);
|
||||||
return EVHTP_RES_FORBIDDEN;
|
|
||||||
return EVHTP_RES_OK;
|
return EVHTP_RES_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
remove_perm_cache (htp_server, repo_id, username, op);
|
||||||
|
|
||||||
if (strcmp(op, "upload") == 0) {
|
if (strcmp(op, "upload") == 0) {
|
||||||
int status = seaf_repo_manager_get_repo_status(seaf->repo_mgr, repo_id);
|
int status = seaf_repo_manager_get_repo_status(seaf->repo_mgr, repo_id);
|
||||||
if (status != REPO_STATUS_NORMAL && status != -1)
|
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,
|
char *perm = seaf_repo_manager_check_permission (seaf->repo_mgr,
|
||||||
repo_id, username, NULL);
|
repo_id, username, NULL);
|
||||||
if (perm) {
|
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);
|
perm_info = g_new0 (PermInfo, 1);
|
||||||
/* Take the reference of perm. */
|
/* Take the reference of perm. */
|
||||||
perm_info->perm = perm;
|
|
||||||
perm_info->expire_time = (gint64)time(NULL) + PERM_EXPIRE_TIME;
|
perm_info->expire_time = (gint64)time(NULL) + PERM_EXPIRE_TIME;
|
||||||
insert_perm_cache (htp_server, repo_id, username, perm_info);
|
insert_perm_cache (htp_server, repo_id, username, op, perm_info);
|
||||||
|
|
||||||
if ((strcmp (perm, "r") == 0 && strcmp (op, "upload") == 0))
|
|
||||||
return EVHTP_RES_FORBIDDEN;
|
|
||||||
return EVHTP_RES_OK;
|
return EVHTP_RES_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Invalidate cache if perm not found in db. */
|
/* Invalidate cache if perm not found in db. */
|
||||||
remove_perm_cache (htp_server, repo_id, username);
|
|
||||||
return EVHTP_RES_FORBIDDEN;
|
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 **parts = g_strsplit (req->uri->path->full + 1, "/", 0);
|
||||||
char *repo_id = parts[1];
|
char *repo_id = parts[1];
|
||||||
char *commit_id = parts[3];
|
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) {
|
if (token_status != EVHTP_RES_OK) {
|
||||||
evhtp_send_reply (req, token_status);
|
evhtp_send_reply (req, token_status);
|
||||||
goto out;
|
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;
|
char *data = NULL;
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
@@ -1291,6 +1313,7 @@ get_commit_info_cb (evhtp_request_t *req, void *arg)
|
|||||||
g_free (data);
|
g_free (data);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
|
g_free (username);
|
||||||
g_strfreev (parts);
|
g_strfreev (parts);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1475,6 +1498,7 @@ get_fs_obj_id_cb (evhtp_request_t *req, void *arg)
|
|||||||
char *repo_id;
|
char *repo_id;
|
||||||
SeafRepo *repo = NULL;
|
SeafRepo *repo = NULL;
|
||||||
gboolean dir_only = FALSE;
|
gboolean dir_only = FALSE;
|
||||||
|
char *username = NULL;
|
||||||
|
|
||||||
const char *server_head = evhtp_kv_find (req->uri->query, "server-head");
|
const char *server_head = evhtp_kv_find (req->uri->query, "server-head");
|
||||||
if (server_head == NULL || !is_object_id_valid (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);
|
parts = g_strsplit (req->uri->path->full + 1, "/", 0);
|
||||||
repo_id = parts[1];
|
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) {
|
if (token_status != EVHTP_RES_OK) {
|
||||||
evhtp_send_reply (req, token_status);
|
evhtp_send_reply (req, token_status);
|
||||||
goto out;
|
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;
|
GList *list = NULL, *ptr;
|
||||||
|
|
||||||
repo = seaf_repo_manager_get_repo (seaf->repo_mgr, repo_id);
|
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);
|
json_decref (obj_array);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
|
g_free (username);
|
||||||
g_strfreev (parts);
|
g_strfreev (parts);
|
||||||
seaf_repo_unref (repo);
|
seaf_repo_unref (repo);
|
||||||
}
|
}
|
||||||
@@ -1848,6 +1880,13 @@ get_block_cb (evhtp_request_t *req, void *arg)
|
|||||||
goto out;
|
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);
|
store_id = get_repo_store_id (htp_server, repo_id);
|
||||||
if (!store_id) {
|
if (!store_id) {
|
||||||
evhtp_send_reply (req, EVHTP_RES_SERVERR);
|
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 **parts = g_strsplit (req->uri->path->full + 1, "/", 0);
|
||||||
char *repo_id = parts[1];
|
char *repo_id = parts[1];
|
||||||
char *store_id = NULL;
|
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) {
|
if (token_status != EVHTP_RES_OK) {
|
||||||
evhtp_send_reply (req, token_status);
|
evhtp_send_reply (req, token_status);
|
||||||
goto out;
|
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);
|
store_id = get_repo_store_id (htp_server, repo_id);
|
||||||
if (!store_id) {
|
if (!store_id) {
|
||||||
evhtp_send_reply (req, EVHTP_RES_SERVERR);
|
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);
|
json_decref (obj_array);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
|
g_free (username);
|
||||||
g_free (store_id);
|
g_free (store_id);
|
||||||
g_strfreev (parts);
|
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,
|
int perm_status = check_permission (htp_server, repo_id, username,
|
||||||
"upload", FALSE);
|
"upload", FALSE);
|
||||||
if (perm_status == EVHTP_RES_FORBIDDEN) {
|
if (perm_status != EVHTP_RES_OK) {
|
||||||
evhtp_send_reply (req, EVHTP_RES_FORBIDDEN);
|
evhtp_send_reply (req, EVHTP_RES_FORBIDDEN);
|
||||||
goto out;
|
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);
|
char **parts = g_strsplit (req->uri->path->full + 1, "/", 0);
|
||||||
const char *repo_id = parts[1];
|
const char *repo_id = parts[1];
|
||||||
char *store_id = NULL;
|
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) {
|
if (token_status != EVHTP_RES_OK) {
|
||||||
evhtp_send_reply (req, token_status);
|
evhtp_send_reply (req, token_status);
|
||||||
goto out;
|
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);
|
store_id = get_repo_store_id (htp_server, repo_id);
|
||||||
if (!store_id) {
|
if (!store_id) {
|
||||||
evhtp_send_reply (req, EVHTP_RES_SERVERR);
|
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);
|
json_decref (fs_id_array);
|
||||||
out:
|
out:
|
||||||
|
g_free (username);
|
||||||
g_free (store_id);
|
g_free (store_id);
|
||||||
g_strfreev (parts);
|
g_strfreev (parts);
|
||||||
}
|
}
|
||||||
@@ -2306,17 +2362,25 @@ get_block_map_cb (evhtp_request_t *req, void *arg)
|
|||||||
BlockMetadata *blk_meta = NULL;
|
BlockMetadata *blk_meta = NULL;
|
||||||
json_t *array = NULL;
|
json_t *array = NULL;
|
||||||
char *data = NULL;
|
char *data = NULL;
|
||||||
|
char *username = NULL;
|
||||||
|
|
||||||
char **parts = g_strsplit (req->uri->path->full + 1, "/", 0);
|
char **parts = g_strsplit (req->uri->path->full + 1, "/", 0);
|
||||||
repo_id = parts[1];
|
repo_id = parts[1];
|
||||||
file_id = parts[3];
|
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) {
|
if (token_status != EVHTP_RES_OK) {
|
||||||
evhtp_send_reply (req, token_status);
|
evhtp_send_reply (req, token_status);
|
||||||
goto out;
|
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);
|
store_id = get_repo_store_id (htp_server, repo_id);
|
||||||
if (!store_id) {
|
if (!store_id) {
|
||||||
evhtp_send_reply (req, EVHTP_RES_SERVERR);
|
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);
|
evhtp_send_reply (req, EVHTP_RES_OK);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
|
g_free (username);
|
||||||
g_free (store_id);
|
g_free (store_id);
|
||||||
seafile_unref (file);
|
seafile_unref (file);
|
||||||
if (array)
|
if (array)
|
||||||
@@ -2719,7 +2784,6 @@ static void
|
|||||||
perm_cache_value_free (gpointer data)
|
perm_cache_value_free (gpointer data)
|
||||||
{
|
{
|
||||||
PermInfo *perm_info = data;
|
PermInfo *perm_info = data;
|
||||||
g_free (perm_info->perm);
|
|
||||||
g_free (perm_info);
|
g_free (perm_info);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user