<commit_before>%%%-------------------------------------------------------------------
%%% @author <NAME>
%%% @copyright (C) 2016 ACK CYFRONET AGH
%%% This software is released under the MIT license
%%% cited in 'LICENSE.txt'.
%%% @end
%%%-------------------------------------------------------------------
%%% @doc
%%% This module implements data_backend_behaviour and is used to synchronize
%%% the share model used in Ember application.
%%% @end
%%%-------------------------------------------------------------------
-module(share_data_backend).
-author("<NAME>").
-author("<NAME>").

-include("proto/common/credentials.hrl").
-include("modules/datastore/datastore_specific_models_def.hrl").
-include_lib("cluster_worker/include/modules/datastore/datastore.hrl").
-include_lib("ctool/include/logging.hrl").
-include_lib("ctool/include/posix/errors.hrl").
-include_lib("ctool/include/posix/file_attr.hrl").


%% API
-export([init/0, terminate/0]).
-export([find/2, find_all/1, find_query/2]).
-export([create_record/2, update_record/3, delete_record/2]).

%%%===================================================================
%%% API functions
%%%===================================================================

%%--------------------------------------------------------------------
%% @doc
%% {@link data_backend_behaviour} callback init/0.
%% @end
%%--------------------------------------------------------------------
-spec init() -> ok.
init() ->
    ok.


%%--------------------------------------------------------------------
%% @doc
%% {@link data_backend_behaviour} callback terminate/0.
%% @end
%%--------------------------------------------------------------------
-spec terminate() -> ok.
terminate() ->
    ok.


%%--------------------------------------------------------------------
%% @doc
%% {@link data_backend_behaviour} callback find/2.
%% @end
%%--------------------------------------------------------------------
-spec find(ResourceType :: binary(), Id :: binary()) ->
    {ok, proplists:proplist()} | gui_error:error_result().
find(<<"share">>, ShareId) ->
    UserId = g_session:get_user_id(),
    UserAuth = op_gui_utils:get_user_auth(),
    {ok, #document{
        value = #share_info{
            name = Name,
            root_file_id = RootFileId,
            parent_space = ParentSpaceId,
            public_url = PublicURL
        }}} = share_logic:get(UserAuth, ShareId),
    % Make sure that user is allowed to view requested share - he must have
    % view privileges in this space.
    Authorized = space_logic:has_effective_privilege(
        ParentSpaceId, UserId, space_view_data
    ),
    case Authorized of
        false ->
            gui_error:unauthorized();
        true ->
            FileId = fslogic_uuid:share_guid_to_guid(RootFileId),
            {ok, [
                {<<"id">>, ShareId},
                {<<"name">>, Name},
                {<<"file">>, FileId},
                {<<"containerDir">>, <<"containerDir.", ShareId/binary>>},
                {<<"dataSpace">>, ParentSpaceId},
                {<<"publicUrl">>, PublicURL}
            ]}
    end;

find(<<"file-shared">>, <<"containerDir.", ShareId/binary>>) ->
    UserAuth = op_gui_utils:get_user_auth(),
    {ok, #document{
        value = #share_info{
            name = Name,
            root_file_id = RootFileId
        }}} = share_logic:get(UserAuth, ShareId),
    FileId = fslogic_uuid:share_guid_to_guid(RootFileId),
    Res = [
        {<<"id">>, <<"containerDir.", ShareId/binary>>},
        {<<"name">>, Name},
        {<<"type">>, <<"dir">>},
        {<<"permissions">>, 0},
        {<<"modificationTime">>, 0},
        {<<"size">>, 0},
        {<<"parent">>, null},
        {<<"children">>, [op_gui_utils:ids_to_association(ShareId, FileId)]},
        {<<"fileAcl">>, null},
        {<<"share">>, null},
        {<<"provider">>, null},
        {<<"fileProperty">>, null}
    ],
    {ok, Res};

find(<<"file-shared">>, AssocId) ->
    SessionId = g_session:get_session_id(),
    {ShareId, FileId} = op_gui_utils:association_to_ids(AssocId),
    case logical_file_manager:stat(SessionId, {guid, FileId}) of
        {error, ?ENOENT} ->
            gui_error:report_error(<<"No such file or directory.">>);
        {ok, FileAttr} ->
            #file_attr{
                name = Name,
                type = TypeAttr,
                size = SizeAttr,
                mtime = ModificationTime,
                mode = PermissionsAttr,
                shares = Shares,
                provider_id = ProviderId
            } = FileAttr,

            ParentUUID = case Shares of
                [ShareId] ->
                    % Check if this is the root dir
                    <<"containerDir.", ShareId/binary>>;
                false ->
                    op_gui_utils:ids_to_association(
                        ShareId, get_parent(SessionId, FileId)
                    )
            end,

            {Type, Size} = case TypeAttr of
                ?DIRECTORY_TYPE -> {<<"dir">>, null};
                _ -> {<<"file">>, SizeAttr}
            end,
            Permissions = integer_to_binary((PermissionsAttr rem 1000), 8),
            Children = case Type of
                <<"file">> ->
                    [];
                <<"dir">> ->
                    case logical_file_manager:ls(
                        SessionId, {guid, FileId}, 0, 1000) of
                        {ok, List} ->
                            List;
                        _ ->
                            []
                    end<commit_msg>VFS-2567 Fix a bug in share data backend<commit_after>%%%-------------------------------------------------------------------
