mirror of
https://github.com/haiwen/seafile-server.git
synced 2025-09-21 02:58:57 +00:00
* Add notification server of go Modify path of pkg Send notification for update-repo event Delete client pkg and use reflect select to send message Modify output of log Add formatter of log Add jwt authentication go add get jwt token api CI support compile libjwt Get group users from database * Add ping to test mysql is alive Co-authored-by: 杨赫然 <heran.yang@seafile.com>
483 lines
15 KiB
C
483 lines
15 KiB
C
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
|
|
#include "common.h"
|
|
|
|
#include <stdint.h>
|
|
#include <dirent.h>
|
|
#include <unistd.h>
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <fcntl.h>
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <errno.h>
|
|
|
|
#include <glib.h>
|
|
|
|
#include "utils.h"
|
|
|
|
#include "seafile-session.h"
|
|
|
|
#include "mq-mgr.h"
|
|
#include "seaf-db.h"
|
|
#include "seaf-utils.h"
|
|
|
|
#include "log.h"
|
|
|
|
#define CONNECT_INTERVAL_MSEC 10 * 1000
|
|
|
|
#define DEFAULT_THREAD_POOL_SIZE 500
|
|
|
|
SeafileSession *
|
|
seafile_session_new(const char *central_config_dir,
|
|
const char *seafile_dir,
|
|
const char *ccnet_dir)
|
|
{
|
|
char *abs_central_config_dir = NULL;
|
|
char *abs_seafile_dir;
|
|
char *abs_ccnet_dir = NULL;
|
|
char *tmp_file_dir;
|
|
char *config_file_path;
|
|
char *config_file_ccnet;
|
|
GKeyFile *config;
|
|
GKeyFile *ccnet_config;
|
|
SeafileSession *session = NULL;
|
|
char *notif_url = NULL;
|
|
char *notif_token = NULL;
|
|
char *private_key = NULL;
|
|
|
|
abs_ccnet_dir = ccnet_expand_path (ccnet_dir);
|
|
abs_seafile_dir = ccnet_expand_path (seafile_dir);
|
|
tmp_file_dir = g_build_filename (abs_seafile_dir, "tmpfiles", NULL);
|
|
if (central_config_dir) {
|
|
abs_central_config_dir = ccnet_expand_path (central_config_dir);
|
|
}
|
|
|
|
if (checkdir_with_mkdir (abs_seafile_dir) < 0) {
|
|
seaf_warning ("Config dir %s does not exist and is unable to create\n",
|
|
abs_seafile_dir);
|
|
goto onerror;
|
|
}
|
|
|
|
if (checkdir_with_mkdir (tmp_file_dir) < 0) {
|
|
seaf_warning ("Temp file dir %s does not exist and is unable to create\n",
|
|
tmp_file_dir);
|
|
goto onerror;
|
|
}
|
|
|
|
if (checkdir_with_mkdir (abs_ccnet_dir) < 0) {
|
|
seaf_warning ("Ccnet config dir %s does not exist and is unable to create\n",
|
|
abs_ccnet_dir);
|
|
goto onerror;
|
|
}
|
|
|
|
config_file_path = g_build_filename(
|
|
abs_central_config_dir ? abs_central_config_dir : abs_seafile_dir,
|
|
"seafile.conf", NULL);
|
|
|
|
config_file_ccnet = g_build_filename(
|
|
abs_central_config_dir ? abs_central_config_dir : abs_ccnet_dir,
|
|
"ccnet.conf", NULL);
|
|
|
|
GError *error = NULL;
|
|
config = g_key_file_new ();
|
|
if (!g_key_file_load_from_file (config, config_file_path,
|
|
G_KEY_FILE_NONE, &error)) {
|
|
seaf_warning ("Failed to load config file.\n");
|
|
g_key_file_free (config);
|
|
g_free (config_file_path);
|
|
goto onerror;
|
|
}
|
|
ccnet_config = g_key_file_new ();
|
|
g_key_file_set_list_separator (ccnet_config, ',');
|
|
if (!g_key_file_load_from_file (ccnet_config, config_file_ccnet,
|
|
G_KEY_FILE_KEEP_COMMENTS, NULL))
|
|
{
|
|
seaf_warning ("Can't load ccnet config file %s.\n", config_file_ccnet);
|
|
g_key_file_free (ccnet_config);
|
|
g_free (config_file_ccnet);
|
|
goto onerror;
|
|
}
|
|
g_free (config_file_path);
|
|
g_free (config_file_ccnet);
|
|
|
|
session = g_new0(SeafileSession, 1);
|
|
session->seaf_dir = abs_seafile_dir;
|
|
session->ccnet_dir = abs_ccnet_dir;
|
|
session->tmp_file_dir = tmp_file_dir;
|
|
session->config = config;
|
|
session->ccnet_config = ccnet_config;
|
|
|
|
session->cloud_mode = g_key_file_get_boolean (config,
|
|
"general", "cloud_mode",
|
|
NULL);
|
|
|
|
session->go_fileserver = g_key_file_get_boolean (config,
|
|
"fileserver", "use_go_fileserver",
|
|
NULL);
|
|
if (session->go_fileserver) {
|
|
char *type = NULL;
|
|
type = g_key_file_get_string (config, "database", "type", NULL);
|
|
if (!type || g_strcmp0 (type, "mysql") != 0) {
|
|
session->go_fileserver = FALSE;
|
|
}
|
|
g_free (type);
|
|
}
|
|
|
|
notif_url = g_key_file_get_string (config,
|
|
"notification", "notification_url",
|
|
NULL);
|
|
|
|
notif_token = g_key_file_get_string (config,
|
|
"notification", "notification_token",
|
|
NULL);
|
|
|
|
private_key = g_key_file_get_string (config,
|
|
"notification", "private_key",
|
|
NULL);
|
|
if (private_key) {
|
|
session->private_key = private_key;
|
|
}
|
|
|
|
if (load_database_config (session) < 0) {
|
|
seaf_warning ("Failed to load database config.\n");
|
|
goto onerror;
|
|
}
|
|
|
|
if (load_ccnet_database_config (session) < 0) {
|
|
seaf_warning ("Failed to load ccnet database config.\n");
|
|
goto onerror;
|
|
}
|
|
|
|
session->cfg_mgr = seaf_cfg_manager_new (session);
|
|
if (!session->cfg_mgr)
|
|
goto onerror;
|
|
session->fs_mgr = seaf_fs_manager_new (session, abs_seafile_dir);
|
|
if (!session->fs_mgr)
|
|
goto onerror;
|
|
session->block_mgr = seaf_block_manager_new (session, abs_seafile_dir);
|
|
if (!session->block_mgr)
|
|
goto onerror;
|
|
session->commit_mgr = seaf_commit_manager_new (session);
|
|
if (!session->commit_mgr)
|
|
goto onerror;
|
|
session->repo_mgr = seaf_repo_manager_new (session);
|
|
if (!session->repo_mgr)
|
|
goto onerror;
|
|
session->branch_mgr = seaf_branch_manager_new (session);
|
|
if (!session->branch_mgr)
|
|
goto onerror;
|
|
|
|
session->share_mgr = seaf_share_manager_new (session);
|
|
if (!session->share_mgr)
|
|
goto onerror;
|
|
|
|
session->web_at_mgr = seaf_web_at_manager_new (session);
|
|
if (!session->web_at_mgr)
|
|
goto onerror;
|
|
|
|
session->passwd_mgr = seaf_passwd_manager_new (session);
|
|
if (!session->passwd_mgr)
|
|
goto onerror;
|
|
|
|
session->quota_mgr = seaf_quota_manager_new (session);
|
|
if (!session->quota_mgr)
|
|
goto onerror;
|
|
|
|
session->copy_mgr = seaf_copy_manager_new (session);
|
|
if (!session->copy_mgr)
|
|
goto onerror;
|
|
|
|
session->job_mgr = ccnet_job_manager_new (DEFAULT_THREAD_POOL_SIZE);
|
|
|
|
session->size_sched = size_scheduler_new (session);
|
|
|
|
session->mq_mgr = seaf_mq_manager_new ();
|
|
if (!session->mq_mgr)
|
|
goto onerror;
|
|
|
|
session->http_server = seaf_http_server_new (session);
|
|
if (!session->http_server)
|
|
goto onerror;
|
|
|
|
session->zip_download_mgr = zip_download_mgr_new ();
|
|
if (!session->zip_download_mgr)
|
|
goto onerror;
|
|
|
|
session->index_blocks_mgr = index_blocks_mgr_new (session);
|
|
if (!session->index_blocks_mgr)
|
|
goto onerror;
|
|
|
|
session->user_mgr = ccnet_user_manager_new (session);
|
|
if (!session->user_mgr)
|
|
goto onerror;
|
|
|
|
session->group_mgr = ccnet_group_manager_new (session);
|
|
if (!session->group_mgr)
|
|
goto onerror;
|
|
|
|
session->org_mgr = ccnet_org_manager_new (session);
|
|
if (!session->org_mgr)
|
|
goto onerror;
|
|
|
|
if (notif_url != NULL && notif_token != NULL) {
|
|
session->notif_mgr = seaf_notif_manager_new (session, notif_url, notif_token);
|
|
if (!session->notif_mgr)
|
|
goto onerror;
|
|
}
|
|
|
|
return session;
|
|
|
|
onerror:
|
|
g_free (notif_url);
|
|
g_free (notif_token);
|
|
g_free (private_key);
|
|
free (abs_seafile_dir);
|
|
free (abs_ccnet_dir);
|
|
g_free (tmp_file_dir);
|
|
g_free (session);
|
|
return NULL;
|
|
}
|
|
|
|
int
|
|
seafile_session_init (SeafileSession *session)
|
|
{
|
|
if (seaf_commit_manager_init (session->commit_mgr) < 0)
|
|
return -1;
|
|
|
|
if (seaf_fs_manager_init (session->fs_mgr) < 0)
|
|
return -1;
|
|
|
|
if (seaf_branch_manager_init (session->branch_mgr) < 0) {
|
|
seaf_warning ("Failed to init branch manager.\n");
|
|
return -1;
|
|
}
|
|
|
|
if (seaf_repo_manager_init (session->repo_mgr) < 0) {
|
|
seaf_warning ("Failed to init repo manager.\n");
|
|
return -1;
|
|
}
|
|
|
|
if (seaf_quota_manager_init (session->quota_mgr) < 0) {
|
|
seaf_warning ("Failed to init quota manager.\n");
|
|
return -1;
|
|
}
|
|
|
|
if (ccnet_user_manager_prepare (session->user_mgr) < 0) {
|
|
seaf_warning ("Failed to init user manager.\n");
|
|
return -1;
|
|
}
|
|
|
|
if (ccnet_group_manager_prepare (session->group_mgr) < 0) {
|
|
seaf_warning ("Failed to init group manager.\n");
|
|
return -1;
|
|
}
|
|
|
|
if (ccnet_org_manager_prepare (session->org_mgr) < 0) {
|
|
seaf_warning ("Failed to init org manager.\n");
|
|
return -1;
|
|
}
|
|
|
|
if ((session->create_tables || seaf_db_type(session->db) == SEAF_DB_TYPE_PGSQL)
|
|
&& seaf_cfg_manager_init (session->cfg_mgr) < 0) {
|
|
seaf_warning ("Failed to init config manager.\n");
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
seafile_session_start (SeafileSession *session)
|
|
{
|
|
if (seaf_share_manager_start (session->share_mgr) < 0) {
|
|
seaf_warning ("Failed to start share manager.\n");
|
|
return -1;
|
|
}
|
|
|
|
if (seaf_web_at_manager_start (session->web_at_mgr) < 0) {
|
|
seaf_warning ("Failed to start web access check manager.\n");
|
|
return -1;
|
|
}
|
|
|
|
if (seaf_passwd_manager_start (session->passwd_mgr) < 0) {
|
|
seaf_warning ("Failed to start password manager.\n");
|
|
return -1;
|
|
}
|
|
|
|
if (size_scheduler_start (session->size_sched) < 0) {
|
|
seaf_warning ("Failed to start size scheduler.\n");
|
|
return -1;
|
|
}
|
|
|
|
if (seaf_copy_manager_start (session->copy_mgr) < 0) {
|
|
seaf_warning ("Failed to start copy manager.\n");
|
|
return -1;
|
|
}
|
|
|
|
if (!session->go_fileserver) {
|
|
if (seaf_http_server_start (session->http_server) < 0) {
|
|
seaf_warning ("Failed to start http server thread.\n");
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
char *
|
|
get_system_default_repo_id (SeafileSession *session)
|
|
{
|
|
char *sql = "SELECT info_value FROM SystemInfo WHERE info_key='default_repo_id'";
|
|
return seaf_db_get_string (session->db, sql);
|
|
}
|
|
|
|
int
|
|
set_system_default_repo_id (SeafileSession *session, const char *repo_id)
|
|
{
|
|
char sql[256];
|
|
snprintf (sql, sizeof(sql),
|
|
"INSERT INTO SystemInfo (info_key, info_value) VALUES ('default_repo_id', '%s')",
|
|
repo_id);
|
|
return seaf_db_query (session->db, sql);
|
|
}
|
|
|
|
static int
|
|
del_system_default_repo_id (SeafileSession *session)
|
|
{
|
|
const char *sql = "DELETE FROM SystemInfo WHERE info_key='default_repo_id'";
|
|
return seaf_db_query (session->db, sql);
|
|
}
|
|
|
|
#define DEFAULT_TEMPLATE_DIR "library-template"
|
|
|
|
static void
|
|
copy_template_files_recursive (SeafileSession *session,
|
|
const char *repo_id,
|
|
const char *repo_dir_path,
|
|
const char *dir_path)
|
|
{
|
|
GDir *dir;
|
|
const char *name;
|
|
char *sub_path, *repo_sub_path;
|
|
SeafStat st;
|
|
GError *error = NULL;
|
|
int rc;
|
|
|
|
dir = g_dir_open (dir_path, 0, &error);
|
|
if (!dir) {
|
|
seaf_warning ("Failed to open template dir %s: %s.\n",
|
|
dir_path, error->message);
|
|
return;
|
|
}
|
|
|
|
while ((name = g_dir_read_name(dir)) != NULL) {
|
|
sub_path = g_build_filename (dir_path, name, NULL);
|
|
if (seaf_stat (sub_path, &st) < 0) {
|
|
seaf_warning ("Failed to stat %s: %s.\n", sub_path, strerror(errno));
|
|
g_free (sub_path);
|
|
continue;
|
|
}
|
|
|
|
if (S_ISREG(st.st_mode)) {
|
|
rc = seaf_repo_manager_post_file (session->repo_mgr,
|
|
repo_id,
|
|
sub_path,
|
|
repo_dir_path,
|
|
name,
|
|
"System",
|
|
NULL);
|
|
if (rc < 0)
|
|
seaf_warning ("Failed to add template file %s.\n", sub_path);
|
|
} else if (S_ISDIR(st.st_mode)) {
|
|
rc = seaf_repo_manager_post_dir (session->repo_mgr,
|
|
repo_id,
|
|
repo_dir_path,
|
|
name,
|
|
"System",
|
|
NULL);
|
|
if (rc < 0) {
|
|
seaf_warning ("Failed to add template dir %s.\n", sub_path);
|
|
g_free (sub_path);
|
|
continue;
|
|
}
|
|
|
|
repo_sub_path = g_build_path ("/", repo_dir_path, name, NULL);
|
|
copy_template_files_recursive (session, repo_id,
|
|
repo_sub_path, sub_path);
|
|
g_free (repo_sub_path);
|
|
}
|
|
g_free (sub_path);
|
|
}
|
|
g_dir_close (dir);
|
|
}
|
|
|
|
static void *
|
|
create_system_default_repo (void *data)
|
|
{
|
|
SeafileSession *session = data;
|
|
char *repo_id;
|
|
char *template_path;
|
|
|
|
/* If default repo is not set or doesn't exist, create a new one. */
|
|
repo_id = get_system_default_repo_id (session);
|
|
if (repo_id != NULL) {
|
|
SeafRepo *repo;
|
|
repo = seaf_repo_manager_get_repo (session->repo_mgr, repo_id);
|
|
if (!repo) {
|
|
seaf_warning ("Failed to get system default repo. Create a new one.\n");
|
|
del_system_default_repo_id (session);
|
|
seaf_repo_manager_del_repo (session->repo_mgr, repo_id, NULL);
|
|
g_free (repo_id);
|
|
} else {
|
|
seaf_repo_unref (repo);
|
|
g_free (repo_id);
|
|
return data;
|
|
}
|
|
}
|
|
|
|
repo_id = seaf_repo_manager_create_new_repo (session->repo_mgr,
|
|
"My Library Template",
|
|
"Template for creating 'My Library' for users",
|
|
"System",
|
|
NULL, -1, NULL);
|
|
if (!repo_id) {
|
|
seaf_warning ("Failed to create system default repo.\n");
|
|
return data;
|
|
}
|
|
|
|
set_system_default_repo_id (session, repo_id);
|
|
|
|
template_path = g_build_filename (session->seaf_dir, DEFAULT_TEMPLATE_DIR, NULL);
|
|
copy_template_files_recursive (session, repo_id, "/", template_path);
|
|
|
|
g_free (repo_id);
|
|
g_free (template_path);
|
|
return data;
|
|
}
|
|
|
|
void
|
|
schedule_create_system_default_repo (SeafileSession *session)
|
|
{
|
|
int db_type = seaf_db_type (session->db);
|
|
char *sql;
|
|
|
|
if (db_type == SEAF_DB_TYPE_MYSQL)
|
|
sql = "CREATE TABLE IF NOT EXISTS SystemInfo "
|
|
"(id BIGINT NOT NULL PRIMARY KEY AUTO_INCREMENT, "
|
|
"info_key VARCHAR(256), info_value VARCHAR(1024))";
|
|
else
|
|
sql = "CREATE TABLE IF NOT EXISTS SystemInfo( "
|
|
"info_key VARCHAR(256), info_value VARCHAR(1024))";
|
|
|
|
if ((session->create_tables || db_type == SEAF_DB_TYPE_PGSQL)
|
|
&& seaf_db_query (session->db, sql) < 0)
|
|
return;
|
|
|
|
ccnet_job_manager_schedule_job (session->job_mgr,
|
|
create_system_default_repo,
|
|
NULL, session);
|
|
}
|