Установить общий префикс ключа для корзины S3 для каждого экземпляра CKFinder 3 - PullRequest
0 голосов
/ 28 февраля 2019

Как сделать так, чтобы интеграция CKFinder ASP.net S3 загружала содержимое из префикса динамического ключа, а не из корневого каталога?


Я использую CKEditor 5 и CKFinder 3 с ASP.net Connector для прямой загрузки изображений в корзину S3.Веб-приложение, к которому мы все это подключаем, не является приложением ASP.net.

Настройка была достаточно простой, если следовать документации.

Однако наш продукт SaaS, поэтому каждый разCKFinder запущен, он нужен мне для назначения другого префикса ключа в нашем сегменте.Несколько веб-сайтов работают с одним и тем же приложением, и у каждого должна быть возможность загружать свою галерею изображений через CKFinder без возможности видеть изображения, принадлежащие другим приложениям.


Наш CKFinder Web.config:

<backend name="s3Bucket" adapter="s3">
   <option name="bucket" value="myBucket" />
   <option name="key" value="KEYHERE" />
   <option name="secret" value="SECRETHERE" />
   <option name="region" value="us-east-1" />
   <option name="root" value="images" />
 </backend>

Этот конфиг получает содержимое в /images/ префикс общего ключа "папка" просто замечательно, но для каждого приложения, использующего CKFinder, я хочу, чтобы оно читало из другого "корня":

/images/app1Id/
/images/app2Id/
/images/app3Id/

В идеале я хочу установить это при вызове экземпляра Editor / Finder;что-то вроде:

ClassicEditor.create( document.querySelector( '#textareaId' ), {
    ckfinder: {
        uploadUrl: '/ckfinder/connector?command=QuickUpload&type=Images&responseType=json',
        connectorRoot: '/images/app1Id/'
    },
    toolbar: [ 'heading', '|', 'bold', 'italic', 'link', 'bulletedList', 'numberedList', 'blockQuote', 'ckfinder' ],
    heading: {
        options: [
            { model: 'paragraph', title: 'Paragraph', class: 'ck-heading_paragraph' },
            { model: 'heading1', view: 'h1', title: 'Heading 1', class: 'ck-heading_heading1' },
            { model: 'heading2', view: 'h2', title: 'Heading 2', class: 'ck-heading_heading2' }
        ]
    }
});

Здесь я добавил connectorRoot: '/images/app1Id/' в качестве примера того, что я хотел бы передать.

Есть ли способ сделать что-то подобное?Я прочитал документацию по ASP.net Connector и вижу, что вы можете создать свой собственный соединитель и использовать pass для отправки ему данных, но необходимость компилировать и поддерживать пользовательский соединитель звучит не очень весело.Соединение с S3 здесь просто великолепно и просто ... если бы только позвольте мне быть более конкретным.

1 Ответ

0 голосов
/ 02 мая 2019

Мы пришли к решению изменить и настроить CKFinder ASP Connector.Большое спасибо команде CKSource за помощь в ее запуске.


ConnectorConfig.cs

namespace CKSource.CKFinder.Connector.WebApp
{
    using System.Configuration;
    using System.Linq;

    using CKSource.CKFinder.Connector.Config;
    using CKSource.CKFinder.Connector.Core.Acl;
    using CKSource.CKFinder.Connector.Core.Builders;
    using CKSource.CKFinder.Connector.Host.Owin;
    using CKSource.CKFinder.Connector.KeyValue.FileSystem;
    using CKSource.FileSystem.Amazon;
    //using CKSource.FileSystem.Azure;
    //using CKSource.FileSystem.Dropbox;
    //using CKSource.FileSystem.Ftp;
    using CKSource.FileSystem.Local;

    using Owin;

    public class ConnectorConfig
    {
        public static void RegisterFileSystems()
        {
            FileSystemFactory.RegisterFileSystem<LocalStorage>();
            //FileSystemFactory.RegisterFileSystem<DropboxStorage>();
            FileSystemFactory.RegisterFileSystem<AmazonStorage>();
            //FileSystemFactory.RegisterFileSystem<AzureStorage>();
            //FileSystemFactory.RegisterFileSystem<FtpStorage>();
        }