%%% @author <NAME>
%%% @copyright (C) 2016 ACK CYFRONET AGH
%%% This software is released under the MIT license
%%% cited in 'LICENSE.txt'.
%%% @end
%%%-------------------------------------------------------------------
%%% @doc
%%% This module implements data_backend_behaviour and is used to synchronize
%%% the share model used in Ember application.
%%% @end
%%%-------------------------------------------------------------------
-module(share_data_backend).
-author("<NAME>").
-author("<NAME>").

-include("proto/common/credentials.hrl").
-include("modules/datastore/datastore_specific_models_def.hrl").
-include_lib("cluster_worker/include/modules/datastore/datastore.hrl").
-include_lib("ctool/include/logging.hrl").
-include_lib("ctool/include/posix/errors.hrl").
-include_lib("ctool/include/posix/file_attr.hrl").


%% API
-export([init/0, terminate/0]).
-export([find/2, find_all/1, find_query/2]).
-export([create_record/2, update_record/3, delete_record/2]).

%%%===================================================================
%%% API functions
%%%===================================================================

%%--------------------------------------------------------------------
%% @doc
%% {@link data_backend_behaviour} callback init/0.
%% @end
%%--------------------------------------------------------------------
-spec init() -> ok.
init() ->
    ok.


%%--------------------------------------------------------------------
%% @doc
%% {@link data_backend_behaviour} callback terminate/0.
%% @end
%%--------------------------------------------------------------------
-spec terminate() -> ok.
terminate() ->
    ok.


%%--------------------------------------------------------------------
%% @doc
%% {@link data_backend_behaviour} callback find/2.
%% @end
%%--------------------------------------------------------------------
-spec find(ResourceType :: binary(), Id :: binary()) ->
    {ok, proplists:proplist()} | gui_error:error_result().
find(<<"share">>, ShareId) ->
    UserId = g_session:get_user_id(),
    UserAuth = op_gui_utils:get_user_auth(),
    {ok, #document{
        value = #share_info{
            name = Name,
            root_file_id = RootFileId,
            parent_space = ParentSpaceId,
            public_url = PublicURL
        }}} = share_logic:get(UserAuth, ShareId),
    % Make sure that user is allowed to view requested share - he must have
    % view privileges in this space.
    Authorized = space_logic:has_effective_privilege(
        ParentSpaceId, UserId, space_view_data
    ),
    case Authorized of
        false ->
            gui_error:unauthorized();
        true ->
            FileId = fslogic_uuid:share_guid_to_guid(RootFileId),
            {ok, [
                {<<"id">>, ShareId},
                {<<"name">>, Name},
                {<<"file">>, FileId},
                {<<"containerDir">>, <<"containerDir.", ShareId/binary>>},
                {<<"dataSpace">>, ParentSpaceId},
                {<<"publicUrl">>, PublicURL}
            ]}
    end;

find(<<"file-shared">>, <<"containerDir.", ShareId/binary>>) ->
    UserAuth = op_gui_utils:get_user_auth(),
    {ok, #document{
        value = #share_info{
            name = Name,
            root_file_id = RootFileId
        }}} = share_logic:get(UserAuth, ShareId),
    FileId = fslogic_uuid:share_guid_to_guid(RootFileId),
    Res = [
        {<<"id">>, <<"containerDir.", ShareId/binary>>},
        {<<"name">>, Name},
        {<<"type">>, <<"dir">>},
        {<<"permissions">>, 0},
        {<<"modificationTime">>, 0},
        {<<"size">>, 0},
        {<<"parent">>, null},
        {<<"children">>, [op_gui_utils:ids_to_association(ShareId, FileId)]},
        {<<"fileAcl">>, null},
        {<<"share">>, null},
        {<<"provider">>, null},
        {<<"fileProperty">>, null}
    ],
    {ok, Res};

find(<<"file-shared">>, AssocId) ->
    SessionId = g_session:get_session_id(),
    {ShareId, FileId} = op_gui_utils:association_to_ids(AssocId),
    case logical_file_manager:stat(SessionId, {guid, FileId}) of
        {error, ?ENOENT} ->
            gui_error:report_error(<<"No such file or directory.">>);
        {ok, FileAttr} ->
            #file_attr{
                name = Name,
                type = TypeAttr,
                size = SizeAttr,
                mtime = ModificationTime,
                mode = PermissionsAttr,
                shares = Shares,
                provider_id = ProviderId
            } = FileAttr,

            ParentUUID = case Shares of
                [ShareId] ->
                    % Check if this is the root dir
                    <<"containerDir.", ShareId/binary>>;
                [] ->
                    op_gui_utils:ids_to_association(
                        ShareId, get_parent(SessionId, FileId)
                    )
            end,

            {Type, Size} = case TypeAttr of
                ?DIRECTORY_TYPE -> {<<"dir">>, null};
                _ -> {<<"file">>, SizeAttr}
            end,
            Permissions = integer_to_binary((PermissionsAttr rem 1000), 8),
            Children = case Type of
                <<"file">> ->
                    [];
                <<"dir">> ->
                    case logical_file_manager:ls(
                        SessionId, {guid, FileId}, 0, 1000) of
                        {ok, List} ->
                            List;
                        _ ->
                            []
                    end
{'fraction_non_alphanumeric': 0.2745643973414766, 'fraction_numerical': 0.005388898868331237, 'mean_word_length': 1.5255159900204127, 'pattern_counts': {'":': 0, '<': 133, '<?xml version=': 0, '>': 173, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2756162', 'n_tokens_mistral': 3146, 'n_tokens_neox': 2989, 'n_words': 601}