static char * check_virtual_repo_permission (SeafRepoManager *mgr, const char *repo_id, const char *origin_repo_id, const char *user, GError **error) { char *owner = NULL; char *permission = NULL; /* If I'm the owner of origin repo, I have full access to sub-repos. */ owner = seaf_repo_manager_get_repo_owner (mgr, origin_repo_id); if (g_strcmp0 (user, owner) == 0) { permission = g_strdup("rw"); return permission; } g_free (owner); /* If I'm not the owner of origin repo, this sub-repo can be created * from a shared repo by me or directly shared by others to me. * The priority of shared sub-folder is higher than top-level repo. */ permission = check_repo_share_permission (mgr, repo_id, user); if (permission) return permission; permission = check_repo_share_permission (mgr, origin_repo_id, user); return permission; }
static char * check_virtual_repo_permission (SeafRepoManager *mgr, const char *repo_id, const char *origin_repo_id, const char *user, GError **error) { char *owner = NULL, *orig_owner = NULL; char *permission = NULL; owner = seaf_repo_manager_get_repo_owner (mgr, repo_id); if (!owner) { seaf_warning ("Failed to get owner for virtual repo %.10s.\n", repo_id); goto out; } /* If this virtual repo is not created by @user, it is shared by others. */ if (strcmp (user, owner) != 0) { permission = check_repo_share_permission (mgr, repo_id, user); goto out; } /* otherwise check @user's permission to the origin repo. */ permission = seaf_repo_manager_check_permission (mgr, origin_repo_id, user, error); out: g_free (owner); g_free (orig_owner); return permission; }
/* * Comprehensive repo access permission checker. * * Returns read/write permission. */ char * seaf_repo_manager_check_permission (SeafRepoManager *mgr, const char *repo_id, const char *user, GError **error) { SeafVirtRepo *vinfo; char *owner = NULL; char *permission = NULL; /* This is a virtual repo.*/ vinfo = seaf_repo_manager_get_virtual_repo_info (mgr, repo_id); if (vinfo) { permission = check_virtual_repo_permission (mgr, repo_id, vinfo->origin_repo_id, user, error); goto out; } owner = seaf_repo_manager_get_repo_owner (mgr, repo_id); if (owner != NULL) { if (strcmp (owner, user) == 0) permission = g_strdup("rw"); else permission = check_repo_share_permission (mgr, repo_id, user); } out: seaf_virtual_repo_info_free (vinfo); g_free (owner); return permission; }
static void * check_tx (void *vprocessor) { CcnetProcessor *processor = vprocessor; USE_PRIV; char *owner = NULL; int org_id; SearpcClient *rpc_client = NULL; char *repo_id = priv->repo_id; rpc_client = create_sync_ccnetrpc_client (seaf->session->config_dir, "ccnet-threaded-rpcserver"); if (!rpc_client) { priv->rsp_code = g_strdup(SC_SERVER_ERROR); priv->rsp_msg = g_strdup(SS_SERVER_ERROR); goto out; } if (!seaf_repo_manager_repo_exists (seaf->repo_mgr, repo_id)) { priv->rsp_code = g_strdup(SC_BAD_REPO); priv->rsp_msg = g_strdup(SS_BAD_REPO); goto out; } if (priv->type == CHECK_TX_TYPE_UPLOAD && check_repo_owner_quota (processor, rpc_client, repo_id) < 0) goto out; owner = seaf_repo_manager_get_repo_owner (seaf->repo_mgr, repo_id); if (owner != NULL) { /* If the user is not owner, check share permission */ if (strcmp (owner, priv->email) != 0) { if(!check_repo_share_permission (rpc_client, repo_id, priv->email)) { priv->rsp_code = g_strdup(SC_ACCESS_DENIED); priv->rsp_msg = g_strdup(SS_ACCESS_DENIED); goto out; } } } else { /* This should be a repo created in an org. */ org_id = seaf_repo_manager_get_repo_org (seaf->repo_mgr, repo_id); if (org_id < 0 || !ccnet_org_user_exists (rpc_client, org_id, priv->email)) { priv->rsp_code = g_strdup(SC_ACCESS_DENIED); priv->rsp_msg = g_strdup(SS_ACCESS_DENIED); goto out; } } get_branch_head (processor); out: g_free (owner); if (rpc_client) free_sync_rpc_client (rpc_client); return vprocessor; }
int seaf_quota_manager_check_quota (SeafQuotaManager *mgr, const char *repo_id) { char *user = NULL; int org_id; gint64 quota, usage; int ret = 0; user = seaf_repo_manager_get_repo_owner (seaf->repo_mgr, repo_id); if (user != NULL) { quota = seaf_quota_manager_get_user_quota (mgr, user); } else if (seaf->cloud_mode) { org_id = seaf_repo_manager_get_repo_org (seaf->repo_mgr, repo_id); if (org_id < 0) { seaf_warning ("Repo %s has no owner.\n", repo_id); ret = -1; goto out; } quota = seaf_quota_manager_get_org_quota (mgr, org_id); } else { seaf_warning ("Repo %s has no owner.\n", repo_id); ret = -1; goto out; } if (quota == INFINITE_QUOTA) goto out; if (user) { if (!mgr->calc_share_usage) { usage = seaf_quota_manager_get_user_usage (mgr, user); } else { gint64 my_usage, share_usage; share_usage = seaf_quota_manager_get_user_share_usage (mgr, user); if (share_usage < 0) { ret = -1; goto out; } my_usage = seaf_quota_manager_get_user_usage (mgr, user); if (my_usage < 0) { ret = -1; goto out; } usage = my_usage + share_usage; } } else usage = seaf_quota_manager_get_org_usage (mgr, org_id); if (usage < 0 || usage >= quota) ret = -1; out: g_free (user); return ret; }
int seaf_quota_manager_check_quota_with_delta (SeafQuotaManager *mgr, const char *repo_id, gint64 delta) { SeafVirtRepo *vinfo; const char *r_repo_id = repo_id; char *user = NULL; gint64 quota, usage; int ret = 0; /* If it's a virtual repo, check quota to origin repo. */ vinfo = seaf_repo_manager_get_virtual_repo_info (seaf->repo_mgr, repo_id); if (vinfo) r_repo_id = vinfo->origin_repo_id; user = seaf_repo_manager_get_repo_owner (seaf->repo_mgr, r_repo_id); if (user != NULL) { quota = seaf_quota_manager_get_user_quota (mgr, user); } else { seaf_warning ("Repo %s has no owner.\n", r_repo_id); ret = -1; goto out; } if (quota == INFINITE_QUOTA) goto out; usage = seaf_quota_manager_get_user_usage (mgr, user); if (usage < 0) { ret = -1; goto out; } if (delta != 0) { usage += delta; } if (usage >= quota) { ret = 1; } out: seaf_virtual_repo_info_free (vinfo); g_free (user); return ret; }
char * seaf_repo_manager_create_virtual_repo (SeafRepoManager *mgr, const char *origin_repo_id, const char *path, const char *repo_name, const char *repo_desc, const char *owner, const char *passwd, GError **error) { SeafRepo *origin_repo = NULL; SeafCommit *origin_head = NULL; char *repo_id = NULL; char *dir_id = NULL; char *orig_owner = NULL; if (seaf_repo_manager_is_virtual_repo (mgr, origin_repo_id)) { g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_GENERAL, "Cannot create sub-library from a sub-library"); return NULL; } repo_id = get_existing_virtual_repo (mgr, origin_repo_id, path); if (repo_id) { return repo_id; } origin_repo = seaf_repo_manager_get_repo (mgr, origin_repo_id); if (!origin_repo) { seaf_warning ("Failed to get origin repo %.10s\n", origin_repo_id); g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_GENERAL, "Origin library not exists"); return NULL; } if (origin_repo->encrypted) { if (origin_repo->enc_version < 2) { g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Library encryption version must be higher than 2"); seaf_repo_unref (origin_repo); return NULL; } if (!passwd || passwd[0] == 0) { g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Password is not set"); seaf_repo_unref (origin_repo); return NULL; } if (seafile_verify_repo_passwd (origin_repo_id, passwd, origin_repo->magic, origin_repo->enc_version) < 0) { g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_GENERAL, "Incorrect password"); seaf_repo_unref (origin_repo); return NULL; } } origin_head = seaf_commit_manager_get_commit (seaf->commit_mgr, origin_repo->id, origin_repo->version, origin_repo->head->commit_id); if (!origin_head) { seaf_warning ("Failed to get head commit %.8s of repo %s.\n", origin_repo->head->commit_id, origin_repo->id); g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_GENERAL, "Bad origin repo head"); goto error; } dir_id = seaf_fs_manager_get_seafdir_id_by_path (seaf->fs_mgr, origin_repo->store_id, origin_repo->version, origin_head->root_id, path, NULL); if (!dir_id) { seaf_warning ("Path %s doesn't exist or is not a dir in repo %.10s.\n", path, origin_repo_id); g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Bad path"); goto error; } repo_id = gen_uuid(); /* Save virtual repo info before actually create the repo. */ if (save_virtual_repo_info (mgr, repo_id, origin_repo_id, path, origin_head->commit_id) < 0) { seaf_warning ("Failed to save virtual repo info for %.10s:%s", origin_repo_id, path); g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_GENERAL, "Internal error"); goto error; } orig_owner = seaf_repo_manager_get_repo_owner (mgr, origin_repo_id); if (do_create_virtual_repo (mgr, origin_repo, repo_id, repo_name, repo_desc, dir_id, orig_owner, passwd, error) < 0) goto error; if (seaf_repo_manager_set_repo_owner (mgr, repo_id, orig_owner) < 0) { seaf_warning ("Failed to set repo owner for %.10s.\n", repo_id); g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_GENERAL, "Failed to set repo owner."); goto error; } /* The size of virtual repo is non-zero at the beginning. */ update_repo_size (repo_id); seaf_repo_unref (origin_repo); seaf_commit_unref (origin_head); g_free (dir_id); g_free (orig_owner); return repo_id; error: seaf_repo_unref (origin_repo); seaf_commit_unref (origin_head); g_free (repo_id); g_free (dir_id); g_free (orig_owner); return NULL; }
int seaf_quota_manager_check_quota (SeafQuotaManager *mgr, const char *repo_id) { SeafVirtRepo *vinfo; const char *r_repo_id = repo_id; char *user = NULL; int org_id; gint64 quota, usage; int ret = 0; /* If it's a virtual repo, check quota to origin repo. */ vinfo = seaf_repo_manager_get_virtual_repo_info (seaf->repo_mgr, repo_id); if (vinfo) r_repo_id = vinfo->origin_repo_id; user = seaf_repo_manager_get_repo_owner (seaf->repo_mgr, r_repo_id); if (user != NULL) { quota = seaf_quota_manager_get_user_quota (mgr, user); } else if (seaf->cloud_mode) { org_id = seaf_repo_manager_get_repo_org (seaf->repo_mgr, r_repo_id); if (org_id < 0) { seaf_warning ("Repo %s has no owner.\n", r_repo_id); ret = -1; goto out; } quota = seaf_quota_manager_get_org_quota (mgr, org_id); } else { seaf_warning ("Repo %s has no owner.\n", r_repo_id); ret = -1; goto out; } if (quota == INFINITE_QUOTA) goto out; if (user) { if (!mgr->calc_share_usage) { usage = seaf_quota_manager_get_user_usage (mgr, user); } else { gint64 my_usage, share_usage; share_usage = seaf_quota_manager_get_user_share_usage (mgr, user); if (share_usage < 0) { ret = -1; goto out; } my_usage = seaf_quota_manager_get_user_usage (mgr, user); if (my_usage < 0) { ret = -1; goto out; } usage = my_usage + share_usage; } } else usage = seaf_quota_manager_get_org_usage (mgr, org_id); if (usage < 0 || usage >= quota) ret = -1; out: seaf_virtual_repo_info_free (vinfo); g_free (user); return ret; }
GList * seaf_repo_manager_list_dir_with_perm (SeafRepoManager *mgr, const char *repo_id, const char *dir_path, const char *dir_id, const char *user, int offset, int limit, GError **error) { SeafRepo *repo; char *perm = NULL; SeafDir *dir; SeafDirent *dent; SeafileDirent *d; GList *res = NULL; GList *p; if (!repo_id || !is_uuid_valid(repo_id) || dir_id == NULL || !user) { g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_DIR_ID, "Bad dir id"); return NULL; } perm = seaf_repo_manager_check_permission (mgr, repo_id, user, error); if (!perm) { if (*error == NULL) g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Access denied"); return NULL; } repo = seaf_repo_manager_get_repo (seaf->repo_mgr, repo_id); if (!repo) { g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Bad repo id"); g_free (perm); return NULL; } dir = seaf_fs_manager_get_seafdir (seaf->fs_mgr, repo->store_id, repo->version, dir_id); if (!dir) { g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_DIR_ID, "Bad dir id"); seaf_repo_unref (repo); g_free (perm); return NULL; } dir->entries = g_list_sort (dir->entries, comp_dirent_func); if (offset < 0) { offset = 0; } int index = 0; gboolean is_shared; char *cur_path; GHashTable *shared_sub_dirs = NULL; if (!repo->virtual_info) { char *repo_owner = seaf_repo_manager_get_repo_owner (seaf->repo_mgr, repo_id); if (repo_owner && strcmp (user, repo_owner) == 0) { shared_sub_dirs = seaf_share_manager_get_shared_sub_dirs (seaf->share_mgr, repo->store_id, dir_path); } g_free (repo_owner); } for (p = dir->entries; p != NULL; p = p->next, index++) { if (index < offset) { continue; } if (limit > 0) { if (index >= offset + limit) break; } dent = p->data; d = g_object_new (SEAFILE_TYPE_DIRENT, "obj_id", dent->id, "obj_name", dent->name, "mode", dent->mode, "version", dent->version, "mtime", dent->mtime, "size", dent->size, "permission", perm, NULL); if (shared_sub_dirs && S_ISDIR(dent->mode)) { if (strcmp (dir_path, "/") == 0) { cur_path = g_strconcat (dir_path, dent->name, NULL); } else { cur_path = g_strconcat (dir_path, "/", dent->name, NULL); } is_shared = g_hash_table_lookup (shared_sub_dirs, cur_path) ? TRUE : FALSE; g_free (cur_path); g_object_set (d, "is_shared", is_shared, NULL); } res = g_list_prepend (res, d); } if (shared_sub_dirs) g_hash_table_destroy (shared_sub_dirs); seaf_dir_free (dir); seaf_repo_unref (repo); g_free (perm); if (res) res = g_list_reverse (res); return res; }