        public static void SetupConnector(IAppBuilder builder)
        {
            var allowedRoleMatcherTemplate = ConfigurationManager.AppSettings["ckfinderAllowedRole"];
            var authenticator = new RoleBasedAuthenticator(allowedRoleMatcherTemplate);

            var connectorFactory = new OwinConnectorFactory();
            var connectorBuilder = new ConnectorBuilder();
            var connector = connectorBuilder
                .LoadConfig()
                .SetAuthenticator(authenticator)
                .SetRequestConfiguration(
                    (request, config) =>
                    {

                        config.LoadConfig();

                        var defaultBackend = config.GetBackend("default");
                        var keyValueStoreProvider = new FileSystemKeyValueStoreProvider(defaultBackend);
                        config.SetKeyValueStoreProvider(keyValueStoreProvider);

                        // Remove dummy resource type
                        config.RemoveResourceType("dummy");

                        var queryParameters = request.QueryParameters;

                        // This code lacks some input validation - make sure the user is allowed to access passed appId
                        string appId = queryParameters.ContainsKey("appId") ? Enumerable.FirstOrDefault(queryParameters["appId"]) : string.Empty;

                        // set up an array of StringMatchers for folder to hide!
                        StringMatcher[] hideFoldersMatcher = new StringMatcher[] { new StringMatcher(".*"), new StringMatcher("CVS"), new StringMatcher("thumbs"), new StringMatcher("__thumbs") };

                        // image type resource setup
                        var fileSystem_Images = new AmazonStorage(secret: "SECRET-HERE",
                                                            key: "KEY-HERE",
                                                            bucket: "BUCKET-HERE",
                                                            region: "us-east-1",
                                                            root: string.Format("images/{0}/userimages/", appId),
                                                            signatureVersion: "4");

                        string[] allowedExtentions_Images = new string[] {"gif","jpeg","jpg","png"};

                        config.AddBackend("s3Images", fileSystem_Images, string.Format("CDNURL-HERE/images/{0}/userimages/", appId), false);

                        config.AddResourceType("Images", resourceBuilder => {
                            resourceBuilder.SetBackend("s3Images", "/")
                            .SetAllowedExtensions(allowedExtentions_Images)
                            .SetHideFoldersMatchers(hideFoldersMatcher)
                            .SetMaxFileSize( 5242880 );
                        });

                         // file type resource setup
                        var fileSystem_Files = new AmazonStorage(secret: "SECRET-HERE",
                                                        key: "KEY-HERE",
                                                        bucket: "BUCKET-HERE",
                                                        region: "us-east-1",
                                                        root: string.Format("docs/{0}/userfiles/", appId),
                                                        signatureVersion: "4");

                        string[] allowedExtentions_Files = new string[] {"csv","doc","docx","gif","jpeg","jpg","ods","odt","pdf","png","ppt","pptx","rtf","txt","xls","xlsx"};

                        config.AddBackend("s3Files", fileSystem_Files, string.Format("CDNURL-HERE/docs/{0}/userfiles/", appId), false);

                        config.AddResourceType("Files", resourceBuilder => {
                            resourceBuilder.SetBackend("s3Files", "/")
                            .SetAllowedExtensions(allowedExtentions_Files)
                            .SetHideFoldersMatchers(hideFoldersMatcher)
                            .SetMaxFileSize( 10485760 );
                        });

                    })
                .Build(connectorFactory);

            builder.UseConnector(connector);
        }
    }
}

Примечания:

  • Добавлено using System.Linq;, чтобы FirstOrDefault работало при получении appId
  • Мы удалили некоторые файловые системы (Azure, Dropbox, Ftp), потому что мы не используем их в нашей интеграции
  • В файле CKFinder web.config мы создаем «фиктивный» тип ресурса, поскольку для Finder требуется хотя бы один из них, но затем мы удаляем его при настройке соединителя и заменяем его на нужные нам типы ресурсов <resourceTypes><resourceType name="dummy" backend="default"></resourceType>resourceTypes>
  • Обратите внимание и позаботьтесь о том, чтобы вы поместили в этот файл некоторую конфиденциальную информацию.Пожалуйста, подумайте, как вы управляете версиями (или нет), и вы можете предпринять дополнительные действия, чтобы сделать это более безопасным

Инициализация экземпляра CKEditor4 / CKFinder3

<script src="/js/ckeditor/ckeditor.js"></script>
<script src="/js/ckfinder3/ckfinder.js"></script>

<script type="text/javascript">

    var myEditor = CKEDITOR.replace( 'bodyContent', {

        toolbar:                    'Default',
        width:                      '100%',
        startupMode:                'wysiwyg',

        filebrowserBrowseUrl:       '/js/ckfinder3/ckfinder.html?type=Files&appId=12345',
        filebrowserUploadUrl:       '/js/ckfinder3/connector?command=QuickUpload&type=Files&appId=12345',

        filebrowserImageBrowseUrl:  '/js/ckfinder3/ckfinder.html?type=Images&appId=12345',
        filebrowserImageUploadUrl:  '/js/ckfinder3/connector?command=QuickUpload&type=Images&appId=12345',

        uploadUrl:                  '/js/ckfinder3/connector?command=QuickUpload&type=Images&responseType=json&appId=12345'

    });
</script>

Примечания:

  • В связи с другими требованиями к интеграции здесь используется метод ручной интеграции, который требует от нас ручного определения нашего filebrowserUrls
  • В настоящее времядобавление &pass=appId к вашему filebrowserUrls или добавление config.pass = 'appId'; к вашему config.js файлу некорректно pass желаемое значение через редактор
  • Я полагаю, что это происходит только при использовании метода ручной интеграции (должно работать правильно, если вы используете CKFinder.setupCKEditor())

ckfinder.html

<!DOCTYPE html>
<!--
Copyright (c) 2007-2019, CKSource - Frederico Knabben. All rights reserved.
For licensing, see LICENSE.html or https://ckeditor.com/sales/license/ckfinder
-->
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1,user-scalable=no">
    <title>CKFinder 3 - File Browser</title>
</head>
<body>

<script src="ckfinder.js"></script>
<script>

    var urlParams = new URLSearchParams( window.location.search );
    var myAppId = ( urlParams.has( 'appId' ) ) ? urlParams.get( 'appId' ) : '';

    if ( myAppId !== '' ) {
        CKFinder.start( { pass: 'appId', appId: myAppId } );
    } else {
        document.write( 'Error loading configuration.' );
    }

</script>

</body>
</html>

Примечания:

  • Похоже, что все это работает гораздо более плавно при интеграции в CKEditor5, но при интеграции в CKEditor4 у нас возникает много проблем с получением значения appId pass в редакторе должным образом.ru используя метод ручной интеграции для CKFinder
  • Мы модифицируем здесь файл ckfinder.html, чтобы искать нужные URL-параметры и pass их в экземпляр CKFinder при его запуске.Это гарантирует, что они будут переданы через весь экземпляр Finder
  • . Проверьте этот вопрос, чтобы получить более подробную информацию об этом процессе, а также более общий метод передачи параметров n в ваш Finder.экземпляры: Как передать пользовательские значения в CKFinder3 при создании экземпляра CKEditor4?
...