Esempio n. 1
0
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;
}
Esempio n. 2
0
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;
}
Esempio n. 3
0
/*
 * 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;
}
Esempio n. 4
0
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;
}
Esempio n. 5
0
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;
}
Esempio n. 6
0
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;
}
Esempio n. 7
0
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;
}
Esempio n. 8
0
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;
}
Esempio n. 9
0
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;
}