├── .dockerignore ├── .gitignore ├── Dockerfile ├── Frontend ├── .editorconfig ├── .gitignore ├── .vscode │ ├── extensions.json │ ├── launch.json │ └── tasks.json ├── angular.json ├── merge-elements.js ├── package-lock.json ├── package.json ├── src │ ├── app │ │ ├── account │ │ │ ├── account.component.html │ │ │ ├── account.component.scss │ │ │ ├── account.component.ts │ │ │ ├── change-password │ │ │ │ ├── change-password.component.html │ │ │ │ ├── change-password.component.scss │ │ │ │ └── change-password.component.ts │ │ │ ├── email-settings │ │ │ │ ├── aws │ │ │ │ │ └── create-aws-ses │ │ │ │ │ │ ├── create-aws-ses.component.html │ │ │ │ │ │ ├── create-aws-ses.component.scss │ │ │ │ │ │ └── create-aws-ses.component.ts │ │ │ │ ├── confirm-email-provider │ │ │ │ │ ├── confirm-email-provider.component.html │ │ │ │ │ ├── confirm-email-provider.component.scss │ │ │ │ │ └── confirm-email-provider.component.ts │ │ │ │ ├── email-settings.component.html │ │ │ │ ├── email-settings.component.scss │ │ │ │ ├── email-settings.component.ts │ │ │ │ ├── resend │ │ │ │ │ └── create-resend │ │ │ │ │ │ ├── create-resend.component.html │ │ │ │ │ │ ├── create-resend.component.scss │ │ │ │ │ │ └── create-resend.component.ts │ │ │ │ └── smtp │ │ │ │ │ └── create-smtp │ │ │ │ │ ├── create-smtp.component.html │ │ │ │ │ ├── create-smtp.component.scss │ │ │ │ │ └── create-smtp.component.ts │ │ │ ├── general-settings │ │ │ │ ├── document-upload │ │ │ │ │ ├── document-upload.component.html │ │ │ │ │ ├── document-upload.component.scss │ │ │ │ │ └── document-upload.component.ts │ │ │ │ ├── general-settings.component.html │ │ │ │ ├── general-settings.component.scss │ │ │ │ └── general-settings.component.ts │ │ │ ├── integrations │ │ │ │ ├── aws │ │ │ │ │ └── textract │ │ │ │ │ │ └── create │ │ │ │ │ │ ├── create-aws-textract.component.html │ │ │ │ │ │ ├── create-aws-textract.component.scss │ │ │ │ │ │ └── create-aws-textract.component.ts │ │ │ │ ├── integrations.component.html │ │ │ │ ├── integrations.component.scss │ │ │ │ ├── integrations.component.ts │ │ │ │ └── openai │ │ │ │ │ └── chatgpt │ │ │ │ │ └── create │ │ │ │ │ ├── create-chatgpt.component.html │ │ │ │ │ ├── create-chatgpt.component.scss │ │ │ │ │ └── create-chatgpt.component.ts │ │ │ ├── multi-factor-auth │ │ │ │ ├── multi-factor-auth.component.html │ │ │ │ ├── multi-factor-auth.component.scss │ │ │ │ ├── multi-factor-auth.component.ts │ │ │ │ └── qr-code.component.ts │ │ │ ├── storage-settings │ │ │ │ ├── aws │ │ │ │ │ ├── create-aws-storage │ │ │ │ │ │ ├── create-aws-storage.component.html │ │ │ │ │ │ ├── create-aws-storage.component.scss │ │ │ │ │ │ └── create-aws-storage.component.ts │ │ │ │ │ └── edit-aws-storage │ │ │ │ │ │ ├── edit-aws-storage.component.html │ │ │ │ │ │ ├── edit-aws-storage.component.scss │ │ │ │ │ │ └── edit-aws-storage.component.ts │ │ │ │ ├── cloudflare │ │ │ │ │ ├── create-cloudflare-storage │ │ │ │ │ │ ├── create-cloudflare-storage.component.html │ │ │ │ │ │ ├── create-cloudflare-storage.component.scss │ │ │ │ │ │ └── create-cloudflare-storage.component.ts │ │ │ │ │ └── edit-cloudflare-storage │ │ │ │ │ │ ├── edit-cloudflare-storage.component.html │ │ │ │ │ │ ├── edit-cloudflare-storage.component.scss │ │ │ │ │ │ └── edit-cloudflare-storage.component.ts │ │ │ │ ├── digitalocean │ │ │ │ │ ├── create-digitalocean-storage │ │ │ │ │ │ ├── create-digitalocean-storage.component.html │ │ │ │ │ │ ├── create-digitalocean-storage.component.scss │ │ │ │ │ │ └── create-digitalocean-storage.component.ts │ │ │ │ │ └── edit-digitalocean-storage │ │ │ │ │ │ ├── edit-digitalocean-storage.component.html │ │ │ │ │ │ ├── edit-digitalocean-storage.component.scss │ │ │ │ │ │ └── edit-digitalocean-storage.component.ts │ │ │ │ ├── hard-drive │ │ │ │ │ └── create-hard-drive-storage │ │ │ │ │ │ ├── create-hard-drive-storage.component.html │ │ │ │ │ │ ├── create-hard-drive-storage.component.scss │ │ │ │ │ │ └── create-hard-drive-storage.component.ts │ │ │ │ ├── storage-settings.component.html │ │ │ │ ├── storage-settings.component.scss │ │ │ │ └── storage-settings.component.ts │ │ │ ├── user-details │ │ │ │ ├── user-details.component.html │ │ │ │ ├── user-details.component.scss │ │ │ │ └── user-details.component.ts │ │ │ └── users-settings │ │ │ │ ├── users-settings.component.html │ │ │ │ ├── users-settings.component.scss │ │ │ │ └── users-settings.component.ts │ │ ├── app.component.html │ │ ├── app.component.scss │ │ ├── app.component.ts │ │ ├── app.config.ts │ │ ├── external-access │ │ │ ├── box-widget │ │ │ │ ├── box-widget.api.ts │ │ │ │ ├── box-widget.component.html │ │ │ │ ├── box-widget.component.scss │ │ │ │ └── box-widget.component.ts │ │ │ ├── contracts │ │ │ │ └── external-access.contracts.ts │ │ │ ├── external-box │ │ │ │ ├── external-box.component.html │ │ │ │ ├── external-box.component.scss │ │ │ │ ├── external-box.component.ts │ │ │ │ └── external-boxes.api.ts │ │ │ └── external-link │ │ │ │ ├── access-codes.api.ts │ │ │ │ ├── external-link.component.html │ │ │ │ ├── external-link.component.scss │ │ │ │ └── external-link.component.ts │ │ ├── files-explorer │ │ │ ├── bulk-upload-preview │ │ │ │ ├── bulk-upload-preview.component.html │ │ │ │ ├── bulk-upload-preview.component.scss │ │ │ │ └── bulk-upload-preview.component.ts │ │ │ ├── directives │ │ │ │ ├── drag-over-stay.directive.ts │ │ │ │ └── drop-files.directive.ts │ │ │ ├── file-content │ │ │ │ ├── audio-preview │ │ │ │ │ ├── audio-preview.component.html │ │ │ │ │ ├── audio-preview.component.scss │ │ │ │ │ └── audio-preview.component.ts │ │ │ │ ├── file-content.component.html │ │ │ │ ├── file-content.component.scss │ │ │ │ ├── file-content.component.ts │ │ │ │ ├── image-preview │ │ │ │ │ ├── image-preview.component.html │ │ │ │ │ ├── image-preview.component.scss │ │ │ │ │ └── image-preview.component.ts │ │ │ │ ├── markdown-preview │ │ │ │ │ ├── markdown-preview.component.html │ │ │ │ │ ├── markdown-preview.component.scss │ │ │ │ │ └── markdown-preview.component.ts │ │ │ │ ├── pdf-preview │ │ │ │ │ ├── pdf-preview.component.html │ │ │ │ │ ├── pdf-preview.component.scss │ │ │ │ │ └── pdf-preview.component.ts │ │ │ │ ├── text-preview │ │ │ │ │ ├── text-preview.component.html │ │ │ │ │ ├── text-preview.component.scss │ │ │ │ │ └── text-preview.component.ts │ │ │ │ ├── video-preview │ │ │ │ │ ├── video-preview.component.html │ │ │ │ │ ├── video-preview.component.scss │ │ │ │ │ └── video-preview.component.ts │ │ │ │ └── zip-preview │ │ │ │ │ ├── zip-preview.component.html │ │ │ │ │ ├── zip-preview.component.scss │ │ │ │ │ └── zip-preview.component.ts │ │ │ ├── file-icon-pipe │ │ │ │ └── file-icon.pipe.ts │ │ │ ├── file-inline-preview │ │ │ │ ├── file-inline-preview-commands-pipeline.ts │ │ │ │ ├── file-inline-preview.component.html │ │ │ │ ├── file-inline-preview.component.scss │ │ │ │ └── file-inline-preview.component.ts │ │ │ ├── files-explorer.component.html │ │ │ ├── files-explorer.component.scss │ │ │ ├── files-explorer.component.ts │ │ │ ├── folder-path │ │ │ │ ├── folder-path.component.html │ │ │ │ ├── folder-path.component.scss │ │ │ │ └── folder-path.component.ts │ │ │ ├── http-headers-factory.ts │ │ │ └── upload-item │ │ │ │ ├── upload-item.component.html │ │ │ │ ├── upload-item.component.scss │ │ │ │ └── upload-item.component.ts │ │ ├── files-processor │ │ │ ├── files-processor.component.html │ │ │ ├── files-processor.component.scss │ │ │ └── files-processor.component.ts │ │ ├── protobuf │ │ │ ├── ancestor-folder-dto.protobuf.ts │ │ │ ├── box-details-and-folder-content-dto.protobuf.ts │ │ │ ├── box-details-dto.protobuf.ts │ │ │ ├── bulk-create-folder-item-dto.protobuf.ts │ │ │ ├── bulk-create-folder-request-dto.protobuf.ts │ │ │ ├── bulk-create-folder-response-dto.protobuf.ts │ │ │ ├── bulk-initiate-file-upload-item-dto.protobuf.ts │ │ │ ├── bulk-initiate-file-upload-request-dto.protobuf.ts │ │ │ ├── bulk-initiate-file-upload-response-dto.protobuf.ts │ │ │ ├── current-folder-dto.protobuf.ts │ │ │ ├── dashboard-content-dto.protobuf.ts │ │ │ ├── datetime.protobuf.ts │ │ │ ├── file-dto.protobuf.ts │ │ │ ├── folder-content-dto.protobuf.ts │ │ │ ├── folder-tree-dto.protobuf.ts │ │ │ ├── search-files-tree-response-dto.protobuf.ts │ │ │ ├── search-response-dto.protobuf.ts │ │ │ ├── subfolder-dto.protobuf.ts │ │ │ ├── top-folder-content-dto.protobuf.ts │ │ │ ├── upload-dto.protobuf.ts │ │ │ ├── zip-file-details-dto.protobuf.ts │ │ │ └── zip-file-details-item-dto.protobuf.ts │ │ ├── services │ │ │ ├── account.api.ts │ │ │ ├── ai-conversations-status.api.ts │ │ │ ├── ai-conversations-status.service.ts │ │ │ ├── antiforgery.api.ts │ │ │ ├── application-settings.api.ts │ │ │ ├── auth-guard.service.ts │ │ │ ├── auth.api.ts │ │ │ ├── auth.interceptor.ts │ │ │ ├── auth.service.ts │ │ │ ├── aws-regions.ts │ │ │ ├── box-external-access.api.ts │ │ │ ├── box-link-token.service.ts │ │ │ ├── box-links.api.ts │ │ │ ├── boxes.api.ts │ │ │ ├── bytes-range.ts │ │ │ ├── chat-gpt.api.ts │ │ │ ├── countdown.ts │ │ │ ├── dashboard.api.ts │ │ │ ├── data-store.service.ts │ │ │ ├── debouncer.ts │ │ │ ├── digitalocean-regions.ts │ │ │ ├── email-providers.api.ts │ │ │ ├── entry-page.service.ts │ │ │ ├── file-lock.service.ts │ │ │ ├── file-upload-manager │ │ │ │ ├── blob-slicer.ts │ │ │ │ ├── compressed-blob-file-slicer.ts │ │ │ │ ├── file-slicer.ts │ │ │ │ ├── file-upload-manager.ts │ │ │ │ ├── file-upload-utils.ts │ │ │ │ ├── multi-file-direct-file-upload.ts │ │ │ │ ├── multi-step-chunk-file-upload.ts │ │ │ │ └── single-chunk-file-upload.ts │ │ │ ├── filte-type.ts │ │ │ ├── folders-and-files.api.ts │ │ │ ├── general-settings.api.ts │ │ │ ├── guid-base-62.ts │ │ │ ├── in-app-sharing.service.ts │ │ │ ├── integrations.api.ts │ │ │ ├── integrations.types.ts │ │ │ ├── is-highlighted-utils.ts │ │ │ ├── loading-chunk-failed-error.handler.ts │ │ │ ├── lock-status.api.ts │ │ │ ├── n-gram-search.ts │ │ │ ├── optimistic-operation.ts │ │ │ ├── protobuf-http.service.ts │ │ │ ├── search.api.ts │ │ │ ├── search.service.ts │ │ │ ├── sign-out.service.ts │ │ │ ├── storages.api.ts │ │ │ ├── text-measurement.service.ts │ │ │ ├── textract-job-status.service.ts │ │ │ ├── textract.api.ts │ │ │ ├── time.service.ts │ │ │ ├── uploads.api.ts │ │ │ ├── users.api.ts │ │ │ ├── widgets.api.ts │ │ │ ├── workspace-files-explorer-api.ts │ │ │ ├── workspaces.api.ts │ │ │ └── zip.ts │ │ ├── shared │ │ │ ├── ai-conversation-item │ │ │ │ ├── ai-conversation-item.component.html │ │ │ │ ├── ai-conversation-item.component.scss │ │ │ │ └── ai-conversation-item.component.ts │ │ │ ├── ai-message │ │ │ │ ├── ai-message.component.html │ │ │ │ ├── ai-message.component.scss │ │ │ │ └── ai-message.component.ts │ │ │ ├── ai-response │ │ │ │ ├── ai-response.component.html │ │ │ │ ├── ai-response.component.scss │ │ │ │ └── ai-response.component.ts │ │ │ ├── app-textract-job-item.ts │ │ │ ├── app-user.ts │ │ │ ├── app-workspace-details.ts │ │ │ ├── box-invitation-item │ │ │ │ ├── box-invitation-item.component.html │ │ │ │ ├── box-invitation-item.component.scss │ │ │ │ └── box-invitation-item.component.ts │ │ │ ├── box-item │ │ │ │ ├── box-item.component.html │ │ │ │ ├── box-item.component.scss │ │ │ │ └── box-item.component.ts │ │ │ ├── box-permissions │ │ │ │ ├── box-permissions-list.component.html │ │ │ │ ├── box-permissions-list.component.scss │ │ │ │ └── box-permissions-list.component.ts │ │ │ ├── buttons │ │ │ │ ├── action-btn │ │ │ │ │ ├── action-btn.component.html │ │ │ │ │ ├── action-btn.component.scss │ │ │ │ │ └── action-btn.component.ts │ │ │ │ ├── action-text-btn │ │ │ │ │ ├── action-text-btn.component.html │ │ │ │ │ ├── action-text-btn.component.scss │ │ │ │ │ └── action-text-btn.component.ts │ │ │ │ ├── item-btn │ │ │ │ │ ├── item-btn.component.html │ │ │ │ │ ├── item-btn.component.scss │ │ │ │ │ └── item-btn.component.ts │ │ │ │ └── permission-btn │ │ │ │ │ ├── permission-btn.component.html │ │ │ │ │ ├── permission-btn.component.scss │ │ │ │ │ └── permission-btn.component.ts │ │ │ ├── comment │ │ │ │ ├── comment.component.html │ │ │ │ ├── comment.component.scss │ │ │ │ └── comment.component.ts │ │ │ ├── cookies.ts │ │ │ ├── ctrl-click.directive.ts │ │ │ ├── debounced-change.directive.ts │ │ │ ├── editable-txt │ │ │ │ ├── editable-txt.component.html │ │ │ │ ├── editable-txt.component.scss │ │ │ │ └── editable-txt.component.ts │ │ │ ├── elapsed-time.pipe.ts │ │ │ ├── email-picker │ │ │ │ ├── email-picker.component.html │ │ │ │ ├── email-picker.component.scss │ │ │ │ └── email-picker.component.ts │ │ │ ├── email-provider-item │ │ │ │ ├── email-provider-item.component.html │ │ │ │ ├── email-provider-item.component.scss │ │ │ │ └── email-provider-item.component.ts │ │ │ ├── external-box-item │ │ │ │ ├── external-box-item.component.html │ │ │ │ ├── external-box-item.component.scss │ │ │ │ └── external-box-item.component.ts │ │ │ ├── file-item │ │ │ │ ├── file-item.component.html │ │ │ │ ├── file-item.component.scss │ │ │ │ └── file-item.component.ts │ │ │ ├── file-tree-view │ │ │ │ ├── file-tree-node │ │ │ │ │ ├── file-tree-node.component.html │ │ │ │ │ ├── file-tree-node.component.scss │ │ │ │ │ └── file-tree-node.component.ts │ │ │ │ ├── file-tree-view.component.html │ │ │ │ ├── file-tree-view.component.scss │ │ │ │ ├── file-tree-view.component.ts │ │ │ │ ├── folder-tree-node │ │ │ │ │ ├── folder-tree-node.component.html │ │ │ │ │ ├── folder-tree-node.component.scss │ │ │ │ │ └── folder-tree-node.component.ts │ │ │ │ ├── tree-checkbox │ │ │ │ │ ├── tree-checkbox.component.html │ │ │ │ │ ├── tree-checkbox.component.scss │ │ │ │ │ └── tree-checkbox.component.ts │ │ │ │ └── tree-item.ts │ │ │ ├── folder-item │ │ │ │ ├── folder-item.component.html │ │ │ │ ├── folder-item.component.scss │ │ │ │ └── folder-item.component.ts │ │ │ ├── generic-message-dialog │ │ │ │ ├── generic-dialog-service.ts │ │ │ │ ├── generic-message-dialog.component.html │ │ │ │ ├── generic-message-dialog.component.scss │ │ │ │ └── generic-message-dialog.component.ts │ │ │ ├── integration-item │ │ │ │ ├── integration-item.component.html │ │ │ │ ├── integration-item.component.scss │ │ │ │ └── integration-item.component.ts │ │ │ ├── item-search │ │ │ │ ├── item-search.component.html │ │ │ │ ├── item-search.component.scss │ │ │ │ └── item-search.component.ts │ │ │ ├── lexical │ │ │ │ ├── Editor.tsx │ │ │ │ ├── MarkdownEditor.tsx │ │ │ │ ├── lexical-editor-wrapper.component.tsx │ │ │ │ ├── lexical-editor.scss │ │ │ │ ├── markdown-editor-wrapper.component.tsx │ │ │ │ └── plugins │ │ │ │ │ ├── AutoLinkPlugin.tsx │ │ │ │ │ ├── FontSize.tsx │ │ │ │ │ ├── ListMaxIndentLevelPlugin.tsx │ │ │ │ │ └── ToolbarPlugin.tsx │ │ │ ├── menu │ │ │ │ ├── app-menu.scss │ │ │ │ └── menu-animation.ts │ │ │ ├── name-with-highlight.ts │ │ │ ├── operation-confirm │ │ │ │ ├── confirm-operation.directive.ts │ │ │ │ ├── operation-confirm.component.html │ │ │ │ ├── operation-confirm.component.scss │ │ │ │ └── operation-confirm.component.ts │ │ │ ├── prefetch.directive.ts │ │ │ ├── region-input │ │ │ │ ├── region-input.component.html │ │ │ │ ├── region-input.component.scss │ │ │ │ └── region-input.component.ts │ │ │ ├── relative-time │ │ │ │ ├── relative-time.component.scss │ │ │ │ └── relative-time.component.ts │ │ │ ├── rich-text-editor │ │ │ │ ├── rich-text-editor.component.html │ │ │ │ ├── rich-text-editor.component.scss │ │ │ │ └── rich-text-editor.component.ts │ │ │ ├── search-input │ │ │ │ ├── search-input.component.html │ │ │ │ ├── search-input.component.scss │ │ │ │ └── search-input.component.ts │ │ │ ├── search │ │ │ │ ├── search.component.html │ │ │ │ ├── search.component.scss │ │ │ │ └── search.component.ts │ │ │ ├── secure-input.directive.ts │ │ │ ├── select-all-text.directive.ts │ │ │ ├── setting-menu-btn │ │ │ │ ├── settings-menu-btn.component.html │ │ │ │ ├── settings-menu-btn.component.scss │ │ │ │ └── settings-menu-btn.component.ts │ │ │ ├── signal-utils.ts │ │ │ ├── storage-item │ │ │ │ ├── storage-item.component.html │ │ │ │ ├── storage-item.component.scss │ │ │ │ └── storage-item.component.ts │ │ │ ├── storage-picker │ │ │ │ ├── storage-picker.component.html │ │ │ │ ├── storage-picker.component.scss │ │ │ │ └── storage-picker.component.ts │ │ │ ├── storage-size.pipe.ts │ │ │ ├── storage-unit-input │ │ │ │ ├── storage-unit-input.component.html │ │ │ │ ├── storage-unit-input.component.scss │ │ │ │ └── storage-unit-input.component.ts │ │ │ ├── trim.directive.ts │ │ │ ├── user-item │ │ │ │ ├── app-user.ts │ │ │ │ ├── user-item.component.html │ │ │ │ ├── user-item.component.scss │ │ │ │ └── user-item.component.ts │ │ │ ├── user-link │ │ │ │ ├── user-link.component.html │ │ │ │ ├── user-link.component.scss │ │ │ │ └── user-link.component.ts │ │ │ ├── user-permissions │ │ │ │ ├── user-permissions-list.component.html │ │ │ │ ├── user-permissions-list.component.scss │ │ │ │ └── user-permissions-list.component.ts │ │ │ ├── user-picker │ │ │ │ ├── user-picker.component.html │ │ │ │ ├── user-picker.component.scss │ │ │ │ └── user-picker.component.ts │ │ │ ├── workspace-invitation-item │ │ │ │ ├── workspace-invitation-item.component.html │ │ │ │ ├── workspace-invitation-item.component.scss │ │ │ │ └── workspace-invitation-item.component.ts │ │ │ ├── workspace-item │ │ │ │ ├── workspace-item.component.html │ │ │ │ ├── workspace-item.component.scss │ │ │ │ └── workspace-item.component.ts │ │ │ ├── workspace-link │ │ │ │ ├── workspace-link.component.html │ │ │ │ ├── workspace-link.component.scss │ │ │ │ └── workspace-link.component.ts │ │ │ ├── workspace-number-config │ │ │ │ ├── workspace-number-config.component.html │ │ │ │ ├── workspace-number-config.component.scss │ │ │ │ └── workspace-number-config.component.ts │ │ │ ├── workspace-size-config │ │ │ │ ├── workspace-size-config.component.html │ │ │ │ ├── workspace-size-config.component.scss │ │ │ │ └── workspace-size-config.component.ts │ │ │ ├── workspace-size │ │ │ │ └── workspace-size.component.ts │ │ │ ├── workspace-team-config │ │ │ │ ├── workspace-team-config.component.html │ │ │ │ ├── workspace-team-config.component.scss │ │ │ │ └── workspace-team-config.component.ts │ │ │ ├── xsrf.ts │ │ │ └── zip-file-tree-view │ │ │ │ ├── zip-file-tree-view.component.html │ │ │ │ ├── zip-file-tree-view.component.scss │ │ │ │ └── zip-file-tree-view.component.ts │ │ ├── static-pages │ │ │ ├── email-confirmation-page │ │ │ │ ├── email-confirmation-page.component.html │ │ │ │ ├── email-confirmation-page.component.scss │ │ │ │ └── email-confirmation-page.component.ts │ │ │ ├── not-found-page │ │ │ │ ├── not-found-page.component.html │ │ │ │ ├── not-found-page.component.scss │ │ │ │ └── not-found-page.component.ts │ │ │ ├── privacy-policy │ │ │ │ ├── privacy-policy.component.html │ │ │ │ ├── privacy-policy.component.scss │ │ │ │ └── privacy-policy.component.ts │ │ │ ├── reset-password-page │ │ │ │ ├── reset-password-page.component.html │ │ │ │ ├── reset-password-page.component.scss │ │ │ │ └── reset-password-page.component.ts │ │ │ ├── services │ │ │ │ └── singup.service.ts │ │ │ ├── shared │ │ │ │ ├── footer │ │ │ │ │ ├── footer.component.html │ │ │ │ │ ├── footer.component.scss │ │ │ │ │ └── footer.component.ts │ │ │ │ └── top-bar │ │ │ │ │ ├── top-bar.component.html │ │ │ │ │ ├── top-bar.component.scss │ │ │ │ │ └── top-bar.component.ts │ │ │ ├── sign-in-page │ │ │ │ ├── sign-in-page.component.html │ │ │ │ ├── sign-in-page.component.scss │ │ │ │ └── sign-in-page.component.ts │ │ │ ├── sign-up-page │ │ │ │ ├── sign-up-page.component.html │ │ │ │ ├── sign-up-page.component.scss │ │ │ │ └── sign-up-page.component.ts │ │ │ ├── styles │ │ │ │ ├── auth.scss │ │ │ │ ├── legal.scss │ │ │ │ ├── spacer.scss │ │ │ │ ├── static-page-variables.scss │ │ │ │ └── static-pages.scss │ │ │ └── terms │ │ │ │ ├── terms.component.html │ │ │ │ ├── terms.component.scss │ │ │ │ └── terms.component.ts │ │ ├── workspace-manager │ │ │ ├── boxes │ │ │ │ ├── box-details │ │ │ │ │ ├── box-details.component.html │ │ │ │ │ ├── box-details.component.scss │ │ │ │ │ ├── box-details.component.ts │ │ │ │ │ ├── box-link-item │ │ │ │ │ │ ├── box-link-item.component.html │ │ │ │ │ │ ├── box-link-item.component.scss │ │ │ │ │ │ └── box-link-item.component.ts │ │ │ │ │ ├── box-rich-text-editor │ │ │ │ │ │ ├── box-rich-text-editor.component.html │ │ │ │ │ │ ├── box-rich-text-editor.component.scss │ │ │ │ │ │ └── box-rich-text-editor.component.ts │ │ │ │ │ ├── box-team-invitation │ │ │ │ │ │ ├── box-team-invitation.component.html │ │ │ │ │ │ ├── box-team-invitation.component.scss │ │ │ │ │ │ └── box-team-invitation.component.ts │ │ │ │ │ ├── box-team-member │ │ │ │ │ │ ├── box-team-member.component.html │ │ │ │ │ │ ├── box-team-member.component.scss │ │ │ │ │ │ └── box-team-member.component.ts │ │ │ │ │ └── box-widget-setup │ │ │ │ │ │ ├── box-widget-setup.component.html │ │ │ │ │ │ ├── box-widget-setup.component.scss │ │ │ │ │ │ └── box-widget-setup.component.ts │ │ │ │ ├── boxes.component.html │ │ │ │ ├── boxes.component.scss │ │ │ │ ├── boxes.component.ts │ │ │ │ └── folder-picker │ │ │ │ │ ├── folder-picker.component.html │ │ │ │ │ ├── folder-picker.component.scss │ │ │ │ │ └── folder-picker.component.ts │ │ │ ├── config │ │ │ │ ├── workspace-config.component.html │ │ │ │ ├── workspace-config.component.scss │ │ │ │ └── workspace-config.component.ts │ │ │ ├── explorer │ │ │ │ ├── explorer.component.html │ │ │ │ ├── explorer.component.scss │ │ │ │ └── explorer.component.ts │ │ │ ├── team │ │ │ │ ├── team.component.html │ │ │ │ ├── team.component.scss │ │ │ │ ├── team.component.ts │ │ │ │ ├── workspace-team-invitation │ │ │ │ │ ├── workspace-team-invitation.component.html │ │ │ │ │ ├── workspace-team-invitation.component.scss │ │ │ │ │ └── workspace-team-invitation.component.ts │ │ │ │ └── workspace-team-member │ │ │ │ │ ├── workspace-team-member.component.html │ │ │ │ │ ├── workspace-team-member.component.scss │ │ │ │ │ └── workspace-team-member.component.ts │ │ │ ├── uploads │ │ │ │ ├── upload-list-item │ │ │ │ │ ├── upload-list-item.component.html │ │ │ │ │ ├── upload-list-item.component.scss │ │ │ │ │ └── upload-list-item.component.ts │ │ │ │ ├── uploads.component.html │ │ │ │ ├── uploads.component.scss │ │ │ │ └── uploads.component.ts │ │ │ ├── workspace-context.service.ts │ │ │ ├── workspace-manager.component.html │ │ │ ├── workspace-manager.component.scss │ │ │ └── workspace-manager.component.ts │ │ └── workspaces │ │ │ ├── workspaces.component.html │ │ │ ├── workspaces.component.scss │ │ │ └── workspaces.component.ts │ ├── bootstrap-elements.ts │ ├── environments │ │ ├── environment.prod.ts │ │ └── environment.ts │ ├── favicon.ico │ ├── icons │ │ └── icons.scss │ ├── index.html │ ├── main.ts │ ├── polyfills.ts │ ├── robots.txt │ ├── styles.scss │ └── styles │ │ ├── action-text-btn.scss │ │ ├── app-btn.scss │ │ ├── app-header.scss │ │ ├── config-row.scss │ │ ├── covered.scss │ │ ├── drop-area.scss │ │ ├── files-explorer-container.scss │ │ ├── hover-switch.scss │ │ ├── icon-merge.scss │ │ ├── item-bar.scss │ │ ├── main-container.scss │ │ ├── margins.scss │ │ ├── mobile-display.scss │ │ ├── nothing-to-show.scss │ │ ├── page-form.scss │ │ ├── questionaire.scss │ │ ├── top-bar.scss │ │ ├── top-nav-btn.scss │ │ └── variables.scss ├── tsconfig.app.json ├── tsconfig.elements.json ├── tsconfig.json └── tsconfig.spec.json ├── LICENSE ├── PlikShare.IntegrationTests ├── Infrastructure │ ├── Apis │ │ ├── AccessCodesApi.cs │ │ ├── AccountApi.cs │ │ ├── AntiforgeryApi.cs │ │ ├── Api.cs │ │ ├── AuthApi.cs │ │ ├── BoxExternalAccessApi.cs │ │ ├── BoxLinksApi.cs │ │ ├── BoxesApi.cs │ │ ├── Cookie.cs │ │ ├── DashboardApi.cs │ │ ├── EmailProvidersApi.cs │ │ ├── EntryPageApi.cs │ │ ├── FlurlRequestExtensions.cs │ │ ├── FoldersApi.cs │ │ ├── GeneralSettingsApi.cs │ │ ├── SessionAuthCookie.cs │ │ ├── StoragesApi.cs │ │ ├── TestApiCallException.cs │ │ ├── User.cs │ │ ├── UsersApi.cs │ │ └── WorkspacesApi.cs │ ├── HostFixture.cs │ ├── IntegrationTestsCollection.cs │ ├── Mocks │ │ ├── ClockMock.cs │ │ ├── OneTimeCodeMock.cs │ │ └── OneTimeInvitationCodeMock.cs │ ├── RandomGenerator.cs │ ├── ResendEmailServer.cs │ ├── TestFixture.cs │ └── TotpCodes.cs ├── PlikShare.IntegrationTests.csproj ├── TestCases │ ├── Account │ │ └── account_tests.cs │ ├── Auth │ │ ├── auth_tests.cs │ │ └── user_registration_tests.cs │ ├── Boxes │ │ ├── box_external_access_tests.cs │ │ ├── box_header_and_footer_tests.cs │ │ ├── box_link_external_access_tests.cs │ │ ├── box_link_tests.cs │ │ ├── create_box_link_tests.cs │ │ └── create_box_tests.cs │ ├── EmailProviders │ │ └── create_resend_email_providers_tests.cs │ ├── Folders │ │ └── create_folder_tests.cs │ ├── Storages │ │ └── storages_tests.cs │ ├── Users │ │ └── user_invitations_tests.cs │ ├── Workspaces │ │ └── create_workspace_tests.cs │ ├── apis_acces_without_logging_in_tests.cs │ ├── entry_page_tests.cs │ └── first_use_of_plikshare_tests.cs └── appsettings.IntegrationTests.json ├── PlikShare.Tests ├── .gitignore ├── EmailAnonymizationTests.cs ├── EncryptionBytesTests.cs ├── GlobalUsings.cs ├── GuidBase62Tests.cs ├── IdsRangeTests.cs ├── PlikShare.Tests.csproj ├── S3FileKeyJsonConverterTests.cs └── SteppingBufferTests.cs ├── PlikShare.sln ├── PlikShare ├── .gitignore ├── Account │ ├── AccountEndpoints.cs │ ├── Contracts │ │ ├── ChangePasswordRequestDto.cs │ │ ├── Disable2FaResponseDto.cs │ │ ├── Enable2FaRequestDto.cs │ │ ├── GenerateRecoveryCodesResponseDto.cs │ │ ├── Get2FaStatusResponseDto.cs │ │ └── GetAccountDetailsResponseDto.cs │ └── GetKnownUsers │ │ ├── Contracts │ │ └── GetKnownUsersResponseDto.cs │ │ └── GetKnownUsersQuery.cs ├── Antiforgery │ ├── AntiforgeryEndpoints.cs │ └── AutoAntiforgeryMiddleware.cs ├── ApplicationSettings │ ├── ApplicationSettingsEndpoints.cs │ └── GetStatus │ │ ├── Contracts │ │ └── GetApplicationSettingsStatusResponseDto.cs │ │ └── GetApplicationSettingsStatusQuery.cs ├── ArtificialIntelligence │ ├── AiIncludes │ │ ├── AiCompletion.cs │ │ └── AiInclude.cs │ ├── ArtificialIntelligenceEndpoints.cs │ ├── Cache │ │ └── AiConversationCache.cs │ ├── CheckConversationStatus │ │ ├── CheckAiConversationsStatusQuery.cs │ │ └── Contracts │ │ │ └── CheckAiConversationStatusRequestDto.cs │ ├── DeleteConversation │ │ ├── DeleteAiConversationOperation.cs │ │ └── QueueJob │ │ │ ├── DeleteAiConversationQueueJobDefinition.cs │ │ │ ├── DeleteAiConversationQueueJobType.cs │ │ │ └── SendAiMessageQueueJobExecutor.cs │ ├── GetFileArtifact │ │ └── GetFileArtifactWithAiConversationQuery.cs │ ├── GetMessages │ │ ├── AiMessageAuthorType.cs │ │ ├── Contracts │ │ │ └── GetAiMessagesResponseDto.cs │ │ └── GetAiMessagesOperation.cs │ ├── Id │ │ ├── AiConversationExtId.cs │ │ └── AiMessageExtId.cs │ ├── SendFileMessage │ │ ├── Contracts │ │ │ └── SendAiFileMessageRequestDto.cs │ │ ├── GetFilesToIncludeDetailsQuery.cs │ │ ├── GetFullAiConversationQuery.cs │ │ ├── QueueJob │ │ │ ├── SendAiMessageQueueJobDefinition.cs │ │ │ ├── SendAiMessageQueueJobExecutor.cs │ │ │ └── SendAiMessageQueueJobType.cs │ │ ├── SaveAiChatCompletionQuery.cs │ │ └── SendAiFileMessageOperation.cs │ ├── SystemPrompts.cs │ └── UpdateConversationName │ │ ├── Contracts │ │ └── UpdateAiConversationNameRequestDto.cs │ │ └── UpdateAiConversationNameOperation.cs ├── Auth │ ├── AuthEndpoints.cs │ ├── CheckInvitation │ │ └── CheckUserInvitationCodeQuery.cs │ └── Contracts │ │ ├── ConfirmEmailRequestDto.cs │ │ ├── ForgotPasswordRequestDto.cs │ │ ├── ResendConfirmationLinkRequestDto.cs │ │ ├── ResetPasswordRequestDto.cs │ │ ├── SignInUser2FaRequestDto.cs │ │ ├── SignInUserRecoveryCodeRequestDto.cs │ │ ├── SignInUserRequestDto.cs │ │ └── SignUpUserRequestDto.cs ├── BoxExternalAccess │ ├── Authorization │ │ ├── BoxAccess.cs │ │ ├── BoxAccessDetailsHttpContextExtensions.cs │ │ ├── ValidateAccessCodeAttribute.cs │ │ └── ValidateExternalBoxAttribute.cs │ ├── BoxExternalAccessEndpoints.cs │ ├── BoxLinkAccessCodesEndpoints.cs │ ├── Contracts │ │ ├── BoxBulkDeleteRequestDto.cs │ │ ├── CompleteBoxFilePartUploadRequestDto.cs │ │ ├── CompleteBoxFileUploadResponseDto.cs │ │ ├── GetBoxDetailsAndContentResponseDto.cs │ │ ├── GetBoxFileDownloadLinkResponseDto.cs │ │ ├── GetBoxHtmlResponseDto.cs │ │ ├── InitiateBoxFilePartUploadResponseDto.cs │ │ ├── MoveBoxItemsToFolderRequestDto.cs │ │ ├── UpdateBoxFileNameRequestDto.cs │ │ ├── UpdateBoxFileNameRequestValidator.cs │ │ └── UpdateBoxFolderNameRequestDto.cs │ ├── Handler │ │ ├── BoxExternalAccessHandler.cs │ │ ├── GetContent │ │ │ └── GetBoxContentHandler.cs │ │ └── GetHtml │ │ │ └── GetBoxHtmlQuery.cs │ ├── Invitations │ │ ├── Accept │ │ │ └── AcceptBoxInvitationQuery.cs │ │ └── Reject │ │ │ └── RejectBoxInvitationQuery.cs │ └── LeaveBox │ │ └── LeaveBoxMembershipQuery.cs ├── BoxLinks │ ├── BoxLinksEndpoints.cs │ ├── Cache │ │ ├── BoxLinkCache.cs │ │ └── BoxLinkContext.cs │ ├── Delete │ │ └── DeleteBoxLinkQuery.cs │ ├── Id │ │ └── BoxLinkExtId.cs │ ├── RegenerateAccessCode │ │ ├── Contracts │ │ │ └── RegenerateBoxLinkAccessCodeResponseDto.cs │ │ └── RegenerateBoxLinkAccessCodeQuery.cs │ ├── UpdateIsEnabled │ │ ├── Contracts │ │ │ └── UpdateBoxLinkIsEnabledRequestDto.cs │ │ └── UpdateBoxLinkIsEnabledQuery.cs │ ├── UpdateName │ │ ├── Contracts │ │ │ └── UpdateBoxLinkNameRequestDto.cs │ │ └── UpdateBoxLinkNameQuery.cs │ ├── UpdatePermissions │ │ ├── Contracts │ │ │ └── UpdateBoxLinkPermissionsRequestDto.cs │ │ └── UpdateBoxLinkPermissionsQuery.cs │ ├── UpdateWidgetOrigins │ │ ├── Contracts │ │ │ └── UpdateBoxLinkWidgetOriginsRequestDto.cs │ │ └── UpdateBoxLinkNameQuery.cs │ └── Validation │ │ ├── BoxLinkDetailsHttpContextExtensions.cs │ │ └── ValidateBoxLinkAttribute.cs ├── Boxes │ ├── BoxesEndpoints.cs │ ├── Cache │ │ ├── BoxCache.cs │ │ ├── BoxContext.cs │ │ ├── BoxMembershipCache.cs │ │ └── BoxMembershipContext.cs │ ├── Create │ │ ├── Contracts │ │ │ ├── CreateBoxRequestDto.cs │ │ │ └── CreateBoxResponseDto.cs │ │ └── CreateBoxQuery.cs │ ├── CreateLink │ │ ├── Contracts │ │ │ ├── CreateBoxLinkRequestDto.cs │ │ │ └── CreateBoxLinkResponseDto.cs │ │ └── CreateBoxLinkQuery.cs │ ├── Delete │ │ ├── QueueJob │ │ │ ├── BatchDeleteBoxesWithDependenciesQuery.cs │ │ │ ├── DeleteBoxesQueueJobDefinition.cs │ │ │ ├── DeleteBoxesQueueJobExecutor.cs │ │ │ └── DeleteBoxesQueueJobType.cs │ │ └── ScheduleBoxesDeleteQuery.cs │ ├── Get │ │ ├── Contracts │ │ │ └── GetBoxResponseDto.cs │ │ └── GetBoxQuery.cs │ ├── Id │ │ └── BoxExtId.cs │ ├── List │ │ ├── Contracts │ │ │ └── GetBoxesResponseDto.cs │ │ └── GetBoxesListQuery.cs │ ├── Members │ │ ├── CreateInvitation │ │ │ ├── Contracts │ │ │ │ ├── CreateBoxInvitationRequestDto.cs │ │ │ │ └── CreateBoxInvitationResponseDto.cs │ │ │ ├── CreateBoxMemberInvitationOperation.cs │ │ │ └── CreateBoxMemberInvitationQuery.cs │ │ ├── Revoke │ │ │ └── RevokeBoxMemberQuery.cs │ │ └── UpdatePermissions │ │ │ ├── Contracts │ │ │ └── UpdateBoxMemberPermissionsRequestDto.cs │ │ │ └── UpdateBoxMemberPermissionsQuery.cs │ ├── Permissions │ │ └── BoxPermissions.cs │ ├── UpdateFolder │ │ ├── Contracts │ │ │ └── UpdateBoxFolderRequestDto.cs │ │ └── UpdateBoxFolderQuery.cs │ ├── UpdateFooter │ │ ├── Contracts │ │ │ └── UpdateBoxFooterRequestDto.cs │ │ └── UpdateBoxFooterQuery.cs │ ├── UpdateFooterIsEnabled │ │ ├── Contracts │ │ │ └── UpdateBoxFooterIsEnabledRequestDto.cs │ │ └── UpdateBoxFooterIsEnabledQuery.cs │ ├── UpdateHeader │ │ ├── Contracts │ │ │ └── UpdateBoxFooterRequestDto.cs │ │ └── UpdateBoxHeaderQuery.cs │ ├── UpdateHeaderIsEnabled │ │ ├── Contracts │ │ │ └── UpdateBoxHeaderIsEnabledRequestDto.cs │ │ └── UpdateBoxHeaderIsEnabledQuery.cs │ ├── UpdateIsEnabled │ │ ├── Contracts │ │ │ └── UpdateBoxIsEnabledRequestDto.cs │ │ └── UpdateBoxIsEnabledQuery.cs │ ├── UpdateName │ │ ├── Contracts │ │ │ └── UpdateBoxNameRequestDto.cs │ │ └── UpdateBoxNameQuery.cs │ └── Validation │ │ ├── BoxHttpContextExtensions.cs │ │ └── ValidateBoxAttribute.cs ├── BulkDelete │ ├── BulkDeleteQuery.cs │ └── Contracts │ │ └── BulkDeleteRequestDto.cs ├── BulkDownload │ ├── BulkDownloadDetailsQuery.cs │ └── BulkDownloadEndpoints.cs ├── Core │ ├── Angular │ │ ├── AngularExtensions.cs │ │ └── AngularRoutingMiddleware.cs │ ├── Authorization │ │ ├── AppOwners.cs │ │ ├── AppOwnersStartupExtensions.cs │ │ ├── AuthorizationStartupExtensions.cs │ │ ├── BoxLinkTokenAuthenticationHandler.cs │ │ ├── Claims.cs │ │ ├── Permissions.cs │ │ ├── RequireAdminClaimAttribute.cs │ │ ├── RequireAdminClaimFilter.cs │ │ ├── RequireAdminPermissionAttribute.cs │ │ ├── RequireAppOwnerAttribute.cs │ │ ├── RequireAppOwnerFilter.cs │ │ ├── RequireClaimAttribute.cs │ │ ├── RequireClaimFilter.cs │ │ ├── RequirePermissionAttribute.cs │ │ ├── Roles.cs │ │ └── UserContextClaimsExtensions.cs │ ├── CORS │ │ ├── CorsStartupExtensions.cs │ │ └── DynamicCorsPolicyProvider.cs │ ├── Clock │ │ ├── Clock.cs │ │ └── IClock.cs │ ├── Configuration │ │ ├── AppConfig.cs │ │ └── IConfig.cs │ ├── CorrelationId │ │ ├── CorrelationIdMiddleware.cs │ │ └── HttpContextCorrelationIdExtensions.cs │ ├── DataProtection │ │ ├── PlikShareXmlDecryptor.cs │ │ ├── PlikShareXmlEncryptor.cs │ │ └── SQLiteDataProtectionRepository.cs │ ├── Database │ │ ├── AiDatabase │ │ │ ├── AiDbWriteQueue.cs │ │ │ ├── Migrations │ │ │ │ ├── 01_initial_ai_db_structure_migration.sql │ │ │ │ └── Migration_Ai_01_InitialDbSetup.cs │ │ │ └── PlikShareAiDb.cs │ │ ├── MainDatabase │ │ │ ├── DbWriteQueue.cs │ │ │ ├── Migrations │ │ │ │ ├── 01_initial_db_structure_migration.sql │ │ │ │ ├── 02_files_created_at_folders_created_at_and_creator.sql │ │ │ │ ├── 03_storage_encryption_introduced.sql │ │ │ │ ├── 04_file_upload_is_completed_introduced.sql │ │ │ │ ├── 05_file_artifacts_table_introduced.sql │ │ │ │ ├── 06_integrations_table_introduced.sql │ │ │ │ ├── 07_integrations_textract_jobs_table_introduced.sql │ │ │ │ ├── 08_copy_file_queue_table_introduced.sql │ │ │ │ ├── 09_files_parent_file_id_column_introduced.sql │ │ │ │ ├── 10_files_metadata_column_introduced.sql │ │ │ │ ├── 11_file_uploads_parent_file_id_and_metadata_columns_introduced.sql │ │ │ │ ├── 12_queue_sagas_table_introduced.sql │ │ │ │ ├── 13_files_and_folders_lookup_indices_introduced.sql │ │ │ │ ├── 14_workspace_id_added_to_integrations_table.sql │ │ │ │ ├── 16_sign_up_checkboxes_introduced.sql │ │ │ │ ├── 17_workspace_max_size_column_introduced.sql │ │ │ │ ├── 18_user_max_workspace_number_and_max_workspace_size_columns_introduced.sql │ │ │ │ ├── 19_max_workspace_team_members_columns_introduced.sql │ │ │ │ ├── 20_widget_origins_column_added_to_box_links_table.sql │ │ │ │ ├── Migration_01_InitialDbSetup.cs │ │ │ │ ├── Migration_02_FilesCreatedAtFoldersCreatedAtAndCreator.cs │ │ │ │ ├── Migration_03_StorageEncryptionIntoruced.cs │ │ │ │ ├── Migration_04_FileUploadIsCompletedIntroduced.cs │ │ │ │ ├── Migration_05_FileArtifactsIntroduced.cs │ │ │ │ ├── Migration_06_IntegrationsTableIntroduced.cs │ │ │ │ ├── Migration_07_IntegrationsTextractJobsTableIntroduced.cs │ │ │ │ ├── Migration_08_CopyFileQueueTableIntroduced.cs │ │ │ │ ├── Migration_09_FilesParentFileIdColumnIntroduced.cs │ │ │ │ ├── Migration_10_FilesMetadataColumnIntroduced.cs │ │ │ │ ├── Migration_11_FileUploadsParentFileIdAndMetadataColumnsIntroduced.cs │ │ │ │ ├── Migration_12_QueueSagasTableIntroduced.cs │ │ │ │ ├── Migration_13_FilesAndFoldersLookupIndicesIntroduced.cs │ │ │ │ ├── Migration_14_WorkspaceIdAddedToIntegrationsTable.cs │ │ │ │ ├── Migration_15_ReencryptDatabaseFromAesCcmToAesGcm.cs │ │ │ │ ├── Migration_16_SignUpCheckboxesIntroduced.cs │ │ │ │ ├── Migration_17_WorkspaceMaxSizeColumnIntroduced.cs │ │ │ │ ├── Migration_18_UserMaxWorkspaceNumberAndMaxWorkspaceSizeColumnsIntroduced.cs │ │ │ │ ├── Migration_19_MaxWorkspaceTeamMembersColumnsIntroduced.cs │ │ │ │ └── Migration_20_WidgetOriginsColumnAddedToBoxLinksTable.cs │ │ │ └── PlikShareDb.cs │ │ └── PlikShareDbType.cs │ ├── Emails │ │ ├── Alerts │ │ │ └── AlertsService.cs │ │ ├── Definitions │ │ │ ├── AlertEmailDefinition.cs │ │ │ ├── BoxMemberLeftEmailDefinition.cs │ │ │ ├── BoxMembershipInvitationAcceptedEmailDefinition.cs │ │ │ ├── BoxMembershipInvitationEmailDefinition.cs │ │ │ ├── BoxMembershipInvitationRejectedEmailDefinition.cs │ │ │ ├── BoxMembershipRevokedEmailDefinition.cs │ │ │ ├── ConfirmationEmailDefinition.cs │ │ │ ├── ResetPasswordEmailDefinition.cs │ │ │ ├── UserInvitationEmailDefinition.cs │ │ │ ├── WorkspaceMemberLeftEmailDefinition.cs │ │ │ ├── WorkspaceMembershipInvitationAcceptedEmailDefinition.cs │ │ │ ├── WorkspaceMembershipInvitationEmailDefinition.cs │ │ │ ├── WorkspaceMembershipInvitationRejectedEmailDefinition.cs │ │ │ └── WorkspaceMembershipRevokedEmailDefinition.cs │ │ ├── EmailProviderStartupExtensions.cs │ │ ├── EmailProviderStore.cs │ │ ├── EmailQueueJobDefinition.cs │ │ ├── EmailQueueJobExecutor.cs │ │ ├── EmailQueueJobType.cs │ │ ├── EmailTemplate.cs │ │ ├── Emails.cs │ │ ├── IEmailSender.cs │ │ └── Templates │ │ │ ├── AlertEmailTemplate.cs │ │ │ ├── GenericEmailTemplate.cs │ │ │ ├── alert-email.html │ │ │ └── generic-email.html │ ├── Encryption │ │ ├── Aes256GcmStreaming.cs │ │ ├── AesCcmMasterDataEncryption.cs │ │ ├── AesGcmMasterDataEncryption.cs │ │ ├── FileEncryptionMetadata.cs │ │ ├── IDerivedMasterDataEncryption.cs │ │ ├── IMasterDataEncryption.cs │ │ ├── MasterDataEncryptionBufferedFactory.cs │ │ ├── MasterDataEncryptionExtensions.cs │ │ ├── MasterEncryptionKey.cs │ │ ├── MasterEncryptionKeyProvider.cs │ │ └── MasterEncryptionStartupExtensions.cs │ ├── ExceptionHandlers │ │ └── OperationCancelledMiddleware.cs │ ├── ExternalIds │ │ ├── ExternalIdJsonConverter.cs │ │ ├── IExternalId.cs │ │ └── PlikShareJsonHybridCacheSerializerFactory.cs │ ├── IdentityProvider │ │ ├── ApplicationRole.cs │ │ ├── ApplicationUser.cs │ │ ├── PlikShareSecurityStampValidator.cs │ │ ├── RoleExtId.cs │ │ ├── SQLiteIdentityBuilderExtensions.cs │ │ ├── SQLiteIdentityRoleStore.cs │ │ └── SQLiteIdentityUserStore.cs │ ├── Logging │ │ └── LogContextProperty.cs │ ├── Protobuf │ │ └── ProtobufResponseFilter.cs │ ├── Queue │ │ ├── BulkQueueJobEntity.cs │ │ ├── DbOnlyQueueConsumer.cs │ │ ├── IQueue.cs │ │ ├── IQueueNormalJobExecutor.cs │ │ ├── LongRunningQueueConsumer.cs │ │ ├── NormalQueueConsumer.cs │ │ ├── Queue.cs │ │ ├── QueueBuilderExtensions.cs │ │ ├── QueueChannels.cs │ │ ├── QueueJob.cs │ │ ├── QueueJobCategory.cs │ │ ├── QueueJobInfoProvider.cs │ │ ├── QueueJobStatusDecisionEngine.cs │ │ ├── QueueProducer.cs │ │ ├── QueueStartupExtensions.cs │ │ └── QueueStatus.cs │ ├── SQLite │ │ ├── CommandExecutor.cs │ │ ├── DbReaderExtensions.cs │ │ ├── ISQLiteMigration.cs │ │ ├── LazySqLiteCommandsPool.cs │ │ ├── NonQueryCommandExecutor.cs │ │ ├── OneRowCommandExecutor.cs │ │ ├── SQLiteCommandExtensions.cs │ │ ├── SQLiteConnectionExtensions.cs │ │ ├── SQLiteExtendedErrorCode.cs │ │ ├── SQLiteInitialization.cs │ │ └── SQLiteStartupExtensions.cs │ ├── UserIdentity │ │ ├── BoxLinkSessionUserIdentity.cs │ │ ├── GenericUserIdentity.cs │ │ ├── IUserIdentity.cs │ │ ├── IntegrationUserIdentity.cs │ │ └── UserIdentity.cs │ ├── Utils │ │ ├── ContentDispositionHelper.cs │ │ ├── ContentTypeHelper.cs │ │ ├── DomainException.cs │ │ ├── EnumUtils.cs │ │ ├── EnumerableExtensions.cs │ │ ├── FileNames.cs │ │ ├── GuidBase62.cs │ │ ├── HttpError.cs │ │ ├── IOneTimeCode.cs │ │ ├── IdsRange.cs │ │ ├── Json.cs │ │ ├── ManifestResourceReader.cs │ │ ├── NullableByteArrayJsonConverter.cs │ │ ├── OneTimeCode.cs │ │ ├── PipeReaderExtensions.cs │ │ ├── PlikShareStreams.cs │ │ ├── RateLimiter.cs │ │ ├── SequenceReaderExtensions.cs │ │ ├── SizeInBytes.cs │ │ ├── TaskWithResourceFinalization.cs │ │ ├── TransferSpeed.cs │ │ ├── Try.cs │ │ ├── UnexpectedOperationResultException.cs │ │ └── UniqueFileNames.cs │ └── Volumes │ │ ├── Volumes.cs │ │ └── VolumesStartupExtensions.cs ├── Dashboard │ ├── Content │ │ ├── Contracts │ │ │ └── GetDashboardContentResponseDto.cs │ │ └── GetDashboardContentQuery.cs │ └── DashboardEndpoints.cs ├── EmailProviders │ ├── Activate │ │ └── ActivateEmailProviderQuery.cs │ ├── Confirm │ │ ├── ConfirmEmailProviderQuery.cs │ │ └── Contracts │ │ │ └── ConfirmEmailProviderRequestDto.cs │ ├── Create │ │ ├── CreateEmailProviderOperation.cs │ │ └── CreateEmailProviderQuery.cs │ ├── Deactivate │ │ └── DeactivateEmailProviderQuery.cs │ ├── Delete │ │ └── DeleteEmailProviderQuery.cs │ ├── EmailProvidersEndpoints.cs │ ├── EmailSender │ │ └── EmailSenderFactory.cs │ ├── Entities │ │ └── EmailProviderType.cs │ ├── ExternalProviders │ │ ├── AwsSes │ │ │ ├── AwsSesDetailsEntity.cs │ │ │ ├── AwsSesEmailSender.cs │ │ │ ├── AwsSesEmailSenderFactory.cs │ │ │ └── Create │ │ │ │ └── Contracts │ │ │ │ └── CreateAwsSesEmailProviderRequestDto.cs │ │ ├── Resend │ │ │ ├── Create │ │ │ │ └── CreateResendEmailProviderRequestDto.cs │ │ │ ├── ResendDetailsEntity.cs │ │ │ ├── ResendEmailSender.cs │ │ │ ├── ResendEmailSenderFactory.cs │ │ │ └── ResendRequestBody.cs │ │ └── Smtp │ │ │ ├── Create │ │ │ └── CreateSmtpEmailProviderRequestDto.cs │ │ │ ├── SmtpDetailsEntity.cs │ │ │ ├── SmtpEmailSender.cs │ │ │ └── SmtpEmailSenderFactory.cs │ ├── Id │ │ └── EmailProviderExtId.cs │ ├── List │ │ ├── Contracts │ │ │ └── GetEmailProvidersResponseDto.cs │ │ └── GetEmailProvidersQuery.cs │ ├── ResendConfirmationEmail │ │ ├── Contracts │ │ │ └── ResendEmailProviderConfirmationEmailRequestDto.cs │ │ ├── GetEmailProviderQuery.cs │ │ └── ResendConfirmationEmailOperation.cs │ ├── SendConfirmationEmail │ │ └── EmailProviderConfirmationEmail.cs │ └── UpdateName │ │ ├── Contracts │ │ └── UpdateEmailProviderNameRequestDto.cs │ │ └── UpdateEmailProviderNameQuery.cs ├── EntryPage │ ├── Contracts │ │ └── GetEntryPageSettingsResponseDto.cs │ └── EntryPageEndpoints.cs ├── Files │ ├── AiConversation │ │ └── FileAiConversationArtifactEntity.cs │ ├── Artifacts │ │ └── FileArtifactTypes.cs │ ├── BulkDelete │ │ └── QueueJob │ │ │ ├── BulkDeleteS3FileQueueJobDefinition.cs │ │ │ ├── BulkDeleteS3FileQueueJobExecutor.cs │ │ │ └── BulkDeleteS3FileQueueJobType.cs │ ├── BulkDownload │ │ ├── Contracts │ │ │ └── GetBulkDownloadLinkResponseDto.cs │ │ ├── GetBulkDownloadDetailsQuery.cs │ │ └── GetFileDownloadLinkOperation.cs │ ├── Delete │ │ ├── DeleteFilesSubQuery.cs │ │ └── QueueJob │ │ │ ├── DeleteS3FileQueueJobDefinition.cs │ │ │ ├── DeleteS3FileQueueJobExecutor.cs │ │ │ └── DeleteS3FileQueueJobType.cs │ ├── Download │ │ ├── Contracts │ │ │ └── GetFileDownloadLinkResponseDto.cs │ │ ├── GetFileDetailsQuery.cs │ │ └── GetFileDownloadLinkOperation.cs │ ├── FilesEndpoints.cs │ ├── Id │ │ ├── FileArtifactExtId.cs │ │ └── FileExtId.cs │ ├── Metadata │ │ └── FileMetadata.cs │ ├── PreSignedLinks │ │ ├── Contracts │ │ │ └── MultiFileDirectUploadResponseDto.cs │ │ ├── PreSignedFilesEndpoints.cs │ │ ├── PreSignedUrlsService.cs │ │ ├── RangeRequests │ │ │ ├── BytesRange.cs │ │ │ └── RangeRequestsHttpContextExtensions.cs │ │ └── Validation │ │ │ ├── GetFilePreSignedDownloadLinkDetailsQuery.cs │ │ │ ├── ValidateProtectedDownloadPayloadAttribute.cs │ │ │ ├── ValidateProtectedMultiFileDirectUploadPayloadFilter.cs │ │ │ ├── ValidateProtectedUploadPayloadAttribute.cs │ │ │ └── ValidateProtectedZipContentDownloadPayloadFilter.cs │ ├── Preview │ │ ├── Comment │ │ │ ├── CommentContentEntity.cs │ │ │ ├── CreateComment │ │ │ │ ├── Contracts │ │ │ │ │ └── CreateFileCommentRequestDto.cs │ │ │ │ └── CreateFileCommentQuery.cs │ │ │ ├── DeleteComment │ │ │ │ └── DeleteFileCommentQuery.cs │ │ │ └── EditComment │ │ │ │ ├── Contracts │ │ │ │ └── EditFileCommentRequestDto.cs │ │ │ │ └── UpdateFileCommentQuery.cs │ │ ├── GetDetails │ │ │ ├── Contracts │ │ │ │ └── GetFilePreviewDetailsResponseDto.cs │ │ │ └── GetFilePreviewDetailsQuery.cs │ │ ├── GetZipContentDownloadLink │ │ │ ├── Contracts │ │ │ │ └── GetZipContentDownloadLinkRequestDto.cs │ │ │ └── GetZipContentDownloadLinkOperation.cs │ │ ├── GetZipDetails │ │ │ ├── Contracts │ │ │ │ └── GetZipFileDetailsResponseDto.cs │ │ │ └── GetZipFileDetailsOperation.cs │ │ └── SaveNote │ │ │ ├── Contracts │ │ │ └── SaveFileNoteRequestDto.cs │ │ │ └── SaveFileNoteQuery.cs │ ├── Records │ │ ├── FilePartDetails.cs │ │ └── FileRecord.cs │ ├── Rename │ │ ├── Contracts │ │ │ ├── UpdateFileNameRequestDto.cs │ │ │ └── UpdateFileNameRequestValidator.cs │ │ └── UpdateFileNameQuery.cs │ ├── UpdateSize │ │ └── UpdateFileSizeQuery.cs │ └── UploadAttachment │ │ ├── InsertFileAttachmentQuery.cs │ │ └── MarkFileAsUploadedQuery.cs ├── Folders │ ├── Create │ │ ├── Contracts │ │ │ ├── BulkCreateFolderRequestDto.cs │ │ │ ├── CreateFolderRequestDto.cs │ │ │ ├── CreateFolderRequestValidator.cs │ │ │ └── CreateFolderResponseDto.cs │ │ ├── CreateFolderQuery.cs │ │ └── GetOrCreateFolderQuery.cs │ ├── Delete │ │ └── QueueJob │ │ │ ├── BulkDeleteFoldersWithDependenciesQuery.cs │ │ │ ├── DeleteFoldersQueueJobDefinition.cs │ │ │ ├── DeleteFoldersQueueJobExecutor.cs │ │ │ └── DeleteFoldersQueueJobType.cs │ ├── FoldersEndpoints.cs │ ├── Id │ │ └── FolderExtId.cs │ ├── List │ │ ├── Contracts │ │ │ ├── GetFolderContentResponseDto.cs │ │ │ └── GetTopFolderContentResponseDto.cs │ │ ├── GetFolderContentQuery.cs │ │ └── GetTopFolderContentQuery.cs │ ├── MoveToFolder │ │ ├── Contracts │ │ │ └── MoveItemsToFolderRequestDto.cs │ │ └── MoveItemsToFolderQuery.cs │ └── Rename │ │ ├── Contracts │ │ └── UpdateFolderNameRequestDto.cs │ │ └── UpdateFolderNameQuery.cs ├── GeneralSettings │ ├── AppSettings.cs │ ├── AppSettingsStartupExtensions.cs │ ├── Contracts │ │ ├── GeneralSettingsRequests.cs │ │ └── GetApplicationSettingsResponse.cs │ ├── GeneralSettingsEndpoints.cs │ ├── LegalFiles │ │ ├── DeleteLegalFile │ │ │ └── DeleteLegalFileOperation.cs │ │ ├── LegalFileUtils.cs │ │ ├── LegalFilesEndpoints.cs │ │ └── UploadLegalFile │ │ │ └── UploadLegalFileOperation.cs │ └── SignUpCheckboxes │ │ ├── CreateOrUpdate │ │ ├── Contracts │ │ │ └── CreateOrUpdateSignUpCheckboxRequestDto.cs │ │ └── CreateOrUpdateSignUpCheckboxQuery.cs │ │ └── Delete │ │ └── DeleteSignUpCheckboxQuery.cs ├── HealthCheck │ ├── HealtCheckEndpoints.cs │ └── HealthCheckUtils.cs ├── Integrations │ ├── Activate │ │ ├── ActivateIntegrationOperation.cs │ │ └── ActivateIntegrationQuery.cs │ ├── Aws │ │ └── Textract │ │ │ ├── AwsTextractClient.cs │ │ │ ├── AwsTextractDetails.cs │ │ │ ├── Id │ │ │ └── TextractJobExtId.cs │ │ │ ├── Jobs │ │ │ ├── CheckStatus │ │ │ │ ├── CheckTextractJobsStatusQuery.cs │ │ │ │ └── Contracts │ │ │ │ │ └── CheckTextractJobsStatusRequestDto.cs │ │ │ ├── CheckTextractAnalysisStatus │ │ │ │ ├── CheckTextractAnalysisStatusQueueJobDefinition.cs │ │ │ │ ├── CheckTextractAnalysisStatusQueueJobExecutor.cs │ │ │ │ └── CheckTextractAnalysisStatusQueueJobType.cs │ │ │ ├── Delete │ │ │ │ └── DeleteTextractJobsSubQuery.cs │ │ │ ├── DownloadTextractAnalysis │ │ │ │ ├── DownloadTextractAnalysisQueueJobDefinition.cs │ │ │ │ ├── DownloadTextractAnalysisQueueJobExecutor.cs │ │ │ │ ├── DownloadTextractAnalysisQueueJobType.cs │ │ │ │ └── TextractMarkdownConverter.cs │ │ │ ├── InitiateTextractAnalysis │ │ │ │ ├── InitiateTextractAnalysisQueueJobDefinition.cs │ │ │ │ ├── InitiateTextractAnalysisQueueJobExecutor.cs │ │ │ │ └── InitiateTextractAnalysisQueueJobType.cs │ │ │ ├── StartJob │ │ │ │ ├── Contracts │ │ │ │ │ ├── StartTextractJobRequestDto.cs │ │ │ │ │ └── StartTextractJobResponseDto.cs │ │ │ │ └── StartTextractJobOperation.cs │ │ │ ├── TextractJobDefinitionEntity.cs │ │ │ ├── TextractJobStatus.cs │ │ │ ├── TextractResultTemporaryStore.cs │ │ │ └── UpdateJobTextractFileAndStatus │ │ │ │ └── UpdateTextractJobFileAndStatusOnCompletedFileCopyHandler.cs │ │ │ ├── Register │ │ │ └── RegisterTextractClientOperation.cs │ │ │ ├── TestConfiguration │ │ │ ├── Contracts │ │ │ │ ├── TestTextractConfigurationRequestDto.cs │ │ │ │ └── TestTextractConfigurationResponseDto.cs │ │ │ ├── TestTextractConfigurationOperation.cs │ │ │ ├── TextractTestImage.cs │ │ │ └── plikshare_is_the_best.png │ │ │ ├── TextractClient.cs │ │ │ ├── TextractClientStore.cs │ │ │ ├── TextractEndpoints.cs │ │ │ ├── TextractFeature.cs │ │ │ ├── TextractResultFileMetadata.cs │ │ │ └── TextractStartupExtensions.cs │ ├── Create │ │ ├── Contracts │ │ │ └── CreateIntegrationRequestDto.cs │ │ ├── CreateIntegrationOperation.cs │ │ └── CreateIntegrationWithWorkspaceQuery.cs │ ├── Deactivate │ │ └── DeactivateIntegrationQuery.cs │ ├── Delete │ │ └── DeleteIntegrationQuery.cs │ ├── IIntegrationWithWorkspace.cs │ ├── Id │ │ └── IntegrationExtId.cs │ ├── IntegrationType.cs │ ├── IntegrationsEndpoints.cs │ ├── List │ │ ├── Contracts │ │ │ └── GetIntegrationsResponseDto.cs │ │ └── GetIntegrationsQuery.cs │ ├── OpenAi │ │ └── ChatGpt │ │ │ ├── ChatGptClient.cs │ │ │ ├── ChatGptClientStore.cs │ │ │ ├── ChatGptDetails.cs │ │ │ ├── ChatGptEndpoints.cs │ │ │ ├── ChatGptModel.cs │ │ │ ├── ChatGptStartupExtensions.cs │ │ │ ├── Register │ │ │ └── RegisterChatGptClientOperation.cs │ │ │ └── TestConfiguration │ │ │ ├── Contracts │ │ │ └── TestChatGptConfigurationRequestDto.cs │ │ │ └── TestChatGptConfigurationOperation.cs │ └── UpdateName │ │ ├── Contracts │ │ └── UpdateIntegrationNameRequestDto.cs │ │ └── UpdateIntegrationNameQuery.cs ├── Locks │ ├── CheckFileLocks │ │ ├── CheckFileLocksQuery.cs │ │ └── Contracts │ │ │ ├── CheckFileLocksRequestDto.cs │ │ │ └── CheckFileLocksResponseDto.cs │ └── LockStatusEndpoints.cs ├── PlikShare.csproj ├── Program.cs ├── Properties │ └── launchSettings.json ├── Search │ ├── Get │ │ ├── Contracts │ │ │ ├── SearchRequestDto.cs │ │ │ └── SearchResponseDto.cs │ │ └── GetSearchQuery.cs │ └── SearchEndpoints.cs ├── Startup.cs ├── Storages │ ├── Create │ │ └── CreateStorageQuery.cs │ ├── Delete │ │ └── DeleteStorageQuery.cs │ ├── Encryption │ │ ├── StorageEncryptionKey.cs │ │ ├── StorageEncryptionKeyProvider.cs │ │ ├── StorageEncryptionType.cs │ │ └── StorageManagedEncryptionDetails.cs │ ├── Entities │ │ └── StorageType.cs │ ├── Exceptions │ │ └── FileNotFoundInStorageException.cs │ ├── FileCopying │ │ ├── BulkInitiateCopyFiles │ │ │ ├── BulkInitiateCopyFilesQueueJobDefinition.cs │ │ │ ├── BulkInitiateCopyFilesQueueJobExecutor.cs │ │ │ └── BulkInitiateCopyFilesQueueJobType.cs │ │ ├── CopyFile │ │ │ ├── CopyFileQueueJobDefinition.cs │ │ │ ├── CopyFileQueueJobExecutor.cs │ │ │ ├── CopyFileQueueJobType.cs │ │ │ └── FinalizeCopyFileUploadQuery.cs │ │ ├── CopyFileQueueJob.cs │ │ ├── CopyFileQueueOnCompletedActionDefinition.cs │ │ ├── CopyFileQueueStartupExtensions.cs │ │ ├── CopyFileQueueStatus.cs │ │ ├── Delete │ │ │ └── DeleteCopyFileQueueJobsSubQuery.cs │ │ └── OnCompletedActionHandler │ │ │ └── ICopyFileQueueCompletedActionHandler.cs │ ├── FileEncryption.cs │ ├── FileReading │ │ ├── FileReader.cs │ │ └── FileWriter.cs │ ├── HardDrive │ │ ├── BulkDownload │ │ │ └── HardDriveBulkDownloadOperation.cs │ │ ├── Create │ │ │ ├── Contracts │ │ │ │ └── CreateHardDriveStorageRequestDto.cs │ │ │ └── CreateHardDriveStorageOperation.cs │ │ ├── Download │ │ │ ├── FileRangeProcessing.cs │ │ │ └── HardDriveDownloadOperation.cs │ │ ├── GetVolumes │ │ │ ├── Contracts │ │ │ │ └── GetHardDriveVolumesResponseDto.cs │ │ │ └── GetHardDriveVolumesOperation.cs │ │ ├── HardDriveDetailsEntity.cs │ │ ├── StorageClient │ │ │ └── HardDriveStorageClient.cs │ │ └── Upload │ │ │ └── HardDriveUploadOperation.cs │ ├── IStorageClient.cs │ ├── IStorageClientExtensions.cs │ ├── Id │ │ └── StorageExtId.cs │ ├── List │ │ ├── Contracts │ │ │ └── GetStoragesResponseDto.cs │ │ └── GetStoragesQuery.cs │ ├── S3 │ │ ├── AwsS3 │ │ │ ├── AwsS3DetailsEntity.cs │ │ │ ├── Create │ │ │ │ ├── Contracts │ │ │ │ │ └── CreateAwsS3StorageRequestDto.cs │ │ │ │ └── CreateAwsS3StorageOperation.cs │ │ │ └── UpdateDetails │ │ │ │ ├── Contracts │ │ │ │ └── UpdateAwsS3StorageDetailsRequestDto.cs │ │ │ │ └── UpdateAwsS3StorageDetailsOperation.cs │ │ ├── BulkDownload │ │ │ └── S3BulkDownloadOperation.cs │ │ ├── CloudflareR2 │ │ │ ├── CloudflareR2DetailsEntity.cs │ │ │ ├── Create │ │ │ │ ├── Contracts │ │ │ │ │ └── CreateCloudflareR2StorageRequestDto.cs │ │ │ │ └── CreateCloudflareR2StorageOperation.cs │ │ │ └── UpdateDetails │ │ │ │ ├── Contracts │ │ │ │ └── UpdateCloudflareR2StorageDetailsRequestDto.cs │ │ │ │ └── UpdateCloudflareR2StorageDetailsOperation.cs │ │ ├── DigitalOcean │ │ │ ├── Create │ │ │ │ ├── Contracts │ │ │ │ │ └── CreateDigitalOceanSpacesStorageRequestDto.cs │ │ │ │ └── CreateDigitalOceanStorageOperation.cs │ │ │ ├── DigitalOceanSpacesDetailsEntity.cs │ │ │ └── UpdateDetails │ │ │ │ ├── Contracts │ │ │ │ └── UpdateDigitalOceanSpacesStorageDetailsRequestDto.cs │ │ │ │ └── UpdateDigitalOceanSpacesStorageDetailsOperation.cs │ │ ├── Download │ │ │ └── S3DownloadOperation.cs │ │ ├── S3Client.cs │ │ ├── S3StorageClient.cs │ │ └── Upload │ │ │ └── S3UploadOperation.cs │ ├── S3FileKey.cs │ ├── StorageClientStore.cs │ ├── StorageStartupExtensions.cs │ ├── StorageUploadDetails.cs │ ├── StoragesEndpoints.cs │ ├── UpdateDetails │ │ └── UpdateStorageDetailsQuery.cs │ ├── UpdateName │ │ ├── Contracts │ │ │ └── UpdateStorageNameRequestDto.cs │ │ └── UpdateStorageNameQuery.cs │ └── Zip │ │ ├── SteppingBuffer.cs │ │ ├── Zip64EocdRecord.cs │ │ ├── Zip64ExtraField.cs │ │ ├── Zip64LocatorRecord.cs │ │ ├── ZipCdfhRecord.cs │ │ ├── ZipDecoder.cs │ │ ├── ZipEntryReader.cs │ │ ├── ZipEocdExtensions.cs │ │ ├── ZipEocdRecord.cs │ │ ├── ZipFileDto.cs │ │ ├── ZipFinalEocdRecord.cs │ │ └── ZipLfhRecord.cs ├── Uploads │ ├── Abort │ │ └── QueueJob │ │ │ ├── AbortS3UploadQueueJobDefinition.cs │ │ │ ├── AbortS3UploadQueueJobExecutor.cs │ │ │ └── AbortS3UploadQueueJobType.cs │ ├── Algorithm │ │ └── UploadAlgorithm.cs │ ├── Cache │ │ └── FileUploadCache.cs │ ├── Chunking │ │ └── FileParts.cs │ ├── CompleteFileUpload │ │ ├── BulkConvertDirectFileUploadsToFilesQuery.cs │ │ ├── Contracts │ │ │ └── CompleteFileUploadResponseDto.cs │ │ ├── ConvertFileUploadToFileOperation.cs │ │ ├── ConvertFileUploadToFileQuery.cs │ │ └── QueueJob │ │ │ ├── CompleteFileUploadQueueJobDefinition.cs │ │ │ ├── CompleteS3UploadQueueJobExecutor.cs │ │ │ ├── CompleteS3UploadQueueJobType.cs │ │ │ └── MarkFileAsUploadedAndDeleteUploadQuery.cs │ ├── Count │ │ ├── Contracts │ │ │ └── GetUploadsCountResponse.cs │ │ └── GetUploadsCountQuery.cs │ ├── Delete │ │ └── DeleteFileUploads.cs │ ├── FilePartUpload │ │ ├── Complete │ │ │ ├── CompleteFilePartUploadQuery.cs │ │ │ ├── Contracts │ │ │ │ └── CompleteFilePartUploadRequestDto.cs │ │ │ └── InsertFileUploadPartQuery.cs │ │ └── Initiate │ │ │ ├── Contracts │ │ │ └── InitiateFilePartUploadResponseDto.cs │ │ │ └── InitiateFilePartUploadOperation.cs │ ├── GetDetails │ │ ├── Contracts │ │ │ └── GetFileUploadDetailsResponseDto.cs │ │ └── GetFileUploadDetailsQuery.cs │ ├── Id │ │ ├── BulkFileUploadExtId.cs │ │ └── FileUploadExtId.cs │ ├── Initiate │ │ ├── BulkInitiateCopyFileUploadOperation.cs │ │ ├── BulkInitiateFileUploadOperation.cs │ │ ├── BulkInsertFileUploadQuery.cs │ │ └── Contracts │ │ │ └── BulkInitiateFileUploadRequestDto.cs │ ├── List │ │ ├── Contracts │ │ │ └── GetUploadsListResponseDto.cs │ │ └── GetUploadsListQuery.cs │ └── UploadsEndpoints.cs ├── Users │ ├── Cache │ │ ├── UserCache.cs │ │ ├── UserContext.cs │ │ └── UserService.cs │ ├── Delete │ │ └── DeleteUserQuery.cs │ ├── Entities │ │ └── Email.cs │ ├── GetDetails │ │ ├── Contracts │ │ │ └── GetUserDetailsResponseDto.cs │ │ └── GetUserDetailsQuery.cs │ ├── GetOrCreate │ │ └── GetOrCreateUserInvitationQuery.cs │ ├── Id │ │ └── UserExtId.cs │ ├── Invite │ │ ├── Contracts │ │ │ └── InviteUsersRequestDto.cs │ │ ├── IOneTimeInvitationCode.cs │ │ └── InviteUsersQuery.cs │ ├── List │ │ ├── Contracts │ │ │ └── GetUsersResponseDto.cs │ │ └── GetUsersQuery.cs │ ├── Middleware │ │ ├── UserHttpContextExtensions.cs │ │ └── UserLoggingMiddleware.cs │ ├── PermissionsAndRoles │ │ └── UserPermissionsAndRolesDto.cs │ ├── Sql │ │ └── UserSql.cs │ ├── UpdateDefaultMaxWorkspaceSizeInBytes │ │ ├── Contracts │ │ │ └── UpdateUserDefaultMaxWorkspaceSizeInBytesRequestDto.cs │ │ └── UpdateUserDefaultMaxWorkspaceSizeInBytesQuery.cs │ ├── UpdateDefaultMaxWorkspaceTeamMembers │ │ ├── Contracts │ │ │ └── UpdateUserDefaultMaxWorkspaceSizeInBytesRequestDto.cs │ │ └── UpdateUserDefaultMaxWorkspaceTeamMembersQuery.cs │ ├── UpdateMaxWorkspaceNumber │ │ ├── Contracts │ │ │ └── UpdateUserMaxWorkspaceNumberRequestDto.cs │ │ └── UpdateUserMaxWorkspaceNumberQuery.cs │ ├── UpdatePermissionsAndRoles │ │ └── UpdateUserPermissionsAndRoleQuery.cs │ ├── UserIdentityResolver │ │ └── UserIdentityResolver.cs │ ├── UsersEndpoints.cs │ └── Validation │ │ └── ValidateUserUpdateFilter.cs ├── Widgets │ └── AccountEndpoints.cs ├── Workspaces │ ├── Cache │ │ ├── WorkspaceCache.cs │ │ ├── WorkspaceContext.cs │ │ ├── WorkspaceMembershipCache.cs │ │ └── WorkspaceMembershipContext.cs │ ├── ChangeOwner │ │ ├── ChangeWorkspaceOwnerQuery.cs │ │ └── Contracts │ │ │ └── ChangeWorkspaceOwnerRequestDto.cs │ ├── CheckBucketStatus │ │ └── Contracts │ │ │ └── CheckWorkspaceBucketStatusRequestDto.cs │ ├── CountSelectedItems │ │ ├── Contracts │ │ │ └── CountSelectedItemsRequestDto.cs │ │ └── CountSelectedItemsQuery.cs │ ├── Create │ │ ├── Contracts │ │ │ ├── CreateWorkspaceRequestDto.cs │ │ │ └── CreateWorkspaceResponseDto.cs │ │ └── CreateWorkspaceQuery.cs │ ├── CreateBucket │ │ ├── CreateWorkspaceBucketJobExecutor.cs │ │ ├── CreateWorkspaceBucketQueueJobDefinition.cs │ │ ├── CreateWorkspaceBucketQueueJobType.cs │ │ └── UpdateWorkspaceIsBucketCreatedQuery.cs │ ├── Delete │ │ ├── QueueJob │ │ │ ├── DeleteWorkspaceQueueJobDefinition.cs │ │ │ ├── DeleteWorkspaceQueueJobExecutor.cs │ │ │ ├── DeleteWorkspaceQueueJobType.cs │ │ │ └── DeleteWorkspaceWithDependenciesQuery.cs │ │ └── ScheduleWorkspaceDeleteQuery.cs │ ├── DeleteBucket │ │ ├── DeleteBucketJobExecutor.cs │ │ ├── DeleteBucketQueueJobDefinition.cs │ │ └── DeleteBucketQueueJobType.cs │ ├── Get │ │ └── Contracts │ │ │ └── GetWorkspaceDetailsResponseDto.cs │ ├── GetSize │ │ └── GetWorkspaceSizeQuery.cs │ ├── Id │ │ └── WorkspaceExtId.cs │ ├── Members │ │ ├── AcceptInvitation │ │ │ ├── AcceptWorkspaceInvitationQuery.cs │ │ │ └── Contracts │ │ │ │ └── AcceptWorkspaceInvitationResponseDto.cs │ │ ├── CountAll │ │ │ └── CountWorkspaceTotalTeamMembersQuery.cs │ │ ├── CreateInvitation │ │ │ ├── Contracts │ │ │ │ ├── CreateWorkspaceMemberInvitationRequestDto.cs │ │ │ │ └── CreateWorkspaceMemberInvitationResponseDto.cs │ │ │ ├── CreateWorkspaceMemberInvitationOperation.cs │ │ │ └── CreateWorkspaceMemberInvitationQuery.cs │ │ ├── LeaveWorkspace │ │ │ └── LeaveSharedWorkspaceQuery.cs │ │ ├── List │ │ │ ├── Contracts │ │ │ │ └── GetWorkspaceMembersListResponseDto.cs │ │ │ └── GetWorkspaceMembersListQuery.cs │ │ ├── RejectInvitation │ │ │ └── RejectWorkspaceInvitationQuery.cs │ │ ├── Revoke │ │ │ └── RevokeWorkspaceMemberQuery.cs │ │ └── UpdatePermissions │ │ │ ├── Contracts │ │ │ └── UpdateWorkspaceMemberPermissionsRequestDto.cs │ │ │ └── UpdateWorkspaceMemberPermissionsQuery.cs │ ├── Permissions │ │ └── WorkspacePermissions.cs │ ├── SearchFilesTree │ │ ├── Contracts │ │ │ └── SearchFilesTreeRequestDto.cs │ │ └── SearchFilesTreeQuery.cs │ ├── UpdateCurrentSizeInBytes │ │ └── QueueJob │ │ │ ├── UpdateWorkspaceCurrentSizeInBytesQuery.cs │ │ │ ├── UpdateWorkspaceCurrentSizeInBytesQueueJobDefinition.cs │ │ │ ├── UpdateWorkspaceCurrentSizeInBytesQueueJobExecutor.cs │ │ │ └── UpdateWorkspaceCurrentSizeInBytesQueueJobType.cs │ ├── UpdateMaxSize │ │ ├── Contracts │ │ │ └── UpdateWorkspaceMaxSizeDto.cs │ │ └── UpdateWorkspaceMaxSizeQuery.cs │ ├── UpdateMaxTeamMembers │ │ ├── Contracts │ │ │ └── UpdateWorkspaceMaxSizeDto.cs │ │ └── UpdateWorkspaceMaxSizeQuery.cs │ ├── UpdateName │ │ ├── Contracts │ │ │ └── UpdateWorkspaceNameRequestDto.cs │ │ └── UpdateWorkspaceNameQuery.cs │ ├── Validation │ │ ├── ValidateWorkspaceFilter.cs │ │ └── WorkspaceMembershipHttpContextExtensions.cs │ ├── WorkspacesAdminEndpoints.cs │ └── WorkspacesEndpoints.cs ├── appsettings.Development.json ├── appsettings.Production.json └── appsettings.json ├── README.md ├── TRADEMARK.md ├── assets ├── dashboard_printscreen.png └── how_to_pronounce.png ├── build-docker-image.ps1 ├── deployment └── plikshare-install.sh └── publish-docker-image.ps1 /.dockerignore: -------------------------------------------------------------------------------- 1 | **/.dockerignore 2 | **/.env 3 | **/.git 4 | **/.gitignore 5 | **/.project 6 | **/.settings 7 | **/.toolstarget 8 | **/.vs 9 | **/.vscode 10 | **/.idea 11 | **/*.*proj.user 12 | **/*.dbmdl 13 | **/*.jfm 14 | **/azds.yaml 15 | **/bin 16 | **/charts 17 | **/docker-compose* 18 | **/Dockerfile* 19 | **/node_modules 20 | **/npm-debug.log 21 | **/obj 22 | **/secrets.dev.yaml 23 | **/values.dev.yaml 24 | **/*.db 25 | **/*.db-shm 26 | **/*.db-wal 27 | LICENSE 28 | README.md -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /PlikShare/wwwroot 2 | PlikShare.sln.DotSettings.user 3 | PlikShare.IntegrationTests/bin/ 4 | PlikShare.IntegrationTests/obj/ 5 | /.vs/PlikShare/config 6 | /.vs/PlikShare/DesignTimeBuild 7 | /.vs/PlikShare/FileContentIndex 8 | /.vs/PlikShare/v17 9 | /.vs/ProjectEvaluation 10 | -------------------------------------------------------------------------------- /Frontend/.editorconfig: -------------------------------------------------------------------------------- 1 | # Editor configuration, see https://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | indent_style = space 7 | indent_size = 2 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | 11 | [*.ts] 12 | quote_type = single 13 | 14 | [*.md] 15 | max_line_length = off 16 | trim_trailing_whitespace = false 17 | -------------------------------------------------------------------------------- /Frontend/.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=827846 3 | "recommendations": ["angular.ng-template"] 4 | } 5 | -------------------------------------------------------------------------------- /Frontend/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 3 | "version": "0.2.0", 4 | "configurations": [ 5 | { 6 | "name": "ng serve", 7 | "type": "chrome", 8 | "request": "launch", 9 | "preLaunchTask": "npm: start", 10 | "url": "http://localhost:4200/" 11 | }, 12 | { 13 | "name": "ng test", 14 | "type": "chrome", 15 | "request": "launch", 16 | "preLaunchTask": "npm: test", 17 | "url": "http://localhost:9876/debug.html" 18 | } 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /Frontend/src/app/account/change-password/change-password.component.scss: -------------------------------------------------------------------------------- 1 | @forward "./../../../styles/questionaire.scss"; 2 | @forward "./../../../styles/mobile-display.scss"; 3 | 4 | .email-picker { 5 | padding: 2rem; 6 | } 7 | 8 | .example-full-width { 9 | width: 100%; 10 | } 11 | 12 | .mat-mdc-form-field-error-wrapper { 13 | padding: 0 !important; 14 | } -------------------------------------------------------------------------------- /Frontend/src/app/account/email-settings/aws/create-aws-ses/create-aws-ses.component.scss: -------------------------------------------------------------------------------- 1 | @forward "./../../../../../styles/questionaire.scss"; 2 | @forward "./../../../../../styles/mobile-display.scss"; 3 | 4 | .email-picker { 5 | padding: 2rem; 6 | } 7 | 8 | .example-full-width { 9 | width: 100%; 10 | } 11 | 12 | .mat-mdc-form-field-error-wrapper { 13 | padding: 0 !important; 14 | } -------------------------------------------------------------------------------- /Frontend/src/app/account/email-settings/confirm-email-provider/confirm-email-provider.component.scss: -------------------------------------------------------------------------------- 1 | @forward "./../../../../styles/questionaire.scss"; 2 | @forward "./../../../../styles/mobile-display.scss"; 3 | 4 | .email-picker { 5 | padding: 2rem; 6 | } 7 | 8 | .example-full-width { 9 | width: 100%; 10 | } 11 | 12 | .mat-mdc-form-field-error-wrapper { 13 | padding: 0 !important; 14 | } 15 | -------------------------------------------------------------------------------- /Frontend/src/app/account/email-settings/email-settings.component.scss: -------------------------------------------------------------------------------- 1 | @forward "./../../../styles/app-header.scss"; 2 | @forward "./../../../styles/top-bar.scss"; 3 | @forward "./../../../styles/top-nav-btn.scss"; 4 | @forward "./../../../styles/item-bar.scss"; 5 | @forward "./../../../styles/icon-merge.scss"; 6 | 7 | 8 | .add-storage-actions { 9 | display: flex; 10 | flex-direction: column; 11 | align-items: flex-start; 12 | gap: 0.5rem; 13 | } 14 | -------------------------------------------------------------------------------- /Frontend/src/app/account/email-settings/resend/create-resend/create-resend.component.scss: -------------------------------------------------------------------------------- 1 | @forward "./../../../../../styles/questionaire.scss"; 2 | @forward "./../../../../../styles/mobile-display.scss"; 3 | 4 | .email-picker { 5 | padding: 2rem; 6 | } 7 | 8 | .example-full-width { 9 | width: 100%; 10 | } 11 | 12 | .mat-mdc-form-field-error-wrapper { 13 | padding: 0 !important; 14 | } 15 | -------------------------------------------------------------------------------- /Frontend/src/app/account/integrations/integrations.component.scss: -------------------------------------------------------------------------------- 1 | @forward "./../../../styles/app-header.scss"; 2 | @forward "./../../../styles/top-bar.scss"; 3 | @forward "./../../../styles/top-nav-btn.scss"; 4 | @forward "./../../../styles/item-bar.scss"; 5 | @forward "./../../../styles/icon-merge.scss"; 6 | @forward "./../../../styles/mobile-display.scss"; 7 | 8 | 9 | .add-storage-actions { 10 | display: flex; 11 | flex-direction: column; 12 | align-items: flex-start; 13 | gap: 0.5rem; 14 | } -------------------------------------------------------------------------------- /Frontend/src/app/account/storage-settings/aws/create-aws-storage/create-aws-storage.component.scss: -------------------------------------------------------------------------------- 1 | @forward "./../../../../../styles/page-form.scss"; 2 | @forward "./../../../../../styles/mobile-display.scss"; 3 | @forward "./../../../../../styles/app-header.scss"; 4 | @forward "./../../../../../styles/top-bar.scss"; 5 | @forward "./../../../../../styles/top-nav-btn.scss"; 6 | @forward "./../../../../../styles/item-bar.scss"; 7 | @forward "./../../../../../styles/icon-merge.scss"; 8 | 9 | .email-picker { 10 | padding: 2rem; 11 | } 12 | 13 | .mat-mdc-form-field-error-wrapper { 14 | padding: 0 !important; 15 | } -------------------------------------------------------------------------------- /Frontend/src/app/account/storage-settings/aws/edit-aws-storage/edit-aws-storage.component.scss: -------------------------------------------------------------------------------- 1 | @forward "./../../../../../styles/questionaire.scss"; 2 | @forward "./../../../../../styles/mobile-display.scss"; 3 | 4 | .email-picker { 5 | padding: 2rem; 6 | } 7 | 8 | .example-full-width { 9 | width: 100%; 10 | } 11 | 12 | .mat-mdc-form-field-error-wrapper { 13 | padding: 0 !important; 14 | } -------------------------------------------------------------------------------- /Frontend/src/app/account/storage-settings/cloudflare/create-cloudflare-storage/create-cloudflare-storage.component.scss: -------------------------------------------------------------------------------- 1 | @forward "./../../../../../styles/page-form.scss"; 2 | @forward "./../../../../../styles/mobile-display.scss"; 3 | @forward "./../../../../../styles/app-header.scss"; 4 | @forward "./../../../../../styles/top-bar.scss"; 5 | @forward "./../../../../../styles/top-nav-btn.scss"; 6 | @forward "./../../../../../styles/item-bar.scss"; 7 | @forward "./../../../../../styles/icon-merge.scss"; 8 | 9 | .email-picker { 10 | padding: 2rem; 11 | } 12 | 13 | .mat-mdc-form-field-error-wrapper { 14 | padding: 0 !important; 15 | } -------------------------------------------------------------------------------- /Frontend/src/app/account/storage-settings/cloudflare/edit-cloudflare-storage/edit-cloudflare-storage.component.scss: -------------------------------------------------------------------------------- 1 | @forward "./../../../../../styles/questionaire.scss"; 2 | @forward "./../../../../../styles/mobile-display.scss"; 3 | 4 | .email-picker { 5 | padding: 2rem; 6 | } 7 | 8 | .example-full-width { 9 | width: 100%; 10 | } 11 | 12 | .mat-mdc-form-field-error-wrapper { 13 | padding: 0 !important; 14 | } -------------------------------------------------------------------------------- /Frontend/src/app/account/storage-settings/digitalocean/create-digitalocean-storage/create-digitalocean-storage.component.scss: -------------------------------------------------------------------------------- 1 | @forward "./../../../../../styles/page-form.scss"; 2 | @forward "./../../../../../styles/mobile-display.scss"; 3 | @forward "./../../../../../styles/app-header.scss"; 4 | @forward "./../../../../../styles/top-bar.scss"; 5 | @forward "./../../../../../styles/top-nav-btn.scss"; 6 | @forward "./../../../../../styles/item-bar.scss"; 7 | @forward "./../../../../../styles/icon-merge.scss"; 8 | 9 | .email-picker { 10 | padding: 2rem; 11 | } 12 | 13 | .mat-mdc-form-field-error-wrapper { 14 | padding: 0 !important; 15 | } -------------------------------------------------------------------------------- /Frontend/src/app/account/storage-settings/digitalocean/edit-digitalocean-storage/edit-digitalocean-storage.component.scss: -------------------------------------------------------------------------------- 1 | @forward "./../../../../../styles/questionaire.scss"; 2 | @forward "./../../../../../styles/mobile-display.scss"; 3 | 4 | .email-picker { 5 | padding: 2rem; 6 | } 7 | 8 | .example-full-width { 9 | width: 100%; 10 | } 11 | 12 | .mat-mdc-form-field-error-wrapper { 13 | padding: 0 !important; 14 | } -------------------------------------------------------------------------------- /Frontend/src/app/account/storage-settings/hard-drive/create-hard-drive-storage/create-hard-drive-storage.component.scss: -------------------------------------------------------------------------------- 1 | @forward "./../../../../../styles/page-form.scss"; 2 | @forward "./../../../../../styles/mobile-display.scss"; 3 | @forward "./../../../../../styles/app-header.scss"; 4 | @forward "./../../../../../styles/top-bar.scss"; 5 | @forward "./../../../../../styles/top-nav-btn.scss"; 6 | @forward "./../../../../../styles/item-bar.scss"; 7 | @forward "./../../../../../styles/icon-merge.scss"; 8 | 9 | .email-picker { 10 | padding: 2rem; 11 | } 12 | 13 | .mat-mdc-form-field-error-wrapper { 14 | padding: 0 !important; 15 | } 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /Frontend/src/app/account/storage-settings/storage-settings.component.scss: -------------------------------------------------------------------------------- 1 | @forward "./../../../styles/app-header.scss"; 2 | @forward "./../../../styles/top-bar.scss"; 3 | @forward "./../../../styles/top-nav-btn.scss"; 4 | @forward "./../../../styles/item-bar.scss"; 5 | @forward "./../../../styles/icon-merge.scss"; 6 | @forward "./../../../styles/mobile-display.scss"; 7 | 8 | 9 | .add-storage-actions { 10 | display: flex; 11 | flex-direction: column; 12 | align-items: flex-start; 13 | gap: 0.5rem; 14 | } -------------------------------------------------------------------------------- /Frontend/src/app/account/user-details/user-details.component.scss: -------------------------------------------------------------------------------- 1 | @forward "./../../../styles/hover-switch.scss"; 2 | @forward "./../../../styles/app-header.scss"; 3 | @forward "./../../../styles/top-bar.scss"; 4 | @forward "./../../../styles/covered.scss"; 5 | @forward "./../../../styles/top-nav-btn.scss"; 6 | @forward "./../../../styles/action-text-btn.scss"; 7 | @forward "./../../../styles/item-bar.scss"; 8 | @forward "./../../../styles/icon-merge.scss"; 9 | 10 | .user-details { 11 | padding-left: 0.5rem; 12 | padding-right: 0.5rem; 13 | } 14 | 15 | .workspace-config { 16 | padding-left: 0.5rem; 17 | padding-right: 0.5rem; 18 | 19 | display: flex; 20 | flex-direction: column; 21 | gap: 1.5rem; 22 | } -------------------------------------------------------------------------------- /Frontend/src/app/app.component.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Frontend/src/app/files-explorer/file-content/audio-preview/audio-preview.component.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Frontend/src/app/files-explorer/file-content/audio-preview/audio-preview.component.scss: -------------------------------------------------------------------------------- 1 | .audio-preview { 2 | max-width: 100%; 3 | max-height: 70vh; 4 | object-fit: contain; 5 | margin: 0 auto; 6 | display: block; 7 | } -------------------------------------------------------------------------------- /Frontend/src/app/files-explorer/file-content/audio-preview/audio-preview.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, input } from "@angular/core"; 2 | 3 | @Component({ 4 | selector: 'app-audio-preview', 5 | imports: [], 6 | templateUrl: './audio-preview.component.html', 7 | styleUrls: ['./audio-preview.component.scss'] 8 | }) 9 | export class AudioPreviewComponent { 10 | fileUrl = input.required(); 11 | 12 | handleMediaError(event: any): void { 13 | console.error('Error loading media:', event); 14 | } 15 | } -------------------------------------------------------------------------------- /Frontend/src/app/files-explorer/file-content/file-content.component.scss: -------------------------------------------------------------------------------- 1 | .non-image-message { 2 | padding: 1rem; 3 | border: 1px dashed var(--company-grey-accent); 4 | background-color: white; 5 | 6 | &__file-name { 7 | font-weight: 500; 8 | font-size: 1.1rem; 9 | } 10 | 11 | &__desc { 12 | color: var(--company-grey-font); 13 | font-size: var(--company-medium-font); 14 | } 15 | } 16 | 17 | .file-content { 18 | position: relative; 19 | 20 | &__close-btn { 21 | position: absolute; 22 | right: 1rem; 23 | top: 1rem; 24 | z-index: 1; 25 | } 26 | } -------------------------------------------------------------------------------- /Frontend/src/app/files-explorer/file-content/markdown-preview/markdown-preview.component.scss: -------------------------------------------------------------------------------- 1 | .markdown-preview { 2 | position: relative; 3 | min-height: 200px; 4 | overflow: auto; 5 | 6 | background-color: white; 7 | padding: 1rem 2.5rem; 8 | border: 1px solid var(--company-grey-accent-light); 9 | 10 | &__loading { 11 | padding: 1rem; 12 | text-align: center; 13 | color: #666; 14 | } 15 | } 16 | 17 | .resize-handle { 18 | height: 5px; 19 | background: transparent; 20 | cursor: ns-resize; 21 | } 22 | 23 | .resize-handle:hover { 24 | background: var(--company-grey-active); 25 | } -------------------------------------------------------------------------------- /Frontend/src/app/files-explorer/file-content/pdf-preview/pdf-preview.component.html: -------------------------------------------------------------------------------- 1 |
2 | 6 |
7 |

It appears you don't have a PDF plugin for this browser. 8 | You can click here to download the PDF file.

9 |
10 |
11 |
-------------------------------------------------------------------------------- /Frontend/src/app/files-explorer/file-content/pdf-preview/pdf-preview.component.scss: -------------------------------------------------------------------------------- 1 | .pdf-container { 2 | flex: 1; 3 | display: flex; 4 | flex-direction: column; 5 | min-height: 70vh 6 | } 7 | 8 | .pdf-object { 9 | flex: 1; 10 | width: 100%; 11 | min-height: 100%; 12 | } -------------------------------------------------------------------------------- /Frontend/src/app/files-explorer/file-content/text-preview/text-preview.component.html: -------------------------------------------------------------------------------- 1 | @let textVal = fileText(); 2 | 3 |
4 |
5 | @if(textVal) { 6 |
7 |
{{textVal}}
8 |
9 | } @else { 10 |
11 | Loading... 12 |
13 | } 14 |
15 | 16 |
17 |
18 |
-------------------------------------------------------------------------------- /Frontend/src/app/files-explorer/file-content/video-preview/video-preview.component.html: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /Frontend/src/app/files-explorer/file-content/video-preview/video-preview.component.scss: -------------------------------------------------------------------------------- 1 | .video-preview { 2 | min-width: 100%; 3 | max-width: 100%; 4 | max-height: 70vh; 5 | object-fit: contain; 6 | margin: 0 auto; 7 | display: block; 8 | } -------------------------------------------------------------------------------- /Frontend/src/app/files-explorer/file-content/video-preview/video-preview.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, input } from "@angular/core"; 2 | 3 | @Component({ 4 | selector: 'app-video-preview', 5 | imports: [], 6 | templateUrl: './video-preview.component.html', 7 | styleUrls: ['./video-preview.component.scss'] 8 | }) 9 | export class VideoPreviewComponent { 10 | fileUrl = input.required(); 11 | 12 | handleMediaError(event: any): void { 13 | console.error('Error loading media:', event); 14 | } 15 | } -------------------------------------------------------------------------------- /Frontend/src/app/files-explorer/http-headers-factory.ts: -------------------------------------------------------------------------------- 1 | export type HttpHeadersFactory = { 2 | prepareAdditionalHttpHeaders: () => Record | undefined; 3 | } -------------------------------------------------------------------------------- /Frontend/src/app/files-explorer/upload-item/upload-item.component.scss: -------------------------------------------------------------------------------- 1 | @forward "./../../../styles/item-bar.scss"; 2 | @forward "./../../../styles/mobile-display.scss"; 3 | 4 | .upload-progress { 5 | display: flex; 6 | flex-direction: row; 7 | align-items: center; 8 | gap: 0.5rem; 9 | height: 1rem; 10 | } -------------------------------------------------------------------------------- /Frontend/src/app/files-processor/files-processor.component.html: -------------------------------------------------------------------------------- 1 |
2 |
3 | Actions 4 |
5 | 6 |
7 |
8 |
-------------------------------------------------------------------------------- /Frontend/src/app/files-processor/files-processor.component.scss: -------------------------------------------------------------------------------- 1 | @forward "./../../styles/app-header.scss"; -------------------------------------------------------------------------------- /Frontend/src/app/protobuf/ancestor-folder-dto.protobuf.ts: -------------------------------------------------------------------------------- 1 | import * as protobuf from "protobufjs"; 2 | 3 | export function getAncestorFolderDtoProtobuf() { 4 | return new protobuf.Type("AncestorFolderDto") 5 | .add(new protobuf.Field("externalId", 1, "string")) 6 | .add(new protobuf.Field("name", 2, "string")); 7 | } -------------------------------------------------------------------------------- /Frontend/src/app/protobuf/bulk-create-folder-item-dto.protobuf.ts: -------------------------------------------------------------------------------- 1 | import * as protobuf from "protobufjs"; 2 | 3 | export function getBulkCreateFolderItemDtoProtobuf() { 4 | return new protobuf.Type("BulkCreateFolderItemDto") 5 | .add(new protobuf.Field("temporaryId", 1, "int32")) 6 | .add(new protobuf.Field("externalId", 2, "string")); 7 | } -------------------------------------------------------------------------------- /Frontend/src/app/protobuf/bulk-create-folder-request-dto.protobuf.ts: -------------------------------------------------------------------------------- 1 | import * as protobuf from "protobufjs"; 2 | import { getFolderTreeDtoProtobuf } from "./folder-tree-dto.protobuf"; 3 | 4 | export function getBulkCreateFolderRequestDtoProtobuf() { 5 | return new protobuf.Type("BulkCreateFolderRequestDto") 6 | .add(new protobuf.Field("parentExternalId", 1, "string")) 7 | .add(new protobuf.Field("ensureUniqueNames", 2, "bool")) 8 | .add(getFolderTreeDtoProtobuf()) 9 | .add(new protobuf.Field("folderTrees", 3, "FolderTreeDto", "repeated")); 10 | } -------------------------------------------------------------------------------- /Frontend/src/app/protobuf/bulk-create-folder-response-dto.protobuf.ts: -------------------------------------------------------------------------------- 1 | import * as protobuf from "protobufjs"; 2 | import { getBulkCreateFolderItemDtoProtobuf } from "./bulk-create-folder-item-dto.protobuf"; 3 | 4 | export function getBulkCreateFolderResponseDtoProtobuf() { 5 | return new protobuf.Type("BulkCreateFolderResponseDto") 6 | .add(getBulkCreateFolderItemDtoProtobuf()) 7 | .add(new protobuf.Field("items", 1, "BulkCreateFolderItemDto", "repeated")); 8 | } -------------------------------------------------------------------------------- /Frontend/src/app/protobuf/bulk-initiate-file-upload-item-dto.protobuf.ts: -------------------------------------------------------------------------------- 1 | import * as protobuf from "protobufjs"; 2 | 3 | export function getBulkInitiateFileUploadItemDtoProtobuf() { 4 | return new protobuf.Type("BulkInitiateFileUploadItemDto") 5 | .add(new protobuf.Field("fileUploadExternalId", 1, "string")) 6 | .add(new protobuf.Field("folderExternalId", 2, "string")) 7 | .add(new protobuf.Field("fileNameWithExtension", 3, "string")) 8 | .add(new protobuf.Field("fileContentType", 4, "string")) 9 | .add(new protobuf.Field("fileSizeInBytes", 5, "int64")); 10 | } -------------------------------------------------------------------------------- /Frontend/src/app/protobuf/bulk-initiate-file-upload-request-dto.protobuf.ts: -------------------------------------------------------------------------------- 1 | import * as protobuf from "protobufjs"; 2 | import { getBulkInitiateFileUploadItemDtoProtobuf } from "./bulk-initiate-file-upload-item-dto.protobuf"; 3 | 4 | export function getBulkInitiateFileUploadRequestDtoProtobuf() { 5 | return new protobuf.Type("BulkInitiateFileUploadRequestDto") 6 | .add(getBulkInitiateFileUploadItemDtoProtobuf()) 7 | .add(new protobuf.Field("items", 1, "BulkInitiateFileUploadItemDto", "repeated")); 8 | } -------------------------------------------------------------------------------- /Frontend/src/app/protobuf/current-folder-dto.protobuf.ts: -------------------------------------------------------------------------------- 1 | import * as protobuf from "protobufjs"; 2 | import { getAncestorFolderDtoProtobuf } from "./ancestor-folder-dto.protobuf"; 3 | 4 | export function getCurrentFolderDtoProtobuf() { 5 | return new protobuf.Type("CurrentFolderDto") 6 | .add(getAncestorFolderDtoProtobuf()) 7 | .add(new protobuf.Field("name", 1, "string")) 8 | .add(new protobuf.Field("externalId", 2, "string")) 9 | .add(new protobuf.Field("ancestors", 3, "AncestorFolderDto", "repeated")); 10 | } -------------------------------------------------------------------------------- /Frontend/src/app/protobuf/file-dto.protobuf.ts: -------------------------------------------------------------------------------- 1 | import * as protobuf from "protobufjs"; 2 | 3 | export function getFileDtoProtobuf() { 4 | return new protobuf.Type("FileDto") 5 | .add(new protobuf.Field("externalId", 1, "string")) 6 | .add(new protobuf.Field("name", 2, "string")) 7 | .add(new protobuf.Field("extension", 3, "string")) 8 | .add(new protobuf.Field("sizeInBytes", 4, "int64")) 9 | .add(new protobuf.Field("isLocked", 5, "bool")) 10 | .add(new protobuf.Field("wasUploadedByUser", 6, "bool")); 11 | } -------------------------------------------------------------------------------- /Frontend/src/app/protobuf/folder-tree-dto.protobuf.ts: -------------------------------------------------------------------------------- 1 | import * as protobuf from "protobufjs"; 2 | 3 | export function getFolderTreeDtoProtobuf() { 4 | return new protobuf.Type("FolderTreeDto") 5 | .add(new protobuf.Field("temporaryId", 1, "int32")) 6 | .add(new protobuf.Field("name", 2, "string")) 7 | .add(new protobuf.Field("subfolders", 3, "FolderTreeDto", "repeated")); 8 | } -------------------------------------------------------------------------------- /Frontend/src/app/protobuf/subfolder-dto.protobuf.ts: -------------------------------------------------------------------------------- 1 | import * as protobuf from "protobufjs"; 2 | import { getDateTimeProtobuf } from "./datetime.protobuf"; 3 | 4 | export function getSubfolderDtoProtobuf() { 5 | return new protobuf.Type("SubfolderDto") 6 | .add(new protobuf.Field("externalId", 1, "string")) 7 | .add(new protobuf.Field("name", 2, "string")) 8 | .add(new protobuf.Field("wasCreatedByUser", 3, "bool")) 9 | .add(new protobuf.Field("createdAt", 4, "appDateTime")) 10 | .add(getDateTimeProtobuf()); 11 | } -------------------------------------------------------------------------------- /Frontend/src/app/protobuf/upload-dto.protobuf.ts: -------------------------------------------------------------------------------- 1 | import * as protobuf from "protobufjs"; 2 | 3 | export function getUploadDtoProtobuf() { 4 | return new protobuf.Type("UploadDto") 5 | .add(new protobuf.Field("externalId", 1, "string")) 6 | .add(new protobuf.Field("fileName", 2, "string")) 7 | .add(new protobuf.Field("fileExtension", 3, "string")) 8 | .add(new protobuf.Field("fileContentType", 4, "string")) 9 | .add(new protobuf.Field("fileSizeInBytes", 5, "int64")) 10 | .add(new protobuf.Field("alreadyUploadedPartNumbers", 6, "int32", "repeated")); 11 | } 12 | -------------------------------------------------------------------------------- /Frontend/src/app/protobuf/zip-file-details-dto.protobuf.ts: -------------------------------------------------------------------------------- 1 | import * as protobuf from "protobufjs"; 2 | import { getZipFileDetailsItemDtoProtobuf } from "./zip-file-details-item-dto.protobuf"; 3 | 4 | export function getZipFileDetailsDtoProtobuf() { 5 | return new protobuf.Type("GetZipFileDetailsResponseDto") 6 | .add(getZipFileDetailsItemDtoProtobuf()) 7 | .add(new protobuf.Field("items", 1, "GetZipFileDetailsItemDto", "repeated")); 8 | } -------------------------------------------------------------------------------- /Frontend/src/app/protobuf/zip-file-details-item-dto.protobuf.ts: -------------------------------------------------------------------------------- 1 | import * as protobuf from "protobufjs"; 2 | 3 | export function getZipFileDetailsItemDtoProtobuf() { 4 | return new protobuf.Type("GetZipFileDetailsItemDto") 5 | .add(new protobuf.Field("filePath", 1, "string")) 6 | .add(new protobuf.Field("compressedSizeInBytes", 2, "int64")) 7 | .add(new protobuf.Field("sizeInBytes", 3, "int64")) 8 | .add(new protobuf.Field("offsetToLocalFileHeader", 4, "int64")) 9 | .add(new protobuf.Field("fileNameLength", 5, "uint32")) 10 | .add(new protobuf.Field("compressionMethod", 6, "uint32")) 11 | .add(new protobuf.Field("indexInArchive", 7, "uint32")); 12 | } -------------------------------------------------------------------------------- /Frontend/src/app/services/box-link-token.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | 3 | export const BOX_LINK_TOKEN_HEADER = "X-BOX-LINK-TOKEN"; 4 | const BOX_LINK_TOKEN_LOCAL_STORAGE_KEY = "PLIKSHARE_BOX_LINK_TOKEN"; 5 | 6 | @Injectable({ 7 | providedIn: 'root' 8 | }) 9 | export class BoxLinkTokenService { 10 | public set(token: string) { 11 | localStorage.setItem(BOX_LINK_TOKEN_LOCAL_STORAGE_KEY, token); 12 | } 13 | 14 | public get(): string | undefined { 15 | const token = localStorage.getItem(BOX_LINK_TOKEN_LOCAL_STORAGE_KEY); 16 | 17 | if(token) return token; 18 | return undefined; 19 | } 20 | } -------------------------------------------------------------------------------- /Frontend/src/app/services/bytes-range.ts: -------------------------------------------------------------------------------- 1 | 2 | ///start: index of first byte in range 3 | ///end: index of last byte in range 4 | ///(note - be careful in JS as in blob slicing an end means first byte not in the slice, so byterange.end + 1) 5 | export type BytesRange = { 6 | start: number; 7 | end: number; 8 | } -------------------------------------------------------------------------------- /Frontend/src/app/services/digitalocean-regions.ts: -------------------------------------------------------------------------------- 1 | 2 | export class DigitalOceanRegions { 3 | public static Spaces() { 4 | return [ 5 | 'fra1', 6 | 'nyc3', 7 | 'sfo2', 8 | 'sfo3', 9 | 'lon1', 10 | 'ams3', 11 | 'sgp1', 12 | 'blr1', 13 | 'syd1', 14 | ]; 15 | } 16 | } -------------------------------------------------------------------------------- /Frontend/src/app/services/file-upload-manager/blob-slicer.ts: -------------------------------------------------------------------------------- 1 | import { IFileSlicer } from "./file-upload-manager"; 2 | 3 | export class BlobSlicer implements IFileSlicer { 4 | constructor(private _blob: Blob){} 5 | 6 | canBeProcessedInParallel(){ 7 | return true; 8 | } 9 | 10 | async takeSlice(start: number, end: number) { 11 | return this._blob.slice(start, end); 12 | }; 13 | 14 | async takeWhole () { 15 | return this._blob; 16 | } 17 | } -------------------------------------------------------------------------------- /Frontend/src/app/services/file-upload-manager/file-slicer.ts: -------------------------------------------------------------------------------- 1 | import { IFileSlicer } from "./file-upload-manager"; 2 | 3 | export class FileSlicer implements IFileSlicer { 4 | constructor(private _file: File){} 5 | 6 | canBeProcessedInParallel(){ 7 | return true; 8 | } 9 | 10 | async takeSlice(start: number, end: number) { 11 | return this._file.slice(start, end); 12 | }; 13 | 14 | async takeWhole () { 15 | return this._file; 16 | } 17 | } -------------------------------------------------------------------------------- /Frontend/src/app/services/integrations.types.ts: -------------------------------------------------------------------------------- 1 | const TEXTRACT_SUPPORTED_EXTENSIONS = ['.pdf', '.png', '.jpeg', '.jpg', '.tiff']; 2 | 3 | export class TextractIntegration { 4 | public static isSupportedForExtension(fileExtension: string): boolean { 5 | return TEXTRACT_SUPPORTED_EXTENSIONS.includes(fileExtension); 6 | } 7 | } -------------------------------------------------------------------------------- /Frontend/src/app/services/is-highlighted-utils.ts: -------------------------------------------------------------------------------- 1 | import { computed, Signal, WritableSignal } from "@angular/core"; 2 | 3 | export function observeIsHighlighted(itemSignal: Signal<{isHighlighted: WritableSignal}>): Signal { 4 | return computed(() => { 5 | const item = itemSignal(); 6 | 7 | if(!item) return false; 8 | 9 | const isHighlighted = item.isHighlighted(); 10 | 11 | if(isHighlighted) { 12 | setTimeout(() => item.isHighlighted.set(false), 5000); 13 | } 14 | 15 | return isHighlighted; 16 | }); 17 | } -------------------------------------------------------------------------------- /Frontend/src/app/services/loading-chunk-failed-error.handler.ts: -------------------------------------------------------------------------------- 1 | import { ErrorHandler, Injectable } from '@angular/core'; 2 | 3 | @Injectable() 4 | export class LoadingChunkFailedErrorHandler implements ErrorHandler { 5 | 6 | handleError(error: any): void { 7 | const chunkFailedMessage = /Loading chunk [\d]+ failed/; 8 | 9 | if (chunkFailedMessage.test(error.message)) { 10 | window.location.reload(); 11 | } 12 | } 13 | } -------------------------------------------------------------------------------- /Frontend/src/app/services/widgets.api.ts: -------------------------------------------------------------------------------- 1 | import { HttpClient } from "@angular/common/http"; 2 | import { Injectable } from "@angular/core"; 3 | import { firstValueFrom } from "rxjs"; 4 | 5 | 6 | @Injectable({ 7 | providedIn: 'root' 8 | }) 9 | export class WidgetsApi { 10 | constructor( 11 | private _http: HttpClient) { 12 | } 13 | 14 | public async getWidgetScripts(): Promise { 15 | const call = this 16 | ._http 17 | .get(`/api/widgets/scripts`, { 18 | responseType: 'text' 19 | }); 20 | 21 | return await firstValueFrom(call); 22 | } 23 | } -------------------------------------------------------------------------------- /Frontend/src/app/shared/ai-conversation-item/ai-conversation-item.component.scss: -------------------------------------------------------------------------------- 1 | @forward "./../../../styles/item-bar.scss"; 2 | @forward "./../../../styles/mobile-display.scss"; 3 | 4 | .blinking { 5 | animation: blink 1s linear infinite; 6 | } 7 | 8 | @keyframes blink { 9 | 0%, 100% { opacity: 1; } 10 | 50% { opacity: 0.3; } 11 | } -------------------------------------------------------------------------------- /Frontend/src/app/shared/app-user.ts: -------------------------------------------------------------------------------- 1 | import { Signal } from '@angular/core'; 2 | 3 | export type AppUser = { 4 | email: Signal; 5 | externalId: string; 6 | } -------------------------------------------------------------------------------- /Frontend/src/app/shared/app-workspace-details.ts: -------------------------------------------------------------------------------- 1 | import { Signal } from "@angular/core"; 2 | 3 | export type AppWorkspaceDetails = { 4 | externalId: string; 5 | name: Signal; 6 | storageName: Signal; 7 | } -------------------------------------------------------------------------------- /Frontend/src/app/shared/box-invitation-item/box-invitation-item.component.scss: -------------------------------------------------------------------------------- 1 | @forward "./../../../styles/hover-switch.scss"; 2 | @forward "./../../../styles/item-bar.scss"; 3 | @forward "./../../../styles/mobile-display.scss"; -------------------------------------------------------------------------------- /Frontend/src/app/shared/box-item/box-item.component.scss: -------------------------------------------------------------------------------- 1 | @forward "./../../../styles/item-bar.scss"; 2 | @forward "./../../../styles/mobile-display.scss"; 3 | @forward "./../../../styles/hover-switch.scss"; -------------------------------------------------------------------------------- /Frontend/src/app/shared/box-permissions/box-permissions-list.component.scss: -------------------------------------------------------------------------------- 1 | .flex-wrap { 2 | flex-wrap: wrap; 3 | } -------------------------------------------------------------------------------- /Frontend/src/app/shared/buttons/action-btn/action-btn.component.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Frontend/src/app/shared/buttons/action-text-btn/action-text-btn.component.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Frontend/src/app/shared/buttons/action-text-btn/action-text-btn.component.scss: -------------------------------------------------------------------------------- 1 | .action-text-btn { 2 | height: 36px !important; 3 | min-width: 36px !important; 4 | padding: 0px 0.5rem !important; 5 | border: 1px solid var(--company-grey-accent) !important; 6 | font-weight: 600; 7 | font-size: var(--company-small-font); 8 | 9 | &--danger { 10 | border-color: var(--company-danger) !important; 11 | color: var(--company-danger) !important; 12 | } 13 | 14 | &--disabled { 15 | color: var(--mdc-filled-button-disabled-label-text-color) !important; 16 | background-color: var(--mdc-filled-button-disabled-container-color) !important; 17 | } 18 | } -------------------------------------------------------------------------------- /Frontend/src/app/shared/buttons/item-btn/item-btn.component.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Frontend/src/app/shared/buttons/item-btn/item-btn.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, input, output } from "@angular/core"; 2 | import { MatButtonModule } from "@angular/material/button"; 3 | 4 | @Component({ 5 | selector: 'app-item-btn', 6 | imports: [ 7 | MatButtonModule 8 | ], 9 | templateUrl: './item-btn.component.html', 10 | styleUrl: './item-btn.component.scss' 11 | }) 12 | export class ItemButtonComponent { 13 | title = input.required(); 14 | subtitle = input.required(); 15 | icon = input.required<`icon-${string}`>(); 16 | 17 | clicked = output(); 18 | } -------------------------------------------------------------------------------- /Frontend/src/app/shared/buttons/permission-btn/permission-btn.component.html: -------------------------------------------------------------------------------- 1 | 11 | -------------------------------------------------------------------------------- /Frontend/src/app/shared/buttons/permission-btn/permission-btn.component.scss: -------------------------------------------------------------------------------- 1 | .permission-btn { 2 | width: 36px !important; 3 | height: 36px !important; 4 | min-width: 36px !important; 5 | 6 | &--readonly { 7 | border: none !important; 8 | cursor: default !important 9 | } 10 | 11 | &--selected { 12 | border: 1px solid var(--company-grey-accent); 13 | padding: 5px; 14 | border-radius: 5px; 15 | } 16 | 17 | &--not-selected { 18 | i { 19 | opacity: 0.3; 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /Frontend/src/app/shared/cookies.ts: -------------------------------------------------------------------------------- 1 | import { XSRF_TOKEN_COOKIE_NAME } from "./xsrf"; 2 | 3 | export class CookieUtils { 4 | public static getValue(cookieName: string): string { 5 | const match = document.cookie.match('(^|;)\\s*' + cookieName + '\\s*=\\s*([^;]+)'); 6 | return match ? match.pop() || '' : ''; 7 | } 8 | 9 | public static GetXsrfToken() { 10 | return this.getValue(XSRF_TOKEN_COOKIE_NAME); 11 | } 12 | } -------------------------------------------------------------------------------- /Frontend/src/app/shared/debounced-change.directive.ts: -------------------------------------------------------------------------------- 1 | import { Directive, EventEmitter, HostListener, input, output, Output } from '@angular/core'; 2 | 3 | @Directive({ 4 | selector: '[debouncedChange]', // Use the directive as an attribute 5 | standalone: true 6 | }) 7 | export class DebouncedChangeDirective { 8 | debouncedChange = output(); 9 | debounceTime = input(500); 10 | 11 | private debounceTimer?: any; 12 | 13 | @HostListener('input', ['$event.target.value']) 14 | onInput(value: string): void { 15 | clearTimeout(this.debounceTimer); 16 | this.debounceTimer = setTimeout(() => { 17 | this.debouncedChange.emit(value); 18 | }, this.debounceTime()); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Frontend/src/app/shared/email-provider-item/email-provider-item.component.scss: -------------------------------------------------------------------------------- 1 | @forward "./../../../styles/item-bar.scss"; 2 | @forward "./../../../styles/mobile-display.scss"; 3 | 4 | .not-confirmed { 5 | opacity: 0.5; 6 | } -------------------------------------------------------------------------------- /Frontend/src/app/shared/external-box-item/external-box-item.component.scss: -------------------------------------------------------------------------------- 1 | @forward "./../../../styles/item-bar.scss"; 2 | @forward "./../../../styles/hover-switch.scss"; -------------------------------------------------------------------------------- /Frontend/src/app/shared/file-item/file-item.component.scss: -------------------------------------------------------------------------------- 1 | @forward "./../../../styles/item-bar.scss"; 2 | @forward "./../../../styles/mobile-display.scss"; -------------------------------------------------------------------------------- /Frontend/src/app/shared/file-tree-view/file-tree-node/file-tree-node.component.scss: -------------------------------------------------------------------------------- 1 | @forward "./../file-tree-view.component.scss"; -------------------------------------------------------------------------------- /Frontend/src/app/shared/file-tree-view/folder-tree-node/folder-tree-node.component.scss: -------------------------------------------------------------------------------- 1 | @forward "./../file-tree-view.component.scss"; -------------------------------------------------------------------------------- /Frontend/src/app/shared/file-tree-view/tree-checkbox/tree-checkbox.component.html: -------------------------------------------------------------------------------- 1 |
2 | @if(isCheckboxExcluded()) { 3 | 4 | 5 | } @else { 6 | 10 | 11 | } 12 |
-------------------------------------------------------------------------------- /Frontend/src/app/shared/file-tree-view/tree-checkbox/tree-checkbox.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/damian-krychowski/plikshare/1b5717473495bb8e02108ac3409cec10eb8a9afe/Frontend/src/app/shared/file-tree-view/tree-checkbox/tree-checkbox.component.scss -------------------------------------------------------------------------------- /Frontend/src/app/shared/folder-item/folder-item.component.scss: -------------------------------------------------------------------------------- 1 | @forward "./../../../styles/hover-switch.scss"; 2 | @forward "./../../../styles/item-bar.scss"; 3 | @forward "./../../../styles/mobile-display.scss"; 4 | 5 | -------------------------------------------------------------------------------- /Frontend/src/app/shared/generic-message-dialog/generic-message-dialog.component.scss: -------------------------------------------------------------------------------- 1 | @forward "./../../../styles/questionaire.scss"; 2 | 3 | .verb-btn { 4 | text-transform: capitalize; 5 | } 6 | 7 | .danger-btn { 8 | background-color: var(--company-danger); 9 | color: white; 10 | } -------------------------------------------------------------------------------- /Frontend/src/app/shared/integration-item/integration-item.component.scss: -------------------------------------------------------------------------------- 1 | @forward "./../../../styles/item-bar.scss"; 2 | @forward "./../../../styles/mobile-display.scss"; 3 | -------------------------------------------------------------------------------- /Frontend/src/app/shared/item-search/item-search.component.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Frontend/src/app/shared/name-with-highlight.ts: -------------------------------------------------------------------------------- 1 | export function getNameWithHighlight(name: string, searchPhraseLower: string): string { 2 | const nameLowered = name.toLowerCase(); 3 | 4 | if (!nameLowered.includes(searchPhraseLower)) { 5 | return name; 6 | } 7 | 8 | const startIndex = nameLowered.indexOf(searchPhraseLower); 9 | const endIndex = startIndex + searchPhraseLower.length; 10 | const highlighted = `${name.slice(0, startIndex)}${name.slice(startIndex, endIndex)}${name.slice(endIndex)}`; 11 | 12 | return highlighted; 13 | } -------------------------------------------------------------------------------- /Frontend/src/app/shared/operation-confirm/operation-confirm.component.scss: -------------------------------------------------------------------------------- 1 | @forward "./../../../styles/questionaire.scss"; 2 | 3 | .verb-btn { 4 | text-transform: capitalize; 5 | } -------------------------------------------------------------------------------- /Frontend/src/app/shared/prefetch.directive.ts: -------------------------------------------------------------------------------- 1 | import { Directive, Output, EventEmitter, HostListener, output } from '@angular/core'; 2 | 3 | @Directive({ 4 | selector: '[prefetch]', 5 | standalone: true 6 | }) 7 | export class PrefetchDirective { 8 | 9 | prefetch = output(); 10 | 11 | private timeoutId: any; 12 | 13 | constructor() { } 14 | 15 | @HostListener('mouseenter') onMouseEnter() { 16 | this.timeoutId = setTimeout(() => this.prefetch.emit(), 50); 17 | } 18 | 19 | @HostListener('mouseleave') onMouseLeave() { 20 | clearTimeout(this.timeoutId); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Frontend/src/app/shared/region-input/region-input.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/damian-krychowski/plikshare/1b5717473495bb8e02108ac3409cec10eb8a9afe/Frontend/src/app/shared/region-input/region-input.component.scss -------------------------------------------------------------------------------- /Frontend/src/app/shared/relative-time/relative-time.component.scss: -------------------------------------------------------------------------------- 1 | .relative-time { 2 | font-size: var(--company-small-font); 3 | color: var(--company-grey-font); 4 | padding-left: 0.1rem; 5 | padding-right: 0.1rem; 6 | 7 | &:hover { 8 | background: var(--company-grey-accent-light); 9 | } 10 | 11 | cursor: default; 12 | } -------------------------------------------------------------------------------- /Frontend/src/app/shared/rich-text-editor/rich-text-editor.component.scss: -------------------------------------------------------------------------------- 1 | .text-btn { 2 | border: 1px solid var(--company-grey-accent) !important; 3 | } 4 | 5 | .editor-badge { 6 | font-size: var(--company-small-font); 7 | border: 1px solid var(--company-grey-accent); 8 | padding: 0.2rem 1rem; 9 | border-radius: 5px; 10 | 11 | &__text { 12 | color: var(--company-grey-font); 13 | } 14 | } -------------------------------------------------------------------------------- /Frontend/src/app/shared/search/search.component.scss: -------------------------------------------------------------------------------- 1 | @use "./../../../styles/variables.scss" as variables; 2 | @forward "./../../../styles/app-header.scss"; 3 | @forward "./../../../styles/nothing-to-show.scss"; 4 | 5 | 6 | .search-results { 7 | padding-left: 2rem; 8 | 9 | @media (max-width: variables.$mobile-early-breakpoint) { 10 | padding-left: 0; 11 | } 12 | } -------------------------------------------------------------------------------- /Frontend/src/app/shared/select-all-text.directive.ts: -------------------------------------------------------------------------------- 1 | import { Directive, ElementRef, AfterViewInit, NgZone } from '@angular/core'; 2 | 3 | @Directive({ 4 | selector: '[selectAllText]', 5 | standalone: true 6 | }) 7 | export class SelectAllTextDirective implements AfterViewInit { 8 | 9 | constructor( 10 | private el: ElementRef, 11 | private ngZone: NgZone 12 | ) { } 13 | 14 | ngAfterViewInit() { 15 | this.ngZone.runOutsideAngular(() => { 16 | setTimeout(() => { 17 | this.el.nativeElement.select(); 18 | }); 19 | }); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Frontend/src/app/shared/setting-menu-btn/settings-menu-btn.component.html: -------------------------------------------------------------------------------- 1 | 10 | -------------------------------------------------------------------------------- /Frontend/src/app/shared/setting-menu-btn/settings-menu-btn.component.scss: -------------------------------------------------------------------------------- 1 | @forward "./../../../styles/top-nav-btn.scss"; -------------------------------------------------------------------------------- /Frontend/src/app/shared/storage-item/storage-item.component.scss: -------------------------------------------------------------------------------- 1 | @forward "./../../../styles/item-bar.scss"; 2 | @forward "./../../../styles/mobile-display.scss"; -------------------------------------------------------------------------------- /Frontend/src/app/shared/storage-picker/storage-picker.component.scss: -------------------------------------------------------------------------------- 1 | @forward "./../../../styles/questionaire.scss"; 2 | 3 | .email-picker { 4 | padding: 2rem; 5 | } 6 | 7 | .example-full-width { 8 | width: 100%; 9 | } 10 | 11 | .remove-email-btn { 12 | position: absolute; 13 | right: -5px; 14 | top: 50%; 15 | transform: translateY(-50%); 16 | } -------------------------------------------------------------------------------- /Frontend/src/app/shared/storage-unit-input/storage-unit-input.component.html: -------------------------------------------------------------------------------- 1 | 2 | Storage Unit 3 | 8 | @for (unit of storageUnits; track unit) { 9 | {{unit}} 10 | } 11 | 12 | @if ((storageUnitControl.touched || wasSubmitted()) && storageUnitControl.hasError('required')) { 13 | Storage unit is required 14 | } 15 | -------------------------------------------------------------------------------- /Frontend/src/app/shared/storage-unit-input/storage-unit-input.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/damian-krychowski/plikshare/1b5717473495bb8e02108ac3409cec10eb8a9afe/Frontend/src/app/shared/storage-unit-input/storage-unit-input.component.scss -------------------------------------------------------------------------------- /Frontend/src/app/shared/user-item/user-item.component.scss: -------------------------------------------------------------------------------- 1 | @forward "./../../../styles/item-bar.scss"; 2 | @forward "./../../../styles/mobile-display.scss"; 3 | 4 | .logged-in-user { 5 | i { 6 | padding: 10px 0px; 7 | border-radius: 10px; 8 | background: var(--company-grey-accent-light); 9 | } 10 | } 11 | 12 | .hide-border.item-bar { 13 | border-bottom-color: white; 14 | 15 | &:hover { 16 | border-bottom-color: var(--company-grey-accent); 17 | } 18 | } -------------------------------------------------------------------------------- /Frontend/src/app/shared/user-link/user-link.component.html: -------------------------------------------------------------------------------- 1 | 5 | {{prefix()}} {{email()}} 6 | -------------------------------------------------------------------------------- /Frontend/src/app/shared/user-link/user-link.component.scss: -------------------------------------------------------------------------------- 1 | .user-link { 2 | &--clickable { 3 | cursor: pointer; 4 | 5 | &:hover { 6 | text-decoration: underline; 7 | } 8 | } 9 | } -------------------------------------------------------------------------------- /Frontend/src/app/shared/user-permissions/user-permissions-list.component.scss: -------------------------------------------------------------------------------- 1 | .flex-wrap { 2 | flex-wrap: wrap; 3 | } 4 | 5 | .permissions-list { 6 | cursor: default; 7 | } -------------------------------------------------------------------------------- /Frontend/src/app/shared/user-picker/user-picker.component.scss: -------------------------------------------------------------------------------- 1 | @forward "./../../../styles/questionaire.scss"; 2 | 3 | .email-picker { 4 | padding: 2rem; 5 | } 6 | 7 | .example-full-width { 8 | width: 100%; 9 | } 10 | 11 | .remove-email-btn { 12 | position: absolute; 13 | right: -5px; 14 | top: 50%; 15 | transform: translateY(-50%); 16 | } -------------------------------------------------------------------------------- /Frontend/src/app/shared/workspace-invitation-item/workspace-invitation-item.component.scss: -------------------------------------------------------------------------------- 1 | @forward "./../../../styles/hover-switch.scss"; 2 | @forward "./../../../styles/item-bar.scss"; 3 | @forward "./../../../styles/mobile-display.scss"; -------------------------------------------------------------------------------- /Frontend/src/app/shared/workspace-item/workspace-item.component.scss: -------------------------------------------------------------------------------- 1 | @forward "./../../../styles/hover-switch.scss"; 2 | @forward "./../../../styles/item-bar.scss"; 3 | @forward "./../../../styles/mobile-display.scss"; 4 | 5 | @keyframes blink { 6 | 0%, 100% { color: black; } 7 | 50% { color: white; } 8 | } -------------------------------------------------------------------------------- /Frontend/src/app/shared/workspace-link/workspace-link.component.html: -------------------------------------------------------------------------------- 1 | @let workspaceVal = workspace(); 2 | 3 | 6 | {{workspaceVal.name}} 7 | -------------------------------------------------------------------------------- /Frontend/src/app/shared/workspace-link/workspace-link.component.scss: -------------------------------------------------------------------------------- 1 | .workspace-link { 2 | &--clickable { 3 | cursor: pointer; 4 | 5 | &:hover { 6 | text-decoration: underline; 7 | } 8 | } 9 | } -------------------------------------------------------------------------------- /Frontend/src/app/shared/workspace-number-config/workspace-number-config.component.scss: -------------------------------------------------------------------------------- 1 | @forward "./../../../styles/config-row.scss"; 2 | 3 | -------------------------------------------------------------------------------- /Frontend/src/app/shared/workspace-size-config/workspace-size-config.component.scss: -------------------------------------------------------------------------------- 1 | @forward "./../../../styles/config-row.scss"; 2 | 3 | -------------------------------------------------------------------------------- /Frontend/src/app/shared/workspace-team-config/workspace-team-config.component.scss: -------------------------------------------------------------------------------- 1 | @forward "./../../../styles/config-row.scss"; -------------------------------------------------------------------------------- /Frontend/src/app/shared/xsrf.ts: -------------------------------------------------------------------------------- 1 | export const XSRF_TOKEN_HEADER_NAME = 'X-XSRF-TOKEN'; 2 | export const XSRF_TOKEN_COOKIE_NAME = 'XSRF-TOKEN'; -------------------------------------------------------------------------------- /Frontend/src/app/static-pages/email-confirmation-page/email-confirmation-page.component.scss: -------------------------------------------------------------------------------- 1 | @forward "./../styles/spacer.scss"; 2 | @forward "./../../../styles/main-container.scss"; 3 | @forward "./../styles/static-page-variables.scss"; 4 | @forward "./../styles/auth.scss"; 5 | -------------------------------------------------------------------------------- /Frontend/src/app/static-pages/not-found-page/not-found-page.component.html: -------------------------------------------------------------------------------- 1 |
2 | 3 | 4 |
5 | 6 |
7 |
8 | 404 - Page not found 9 |
10 |
11 | 12 |
13 | 14 |
15 | 16 |
17 |
18 | -------------------------------------------------------------------------------- /Frontend/src/app/static-pages/not-found-page/not-found-page.component.ts: -------------------------------------------------------------------------------- 1 | import { CommonModule } from '@angular/common'; 2 | import { Component } from '@angular/core'; 3 | import { TopBarComponent } from '../shared/top-bar/top-bar.component'; 4 | import { FooterComponent } from '../shared/footer/footer.component'; 5 | 6 | @Component({ 7 | selector: 'app-not-found-page', 8 | imports: [ 9 | CommonModule, 10 | TopBarComponent, 11 | FooterComponent 12 | ], 13 | templateUrl: './not-found-page.component.html', 14 | styleUrl: './not-found-page.component.scss' 15 | }) 16 | export class NotFoundPageComponent { 17 | constructor() { 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Frontend/src/app/static-pages/privacy-policy/privacy-policy.component.html: -------------------------------------------------------------------------------- 1 |
2 | 3 | 4 |
5 | @if(entryPage.privacyPolicySafePath(); as safePath) { 6 | 7 |

Unable to display PDF file. Download instead.

8 |
9 | } 10 |
11 | 12 |
13 | 14 |
15 |
-------------------------------------------------------------------------------- /Frontend/src/app/static-pages/privacy-policy/privacy-policy.component.scss: -------------------------------------------------------------------------------- 1 | @forward "./../styles/spacer.scss"; 2 | @forward "./../styles/legal.scss"; 3 | @forward "./../../../styles/main-container.scss"; 4 | 5 | .pdf-container { 6 | flex: 1; 7 | display: flex; 8 | flex-direction: column; 9 | min-height: var(400px); 10 | } 11 | 12 | .pdf-object { 13 | flex: 1; 14 | width: 100%; 15 | min-height: 100%; 16 | } -------------------------------------------------------------------------------- /Frontend/src/app/static-pages/reset-password-page/reset-password-page.component.scss: -------------------------------------------------------------------------------- 1 | @forward "./../styles/spacer.scss"; 2 | @forward "./../../../styles/main-container.scss"; 3 | @forward "./../styles/static-page-variables.scss"; 4 | @forward "./../styles/auth.scss"; 5 | -------------------------------------------------------------------------------- /Frontend/src/app/static-pages/sign-in-page/sign-in-page.component.scss: -------------------------------------------------------------------------------- 1 | @forward "./../styles/spacer.scss"; 2 | @forward "./../../../styles/main-container.scss"; 3 | @forward "./../styles/auth.scss"; 4 | 5 | .text-center { 6 | text-align: center; 7 | } 8 | 9 | -------------------------------------------------------------------------------- /Frontend/src/app/static-pages/sign-up-page/sign-up-page.component.scss: -------------------------------------------------------------------------------- 1 | @forward "./../styles/spacer.scss"; 2 | @forward "./../../../styles/main-container.scss"; 3 | @forward "./../styles/static-page-variables.scss"; 4 | @forward "./../styles/auth.scss"; 5 | 6 | .checkbox-text { 7 | white-space: normal; 8 | display: inline; 9 | } 10 | 11 | .required { 12 | color: var(--company-danger); 13 | display: inline; 14 | white-space: nowrap; 15 | } -------------------------------------------------------------------------------- /Frontend/src/app/static-pages/styles/spacer.scss: -------------------------------------------------------------------------------- 1 | .spacer { 2 | margin-top: 6rem; 3 | 4 | @media (max-width: 768px) { 5 | margin-top: 4rem; 6 | } 7 | } -------------------------------------------------------------------------------- /Frontend/src/app/static-pages/styles/static-page-variables.scss: -------------------------------------------------------------------------------- 1 | $headerFontFamily: "League Spartan", sans-serif; -------------------------------------------------------------------------------- /Frontend/src/app/static-pages/styles/static-pages.scss: -------------------------------------------------------------------------------- 1 | @forward "./static-page-variables.scss"; 2 | 3 | 4 | .call-to-action-btn { 5 | border-radius: 100px !important; 6 | color: white !important; 7 | background: var(--company-blue) !important; 8 | padding: 1rem 1.6rem !important; 9 | font-size: 1.2rem !important; 10 | text-decoration: none; 11 | 12 | &:hover { 13 | background: var(--company-blue-dark) !important; 14 | } 15 | 16 | @media (max-width: 768px) { 17 | font-size: 1rem !important; 18 | } 19 | } -------------------------------------------------------------------------------- /Frontend/src/app/static-pages/terms/terms.component.html: -------------------------------------------------------------------------------- 1 |
2 | 3 | 4 |
5 | @if(entryPage.termsOfServiceSafePath(); as safePath) { 6 | 7 |

Unable to display PDF file. Download instead.

8 |
9 | } 10 |
11 | 12 |
13 | 14 |
15 |
-------------------------------------------------------------------------------- /Frontend/src/app/static-pages/terms/terms.component.scss: -------------------------------------------------------------------------------- 1 | @forward "./../styles/spacer.scss"; 2 | @forward "./../styles/legal.scss"; 3 | @forward "./../../../styles/main-container.scss"; 4 | 5 | .pdf-container { 6 | flex: 1; 7 | display: flex; 8 | flex-direction: column; 9 | min-height: var(400px); 10 | } 11 | 12 | .pdf-object { 13 | flex: 1; 14 | width: 100%; 15 | min-height: 100%; 16 | } -------------------------------------------------------------------------------- /Frontend/src/app/workspace-manager/boxes/box-details/box-team-invitation/box-team-invitation.component.scss: -------------------------------------------------------------------------------- 1 | @forward "./../../../../../styles/item-bar.scss"; 2 | @forward "./../../../../../styles/mobile-display.scss"; -------------------------------------------------------------------------------- /Frontend/src/app/workspace-manager/boxes/box-details/box-team-member/box-team-member.component.scss: -------------------------------------------------------------------------------- 1 | @forward "./../../../../../styles/item-bar.scss"; 2 | @forward "./../../../../../styles/mobile-display.scss"; -------------------------------------------------------------------------------- /Frontend/src/app/workspace-manager/boxes/boxes.component.scss: -------------------------------------------------------------------------------- 1 | @forward "./../../../styles/app-header.scss"; -------------------------------------------------------------------------------- /Frontend/src/app/workspace-manager/boxes/folder-picker/folder-picker.component.scss: -------------------------------------------------------------------------------- 1 | @forward "./../../../../styles/questionaire.scss"; 2 | 3 | 4 | .sticky-wrapper { 5 | background-color: white !important; 6 | } -------------------------------------------------------------------------------- /Frontend/src/app/workspace-manager/config/workspace-config.component.html: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 |
5 | Workspace configuration: 6 |
7 |
8 | 9 |
10 | 11 |
12 | 15 | 16 | 17 | 20 | 21 |
22 | -------------------------------------------------------------------------------- /Frontend/src/app/workspace-manager/config/workspace-config.component.scss: -------------------------------------------------------------------------------- 1 | @forward "./../../../styles/app-header.scss"; 2 | 3 | .config-container { 4 | display: flex; 5 | flex-direction: column; 6 | gap: 1.5rem; 7 | } 8 | -------------------------------------------------------------------------------- /Frontend/src/app/workspace-manager/explorer/explorer.component.scss: -------------------------------------------------------------------------------- 1 | .actions-bar { 2 | display: flex; 3 | flex-direction: row; 4 | gap: 0.5rem; 5 | } 6 | 7 | .file-input { 8 | display: none; 9 | } -------------------------------------------------------------------------------- /Frontend/src/app/workspace-manager/team/team.component.scss: -------------------------------------------------------------------------------- 1 | @forward "./../../../styles/app-header.scss"; -------------------------------------------------------------------------------- /Frontend/src/app/workspace-manager/team/workspace-team-invitation/workspace-team-invitation.component.scss: -------------------------------------------------------------------------------- 1 | @forward "./../../../../styles/item-bar.scss"; -------------------------------------------------------------------------------- /Frontend/src/app/workspace-manager/team/workspace-team-member/workspace-team-member.component.html: -------------------------------------------------------------------------------- 1 |
2 |
3 | 4 | 5 |
6 |
7 | {{ memberEmail() }} 8 |
9 |
10 |
11 | 12 |
13 | 17 | 18 |
19 |
-------------------------------------------------------------------------------- /Frontend/src/app/workspace-manager/team/workspace-team-member/workspace-team-member.component.scss: -------------------------------------------------------------------------------- 1 | @forward "./../../../../styles/item-bar.scss"; -------------------------------------------------------------------------------- /Frontend/src/app/workspace-manager/uploads/upload-list-item/upload-list-item.component.scss: -------------------------------------------------------------------------------- 1 | @forward "./../../../../styles/item-bar.scss"; 2 | 3 | .upload-progress { 4 | display: flex; 5 | flex-direction: row; 6 | align-items: center; 7 | gap: 0.5rem; 8 | height: 1rem; 9 | } -------------------------------------------------------------------------------- /Frontend/src/app/workspace-manager/uploads/uploads.component.html: -------------------------------------------------------------------------------- 1 |
2 |
3 | Your pending uploads: 4 |
5 |
6 | 7 |
8 | 9 | 10 | @if(fileUploadApi(); as fileUploadApiValue) { 11 | @for(upload of uploads(); track upload.externalId()) { 12 | 16 | 17 | } 18 | } -------------------------------------------------------------------------------- /Frontend/src/app/workspace-manager/uploads/uploads.component.scss: -------------------------------------------------------------------------------- 1 | @forward "./../../../styles/app-header.scss"; 2 | -------------------------------------------------------------------------------- /Frontend/src/app/workspaces/workspaces.component.scss: -------------------------------------------------------------------------------- 1 | @forward "./../../styles/hover-switch.scss"; 2 | @forward "./../../styles/app-header.scss"; 3 | @forward "./../../styles/top-bar.scss"; 4 | @forward "./../../styles/covered.scss"; 5 | @forward "./../../styles/top-nav-btn.scss"; 6 | 7 | .setup-explanation { 8 | font-size: 1rem; 9 | opacity: 0.8; 10 | padding-left: 0.5rem; 11 | } 12 | 13 | .step { 14 | padding-left: 1rem; 15 | 16 | &__number { 17 | font-weight: 600; 18 | } 19 | } -------------------------------------------------------------------------------- /Frontend/src/environments/environment.prod.ts: -------------------------------------------------------------------------------- 1 | export const environment = { 2 | production: true 3 | }; 4 | -------------------------------------------------------------------------------- /Frontend/src/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/damian-krychowski/plikshare/1b5717473495bb8e02108ac3409cec10eb8a9afe/Frontend/src/favicon.ico -------------------------------------------------------------------------------- /Frontend/src/main.ts: -------------------------------------------------------------------------------- 1 | import { bootstrapApplication } from '@angular/platform-browser'; 2 | import { appConfig } from './app/app.config'; 3 | import { AppComponent } from './app/app.component'; 4 | import { enableProdMode } from '@angular/core'; 5 | import { environment } from './environments/environment'; 6 | 7 | if (environment.production) { 8 | enableProdMode(); 9 | } 10 | 11 | bootstrapApplication(AppComponent, appConfig) 12 | .catch((err) => console.error(err)); 13 | -------------------------------------------------------------------------------- /Frontend/src/polyfills.ts: -------------------------------------------------------------------------------- 1 | /*************************************************************************************************** 2 | * APPLICATION IMPORTS 3 | */ 4 | (window as any).global = window; 5 | (window as any).process = { 6 | env: { DEBUG: undefined }, 7 | }; 8 | -------------------------------------------------------------------------------- /Frontend/src/robots.txt: -------------------------------------------------------------------------------- 1 | User-agent: * 2 | Disallow: / -------------------------------------------------------------------------------- /Frontend/src/styles/app-btn.scss: -------------------------------------------------------------------------------- 1 | .app-btn { 2 | width: 36px !important; 3 | height: 36px !important; 4 | min-width: 36px !important; 5 | padding: 0px !important; 6 | 7 | &--disabled { 8 | color: var(--mdc-filled-button-disabled-label-text-color) !important; 9 | background-color: var(--mdc-filled-button-disabled-container-color) !important; 10 | } 11 | } -------------------------------------------------------------------------------- /Frontend/src/styles/covered.scss: -------------------------------------------------------------------------------- 1 | .covered { 2 | position: relative; 3 | 4 | &::after { 5 | content: ""; 6 | position: absolute; 7 | background-color: var(--company-background); 8 | opacity: 0.5; 9 | top: 0; 10 | left: 0; 11 | right: 0; 12 | bottom: 0; 13 | z-index: 1; 14 | } 15 | } -------------------------------------------------------------------------------- /Frontend/src/styles/files-explorer-container.scss: -------------------------------------------------------------------------------- 1 | .files-explorer-container { 2 | border: 1px solid var(--company-grey-accent); 3 | padding: 1rem 1.5rem 0.5rem 1.5rem; 4 | } -------------------------------------------------------------------------------- /Frontend/src/styles/hover-switch.scss: -------------------------------------------------------------------------------- 1 | .hover-switch { 2 | &:hover { 3 | .hide-on-hover { 4 | display: none; 5 | } 6 | 7 | .show-on-hover { 8 | display: block; 9 | } 10 | } 11 | 12 | .hide-on-hover { 13 | display: block; 14 | } 15 | 16 | .show-on-hover { 17 | display: none; 18 | } 19 | } -------------------------------------------------------------------------------- /Frontend/src/styles/icon-merge.scss: -------------------------------------------------------------------------------- 1 | .icon-merge { 2 | position: relative; 3 | margin-right: -15px; 4 | 5 | &--back { 6 | position: absolute; 7 | top: 50%; 8 | transform: translateY(-50%); 9 | left: -18px; 10 | z-index: 1; 11 | } 12 | 13 | &--front { 14 | position: relative; 15 | z-index: 2; 16 | overflow: hidden; 17 | } 18 | } -------------------------------------------------------------------------------- /Frontend/src/styles/main-container.scss: -------------------------------------------------------------------------------- 1 | .main-container{ 2 | display: flex; 3 | flex-direction: column; 4 | min-height: 100vh; 5 | 6 | padding-top: 6rem; 7 | } -------------------------------------------------------------------------------- /Frontend/src/styles/nothing-to-show.scss: -------------------------------------------------------------------------------- 1 | .nothing-to-show { 2 | padding: 3rem; 3 | display: flex; 4 | flex-direction: column; 5 | min-height: 200px; 6 | justify-content: center; 7 | 8 | border: 2px dashed var(--company-grey-accent-light); 9 | 10 | &__label { 11 | margin-left: auto; 12 | margin-right: auto; 13 | 14 | font-size: 1.5rem; 15 | color: var(--company-grey-accent); 16 | } 17 | 18 | &--danger { 19 | border-color: var(--company-danger); 20 | 21 | .nothing-to-show__label { 22 | color: var(--company-danger); 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /Frontend/src/styles/top-bar.scss: -------------------------------------------------------------------------------- 1 | .top-bar { 2 | width: 100%; 3 | height: 60px; 4 | 5 | border: 1px solid var(--company-grey-accent-light); 6 | padding: 0.2rem 0.5rem; 7 | 8 | margin-top: 1rem; 9 | margin-bottom: 1rem; 10 | 11 | display: flex; 12 | flex-direction: row; 13 | align-items: center; 14 | 15 | background-color: white; 16 | 17 | &__header { 18 | display: flex; 19 | flex-direction: row; 20 | align-items: center; 21 | gap: 0.5rem; 22 | } 23 | 24 | &__title { 25 | font-size: 1rem; 26 | } 27 | 28 | &__subtitle { 29 | font-size: var(--company-small-font); 30 | color: var(--company-grey-font); 31 | } 32 | } -------------------------------------------------------------------------------- /Frontend/src/styles/variables.scss: -------------------------------------------------------------------------------- 1 | $mobile-breakpoint: 500px; 2 | $mobile-early-breakpoint: 800px; 3 | 4 | $company-blue-hover: #ecf2f7; 5 | $company-danger: #FF4D4F; -------------------------------------------------------------------------------- /Frontend/tsconfig.app.json: -------------------------------------------------------------------------------- 1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */ 2 | { 3 | "extends": "./tsconfig.json", 4 | "compilerOptions": { 5 | "outDir": "./out-tsc/app", 6 | "resolveJsonModule": true, 7 | "types": [] 8 | }, 9 | "files": [ 10 | "src/main.ts", 11 | "src/polyfills.ts", 12 | "src/bootstrap-elements.ts", 13 | ], 14 | "include": [ 15 | "src/**/*.d.ts" 16 | ] 17 | } 18 | -------------------------------------------------------------------------------- /Frontend/tsconfig.elements.json: -------------------------------------------------------------------------------- 1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */ 2 | { 3 | "extends": "./tsconfig.json", 4 | "compilerOptions": { 5 | "outDir": "./out-tsc/app", 6 | "resolveJsonModule": true, 7 | "types": [] 8 | }, 9 | "files": [ 10 | "src/polyfills.ts", 11 | "src/bootstrap-elements.ts", 12 | ], 13 | "include": [ 14 | "src/**/*.d.ts" 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /Frontend/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */ 2 | { 3 | "extends": "./tsconfig.json", 4 | "compilerOptions": { 5 | "outDir": "./out-tsc/spec", 6 | "types": [ 7 | "jasmine" 8 | ] 9 | }, 10 | "include": [ 11 | "src/**/*.spec.ts", 12 | "src/**/*.d.ts" 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /PlikShare.IntegrationTests/Infrastructure/Apis/BoxExternalAccessApi.cs: -------------------------------------------------------------------------------- 1 | using Flurl.Http; 2 | using PlikShare.Boxes.Id; 3 | using PlikShare.BoxExternalAccess.Contracts; 4 | 5 | namespace PlikShare.IntegrationTests.Infrastructure.Apis; 6 | 7 | public class BoxExternalAccessApi(IFlurlClient flurlClient, string appUrl) 8 | { 9 | public async Task GetHtml( 10 | BoxExtId boxExternalId, 11 | SessionAuthCookie? cookie) 12 | { 13 | return await flurlClient.ExecuteGet( 14 | appUrl: appUrl, 15 | apiPath: $"api/boxes/{boxExternalId}/html", 16 | cookie: cookie); 17 | } 18 | } -------------------------------------------------------------------------------- /PlikShare.IntegrationTests/Infrastructure/Apis/Cookie.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.IntegrationTests.Infrastructure.Apis; 2 | 3 | public abstract class Cookie 4 | { 5 | public abstract string Name { get; } 6 | public abstract string Value { get; } 7 | }; 8 | 9 | public abstract class Header 10 | { 11 | public abstract string Name { get; } 12 | public abstract string Value { get; } 13 | } -------------------------------------------------------------------------------- /PlikShare.IntegrationTests/Infrastructure/Apis/DashboardApi.cs: -------------------------------------------------------------------------------- 1 | using Flurl.Http; 2 | using PlikShare.Dashboard.Content.Contracts; 3 | 4 | namespace PlikShare.IntegrationTests.Infrastructure.Apis; 5 | 6 | public class DashboardApi(IFlurlClient flurlClient, string appUrl) 7 | { 8 | public async Task Get(SessionAuthCookie? cookie) 9 | { 10 | return await flurlClient.ExecuteGet( 11 | appUrl: appUrl, 12 | apiPath: "api/dashboard", 13 | cookie: cookie, 14 | isResponseInProtobuf: true); 15 | } 16 | } -------------------------------------------------------------------------------- /PlikShare.IntegrationTests/Infrastructure/Apis/EntryPageApi.cs: -------------------------------------------------------------------------------- 1 | using Flurl.Http; 2 | using PlikShare.EntryPage.Contracts; 3 | 4 | namespace PlikShare.IntegrationTests.Infrastructure.Apis; 5 | 6 | public class EntryPageApi(IFlurlClient flurlClient, string appUrl) 7 | { 8 | public async Task GetSettings(SessionAuthCookie? cookie) 9 | { 10 | return await flurlClient.ExecuteGet( 11 | appUrl: appUrl, 12 | apiPath: "api/entry-page", 13 | cookie: cookie); 14 | } 15 | } -------------------------------------------------------------------------------- /PlikShare.IntegrationTests/Infrastructure/Apis/GeneralSettingsApi.cs: -------------------------------------------------------------------------------- 1 | using Flurl.Http; 2 | using PlikShare.GeneralSettings.Contracts; 3 | 4 | namespace PlikShare.IntegrationTests.Infrastructure.Apis; 5 | 6 | public class GeneralSettingsApi(IFlurlClient flurlClient, string appUrl) 7 | { 8 | public async Task Get(SessionAuthCookie? cookie) 9 | { 10 | return await flurlClient.ExecuteGet( 11 | appUrl: appUrl, 12 | apiPath: "api/general-settings", 13 | cookie: cookie); 14 | } 15 | } -------------------------------------------------------------------------------- /PlikShare.IntegrationTests/Infrastructure/Apis/User.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.IntegrationTests.Infrastructure.Apis; 2 | 3 | public record User(string Email, string Password); -------------------------------------------------------------------------------- /PlikShare.IntegrationTests/Infrastructure/IntegrationTestsCollection.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.IntegrationTests.Infrastructure; 2 | 3 | [CollectionDefinition(Name)] 4 | public class IntegrationTestsCollection: ICollectionFixture 5 | { 6 | public const string Name = "IntegrationTests"; 7 | } 8 | -------------------------------------------------------------------------------- /PlikShare.IntegrationTests/Infrastructure/Mocks/ClockMock.cs: -------------------------------------------------------------------------------- 1 | using PlikShare.Core.Clock; 2 | 3 | namespace PlikShare.IntegrationTests.Infrastructure.Mocks; 4 | 5 | public class ClockMock : IClock 6 | { 7 | private DateTimeOffset? _utcNow; 8 | 9 | public void CurrentTime(DateTimeOffset utcNow) 10 | { 11 | _utcNow = utcNow; 12 | } 13 | 14 | public void SetToNow() 15 | { 16 | _utcNow = DateTimeOffset.UtcNow; 17 | } 18 | 19 | public DateTimeOffset UtcNow => _utcNow ?? DateTimeOffset.UtcNow; 20 | public DateTime Now => _utcNow?.DateTime ?? DateTime.Now; 21 | } -------------------------------------------------------------------------------- /PlikShare.IntegrationTests/Infrastructure/Mocks/OneTimeCodeMock.cs: -------------------------------------------------------------------------------- 1 | using PlikShare.Core.Utils; 2 | 3 | namespace PlikShare.IntegrationTests.Infrastructure.Mocks; 4 | 5 | public class OneTimeCodeMock : IOneTimeCode 6 | { 7 | private OneTimeCode _realOneTimeCode = new(); 8 | 9 | public string? Code { get; private set; } 10 | 11 | public void NextCodeToGenerate(string code) 12 | { 13 | Code = code; 14 | } 15 | 16 | public string Generate() 17 | { 18 | return Code ?? _realOneTimeCode.Generate(); 19 | } 20 | } -------------------------------------------------------------------------------- /PlikShare.Tests/.gitignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | *.*~ 3 | project.lock.json 4 | .DS_Store 5 | *.pyc 6 | nupkg/ 7 | 8 | # Visual Studio Code 9 | .vscode/ 10 | 11 | # Rider 12 | .idea/ 13 | 14 | # Visual Studio 15 | .vs/ 16 | 17 | # Fleet 18 | .fleet/ 19 | 20 | # Code Rush 21 | .cr/ 22 | 23 | # User-specific files 24 | *.suo 25 | *.user 26 | *.userosscache 27 | *.sln.docstates 28 | 29 | # Build results 30 | [Dd]ebug/ 31 | [Dd]ebugPublic/ 32 | [Rr]elease/ 33 | [Rr]eleases/ 34 | [Bb]in/ 35 | [Oo]bj/ 36 | x64/ 37 | x86/ 38 | build/ 39 | bld/ 40 | [Bb]in/ 41 | [Oo]bj/ 42 | [Oo]ut/ 43 | msbuild.log 44 | msbuild.err 45 | msbuild.wrn 46 | wwwroot/ 47 | /bin/ 48 | /obj/ 49 | -------------------------------------------------------------------------------- /PlikShare.Tests/GlobalUsings.cs: -------------------------------------------------------------------------------- 1 | global using Xunit; -------------------------------------------------------------------------------- /PlikShare.Tests/GuidBase62Tests.cs: -------------------------------------------------------------------------------- 1 | using FluentAssertions; 2 | using PlikShare.Core.Utils; 3 | 4 | namespace PlikShare.Tests; 5 | 6 | public class GuidBase62Tests 7 | { 8 | [Fact] 9 | public void can_convert_guid_to_base62_and_back() 10 | { 11 | var guid = Guid.NewGuid(); 12 | var base62 = guid.ToBase62(); 13 | var guidConvertedBack = GuidBase62.FromBase62ToGuid(base62); 14 | 15 | guidConvertedBack.Should().Be(guid); 16 | } 17 | } -------------------------------------------------------------------------------- /PlikShare/.gitignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | *.*~ 3 | project.lock.json 4 | .DS_Store 5 | *.pyc 6 | nupkg/ 7 | 8 | # Visual Studio Code 9 | .vscode/ 10 | 11 | # Rider 12 | .idea/ 13 | 14 | # Visual Studio 15 | .vs/ 16 | 17 | # Fleet 18 | .fleet/ 19 | 20 | # Code Rush 21 | .cr/ 22 | 23 | # User-specific files 24 | *.suo 25 | *.user 26 | *.userosscache 27 | *.sln.docstates 28 | 29 | # Build results 30 | [Dd]ebug/ 31 | [Dd]ebugPublic/ 32 | [Rr]elease/ 33 | [Rr]eleases/ 34 | [Bb]in/ 35 | [Oo]bj/ 36 | x64/ 37 | x86/ 38 | build/ 39 | bld/ 40 | [Bb]in/ 41 | [Oo]bj/ 42 | [Oo]ut/ 43 | msbuild.log 44 | msbuild.err 45 | msbuild.wrn 46 | wwwroot/ 47 | /bin/ 48 | /obj/ 49 | /volumes/ 50 | -------------------------------------------------------------------------------- /PlikShare/Account/Contracts/ChangePasswordRequestDto.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Account.Contracts; 2 | 3 | public record ChangePasswordRequestDto( 4 | string CurrentPassword, 5 | string NewPassword); 6 | 7 | public record ChangePasswordResponseDto(string Code) 8 | { 9 | public static ChangePasswordResponseDto Success => new ChangePasswordResponseDto("success"); 10 | public static ChangePasswordResponseDto Failed => new ChangePasswordResponseDto("failed"); 11 | public static ChangePasswordResponseDto PasswordMismatch => new ChangePasswordResponseDto("password-mismatch"); 12 | } -------------------------------------------------------------------------------- /PlikShare/Account/Contracts/Disable2FaResponseDto.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Account.Contracts; 2 | 3 | public record Disable2FaResponseDto(string Code) 4 | { 5 | public static Disable2FaResponseDto Disabled => new("disabled"); 6 | public static Disable2FaResponseDto Failed => new("failed"); 7 | } -------------------------------------------------------------------------------- /PlikShare/Account/Contracts/Enable2FaRequestDto.cs: -------------------------------------------------------------------------------- 1 | using PlikShare.Core.Utils; 2 | 3 | namespace PlikShare.Account.Contracts; 4 | 5 | public record Enable2FaRequestDto( 6 | string VerificationCode); 7 | 8 | public record Enable2FaResponseDto( 9 | string Code, 10 | List RecoveryCodes) 11 | { 12 | public const string EnabledCode = "enabled"; 13 | public static Enable2FaResponseDto Enabled(IEnumerable recoveryCodes) => new(EnabledCode, recoveryCodes.AsList()); 14 | public static Enable2FaResponseDto InvalidVerificationCode => new("invalid-verification-code", []); 15 | 16 | public static Enable2FaResponseDto Failed => new("failed", []); 17 | } -------------------------------------------------------------------------------- /PlikShare/Account/Contracts/GenerateRecoveryCodesResponseDto.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Account.Contracts; 2 | 3 | public record GenerateRecoveryCodesResponseDto( 4 | List RecoveryCodes); -------------------------------------------------------------------------------- /PlikShare/Account/Contracts/Get2FaStatusResponseDto.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Account.Contracts; 2 | 3 | public record Get2FaStatusResponseDto( 4 | bool IsEnabled, 5 | int? RecoveryCodesLeft, 6 | string? QrCodeUri); -------------------------------------------------------------------------------- /PlikShare/Account/Contracts/GetAccountDetailsResponseDto.cs: -------------------------------------------------------------------------------- 1 | using PlikShare.Users.Id; 2 | 3 | namespace PlikShare.Account.Contracts; 4 | 5 | public record GetAccountDetailsResponseDto( 6 | UserExtId ExternalId, 7 | string Email, 8 | GetAccountRolesResponseDto Roles, 9 | GetAccountPermissionsResponseDto Permissions, 10 | int? MaxWorkspaceNumber); 11 | 12 | public record GetAccountRolesResponseDto( 13 | bool IsAppOwner, 14 | bool IsAdmin); 15 | 16 | public record GetAccountPermissionsResponseDto( 17 | bool CanAddWorkspace, 18 | bool CanManageGeneralSettings, 19 | bool CanManageUsers, 20 | bool CanManageStorages, 21 | bool CanManageEmailProviders); -------------------------------------------------------------------------------- /PlikShare/Account/GetKnownUsers/Contracts/GetKnownUsersResponseDto.cs: -------------------------------------------------------------------------------- 1 | using PlikShare.Users.Id; 2 | 3 | namespace PlikShare.Account.GetKnownUsers.Contracts; 4 | 5 | public record GetKnownUsersResponseDto( 6 | KnownUserDto[] Items); 7 | 8 | public record KnownUserDto( 9 | UserExtId ExternalId, 10 | string Email); -------------------------------------------------------------------------------- /PlikShare/ApplicationSettings/GetStatus/Contracts/GetApplicationSettingsStatusResponseDto.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.ApplicationSettings.GetStatus.Contracts; 2 | 3 | public class GetApplicationSettingsStatusResponseDto 4 | { 5 | public required bool? IsEmailProviderConfigured { get; init; } 6 | public required bool? IsStorageConfigured { get; init; } 7 | } -------------------------------------------------------------------------------- /PlikShare/ArtificialIntelligence/AiIncludes/AiCompletion.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.ArtificialIntelligence.AiIncludes; 2 | 3 | public class AiCompletion 4 | { 5 | public required string Id { get; init; } 6 | public required string Text { get; init; } 7 | } -------------------------------------------------------------------------------- /PlikShare/ArtificialIntelligence/AiIncludes/AiInclude.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | using PlikShare.Files.Id; 3 | 4 | namespace PlikShare.ArtificialIntelligence.AiIncludes; 5 | 6 | [JsonDerivedType(derivedType: typeof(AiFileInclude), typeDiscriminator: "file")] 7 | [JsonDerivedType(derivedType: typeof(AiNotesInclude), typeDiscriminator: "notes")] 8 | [JsonDerivedType(derivedType: typeof(AiCommentsInclude), typeDiscriminator: "comments")] 9 | public abstract record AiInclude; 10 | 11 | public record AiFileInclude(FileExtId ExternalId) : AiInclude; 12 | public record AiNotesInclude(FileExtId ExternalId) : AiInclude; 13 | public record AiCommentsInclude(FileExtId ExternalId) : AiInclude; -------------------------------------------------------------------------------- /PlikShare/ArtificialIntelligence/DeleteConversation/QueueJob/DeleteAiConversationQueueJobDefinition.cs: -------------------------------------------------------------------------------- 1 | using PlikShare.ArtificialIntelligence.Id; 2 | 3 | namespace PlikShare.ArtificialIntelligence.DeleteConversation.QueueJob; 4 | 5 | public class DeleteAiConversationQueueJobDefinition 6 | { 7 | public required AiConversationExtId AiConversationExternalId { get; init; } 8 | } -------------------------------------------------------------------------------- /PlikShare/ArtificialIntelligence/DeleteConversation/QueueJob/DeleteAiConversationQueueJobType.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.ArtificialIntelligence.DeleteConversation.QueueJob; 2 | 3 | public static class DeleteAiConversationQueueJobType 4 | { 5 | public const string Value = "delete-ai-conversation"; 6 | } -------------------------------------------------------------------------------- /PlikShare/ArtificialIntelligence/GetMessages/AiMessageAuthorType.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.ArtificialIntelligence.GetMessages; 2 | 3 | public enum AiMessageAuthorType 4 | { 5 | Human, 6 | Ai 7 | } -------------------------------------------------------------------------------- /PlikShare/ArtificialIntelligence/SendFileMessage/QueueJob/SendAiMessageQueueJobDefinition.cs: -------------------------------------------------------------------------------- 1 | using PlikShare.ArtificialIntelligence.Id; 2 | 3 | namespace PlikShare.ArtificialIntelligence.SendFileMessage.QueueJob; 4 | 5 | public class SendAiMessageQueueJobDefinition 6 | { 7 | public required AiMessageExtId AiMessageExternalId{ get; init; } 8 | } -------------------------------------------------------------------------------- /PlikShare/ArtificialIntelligence/SendFileMessage/QueueJob/SendAiMessageQueueJobType.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.ArtificialIntelligence.SendFileMessage.QueueJob; 2 | 3 | public static class SendAiMessageQueueJobType 4 | { 5 | public const string Value = "send-ai-message"; 6 | } -------------------------------------------------------------------------------- /PlikShare/ArtificialIntelligence/UpdateConversationName/Contracts/UpdateAiConversationNameRequestDto.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.ArtificialIntelligence.UpdateConversationName.Contracts; 2 | 3 | public class UpdateAiConversationNameRequestDto 4 | { 5 | public required string Name { get; init; } 6 | } -------------------------------------------------------------------------------- /PlikShare/Auth/Contracts/ConfirmEmailRequestDto.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Auth.Contracts; 2 | 3 | public record ConfirmEmailRequestDto( 4 | string UserExternalId, 5 | string Code); 6 | 7 | public record ConfirmEmailResponseDto(string Code) 8 | { 9 | public static ConfirmEmailResponseDto InvalidToken => new("invalid-token"); 10 | public static ConfirmEmailResponseDto EmailConfirmed => new("email-confirmed"); 11 | }; 12 | -------------------------------------------------------------------------------- /PlikShare/Auth/Contracts/ForgotPasswordRequestDto.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Auth.Contracts; 2 | 3 | public record ForgotPasswordRequestDto( 4 | string Email); -------------------------------------------------------------------------------- /PlikShare/Auth/Contracts/ResendConfirmationLinkRequestDto.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Auth.Contracts; 2 | 3 | public record ResendConfirmationLinkRequestDto( 4 | string Email); 5 | 6 | public record ResendConfirmationLinkResponseDto(string Code) 7 | { 8 | public static ResendConfirmationLinkResponseDto ConfirmationEmailSent => new("confirmation-email-sent"); 9 | } -------------------------------------------------------------------------------- /PlikShare/Auth/Contracts/ResetPasswordRequestDto.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Auth.Contracts; 2 | 3 | public record ResetPasswordRequestDto( 4 | string UserExternalId, 5 | string Code, 6 | string NewPassword); 7 | 8 | public record ResetPasswordResponseDto(string Code) 9 | { 10 | public static ResetPasswordResponseDto InvalidToken => new("invalid-token"); 11 | public static ResetPasswordResponseDto PasswordReset => new("password-reset"); 12 | }; 13 | -------------------------------------------------------------------------------- /PlikShare/Auth/Contracts/SignInUser2FaRequestDto.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Auth.Contracts; 2 | 3 | public record SignInUser2FaRequestDto( 4 | string VerificationCode, 5 | bool RememberMe, 6 | bool RememberDevice); 7 | 8 | public record SignInUser2FaResponseDto(string Code) 9 | { 10 | public static SignInUser2FaResponseDto Successful => new("signed-in"); 11 | public static SignInUser2FaResponseDto Failed => new("sign-in-failed"); 12 | public static SignInUser2FaResponseDto InvalidVerificationCode => new("invalid-verification-code"); 13 | } -------------------------------------------------------------------------------- /PlikShare/Auth/Contracts/SignInUserRecoveryCodeRequestDto.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Auth.Contracts; 2 | 3 | public record SignInUserRecoveryCodeRequestDto( 4 | string RecoveryCode); 5 | 6 | public record SignInUserRecoveryCodeResponseDto(string Code) 7 | { 8 | public static SignInUserRecoveryCodeResponseDto Successful => new("signed-in"); 9 | public static SignInUserRecoveryCodeResponseDto Failed => new("sign-in-failed"); 10 | public static SignInUserRecoveryCodeResponseDto InvalidRecoveryCode => new("invalid-recovery-code"); 11 | } -------------------------------------------------------------------------------- /PlikShare/Auth/Contracts/SignInUserRequestDto.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Auth.Contracts; 2 | 3 | public record SignInUserRequestDto( 4 | string Email, 5 | string Password, 6 | bool RememberMe); 7 | 8 | public record SignInUserResponseDto(string Code) 9 | { 10 | public static SignInUserResponseDto Successful => new("signed-in"); 11 | public static SignInUserResponseDto Failed => new("sign-in-failed"); 12 | public static SignInUserResponseDto Required2Fa => new("2fa-required"); 13 | } -------------------------------------------------------------------------------- /PlikShare/BoxExternalAccess/Authorization/BoxAccessDetailsHttpContextExtensions.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.BoxExternalAccess.Authorization; 2 | 3 | public static class BoxAccessDetailsHttpContextExtensions 4 | { 5 | public static BoxAccess GetBoxAccess(this HttpContext httpContext) 6 | { 7 | var boxAccess = httpContext.Items[BoxAccess.HttpContextName]; 8 | 9 | if (boxAccess is not BoxAccess ba) 10 | { 11 | throw new InvalidOperationException( 12 | $"Cannot extract BoxAccess from HttpContext."); 13 | } 14 | 15 | return ba; 16 | } 17 | } -------------------------------------------------------------------------------- /PlikShare/BoxExternalAccess/Contracts/BoxBulkDeleteRequestDto.cs: -------------------------------------------------------------------------------- 1 | using PlikShare.Files.Id; 2 | using PlikShare.Folders.Id; 3 | using PlikShare.Uploads.Id; 4 | 5 | namespace PlikShare.BoxExternalAccess.Contracts; 6 | 7 | public record BoxBulkDeleteRequestDto( 8 | List FileExternalIds, 9 | List FolderExternalIds, 10 | List FileUploadExternalIds); -------------------------------------------------------------------------------- /PlikShare/BoxExternalAccess/Contracts/CompleteBoxFilePartUploadRequestDto.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.BoxExternalAccess.Contracts; 2 | 3 | public record CompleteBoxFilePartUploadRequestDto( 4 | string ETag); -------------------------------------------------------------------------------- /PlikShare/BoxExternalAccess/Contracts/CompleteBoxFileUploadResponseDto.cs: -------------------------------------------------------------------------------- 1 | using PlikShare.Files.Id; 2 | 3 | namespace PlikShare.BoxExternalAccess.Contracts; 4 | 5 | public record CompleteBoxFileUploadResponseDto(FileExtId FileExternalId); -------------------------------------------------------------------------------- /PlikShare/BoxExternalAccess/Contracts/GetBoxFileDownloadLinkResponseDto.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.BoxExternalAccess.Contracts; 2 | 3 | public record GetBoxFileDownloadLinkResponseDto( 4 | string DownloadPreSignedUrl); -------------------------------------------------------------------------------- /PlikShare/BoxExternalAccess/Contracts/GetBoxHtmlResponseDto.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.BoxExternalAccess.Contracts; 2 | 3 | public record GetBoxHtmlResponseDto( 4 | string? HeaderHtml, 5 | string? FooterHtml); -------------------------------------------------------------------------------- /PlikShare/BoxExternalAccess/Contracts/InitiateBoxFilePartUploadResponseDto.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.BoxExternalAccess.Contracts; 2 | 3 | public record InitiateBoxFilePartUploadResponseDto( 4 | string UploadPreSignedUrl, 5 | long StartsAtByte, 6 | long EndsAtByte, 7 | bool IsCompleteFilePartUploadCallbackRequired); -------------------------------------------------------------------------------- /PlikShare/BoxExternalAccess/Contracts/MoveBoxItemsToFolderRequestDto.cs: -------------------------------------------------------------------------------- 1 | using PlikShare.Files.Id; 2 | using PlikShare.Folders.Id; 3 | using PlikShare.Uploads.Id; 4 | 5 | namespace PlikShare.BoxExternalAccess.Contracts; 6 | 7 | public record MoveBoxItemsToFolderRequestDto( 8 | FileExtId[] FileExternalIds, 9 | FolderExtId[] FolderExternalIds, 10 | FileUploadExtId[] FileUploadExternalIds, 11 | FolderExtId? DestinationFolderExternalId); -------------------------------------------------------------------------------- /PlikShare/BoxExternalAccess/Contracts/UpdateBoxFileNameRequestDto.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.BoxExternalAccess.Contracts; 2 | 3 | public record UpdateBoxFileNameRequestDto( 4 | string Name); -------------------------------------------------------------------------------- /PlikShare/BoxExternalAccess/Contracts/UpdateBoxFileNameRequestValidator.cs: -------------------------------------------------------------------------------- 1 | using FluentValidation; 2 | 3 | namespace PlikShare.BoxExternalAccess.Contracts; 4 | 5 | public class UpdateBoxFileNameRequestValidator : AbstractValidator 6 | { 7 | public UpdateBoxFileNameRequestValidator() 8 | { 9 | RuleFor(x => x.Name).NotEmpty(); 10 | } 11 | } -------------------------------------------------------------------------------- /PlikShare/BoxExternalAccess/Contracts/UpdateBoxFolderNameRequestDto.cs: -------------------------------------------------------------------------------- 1 | using FluentValidation; 2 | 3 | namespace PlikShare.BoxExternalAccess.Contracts; 4 | 5 | public record UpdateBoxFolderNameRequestDto( 6 | string Name); 7 | 8 | public class UpdateAccessCodeFolderNameRequestValidator : AbstractValidator 9 | { 10 | public UpdateAccessCodeFolderNameRequestValidator() 11 | { 12 | RuleFor(x => x.Name).NotEmpty(); 13 | } 14 | } -------------------------------------------------------------------------------- /PlikShare/BoxLinks/Cache/BoxLinkContext.cs: -------------------------------------------------------------------------------- 1 | using PlikShare.Boxes.Cache; 2 | using PlikShare.Boxes.Permissions; 3 | using PlikShare.BoxLinks.Id; 4 | 5 | namespace PlikShare.BoxLinks.Cache; 6 | 7 | public record BoxLinkContext( 8 | int Id, 9 | BoxLinkExtId ExternalId, 10 | string Name, 11 | bool IsEnabled, 12 | BoxPermissions Permissions, 13 | BoxContext Box, 14 | List? WidgetOrigins); -------------------------------------------------------------------------------- /PlikShare/BoxLinks/RegenerateAccessCode/Contracts/RegenerateBoxLinkAccessCodeResponseDto.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.BoxLinks.RegenerateAccessCode.Contracts; 2 | 3 | public record RegenerateBoxLinkAccessCodeResponseDto( 4 | string AccessCode); -------------------------------------------------------------------------------- /PlikShare/BoxLinks/UpdateIsEnabled/Contracts/UpdateBoxLinkIsEnabledRequestDto.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.BoxLinks.UpdateIsEnabled.Contracts; 2 | 3 | public record UpdateBoxLinkIsEnabledRequestDto(bool IsEnabled); -------------------------------------------------------------------------------- /PlikShare/BoxLinks/UpdateName/Contracts/UpdateBoxLinkNameRequestDto.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.BoxLinks.UpdateName.Contracts; 2 | 3 | public record UpdateBoxLinkNameRequestDto( 4 | string Name); -------------------------------------------------------------------------------- /PlikShare/BoxLinks/UpdatePermissions/Contracts/UpdateBoxLinkPermissionsRequestDto.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.BoxLinks.UpdatePermissions.Contracts; 2 | 3 | public record UpdateBoxLinkPermissionsRequestDto( 4 | bool AllowDownload = false, 5 | bool AllowUpload = false, 6 | bool AllowList = false, 7 | bool AllowDeleteFile = false, 8 | bool AllowRenameFile = false, 9 | bool AllowMoveItems = false, 10 | bool AllowCreateFolder = false, 11 | bool AllowRenameFolder = false, 12 | bool AllowDeleteFolder = false); -------------------------------------------------------------------------------- /PlikShare/BoxLinks/UpdateWidgetOrigins/Contracts/UpdateBoxLinkWidgetOriginsRequestDto.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.BoxLinks.UpdateWidgetOrigins.Contracts; 2 | 3 | public class UpdateBoxLinkWidgetOriginsRequestDto 4 | { 5 | public required List WidgetOrigins { get; init; } 6 | } -------------------------------------------------------------------------------- /PlikShare/BoxLinks/Validation/BoxLinkDetailsHttpContextExtensions.cs: -------------------------------------------------------------------------------- 1 | using PlikShare.BoxLinks.Cache; 2 | 3 | namespace PlikShare.BoxLinks.Validation; 4 | 5 | public static class BoxLinkDetailsHttpContextExtensions 6 | { 7 | public static BoxLinkContext GetBoxLinkContext(this HttpContext httpContext) 8 | { 9 | var boxLink = httpContext.Items[ValidateBoxLinkFilter.BoxLinkContext]; 10 | 11 | if (boxLink is not BoxLinkContext context) 12 | { 13 | throw new InvalidOperationException( 14 | $"Cannot extract BoxContext from HttpContext."); 15 | } 16 | 17 | return context; 18 | } 19 | } -------------------------------------------------------------------------------- /PlikShare/Boxes/Cache/BoxContext.cs: -------------------------------------------------------------------------------- 1 | using PlikShare.Boxes.Id; 2 | using PlikShare.Folders.Id; 3 | using PlikShare.Workspaces.Cache; 4 | 5 | namespace PlikShare.Boxes.Cache; 6 | 7 | public record BoxContext( 8 | int Id, 9 | BoxExtId ExternalId, 10 | string Name, 11 | bool IsEnabled, 12 | bool IsBeingDeleted, 13 | WorkspaceContext Workspace, 14 | FolderContext? Folder); 15 | 16 | public record FolderContext( 17 | int Id, 18 | FolderExtId ExternalId); -------------------------------------------------------------------------------- /PlikShare/Boxes/Cache/BoxMembershipContext.cs: -------------------------------------------------------------------------------- 1 | using PlikShare.Boxes.Permissions; 2 | using PlikShare.Users.Cache; 3 | 4 | namespace PlikShare.Boxes.Cache; 5 | 6 | public record BoxMembershipContext( 7 | bool? WasInvitationAccepted, 8 | UserContext? Inviter, 9 | UserContext Member, 10 | BoxContext Box, 11 | BoxPermissions Permissions); -------------------------------------------------------------------------------- /PlikShare/Boxes/Create/Contracts/CreateBoxRequestDto.cs: -------------------------------------------------------------------------------- 1 | using PlikShare.Folders.Id; 2 | 3 | namespace PlikShare.Boxes.Create.Contracts; 4 | 5 | public record CreateBoxRequestDto( 6 | string Name, 7 | FolderExtId FolderExternalId); -------------------------------------------------------------------------------- /PlikShare/Boxes/Create/Contracts/CreateBoxResponseDto.cs: -------------------------------------------------------------------------------- 1 | using PlikShare.Boxes.Id; 2 | 3 | namespace PlikShare.Boxes.Create.Contracts; 4 | 5 | public record CreateBoxResponseDto( 6 | BoxExtId ExternalId); -------------------------------------------------------------------------------- /PlikShare/Boxes/CreateLink/Contracts/CreateBoxLinkRequestDto.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Boxes.CreateLink.Contracts; 2 | 3 | public record CreateBoxLinkRequestDto( 4 | string Name); -------------------------------------------------------------------------------- /PlikShare/Boxes/CreateLink/Contracts/CreateBoxLinkResponseDto.cs: -------------------------------------------------------------------------------- 1 | using PlikShare.BoxLinks.Id; 2 | 3 | namespace PlikShare.Boxes.CreateLink.Contracts; 4 | 5 | public record CreateBoxLinkResponseDto( 6 | BoxLinkExtId ExternalId, 7 | string AccessCode); -------------------------------------------------------------------------------- /PlikShare/Boxes/Delete/QueueJob/DeleteBoxesQueueJobDefinition.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Boxes.Delete.QueueJob; 2 | 3 | public record DeleteBoxesQueueJobDefinition( 4 | List BoxIds, 5 | int WorkspaceId); -------------------------------------------------------------------------------- /PlikShare/Boxes/Delete/QueueJob/DeleteBoxesQueueJobType.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Boxes.Delete.QueueJob; 2 | 3 | public static class DeleteBoxesQueueJobType 4 | { 5 | public const string Value = "delete-boxes"; 6 | } -------------------------------------------------------------------------------- /PlikShare/Boxes/List/Contracts/GetBoxesResponseDto.cs: -------------------------------------------------------------------------------- 1 | using PlikShare.Boxes.Id; 2 | 3 | namespace PlikShare.Boxes.List.Contracts; 4 | 5 | public class GetBoxesResponseDto 6 | { 7 | public required List Items { get; init; } 8 | 9 | public class Box 10 | { 11 | public required BoxExtId ExternalId { get; init; } 12 | public required string Name { get; init; } 13 | public required bool IsEnabled { get; init; } 14 | public required List FolderPath { get; init; } 15 | } 16 | 17 | public class FolderItem 18 | { 19 | public required string ExternalId { get; init; } 20 | public required string Name { get; init; } 21 | } 22 | } -------------------------------------------------------------------------------- /PlikShare/Boxes/Members/CreateInvitation/Contracts/CreateBoxInvitationRequestDto.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Boxes.Members.CreateInvitation.Contracts; 2 | 3 | public record CreateBoxInvitationRequestDto( 4 | List MemberEmails); -------------------------------------------------------------------------------- /PlikShare/Boxes/Members/CreateInvitation/Contracts/CreateBoxInvitationResponseDto.cs: -------------------------------------------------------------------------------- 1 | using PlikShare.Users.Id; 2 | 3 | namespace PlikShare.Boxes.Members.CreateInvitation.Contracts; 4 | 5 | public class CreateBoxInvitationResponseDto 6 | { 7 | public required List Members { get; set; } 8 | 9 | public record BoxInvitationMember( 10 | string Email, 11 | UserExtId ExternalId); 12 | } -------------------------------------------------------------------------------- /PlikShare/Boxes/Members/UpdatePermissions/Contracts/UpdateBoxMemberPermissionsRequestDto.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Boxes.Members.UpdatePermissions.Contracts; 2 | 3 | public class UpdateBoxMemberPermissionsRequestDto 4 | { 5 | public bool AllowDownload { get; set; } 6 | public bool AllowUpload { get; set; } 7 | public bool AllowList { get; set; } 8 | public bool AllowDeleteFile { get; set; } 9 | public bool AllowRenameFile { get; set; } 10 | public bool AllowMoveItems { get; set; } 11 | public bool AllowCreateFolder { get; set; } 12 | public bool AllowRenameFolder { get; set; } 13 | public bool AllowDeleteFolder { get; set; } 14 | } -------------------------------------------------------------------------------- /PlikShare/Boxes/UpdateFolder/Contracts/UpdateBoxFolderRequestDto.cs: -------------------------------------------------------------------------------- 1 | using PlikShare.Folders.Id; 2 | 3 | namespace PlikShare.Boxes.UpdateFolder.Contracts; 4 | 5 | public record UpdateBoxFolderRequestDto( 6 | FolderExtId FolderExternalId); -------------------------------------------------------------------------------- /PlikShare/Boxes/UpdateFooter/Contracts/UpdateBoxFooterRequestDto.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Boxes.UpdateFooter.Contracts; 2 | 3 | public record UpdateBoxFooterRequestDto( 4 | string Json, 5 | string Html); -------------------------------------------------------------------------------- /PlikShare/Boxes/UpdateFooterIsEnabled/Contracts/UpdateBoxFooterIsEnabledRequestDto.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Boxes.UpdateFooterIsEnabled.Contracts; 2 | 3 | public record UpdateBoxFooterIsEnabledRequestDto(bool IsEnabled); -------------------------------------------------------------------------------- /PlikShare/Boxes/UpdateHeader/Contracts/UpdateBoxFooterRequestDto.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Boxes.UpdateHeader.Contracts; 2 | 3 | public record UpdateBoxHeaderRequestDto( 4 | string Json, 5 | string Html); -------------------------------------------------------------------------------- /PlikShare/Boxes/UpdateHeaderIsEnabled/Contracts/UpdateBoxHeaderIsEnabledRequestDto.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Boxes.UpdateHeaderIsEnabled.Contracts; 2 | 3 | public record UpdateBoxHeaderIsEnabledRequestDto( 4 | bool IsEnabled); -------------------------------------------------------------------------------- /PlikShare/Boxes/UpdateIsEnabled/Contracts/UpdateBoxIsEnabledRequestDto.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Boxes.UpdateIsEnabled.Contracts; 2 | 3 | public record UpdateBoxIsEnabledRequestDto(bool IsEnabled); -------------------------------------------------------------------------------- /PlikShare/Boxes/UpdateName/Contracts/UpdateBoxNameRequestDto.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Boxes.UpdateName.Contracts; 2 | 3 | public record UpdateBoxNameRequestDto( 4 | string Name); -------------------------------------------------------------------------------- /PlikShare/Boxes/Validation/BoxHttpContextExtensions.cs: -------------------------------------------------------------------------------- 1 | using PlikShare.Boxes.Cache; 2 | 3 | namespace PlikShare.Boxes.Validation; 4 | 5 | public static class BoxHttpContextExtensions 6 | { 7 | public static BoxContext GetBoxContext(this HttpContext httpContext) 8 | { 9 | var box = httpContext.Items[ValidateBoxFilter.BoxContext]; 10 | 11 | if (box is not BoxContext context) 12 | { 13 | throw new InvalidOperationException( 14 | $"Cannot extract BoxContext from HttpContext."); 15 | } 16 | 17 | return context; 18 | } 19 | } -------------------------------------------------------------------------------- /PlikShare/BulkDelete/Contracts/BulkDeleteRequestDto.cs: -------------------------------------------------------------------------------- 1 | using PlikShare.Files.Id; 2 | using PlikShare.Folders.Id; 3 | using PlikShare.Uploads.Id; 4 | 5 | namespace PlikShare.BulkDelete.Contracts; 6 | 7 | public class BulkDeleteRequestDto 8 | { 9 | public required List FileExternalIds { get; init; } 10 | public required List FolderExternalIds { get; init; } 11 | public required List FileUploadExternalIds { get; init; } 12 | } 13 | 14 | public class BulkDeleteResponseDto 15 | { 16 | public required long? NewWorkspaceSizeInBytes { get; init; } 17 | } -------------------------------------------------------------------------------- /PlikShare/Core/Authorization/RequireAdminClaimAttribute.cs: -------------------------------------------------------------------------------- 1 | using System.Security.Claims; 2 | using Microsoft.AspNetCore.Mvc; 3 | 4 | namespace PlikShare.Core.Authorization; 5 | 6 | public class RequireAdminClaimAttribute : TypeFilterAttribute 7 | { 8 | public RequireAdminClaimAttribute(string claimType, string claimValue) : base(typeof(RequireAdminClaimFilter)) 9 | { 10 | Arguments = [new Claim(claimType, claimValue)]; 11 | } 12 | } -------------------------------------------------------------------------------- /PlikShare/Core/Authorization/RequireAdminPermissionAttribute.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Core.Authorization; 2 | 3 | public class RequireAdminPermissionAttribute(string permission) 4 | : RequireAdminClaimAttribute("permission", permission); -------------------------------------------------------------------------------- /PlikShare/Core/Authorization/RequireAppOwnerAttribute.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Mvc; 2 | 3 | namespace PlikShare.Core.Authorization; 4 | 5 | public class RequireAppOwnerAttribute() : TypeFilterAttribute(typeof(RequireAppOwnerFilter)); -------------------------------------------------------------------------------- /PlikShare/Core/Authorization/RequireClaimAttribute.cs: -------------------------------------------------------------------------------- 1 | using System.Security.Claims; 2 | using Microsoft.AspNetCore.Mvc; 3 | 4 | namespace PlikShare.Core.Authorization; 5 | 6 | public class RequireClaimAttribute : TypeFilterAttribute 7 | { 8 | public RequireClaimAttribute(string claimType, string claimValue) : base(typeof(RequireClaimFilter)) 9 | { 10 | Arguments = [new Claim(claimType, claimValue)]; 11 | } 12 | } -------------------------------------------------------------------------------- /PlikShare/Core/Authorization/RequirePermissionAttribute.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Core.Authorization; 2 | 3 | public class RequirePermissionAttribute(string permission) 4 | : RequireClaimAttribute("permission", permission); -------------------------------------------------------------------------------- /PlikShare/Core/Authorization/Roles.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Core.Authorization; 2 | 3 | public class Roles 4 | { 5 | public const string Admin = "admin"; 6 | public const string AdminNormalized = "ADMIN"; 7 | 8 | 9 | public static bool IsValidRole(string role) => role == Admin; 10 | } -------------------------------------------------------------------------------- /PlikShare/Core/Clock/Clock.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Core.Clock; 2 | 3 | public class Clock: IClock 4 | { 5 | public DateTimeOffset UtcNow => DateTimeOffset.UtcNow; 6 | public DateTime Now => DateTime.Now; 7 | } -------------------------------------------------------------------------------- /PlikShare/Core/Clock/IClock.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Core.Clock; 2 | 3 | public interface IClock 4 | { 5 | DateTimeOffset UtcNow { get; } 6 | DateTime Now { get; } 7 | } -------------------------------------------------------------------------------- /PlikShare/Core/Configuration/AppConfig.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Core.Configuration; 2 | 3 | public class AppConfig : IConfig 4 | { 5 | public AppConfig(IConfiguration configuration) 6 | { 7 | QueueProcessingBatchSize = int.Parse( 8 | configuration.GetSection("Queue").GetSection("ProcessingBatchSize").Value ?? 9 | throw new InvalidOperationException("Config for 'Queue.ProcessingBatchSize' not found.")); 10 | 11 | AppUrl = configuration.GetValue("AppUrl") ?? 12 | throw new InvalidOperationException("Config for 'AppUrl' not found."); 13 | } 14 | 15 | public int QueueProcessingBatchSize { get; } 16 | 17 | 18 | public string AppUrl { get; } 19 | } -------------------------------------------------------------------------------- /PlikShare/Core/Configuration/IConfig.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Core.Configuration; 2 | 3 | public interface IConfig 4 | { 5 | int QueueProcessingBatchSize { get; } 6 | 7 | string AppUrl { get; } 8 | } -------------------------------------------------------------------------------- /PlikShare/Core/CorrelationId/HttpContextCorrelationIdExtensions.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Core.CorrelationId; 2 | 3 | public static class HttpContextCorrelationIdExtensions 4 | { 5 | public static Guid GetCorrelationId(this HttpContext context) 6 | { 7 | if (Guid.TryParse(context.TraceIdentifier, out var correlationId)) 8 | { 9 | return correlationId; 10 | } 11 | 12 | throw new InvalidOperationException("CorrelationId is missing in the httpContext"); 13 | } 14 | } -------------------------------------------------------------------------------- /PlikShare/Core/Database/AiDatabase/Migrations/Migration_Ai_01_InitialDbSetup.cs: -------------------------------------------------------------------------------- 1 | using PlikShare.Core.Database.AiDatabase; 2 | using PlikShare.Core.SQLite; 3 | 4 | namespace PlikShare.Core.Database.MainDatabase.Migrations; 5 | 6 | public class Migration_Ai_01_InitialDbSetup: SQLiteMigrationBase 7 | { 8 | public override string Name => "initial_ai_db_setup"; 9 | public override DateOnly Date { get; } = new(2025, 2, 23); 10 | public override PlikShareDbType Type { get; } = PlikShareAiDb.Type; 11 | 12 | protected override string[] ManifestResourceNames { get; } = 13 | [ 14 | "PlikShare.Core.Database.AiDatabase.Migrations.01_initial_ai_db_structure_migration.sql" 15 | ]; 16 | } -------------------------------------------------------------------------------- /PlikShare/Core/Database/MainDatabase/Migrations/02_files_created_at_folders_created_at_and_creator.sql: -------------------------------------------------------------------------------- 1 | -- 1. Add fi_created_at to fi_files 2 | ALTER TABLE fi_files ADD COLUMN fi_created_at TEXT NULL; 3 | 4 | -- 2. Add new columns to fo_folders 5 | ALTER TABLE fo_folders ADD COLUMN fo_created_at TEXT NULL; 6 | ALTER TABLE fo_folders ADD COLUMN fo_creator_identity_type TEXT NULL; 7 | ALTER TABLE fo_folders ADD COLUMN fo_creator_identity TEXT NULL; 8 | CREATE INDEX IF NOT EXISTS index__fo_folders__fo_creator_identity_and_type ON fo_folders (fo_creator_identity_type, fo_creator_identity); -------------------------------------------------------------------------------- /PlikShare/Core/Database/MainDatabase/Migrations/04_file_upload_is_completed_introduced.sql: -------------------------------------------------------------------------------- 1 | -- 1. fu_file_uploads table changes 2 | ALTER TABLE fu_file_uploads ADD COLUMN fu_is_completed BOOLEAN DEFAULT FALSE NOT NULL; -------------------------------------------------------------------------------- /PlikShare/Core/Database/MainDatabase/Migrations/09_files_parent_file_id_column_introduced.sql: -------------------------------------------------------------------------------- 1 | ALTER TABLE fi_files ADD COLUMN fi_parent_file_id INTEGER NULL REFERENCES fi_files(fi_id); 2 | CREATE INDEX IF NOT EXISTS index__fi_files__fi_parent_file_id ON fi_files (fi_parent_file_id); -------------------------------------------------------------------------------- /PlikShare/Core/Database/MainDatabase/Migrations/10_files_metadata_column_introduced.sql: -------------------------------------------------------------------------------- 1 | ALTER TABLE fi_files ADD COLUMN fi_metadata BLOB NULL; -------------------------------------------------------------------------------- /PlikShare/Core/Database/MainDatabase/Migrations/11_file_uploads_parent_file_id_and_metadata_columns_introduced.sql: -------------------------------------------------------------------------------- 1 | ALTER TABLE fu_file_uploads ADD COLUMN fu_parent_file_id INTEGER NULL REFERENCES fi_files(fi_id); 2 | ALTER TABLE fu_file_uploads ADD COLUMN fu_file_metadata BLOB NULL; 3 | CREATE INDEX IF NOT EXISTS index__fu_file_uploads__fu_parent_file_id ON fu_file_uploads (fu_parent_file_id); -------------------------------------------------------------------------------- /PlikShare/Core/Database/MainDatabase/Migrations/12_queue_sagas_table_introduced.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE IF NOT EXISTS qs_queue_sagas 2 | ( 3 | qs_id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, 4 | qs_on_completed_queue_job_type TEXT NOT NULL, 5 | qs_on_completed_queue_job_definition TEXT NOT NULL , 6 | qs_correlation_id TEXT NOT NULL 7 | ); 8 | 9 | ALTER TABLE q_queue ADD COLUMN q_saga_id INTEGER NULL REFERENCES qs_queue_sagas(qs_id); 10 | CREATE INDEX IF NOT EXISTS index__q_queue__q_saga_id ON q_queue (q_saga_id); -------------------------------------------------------------------------------- /PlikShare/Core/Database/MainDatabase/Migrations/16_sign_up_checkboxes_introduced.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE IF NOT EXISTS suc_sign_up_checkboxes 2 | ( 3 | suc_id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, 4 | suc_text TEXT NOT NULL, 5 | suc_is_required BOOLEAN NOT NULL, 6 | suc_is_deleted BOOLEAN NOT NULL 7 | ); 8 | 9 | CREATE TABLE IF NOT EXISTS usuc_user_sign_up_checkboxes 10 | ( 11 | usuc_user_id INTEGER NOT NULL, 12 | usuc_sign_up_checkbox_id INTEGER NOT NULL, 13 | 14 | PRIMARY KEY (usuc_user_id, usuc_sign_up_checkbox_id), 15 | FOREIGN KEY (usuc_user_id) REFERENCES u_users (u_id), 16 | FOREIGN KEY (usuc_sign_up_checkbox_id) REFERENCES suc_sign_up_checkboxes (suc_id) 17 | ); -------------------------------------------------------------------------------- /PlikShare/Core/Database/MainDatabase/Migrations/17_workspace_max_size_column_introduced.sql: -------------------------------------------------------------------------------- 1 | ALTER TABLE w_workspaces ADD COLUMN w_max_size_in_bytes INTEGER NULL; 2 | 3 | -- Create optimized indexes for workspace size calculation 4 | CREATE INDEX index__fu_file_uploads__fu_workspace_id__fu_file_size_in_bytes__fu_folder_id ON fu_file_uploads(fu_workspace_id, fu_file_size_in_bytes, fu_folder_id); 5 | CREATE INDEX index__fi_files__fi_workspace_id__fi_size_in_bytes__fi_folder_id ON fi_files(fi_workspace_id, fi_size_in_bytes, fi_folder_id); -------------------------------------------------------------------------------- /PlikShare/Core/Database/MainDatabase/Migrations/18_user_max_workspace_number_and_max_workspace_size_columns_introduced.sql: -------------------------------------------------------------------------------- 1 | ALTER TABLE u_users ADD COLUMN u_max_workspace_number INTEGER NULL; 2 | ALTER TABLE u_users ADD COLUMN u_default_max_workspace_size_in_bytes INTEGER NULL; -------------------------------------------------------------------------------- /PlikShare/Core/Database/MainDatabase/Migrations/19_max_workspace_team_members_columns_introduced.sql: -------------------------------------------------------------------------------- 1 | ALTER TABLE w_workspaces ADD COLUMN w_max_team_members INTEGER NULL; 2 | ALTER TABLE u_users ADD COLUMN u_default_max_workspace_team_members INTEGER NULL; -------------------------------------------------------------------------------- /PlikShare/Core/Database/MainDatabase/Migrations/20_widget_origins_column_added_to_box_links_table.sql: -------------------------------------------------------------------------------- 1 | ALTER TABLE bl_box_links ADD COLUMN bl_widget_origins TEXT NULL; -------------------------------------------------------------------------------- /PlikShare/Core/Database/MainDatabase/Migrations/Migration_01_InitialDbSetup.cs: -------------------------------------------------------------------------------- 1 | using PlikShare.Core.Database; 2 | using PlikShare.Core.Database.MainDatabase; 3 | using PlikShare.Core.SQLite; 4 | 5 | namespace PlikShare.Core.Database.MainDatabase.Migrations; 6 | 7 | public class Migration_01_InitialDbSetup: SQLiteMigrationBase 8 | { 9 | public override string Name => "initial_db_setup"; 10 | public override DateOnly Date { get; } = new(2024, 6, 7); 11 | public override PlikShareDbType Type { get; } = PlikShareDb.Type; 12 | 13 | protected override string[] ManifestResourceNames { get; } = 14 | [ 15 | "PlikShare.Core.Database.MainDatabase.Migrations.01_initial_db_structure_migration.sql" 16 | ]; 17 | } -------------------------------------------------------------------------------- /PlikShare/Core/Database/MainDatabase/Migrations/Migration_03_StorageEncryptionIntoruced.cs: -------------------------------------------------------------------------------- 1 | using PlikShare.Core.SQLite; 2 | 3 | namespace PlikShare.Core.Database.MainDatabase.Migrations; 4 | 5 | public class Migration_03_StorageEncryptionIntoruced: SQLiteMigrationBase 6 | { 7 | public override string Name => "storage_encryption_introduced"; 8 | public override DateOnly Date { get; } = new(2024, 11, 20); 9 | public override PlikShareDbType Type { get; } = PlikShareDb.Type; 10 | 11 | protected override string[] ManifestResourceNames { get; } = 12 | [ 13 | "PlikShare.Core.Database.MainDatabase.Migrations.03_storage_encryption_introduced.sql" 14 | ]; 15 | } -------------------------------------------------------------------------------- /PlikShare/Core/Database/MainDatabase/Migrations/Migration_04_FileUploadIsCompletedIntroduced.cs: -------------------------------------------------------------------------------- 1 | using PlikShare.Core.SQLite; 2 | 3 | namespace PlikShare.Core.Database.MainDatabase.Migrations; 4 | 5 | public class Migration_04_FileUploadIsCompletedIntroduced: SQLiteMigrationBase 6 | { 7 | public override string Name => "file_upload_is_completed_introduced"; 8 | public override DateOnly Date { get; } = new(2024, 11, 23); 9 | public override PlikShareDbType Type { get; } = PlikShareDb.Type; 10 | 11 | protected override string[] ManifestResourceNames { get; } = 12 | [ 13 | "PlikShare.Core.Database.MainDatabase.Migrations.04_file_upload_is_completed_introduced.sql" 14 | ]; 15 | } -------------------------------------------------------------------------------- /PlikShare/Core/Database/MainDatabase/Migrations/Migration_05_FileArtifactsIntroduced.cs: -------------------------------------------------------------------------------- 1 | using PlikShare.Core.SQLite; 2 | 3 | namespace PlikShare.Core.Database.MainDatabase.Migrations; 4 | 5 | public class Migration_05_FileArtifactsIntroduced: SQLiteMigrationBase 6 | { 7 | public override string Name => "file_artifacts_table_introduced"; 8 | public override DateOnly Date { get; } = new(2024, 12, 1); 9 | public override PlikShareDbType Type { get; } = PlikShareDb.Type; 10 | 11 | protected override string[] ManifestResourceNames { get; } = 12 | [ 13 | "PlikShare.Core.Database.MainDatabase.Migrations.05_file_artifacts_table_introduced.sql" 14 | ]; 15 | } -------------------------------------------------------------------------------- /PlikShare/Core/Database/MainDatabase/Migrations/Migration_06_IntegrationsTableIntroduced.cs: -------------------------------------------------------------------------------- 1 | using PlikShare.Core.SQLite; 2 | 3 | namespace PlikShare.Core.Database.MainDatabase.Migrations; 4 | 5 | public class Migration_06_IntegrationsTableIntroduced: SQLiteMigrationBase 6 | { 7 | public override string Name => "integrations_table_introduced"; 8 | public override DateOnly Date { get; } = new(2024, 12, 31); 9 | public override PlikShareDbType Type { get; } = PlikShareDb.Type; 10 | 11 | protected override string[] ManifestResourceNames { get; } = 12 | [ 13 | "PlikShare.Core.Database.MainDatabase.Migrations.06_integrations_table_introduced.sql" 14 | ]; 15 | } -------------------------------------------------------------------------------- /PlikShare/Core/Database/MainDatabase/Migrations/Migration_07_IntegrationsTextractJobsTableIntroduced.cs: -------------------------------------------------------------------------------- 1 | using PlikShare.Core.SQLite; 2 | 3 | namespace PlikShare.Core.Database.MainDatabase.Migrations; 4 | 5 | public class Migration_07_IntegrationsTextractJobsTableIntroduced: SQLiteMigrationBase 6 | { 7 | public override string Name => "integrations_textract_jobs_table_introduced"; 8 | public override DateOnly Date { get; } = new(2025, 1, 7); 9 | public override PlikShareDbType Type { get; } = PlikShareDb.Type; 10 | 11 | protected override string[] ManifestResourceNames { get; } = 12 | [ 13 | "PlikShare.Core.Database.MainDatabase.Migrations.07_integrations_textract_jobs_table_introduced.sql" 14 | ]; 15 | } -------------------------------------------------------------------------------- /PlikShare/Core/Database/MainDatabase/Migrations/Migration_08_CopyFileQueueTableIntroduced.cs: -------------------------------------------------------------------------------- 1 | using PlikShare.Core.SQLite; 2 | 3 | namespace PlikShare.Core.Database.MainDatabase.Migrations; 4 | 5 | public class Migration_08_CopyFileQueueTableIntroduced: SQLiteMigrationBase 6 | { 7 | public override string Name => "copy_file_queue_table_introduced"; 8 | public override DateOnly Date { get; } = new(2025, 1, 8); 9 | public override PlikShareDbType Type { get; } = PlikShareDb.Type; 10 | 11 | protected override string[] ManifestResourceNames { get; } = 12 | [ 13 | "PlikShare.Core.Database.MainDatabase.Migrations.08_copy_file_queue_table_introduced.sql" 14 | ]; 15 | } -------------------------------------------------------------------------------- /PlikShare/Core/Database/MainDatabase/Migrations/Migration_09_FilesParentFileIdColumnIntroduced.cs: -------------------------------------------------------------------------------- 1 | using PlikShare.Core.SQLite; 2 | 3 | namespace PlikShare.Core.Database.MainDatabase.Migrations; 4 | 5 | public class Migration_09_FilesParentFileIdColumnIntroduced : SQLiteMigrationBase 6 | { 7 | public override string Name => "files_parent_file_id_column_introduced"; 8 | public override DateOnly Date { get; } = new(2025, 1, 19); 9 | public override PlikShareDbType Type { get; } = PlikShareDb.Type; 10 | 11 | protected override string[] ManifestResourceNames { get; } = 12 | [ 13 | "PlikShare.Core.Database.MainDatabase.Migrations.09_files_parent_file_id_column_introduced.sql" 14 | ]; 15 | } -------------------------------------------------------------------------------- /PlikShare/Core/Database/MainDatabase/Migrations/Migration_10_FilesMetadataColumnIntroduced.cs: -------------------------------------------------------------------------------- 1 | using PlikShare.Core.SQLite; 2 | 3 | namespace PlikShare.Core.Database.MainDatabase.Migrations; 4 | 5 | public class Migration_10_FilesMetadataColumnIntroduced : SQLiteMigrationBase 6 | { 7 | public override string Name => "files_metadata_column_introduced"; 8 | public override DateOnly Date { get; } = new(2025, 1, 21); 9 | public override PlikShareDbType Type { get; } = PlikShareDb.Type; 10 | 11 | protected override string[] ManifestResourceNames { get; } = 12 | [ 13 | "PlikShare.Core.Database.MainDatabase.Migrations.10_files_metadata_column_introduced.sql" 14 | ]; 15 | } -------------------------------------------------------------------------------- /PlikShare/Core/Database/MainDatabase/Migrations/Migration_12_QueueSagasTableIntroduced.cs: -------------------------------------------------------------------------------- 1 | using PlikShare.Core.SQLite; 2 | 3 | namespace PlikShare.Core.Database.MainDatabase.Migrations; 4 | 5 | public class Migration_12_QueueSagasTableIntroduced : SQLiteMigrationBase 6 | { 7 | public override string Name => "queue_sagas_table_introduced"; 8 | public override DateOnly Date { get; } = new(2025, 1, 26); 9 | public override PlikShareDbType Type { get; } = PlikShareDb.Type; 10 | 11 | protected override string[] ManifestResourceNames { get; } = 12 | [ 13 | "PlikShare.Core.Database.MainDatabase.Migrations.12_queue_sagas_table_introduced.sql" 14 | ]; 15 | } -------------------------------------------------------------------------------- /PlikShare/Core/Database/MainDatabase/Migrations/Migration_13_FilesAndFoldersLookupIndicesIntroduced.cs: -------------------------------------------------------------------------------- 1 | using PlikShare.Core.SQLite; 2 | 3 | namespace PlikShare.Core.Database.MainDatabase.Migrations; 4 | 5 | public class Migration_13_FilesAndFoldersLookupIndicesIntroduced : SQLiteMigrationBase 6 | { 7 | public override string Name => "files_and_folders_lookup_indices_introduced"; 8 | public override DateOnly Date { get; } = new(2025, 2, 8); 9 | public override PlikShareDbType Type { get; } = PlikShareDb.Type; 10 | 11 | protected override string[] ManifestResourceNames { get; } = 12 | [ 13 | "PlikShare.Core.Database.MainDatabase.Migrations.13_files_and_folders_lookup_indices_introduced.sql" 14 | ]; 15 | } -------------------------------------------------------------------------------- /PlikShare/Core/Database/MainDatabase/Migrations/Migration_14_WorkspaceIdAddedToIntegrationsTable.cs: -------------------------------------------------------------------------------- 1 | using PlikShare.Core.SQLite; 2 | 3 | namespace PlikShare.Core.Database.MainDatabase.Migrations; 4 | 5 | public class Migration_14_WorkspaceIdAddedToIntegrationsTable : SQLiteMigrationBase 6 | { 7 | public override string Name => "workspace_id_added_to_integrations_table"; 8 | public override DateOnly Date { get; } = new(2025, 2, 19); 9 | public override PlikShareDbType Type { get; } = PlikShareDb.Type; 10 | 11 | protected override string[] ManifestResourceNames { get; } = 12 | [ 13 | "PlikShare.Core.Database.MainDatabase.Migrations.14_workspace_id_added_to_integrations_table.sql" 14 | ]; 15 | } -------------------------------------------------------------------------------- /PlikShare/Core/Database/MainDatabase/Migrations/Migration_16_SignUpCheckboxesIntroduced.cs: -------------------------------------------------------------------------------- 1 | using PlikShare.Core.SQLite; 2 | 3 | namespace PlikShare.Core.Database.MainDatabase.Migrations; 4 | 5 | public class Migration_16_SignUpCheckboxesIntroduced : SQLiteMigrationBase 6 | { 7 | public override string Name => "sign_up_checkboxes_introduced"; 8 | public override DateOnly Date { get; } = new(2025, 3, 17); 9 | public override PlikShareDbType Type { get; } = PlikShareDb.Type; 10 | 11 | protected override string[] ManifestResourceNames { get; } = 12 | [ 13 | "PlikShare.Core.Database.MainDatabase.Migrations.16_sign_up_checkboxes_introduced.sql" 14 | ]; 15 | } -------------------------------------------------------------------------------- /PlikShare/Core/Database/MainDatabase/Migrations/Migration_17_WorkspaceMaxSizeColumnIntroduced.cs: -------------------------------------------------------------------------------- 1 | using PlikShare.Core.SQLite; 2 | 3 | namespace PlikShare.Core.Database.MainDatabase.Migrations; 4 | 5 | public class Migration_17_WorkspaceMaxSizeColumnIntroduced : SQLiteMigrationBase 6 | { 7 | public override string Name => "workspace_max_size_column_introduced"; 8 | public override DateOnly Date { get; } = new(2025, 3, 24); 9 | public override PlikShareDbType Type { get; } = PlikShareDb.Type; 10 | 11 | protected override string[] ManifestResourceNames { get; } = 12 | [ 13 | "PlikShare.Core.Database.MainDatabase.Migrations.17_workspace_max_size_column_introduced.sql" 14 | ]; 15 | } -------------------------------------------------------------------------------- /PlikShare/Core/Database/PlikShareDbType.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Core.Database; 2 | 3 | public enum PlikShareDbType 4 | { 5 | Main, 6 | Ai 7 | } -------------------------------------------------------------------------------- /PlikShare/Core/Emails/Definitions/AlertEmailDefinition.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Core.Emails.Definitions; 2 | 3 | public class AlertEmailDefinition 4 | { 5 | public required string Title { get; init; } 6 | public required string Content { get; init; } 7 | public required DateTimeOffset EventDateTime { get; init; } 8 | } -------------------------------------------------------------------------------- /PlikShare/Core/Emails/Definitions/BoxMemberLeftEmailDefinition.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Core.Emails.Definitions; 2 | 3 | public record BoxMemberLeftEmailDefinition( 4 | string BoxName, 5 | string MemberEmail); -------------------------------------------------------------------------------- /PlikShare/Core/Emails/Definitions/BoxMembershipInvitationAcceptedEmailDefinition.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Core.Emails.Definitions; 2 | 3 | public record BoxMembershipInvitationAcceptedEmailDefinition( 4 | string InviteeEmail, 5 | string BoxName); -------------------------------------------------------------------------------- /PlikShare/Core/Emails/Definitions/BoxMembershipInvitationEmailDefinition.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Core.Emails.Definitions; 2 | 3 | public record BoxMembershipInvitationEmailDefinition( 4 | string InviterEmail, 5 | string BoxName, 6 | string? InvitationCode); -------------------------------------------------------------------------------- /PlikShare/Core/Emails/Definitions/BoxMembershipInvitationRejectedEmailDefinition.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Core.Emails.Definitions; 2 | 3 | public record BoxMembershipInvitationRejectedEmailDefinition( 4 | string InviteeEmail, 5 | string BoxName); -------------------------------------------------------------------------------- /PlikShare/Core/Emails/Definitions/BoxMembershipRevokedEmailDefinition.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Core.Emails.Definitions; 2 | 3 | public class BoxMembershipRevokedEmailDefinition 4 | { 5 | public required string BoxName { get; init; } 6 | } -------------------------------------------------------------------------------- /PlikShare/Core/Emails/Definitions/ConfirmationEmailDefinition.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Core.Emails.Definitions; 2 | 3 | public record ConfirmationEmailDefinition( 4 | string Link); -------------------------------------------------------------------------------- /PlikShare/Core/Emails/Definitions/ResetPasswordEmailDefinition.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Core.Emails.Definitions; 2 | 3 | public record ResetPasswordEmailDefinition( 4 | string Link); -------------------------------------------------------------------------------- /PlikShare/Core/Emails/Definitions/UserInvitationEmailDefinition.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Core.Emails.Definitions; 2 | 3 | public record UserInvitationEmailDefinition( 4 | string InviterEmail, 5 | string InvitationCode); -------------------------------------------------------------------------------- /PlikShare/Core/Emails/Definitions/WorkspaceMemberLeftEmailDefinition.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Core.Emails.Definitions; 2 | 3 | public class WorkspaceMemberLeftEmailDefinition 4 | { 5 | public required string WorkspaceName { get; init; } 6 | public required string MemberEmail { get; init; } 7 | } -------------------------------------------------------------------------------- /PlikShare/Core/Emails/Definitions/WorkspaceMembershipInvitationAcceptedEmailDefinition.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Core.Emails.Definitions; 2 | 3 | public class WorkspaceMembershipInvitationAcceptedEmailDefinition 4 | { 5 | public required string InviteeEmail {get;init;} 6 | public required string WorkspaceName { get; init; } 7 | } -------------------------------------------------------------------------------- /PlikShare/Core/Emails/Definitions/WorkspaceMembershipInvitationEmailDefinition.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Core.Emails.Definitions; 2 | 3 | public record WorkspaceMembershipInvitationEmailDefinition( 4 | string InviterEmail, 5 | string WorkspaceName, 6 | string? InvitationCode); -------------------------------------------------------------------------------- /PlikShare/Core/Emails/Definitions/WorkspaceMembershipInvitationRejectedEmailDefinition.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Core.Emails.Definitions; 2 | 3 | public class WorkspaceMembershipInvitationRejectedEmailDefinition 4 | { 5 | public required string MemberEmail { get; init; } 6 | public required string WorkspaceName { get; init; } 7 | } -------------------------------------------------------------------------------- /PlikShare/Core/Emails/Definitions/WorkspaceMembershipRevokedEmailDefinition.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Core.Emails.Definitions; 2 | 3 | public class WorkspaceMembershipRevokedEmailDefinition 4 | { 5 | public required string WorkspaceName { get; init; } 6 | } -------------------------------------------------------------------------------- /PlikShare/Core/Emails/EmailQueueJobDefinition.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Core.Emails; 2 | 3 | public class EmailQueueJobDefinition 4 | { 5 | public required string Email { get; init; } 6 | public required EmailTemplate Template { get; init; } 7 | public required TEmailDefinition Definition { get; init; } 8 | } -------------------------------------------------------------------------------- /PlikShare/Core/Emails/EmailQueueJobType.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Core.Emails; 2 | 3 | public static class EmailQueueJobType 4 | { 5 | public const string Value = "send-email"; 6 | } -------------------------------------------------------------------------------- /PlikShare/Core/Emails/EmailTemplate.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Core.Emails; 2 | 3 | public enum EmailTemplate 4 | { 5 | WorkspaceMembershipInvitation = 1, 6 | WorkspaceMembershipInvitationAccepted, 7 | WorkspaceMembershipInvitationRejected, 8 | WorkspaceMembershipRevoked, 9 | WorkspaceMemberLeft, 10 | 11 | BoxMembershipInvitation, 12 | BoxMembershipInvitationAccepted, 13 | BoxMembershipInvitationRejected, 14 | BoxMembershipRevoked, 15 | BoxMemberLeft, 16 | 17 | Alert, 18 | 19 | ConfirmationEmail, 20 | ResetPassword, 21 | 22 | UserInvitation 23 | } -------------------------------------------------------------------------------- /PlikShare/Core/Emails/IEmailSender.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Core.Emails; 2 | 3 | public interface IEmailSender 4 | { 5 | Task SendEmail( 6 | string to, 7 | string subject, 8 | string htmlContent, 9 | CancellationToken cancellationToken = default); 10 | } -------------------------------------------------------------------------------- /PlikShare/Core/Encryption/FileEncryptionMetadata.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | 3 | namespace PlikShare.Core.Encryption; 4 | 5 | [ImmutableObject(true)] 6 | public sealed class FileEncryptionMetadata 7 | { 8 | public required byte KeyVersion { get; init; } 9 | public required byte[] Salt { get; init; } 10 | public required byte[] NoncePrefix { get; init; } 11 | } -------------------------------------------------------------------------------- /PlikShare/Core/Encryption/IMasterDataEncryption.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Core.Encryption; 2 | 3 | public interface IMasterDataEncryption 4 | { 5 | byte[] Encrypt(string plainText); 6 | string Decrypt(byte[] versionedEncryptedBytes); 7 | 8 | IDerivedMasterDataEncryption NewDerived(); 9 | IDerivedMasterDataEncryption DerivedFrom(byte[] versionedEncryptedBytes); 10 | IDerivedMasterDataEncryption DeserializeDerived(byte[] serialized); 11 | } -------------------------------------------------------------------------------- /PlikShare/Core/Encryption/MasterEncryptionKey.cs: -------------------------------------------------------------------------------- 1 | using System.Text; 2 | 3 | namespace PlikShare.Core.Encryption; 4 | 5 | public class MasterEncryptionKey( 6 | byte id, 7 | string password) 8 | { 9 | public byte Id { get; } = id; 10 | public string Password { get; } = password; 11 | 12 | public ReadOnlyMemory PasswordBytes { get; } = Encoding.UTF8.GetBytes(password); 13 | } -------------------------------------------------------------------------------- /PlikShare/Core/ExternalIds/ExternalIdJsonConverter.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json; 2 | using System.Text.Json.Serialization; 3 | 4 | namespace PlikShare.Core.ExternalIds; 5 | 6 | public class ExternalIdJsonConverter : JsonConverter where TId: IExternalId 7 | { 8 | public override TId Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) 9 | { 10 | return TId.Parse(reader.GetString()!, null); 11 | } 12 | 13 | public override void Write(Utf8JsonWriter writer, TId value, JsonSerializerOptions options) 14 | { 15 | writer.WriteStringValue(value.Value); 16 | } 17 | } -------------------------------------------------------------------------------- /PlikShare/Core/ExternalIds/IExternalId.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Core.ExternalIds; 2 | 3 | public interface IExternalId: IParsable where T: IParsable 4 | { 5 | public string Value { get; } 6 | } 7 | -------------------------------------------------------------------------------- /PlikShare/Core/IdentityProvider/ApplicationRole.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Identity; 2 | 3 | namespace PlikShare.Core.IdentityProvider; 4 | 5 | public class ApplicationRole : IdentityRole 6 | { 7 | public int DatabaseId { get; set; } 8 | } 9 | 10 | public class ApplicationUserToken : IdentityUserToken 11 | { 12 | 13 | } -------------------------------------------------------------------------------- /PlikShare/Core/IdentityProvider/ApplicationUser.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Identity; 2 | 3 | namespace PlikShare.Core.IdentityProvider; 4 | 5 | public class ApplicationUser: IdentityUser 6 | { 7 | public int DatabaseId { get; set; } 8 | public List SelectedCheckboxIds { get; set; } 9 | public bool IsAppOwner { get; set; } = false; 10 | 11 | public ApplicationUser() 12 | { 13 | SecurityStamp = Guid.NewGuid().ToString(); 14 | SelectedCheckboxIds = []; 15 | } 16 | 17 | public ApplicationUser(string userName) 18 | : this() 19 | { 20 | UserName = userName; 21 | } 22 | } -------------------------------------------------------------------------------- /PlikShare/Core/Queue/BulkQueueJobEntity.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Core.Queue; 2 | 3 | public class BulkQueueJobEntity 4 | { 5 | public required string JobType { get; init; } 6 | public required string Status { get; init; } 7 | public required string Definition { get; init; } 8 | public required int? SagaId { get; init; } 9 | } 10 | -------------------------------------------------------------------------------- /PlikShare/Core/Queue/QueueJobCategory.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Core.Queue; 2 | 3 | public enum QueueJobCategory 4 | { 5 | DbOnly, 6 | Normal, 7 | LongRunning 8 | } -------------------------------------------------------------------------------- /PlikShare/Core/Queue/QueueJobStatusDecisionEngine.cs: -------------------------------------------------------------------------------- 1 | using PlikShare.Core.Emails; 2 | 3 | namespace PlikShare.Core.Queue; 4 | 5 | public class QueueJobStatusDecisionEngine(EmailProviderStore emailProviderStore) 6 | { 7 | public QueueStatus GetNewJobStatus(string jobType) 8 | { 9 | return jobType switch 10 | { 11 | EmailQueueJobType.Value => GetNewEmailJobStatus(), 12 | _ => QueueStatus.PendingStatus 13 | }; 14 | } 15 | 16 | private QueueStatus GetNewEmailJobStatus() 17 | { 18 | return emailProviderStore.IsEmailSenderAvailable 19 | ? QueueStatus.PendingStatus 20 | : QueueStatus.BlockedStatus; 21 | } 22 | } -------------------------------------------------------------------------------- /PlikShare/Core/SQLite/SQLiteConnectionExtensions.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Data.Sqlite; 2 | using PlikShare.Core.Utils; 3 | 4 | namespace PlikShare.Core.SQLite; 5 | 6 | public static class SQLiteConnectionExtensions 7 | { 8 | public static void RegisterJsonArrayToBlobFunction(this SqliteConnection connection) 9 | { 10 | connection.CreateFunction( 11 | "app_json_array_to_blob", 12 | (string? jsonArray) => 13 | { 14 | if (string.IsNullOrWhiteSpace(jsonArray)) 15 | return null; 16 | 17 | // Parse JSON array string into byte array 18 | return Json.Deserialize(jsonArray); 19 | }); 20 | } 21 | } -------------------------------------------------------------------------------- /PlikShare/Core/UserIdentity/BoxLinkSessionUserIdentity.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Core.UserIdentity; 2 | 3 | public record BoxLinkSessionUserIdentity(Guid BoxLinkSessionId) : IUserIdentity 4 | { 5 | public const string Type = "box_link_session_id"; 6 | 7 | public string IdentityType => Type; 8 | public string Identity { get; } = BoxLinkSessionId.ToString(); 9 | } -------------------------------------------------------------------------------- /PlikShare/Core/UserIdentity/GenericUserIdentity.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Core.UserIdentity; 2 | 3 | public record GenericUserIdentity( 4 | string IdentityType, 5 | string Identity) : IUserIdentity; -------------------------------------------------------------------------------- /PlikShare/Core/UserIdentity/IntegrationUserIdentity.cs: -------------------------------------------------------------------------------- 1 | using PlikShare.Integrations.Id; 2 | 3 | namespace PlikShare.Core.UserIdentity; 4 | 5 | /// 6 | /// This class represents situation where given entity/message/file/etc was created by app integration rather than user 7 | /// For example, ai message created by response from AI integration, like ChatGpt 8 | /// 9 | /// 10 | public record IntegrationUserIdentity(IntegrationExtId IntegrationExternalId) : IUserIdentity 11 | { 12 | public const string Type = "integration_external_id"; 13 | 14 | public string IdentityType => Type; 15 | public string Identity => IntegrationExternalId.Value; 16 | } -------------------------------------------------------------------------------- /PlikShare/Core/UserIdentity/UserIdentity.cs: -------------------------------------------------------------------------------- 1 | using PlikShare.Users.Id; 2 | 3 | namespace PlikShare.Core.UserIdentity; 4 | 5 | public record UserIdentity(UserExtId UserExternalId) : IUserIdentity 6 | { 7 | public const string Type = "user_external_id"; 8 | public string IdentityType => Type; 9 | public string Identity => UserExternalId.Value; 10 | } -------------------------------------------------------------------------------- /PlikShare/Core/Utils/DomainException.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Core.Utils; 2 | 3 | public abstract class DomainException(string message) : Exception(message); -------------------------------------------------------------------------------- /PlikShare/Core/Utils/EnumerableExtensions.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Core.Utils; 2 | 3 | public static class EnumerableExtensions 4 | { 5 | public static List AsList(this IEnumerable enumerable) 6 | { 7 | return enumerable as List ?? enumerable.ToList(); 8 | } 9 | } -------------------------------------------------------------------------------- /PlikShare/Core/Utils/IOneTimeCode.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Core.Utils; 2 | 3 | public interface IOneTimeCode 4 | { 5 | string Generate(); 6 | } -------------------------------------------------------------------------------- /PlikShare/Core/Utils/ManifestResourceReader.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | 3 | namespace PlikShare.Core.Utils; 4 | 5 | public static class ManifestResourceReader 6 | { 7 | public static string Read(string name) 8 | { 9 | var assembly = Assembly.GetExecutingAssembly(); 10 | using var stream = assembly.GetManifestResourceStream(name); 11 | 12 | if (stream == null) 13 | { 14 | throw new InvalidOperationException($"Cannot find '{name}' email template"); 15 | } 16 | 17 | using var reader = new StreamReader(stream); 18 | 19 | return reader.ReadToEnd(); 20 | } 21 | } -------------------------------------------------------------------------------- /PlikShare/Core/Utils/OneTimeCode.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Core.Utils; 2 | 3 | public class OneTimeCode: IOneTimeCode 4 | { 5 | private readonly Random _random = new(); 6 | 7 | public string Generate() 8 | { 9 | return _random.Next(100000, 999999).ToString(); 10 | } 11 | } -------------------------------------------------------------------------------- /PlikShare/Core/Utils/PlikShareStreams.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Core.Utils; 2 | 3 | public class PlikShareStreams 4 | { 5 | public const int DefaultBufferSize = 64 * 1024; 6 | } -------------------------------------------------------------------------------- /PlikShare/Core/Utils/SizeInBytes.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Core.Utils; 2 | 3 | public class SizeInBytes 4 | { 5 | public const int Mb = 1024 * 1024; 6 | 7 | public static long Mbs(int mbs) 8 | { 9 | return mbs * Mb; 10 | } 11 | 12 | public static decimal AsMb(long sizeInBytes) 13 | { 14 | return (decimal)sizeInBytes / Mb; 15 | } 16 | } -------------------------------------------------------------------------------- /PlikShare/Core/Utils/TransferSpeed.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Core.Utils; 2 | 3 | public class TransferSpeed 4 | { 5 | public static string Format(long bytes, TimeSpan duration) 6 | { 7 | // For very quick transfers (less than 100ms), report instantaneous speed 8 | if (duration.TotalMilliseconds < 100) 9 | { 10 | return "< 100ms transfer"; 11 | } 12 | 13 | var speedInBytesPerSec = bytes / duration.TotalSeconds; 14 | var speedInMBPerSec = speedInBytesPerSec / 1024.0 / 1024.0; 15 | 16 | return $"{speedInMBPerSec:N2} MB/s"; 17 | } 18 | } -------------------------------------------------------------------------------- /PlikShare/Core/Utils/Try.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Core.Utils; 2 | 3 | public static class Try 4 | { 5 | public static async Task Execute(Func @try, Func @finally) 6 | { 7 | try 8 | { 9 | await @try(); 10 | } 11 | finally 12 | { 13 | await @finally(); 14 | } 15 | } 16 | 17 | public static async Task Execute(Func> @try, Func @finally) 18 | { 19 | try 20 | { 21 | return await @try(); 22 | } 23 | finally 24 | { 25 | await @finally(); 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /PlikShare/Core/Utils/UnexpectedOperationResultException.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Core.Utils; 2 | 3 | public class UnexpectedOperationResultException: InvalidOperationException 4 | { 5 | public UnexpectedOperationResultException( 6 | string operationName, 7 | Type resultType): base(message: $"Unexpected '{operationName}' result: '{resultType}'") 8 | { 9 | 10 | } 11 | 12 | public UnexpectedOperationResultException( 13 | string operationName, 14 | string resultValueStr): base(message: $"Unexpected '{operationName}' result: '{resultValueStr}'") 15 | { 16 | 17 | } 18 | } -------------------------------------------------------------------------------- /PlikShare/EmailProviders/Confirm/Contracts/ConfirmEmailProviderRequestDto.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.EmailProviders.Confirm.Contracts; 2 | 3 | public record ConfirmEmailProviderRequestDto( 4 | string ConfirmationCode); -------------------------------------------------------------------------------- /PlikShare/EmailProviders/ExternalProviders/AwsSes/AwsSesDetailsEntity.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.EmailProviders.ExternalProviders.AwsSes; 2 | 3 | public record AwsSesDetailsEntity( 4 | string AccessKey, 5 | string SecretAccessKey, 6 | string Region); -------------------------------------------------------------------------------- /PlikShare/EmailProviders/ExternalProviders/AwsSes/Create/Contracts/CreateAwsSesEmailProviderRequestDto.cs: -------------------------------------------------------------------------------- 1 | using PlikShare.EmailProviders.Id; 2 | 3 | namespace PlikShare.EmailProviders.ExternalProviders.AwsSes.Create.Contracts; 4 | 5 | public record CreateAwsSesEmailProviderRequestDto( 6 | string Name, 7 | string EmailFrom, 8 | string AccessKey, 9 | string SecretAccessKey, 10 | string Region); 11 | 12 | public record CreateAwsSesEmailProviderResponseDto( 13 | EmailProviderExtId ExternalId); -------------------------------------------------------------------------------- /PlikShare/EmailProviders/ExternalProviders/Resend/Create/CreateResendEmailProviderRequestDto.cs: -------------------------------------------------------------------------------- 1 | using PlikShare.EmailProviders.Id; 2 | 3 | namespace PlikShare.EmailProviders.ExternalProviders.Resend.Create; 4 | 5 | public record CreateResendEmailProviderRequestDto( 6 | string Name, 7 | string EmailFrom, 8 | string ApiKey); 9 | 10 | public record CreateResendEmailProviderResponseDto( 11 | EmailProviderExtId ExternalId); -------------------------------------------------------------------------------- /PlikShare/EmailProviders/ExternalProviders/Resend/ResendDetailsEntity.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.EmailProviders.ExternalProviders.Resend; 2 | 3 | public record ResendDetailsEntity( 4 | string ApiKey); -------------------------------------------------------------------------------- /PlikShare/EmailProviders/ExternalProviders/Resend/ResendRequestBody.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.EmailProviders.ExternalProviders.Resend; 2 | 3 | public record ResendRequestBody( 4 | string From, 5 | string[] To, 6 | string Subject, 7 | string Html); -------------------------------------------------------------------------------- /PlikShare/EmailProviders/ExternalProviders/Smtp/Create/CreateSmtpEmailProviderRequestDto.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.EmailProviders.ExternalProviders.Smtp.Create; 2 | 3 | public record CreateSmtpEmailProviderRequestDto( 4 | string Name, 5 | string EmailFrom, 6 | string Hostname, 7 | int Port, 8 | SslMode SslMode, 9 | string Username, 10 | string Password); -------------------------------------------------------------------------------- /PlikShare/EmailProviders/ExternalProviders/Smtp/SmtpDetailsEntity.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.EmailProviders.ExternalProviders.Smtp; 2 | 3 | public record SmtpDetailsEntity( 4 | string Hostname, 5 | int Port, 6 | SslMode SslMode, 7 | string Username, 8 | string Password); 9 | 10 | public enum SslMode 11 | { 12 | None = 0, 13 | Auto, 14 | SslOnConnect, 15 | StartTls, 16 | StartTlsWhenAvailable 17 | } -------------------------------------------------------------------------------- /PlikShare/EmailProviders/ExternalProviders/Smtp/SmtpEmailSenderFactory.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.EmailProviders.ExternalProviders.Smtp; 2 | 3 | public class SmtpEmailSenderFactory 4 | { 5 | public SmtpEmailSender Build(string emailFrom, SmtpDetailsEntity details) 6 | { 7 | return new SmtpEmailSender( 8 | emailFrom: emailFrom, 9 | hostname: details.Hostname, 10 | port: details.Port, 11 | sslMode: details.SslMode, 12 | username: details.Username, 13 | password: details.Password); 14 | } 15 | } -------------------------------------------------------------------------------- /PlikShare/EmailProviders/List/Contracts/GetEmailProvidersResponseDto.cs: -------------------------------------------------------------------------------- 1 | using PlikShare.EmailProviders.Id; 2 | 3 | namespace PlikShare.EmailProviders.List.Contracts; 4 | 5 | public record GetEmailProvidersResponseDto( 6 | GetEmailProvidersItemResponseDto[] Items); 7 | 8 | public record GetEmailProvidersItemResponseDto( 9 | EmailProviderExtId ExternalId, 10 | string Type, 11 | string Name, 12 | string EmailFrom, 13 | bool IsConfirmed, 14 | bool IsActive); 15 | -------------------------------------------------------------------------------- /PlikShare/EmailProviders/ResendConfirmationEmail/Contracts/ResendEmailProviderConfirmationEmailRequestDto.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.EmailProviders.ResendConfirmationEmail.Contracts; 2 | 3 | public record ResendEmailProviderConfirmationEmailRequestDto(string? EmailTo); -------------------------------------------------------------------------------- /PlikShare/EmailProviders/UpdateName/Contracts/UpdateEmailProviderNameRequestDto.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.EmailProviders.UpdateName.Contracts; 2 | 3 | public record UpdateEmailProviderNameRequestDto( 4 | string Name); -------------------------------------------------------------------------------- /PlikShare/EntryPage/Contracts/GetEntryPageSettingsResponseDto.cs: -------------------------------------------------------------------------------- 1 | using PlikShare.GeneralSettings; 2 | 3 | namespace PlikShare.EntryPage.Contracts; 4 | 5 | public class GetEntryPageSettingsResponseDto 6 | { 7 | public required string ApplicationSignUp { get; init; } 8 | public required string? TermsOfServiceFilePath { get; init; } 9 | public required string? PrivacyPolicyFilePath { get; init; } 10 | public required List SignUpCheckboxes { get; init; } 11 | } -------------------------------------------------------------------------------- /PlikShare/Files/AiConversation/FileAiConversationArtifactEntity.cs: -------------------------------------------------------------------------------- 1 | using PlikShare.ArtificialIntelligence.Id; 2 | 3 | namespace PlikShare.Files.AiConversation; 4 | 5 | public class FileAiConversationArtifactEntity 6 | { 7 | public required AiConversationExtId AiConversationExternalId { get; init; } 8 | } -------------------------------------------------------------------------------- /PlikShare/Files/Artifacts/FileArtifactTypes.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Files.Artifacts; 2 | 3 | public enum FileArtifactType 4 | { 5 | Note = 0, 6 | Comment, 7 | AiConversation 8 | } -------------------------------------------------------------------------------- /PlikShare/Files/BulkDelete/QueueJob/BulkDeleteS3FileQueueJobDefinition.cs: -------------------------------------------------------------------------------- 1 | using PlikShare.Storages; 2 | 3 | namespace PlikShare.Files.BulkDelete.QueueJob; 4 | 5 | public class BulkDeleteS3FileQueueJobDefinition 6 | { 7 | public required int StorageId {get; init;} 8 | public required string BucketName {get; init;} 9 | public required S3FileKey[] S3FileKeys {get; init;} 10 | } -------------------------------------------------------------------------------- /PlikShare/Files/BulkDelete/QueueJob/BulkDeleteS3FileQueueJobType.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Files.BulkDelete.QueueJob; 2 | 3 | public static class BulkDeleteS3FileQueueJobType 4 | { 5 | public const int MaxChunkSize = 1000; 6 | 7 | public const string Value = "bulk-delete-s3-files"; 8 | } -------------------------------------------------------------------------------- /PlikShare/Files/BulkDownload/Contracts/GetBulkDownloadLinkResponseDto.cs: -------------------------------------------------------------------------------- 1 | using PlikShare.Files.Id; 2 | using PlikShare.Folders.Id; 3 | 4 | namespace PlikShare.Files.BulkDownload.Contracts; 5 | 6 | public class GetBulkDownloadLinkRequestDto 7 | { 8 | public required List SelectedFolders { get; init; } 9 | public required List SelectedFiles { get; init; } 10 | public required List ExcludedFolders { get; init; } 11 | public required List ExcludedFiles { get; init; } 12 | } 13 | 14 | public class GetBulkDownloadLinkResponseDto 15 | { 16 | public required string PreSignedUrl { get; init; } 17 | } -------------------------------------------------------------------------------- /PlikShare/Files/Delete/QueueJob/DeleteS3FileQueueJobDefinition.cs: -------------------------------------------------------------------------------- 1 | using PlikShare.Files.Id; 2 | 3 | namespace PlikShare.Files.Delete.QueueJob; 4 | 5 | public class DeleteS3FileQueueJobDefinition 6 | { 7 | public required int StorageId {get; init;} 8 | public required string BucketName {get; init;} 9 | public required FileExtId FileExternalId {get; init;} 10 | public required string S3KeySecretPart { get; init; } 11 | } -------------------------------------------------------------------------------- /PlikShare/Files/Delete/QueueJob/DeleteS3FileQueueJobType.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Files.Delete.QueueJob; 2 | 3 | public static class DeleteS3FileQueueJobType 4 | { 5 | public const string Value = "delete-s3-file"; 6 | } -------------------------------------------------------------------------------- /PlikShare/Files/Download/Contracts/GetFileDownloadLinkResponseDto.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Files.Download.Contracts; 2 | 3 | public record GetFileDownloadLinkResponseDto( 4 | string DownloadPreSignedUrl); -------------------------------------------------------------------------------- /PlikShare/Files/Metadata/FileMetadata.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | using PlikShare.Integrations.Aws.Textract; 3 | 4 | namespace PlikShare.Files.Metadata; 5 | 6 | [JsonDerivedType(derivedType: typeof(TextractResultFileMetadata), typeDiscriminator: "aws-textract-result")] 7 | public abstract class FileMetadata 8 | { 9 | } -------------------------------------------------------------------------------- /PlikShare/Files/PreSignedLinks/Contracts/MultiFileDirectUploadResponseDto.cs: -------------------------------------------------------------------------------- 1 | using PlikShare.Files.Id; 2 | using PlikShare.Uploads.Id; 3 | 4 | namespace PlikShare.Files.PreSignedLinks.Contracts; 5 | 6 | public class MultiFileDirectUploadItemResponseDto 7 | { 8 | public required FileExtId FileExternalId { get; init; } 9 | public required FileUploadExtId UploadExternalId { get; init; } 10 | } -------------------------------------------------------------------------------- /PlikShare/Files/Preview/Comment/CommentContentEntity.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Files.Preview.Comment; 2 | 3 | public record CommentContentEntity( 4 | string ContentJson, 5 | bool WasEdited); -------------------------------------------------------------------------------- /PlikShare/Files/Preview/Comment/CreateComment/Contracts/CreateFileCommentRequestDto.cs: -------------------------------------------------------------------------------- 1 | using PlikShare.Files.Id; 2 | 3 | namespace PlikShare.Files.Preview.Comment.CreateComment.Contracts; 4 | 5 | public record CreateFileCommentRequestDto( 6 | FileArtifactExtId ExternalId, 7 | string ContentJson); 8 | -------------------------------------------------------------------------------- /PlikShare/Files/Preview/Comment/EditComment/Contracts/EditFileCommentRequestDto.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Files.Preview.Comment.EditComment.Contracts; 2 | 3 | public record EditFileCommentRequestDto( 4 | string ContentJson); -------------------------------------------------------------------------------- /PlikShare/Files/Preview/GetZipContentDownloadLink/Contracts/GetZipContentDownloadLinkRequestDto.cs: -------------------------------------------------------------------------------- 1 | using PlikShare.Core.Utils; 2 | using PlikShare.Storages.Zip; 3 | 4 | namespace PlikShare.Files.Preview.GetZipContentDownloadLink.Contracts; 5 | 6 | public record GetZipContentDownloadLinkRequestDto( 7 | ZipFileDto Item, 8 | ContentDispositionType ContentDisposition); 9 | 10 | public record GetZipContentDownloadLinkResponseDto( 11 | string DownloadPreSignedUrl); -------------------------------------------------------------------------------- /PlikShare/Files/Preview/SaveNote/Contracts/SaveFileNoteRequestDto.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Files.Preview.SaveNote.Contracts; 2 | 3 | public record SaveFileNoteRequestDto( 4 | string ContentJson); -------------------------------------------------------------------------------- /PlikShare/Files/Records/FilePartDetails.cs: -------------------------------------------------------------------------------- 1 | using PlikShare.Uploads.Algorithm; 2 | 3 | namespace PlikShare.Files.Records; 4 | 5 | public readonly record struct FilePartDetails( 6 | int Number, 7 | int SizeInBytes, 8 | UploadAlgorithm UploadAlgorithm) 9 | { 10 | public static FilePartDetails First( 11 | int sizeInBytes, 12 | UploadAlgorithm uploadAlgorithm) 13 | { 14 | return new FilePartDetails(1, sizeInBytes, uploadAlgorithm); 15 | } 16 | } -------------------------------------------------------------------------------- /PlikShare/Files/Records/FileRecord.cs: -------------------------------------------------------------------------------- 1 | using PlikShare.Files.Id; 2 | using PlikShare.Storages; 3 | 4 | namespace PlikShare.Files.Records; 5 | 6 | public class FileRecord 7 | { 8 | public required FileExtId ExternalId { get; init; } 9 | public required string Name { get; init; } 10 | public required string ContentType { get; init; } 11 | public required string Extension { get; init; } 12 | public required string S3KeySecretPart { get; init; } 13 | public required long SizeInBytes { get; init; } 14 | public required int WorkspaceId { get; init; } 15 | public required FileEncryption Encryption { get; init; } 16 | 17 | public string FullName => $"{Name}{Extension}"; 18 | } 19 | -------------------------------------------------------------------------------- /PlikShare/Files/Rename/Contracts/UpdateFileNameRequestDto.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Files.Rename.Contracts; 2 | 3 | public record UpdateFileNameRequestDto( 4 | string Name); -------------------------------------------------------------------------------- /PlikShare/Files/Rename/Contracts/UpdateFileNameRequestValidator.cs: -------------------------------------------------------------------------------- 1 | using FluentValidation; 2 | 3 | namespace PlikShare.Files.Rename.Contracts; 4 | 5 | public class UpdateFileNameRequestValidator : AbstractValidator 6 | { 7 | public UpdateFileNameRequestValidator() 8 | { 9 | RuleFor(x => x.Name).NotEmpty(); 10 | } 11 | } -------------------------------------------------------------------------------- /PlikShare/Folders/Create/Contracts/CreateFolderRequestDto.cs: -------------------------------------------------------------------------------- 1 | using PlikShare.Folders.Id; 2 | 3 | namespace PlikShare.Folders.Create.Contracts; 4 | 5 | public class CreateFolderRequestDto 6 | { 7 | public required FolderExtId ExternalId { get; init; } 8 | public required FolderExtId? ParentExternalId { get; init; } 9 | public required string Name { get; init; } 10 | } -------------------------------------------------------------------------------- /PlikShare/Folders/Create/Contracts/CreateFolderRequestValidator.cs: -------------------------------------------------------------------------------- 1 | using FluentValidation; 2 | 3 | namespace PlikShare.Folders.Create.Contracts; 4 | 5 | public class CreateFolderRequestValidator : AbstractValidator 6 | { 7 | public CreateFolderRequestValidator() 8 | { 9 | RuleFor(x => x.Name) 10 | .NotEmpty(); 11 | } 12 | } -------------------------------------------------------------------------------- /PlikShare/Folders/Create/Contracts/CreateFolderResponseDto.cs: -------------------------------------------------------------------------------- 1 | using PlikShare.Folders.Id; 2 | using ProtoBuf; 3 | 4 | namespace PlikShare.Folders.Create.Contracts; 5 | 6 | public class CreateFolderResponseDto 7 | { 8 | public required FolderExtId ExternalId { get; init; } 9 | } 10 | 11 | 12 | [ProtoContract] 13 | public class BulkCreateFolderResponseDto 14 | { 15 | [ProtoMember(1)] 16 | public required List Items { get; init; } 17 | } 18 | 19 | [ProtoContract] 20 | public class BulkCreateFolderItemDto 21 | { 22 | [ProtoMember(1)] 23 | public required int TemporaryId { get; init; } 24 | 25 | [ProtoMember(2)] 26 | public required string ExternalId { get; init; } 27 | } -------------------------------------------------------------------------------- /PlikShare/Folders/Delete/QueueJob/DeleteFoldersQueueJobDefinition.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Folders.Delete.QueueJob; 2 | 3 | public class DeleteFoldersQueueJobDefinition 4 | { 5 | public required int[] FolderIds { get; init; } 6 | public required int WorkspaceId { get; init; } 7 | public required DateTimeOffset DeletedAt { get; init; } 8 | } -------------------------------------------------------------------------------- /PlikShare/Folders/Delete/QueueJob/DeleteFoldersQueueJobType.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Folders.Delete.QueueJob; 2 | 3 | public static class DeleteFoldersQueueJobType 4 | { 5 | public const string Value = "delete-folders"; 6 | } -------------------------------------------------------------------------------- /PlikShare/Folders/MoveToFolder/Contracts/MoveItemsToFolderRequestDto.cs: -------------------------------------------------------------------------------- 1 | using PlikShare.Files.Id; 2 | using PlikShare.Folders.Id; 3 | using PlikShare.Uploads.Id; 4 | 5 | namespace PlikShare.Folders.MoveToFolder.Contracts; 6 | 7 | public record MoveItemsToFolderRequestDto( 8 | FileExtId[] FileExternalIds, 9 | FolderExtId[] FolderExternalIds, 10 | FileUploadExtId[] FileUploadExternalIds, 11 | FolderExtId? DestinationFolderExternalId); -------------------------------------------------------------------------------- /PlikShare/Folders/Rename/Contracts/UpdateFolderNameRequestDto.cs: -------------------------------------------------------------------------------- 1 | using FluentValidation; 2 | 3 | namespace PlikShare.Folders.Rename.Contracts; 4 | 5 | public record UpdateFolderNameRequestDto( 6 | string Name); 7 | 8 | public class UpdateFolderNameRequestValidator : AbstractValidator 9 | { 10 | public UpdateFolderNameRequestValidator() 11 | { 12 | RuleFor(x => x.Name).NotEmpty(); 13 | } 14 | } -------------------------------------------------------------------------------- /PlikShare/GeneralSettings/Contracts/GeneralSettingsRequests.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.GeneralSettings.Contracts; 2 | 3 | public class SetSettingRequest 4 | { 5 | public string? Value { get; set; } 6 | } 7 | 8 | public class SetNewUserDefaultMaxWorkspaceNumberRequestDto 9 | { 10 | public required int? Value { get; init; } 11 | } 12 | 13 | public class SetNewUserDefaultMaxWorkspaceSizeInBytesRequestDto 14 | { 15 | public required long? Value { get; init; } 16 | } 17 | 18 | public class SetNewUserDefaultMaxWorkspaceTeamMembersRequestDto 19 | { 20 | public required int? Value { get; init; } 21 | } 22 | 23 | public class SetAlertSettingReuqest 24 | { 25 | public required bool IsTurnedOn { get; init; } 26 | } -------------------------------------------------------------------------------- /PlikShare/GeneralSettings/SignUpCheckboxes/CreateOrUpdate/Contracts/CreateOrUpdateSignUpCheckboxRequestDto.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.GeneralSettings.SignUpCheckboxes.CreateOrUpdate.Contracts; 2 | 3 | public class CreateOrUpdateSignUpCheckboxRequestDto 4 | { 5 | public required int? Id { get; init; } 6 | public required string Text { get; init; } 7 | public required bool IsRequired { get; init; } 8 | } 9 | 10 | public class CreateOrUpdateSignUpCheckboxResponseDto 11 | { 12 | public required int NewId { get; init; } 13 | } -------------------------------------------------------------------------------- /PlikShare/HealthCheck/HealtCheckEndpoints.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.HealthCheck; 2 | 3 | public record HealthCheckResponse(string Message); 4 | 5 | public static class HealthCheckEndpoints 6 | { 7 | public static void MapHealthCheckEndpoints(this WebApplication app) 8 | { 9 | var group = app.MapGroup("/api/health-check") 10 | .WithTags("Health Check") 11 | .AllowAnonymous(); 12 | 13 | group.MapGet("/", () => new HealthCheckResponse("App is running")) 14 | .WithName("GetHealthCheck"); 15 | } 16 | } -------------------------------------------------------------------------------- /PlikShare/HealthCheck/HealthCheckUtils.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.HealthCheck; 2 | 3 | public static class HealthCheckUtils 4 | { 5 | public static bool IsHealthCheckEndpoint(HttpContext ctx) 6 | { 7 | var path = ctx.Request.Path; 8 | 9 | if (!path.HasValue) 10 | return false; 11 | 12 | return path.Value.Equals("/api/health-check"); 13 | } 14 | } -------------------------------------------------------------------------------- /PlikShare/Integrations/Aws/Textract/AwsTextractDetails.cs: -------------------------------------------------------------------------------- 1 | using PlikShare.Storages.Id; 2 | 3 | namespace PlikShare.Integrations.Aws.Textract; 4 | 5 | public class AwsTextractDetails: IIntegrationWithWorkspace 6 | { 7 | public required string AccessKey { get; init; } 8 | public required string SecretAccessKey { get; init; } 9 | public required string Region { get; init; } 10 | public required StorageExtId StorageExternalId { get; init; } 11 | } -------------------------------------------------------------------------------- /PlikShare/Integrations/Aws/Textract/Jobs/CheckStatus/Contracts/CheckTextractJobsStatusRequestDto.cs: -------------------------------------------------------------------------------- 1 | using PlikShare.Integrations.Aws.Textract.Id; 2 | 3 | namespace PlikShare.Integrations.Aws.Textract.Jobs.CheckStatus.Contracts; 4 | 5 | public class CheckTextractJobsStatusRequestDto 6 | { 7 | public required List ExternalIds { get; init; } 8 | } 9 | 10 | public class CheckTextractJobsStatusResponseDto 11 | { 12 | public required List Items { get; init; } 13 | } 14 | 15 | public class TextractJobStatusItemDto 16 | { 17 | public required TextractJobExtId ExternalId { get; init; } 18 | public required TextractJobStatus Status { get; init; } 19 | } -------------------------------------------------------------------------------- /PlikShare/Integrations/Aws/Textract/Jobs/CheckTextractAnalysisStatus/CheckTextractAnalysisStatusQueueJobDefinition.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Integrations.Aws.Textract.Jobs.CheckTextractAnalysisStatus; 2 | 3 | public class CheckTextractAnalysisStatusQueueJobDefinition 4 | { 5 | public required int TextractJobId { get; init; } 6 | } -------------------------------------------------------------------------------- /PlikShare/Integrations/Aws/Textract/Jobs/CheckTextractAnalysisStatus/CheckTextractAnalysisStatusQueueJobType.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Integrations.Aws.Textract.Jobs.CheckTextractAnalysisStatus; 2 | 3 | public static class CheckTextractAnalysisStatusQueueJobType 4 | { 5 | public const string Value = "check-textract-analysis-status"; 6 | } -------------------------------------------------------------------------------- /PlikShare/Integrations/Aws/Textract/Jobs/DownloadTextractAnalysis/DownloadTextractAnalysisQueueJobDefinition.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Integrations.Aws.Textract.Jobs.DownloadTextractAnalysis; 2 | 3 | public class DownloadTextractAnalysisQueueJobDefinition 4 | { 5 | public required int TextractJobId { get; init; } 6 | public required Guid TextractTemporaryStoreId { get; init; } 7 | } -------------------------------------------------------------------------------- /PlikShare/Integrations/Aws/Textract/Jobs/DownloadTextractAnalysis/DownloadTextractAnalysisQueueJobType.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Integrations.Aws.Textract.Jobs.DownloadTextractAnalysis; 2 | 3 | public static class DownloadTextractAnalysisQueueJobType 4 | { 5 | public const string Value = "download-textract-analysis"; 6 | } -------------------------------------------------------------------------------- /PlikShare/Integrations/Aws/Textract/Jobs/InitiateTextractAnalysis/InitiateTextractAnalysisQueueJobDefinition.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Integrations.Aws.Textract.Jobs.InitiateTextractAnalysis; 2 | 3 | public class InitiateTextractAnalysisQueueJobDefinition 4 | { 5 | public required int TextractJobId { get; init; } 6 | } -------------------------------------------------------------------------------- /PlikShare/Integrations/Aws/Textract/Jobs/InitiateTextractAnalysis/InitiateTextractAnalysisQueueJobType.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Integrations.Aws.Textract.Jobs.InitiateTextractAnalysis; 2 | 3 | public static class InitiateTextractAnalysisQueueJobType 4 | { 5 | public const string Value = "initiate-textract-analysis"; 6 | } -------------------------------------------------------------------------------- /PlikShare/Integrations/Aws/Textract/Jobs/StartJob/Contracts/StartTextractJobRequestDto.cs: -------------------------------------------------------------------------------- 1 | using PlikShare.Files.Id; 2 | 3 | namespace PlikShare.Integrations.Aws.Textract.Jobs.StartJob.Contracts; 4 | 5 | public class StartTextractJobRequestDto 6 | { 7 | public required FileExtId FileExternalId { get; init; } 8 | public required TextractFeature[] Features { get; init; } 9 | } -------------------------------------------------------------------------------- /PlikShare/Integrations/Aws/Textract/Jobs/StartJob/Contracts/StartTextractJobResponseDto.cs: -------------------------------------------------------------------------------- 1 | using PlikShare.Integrations.Aws.Textract.Id; 2 | 3 | namespace PlikShare.Integrations.Aws.Textract.Jobs.StartJob.Contracts; 4 | 5 | public class StartTextractJobResponseDto 6 | { 7 | public required TextractJobExtId ExternalId { get; init; } 8 | } -------------------------------------------------------------------------------- /PlikShare/Integrations/Aws/Textract/Jobs/TextractJobDefinitionEntity.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Integrations.Aws.Textract.Jobs; 2 | 3 | public class TextractJobDefinitionEntity 4 | { 5 | public required TextractFeature[] Features { get; init; } 6 | } -------------------------------------------------------------------------------- /PlikShare/Integrations/Aws/Textract/Jobs/TextractJobStatus.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Integrations.Aws.Textract.Jobs; 2 | 3 | public enum TextractJobStatus 4 | { 5 | WaitsForFile = 0, 6 | Pending, 7 | Processing, 8 | DownloadingResults, 9 | Completed, 10 | PartiallyCompleted, 11 | Failed, 12 | } -------------------------------------------------------------------------------- /PlikShare/Integrations/Aws/Textract/TestConfiguration/Contracts/TestTextractConfigurationRequestDto.cs: -------------------------------------------------------------------------------- 1 | using PlikShare.Storages.Id; 2 | 3 | namespace PlikShare.Integrations.Aws.Textract.TestConfiguration.Contracts; 4 | 5 | public class TestTextractConfigurationRequestDto 6 | { 7 | public required string AccessKey {get;init;} 8 | public required string SecretAccessKey {get;init;} 9 | public required string Region { get; init; } 10 | public required StorageExtId StorageExternalId { get; init; } 11 | } -------------------------------------------------------------------------------- /PlikShare/Integrations/Aws/Textract/TestConfiguration/Contracts/TestTextractConfigurationResponseDto.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Integrations.Aws.Textract.TestConfiguration.Contracts; 2 | 3 | public class TestTextractConfigurationResponseDto 4 | { 5 | public required TestTextractConfigurationResultCode Code { get; init; } 6 | public required List DetectedLines { get; init; } 7 | } 8 | 9 | public enum TestTextractConfigurationResultCode 10 | { 11 | Ok 12 | } -------------------------------------------------------------------------------- /PlikShare/Integrations/Aws/Textract/TestConfiguration/plikshare_is_the_best.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/damian-krychowski/plikshare/1b5717473495bb8e02108ac3409cec10eb8a9afe/PlikShare/Integrations/Aws/Textract/TestConfiguration/plikshare_is_the_best.png -------------------------------------------------------------------------------- /PlikShare/Integrations/Aws/Textract/TextractResultFileMetadata.cs: -------------------------------------------------------------------------------- 1 | using PlikShare.Files.Metadata; 2 | 3 | namespace PlikShare.Integrations.Aws.Textract; 4 | 5 | public class TextractResultFileMetadata: FileMetadata 6 | { 7 | public required TextractFeature[] Features { get; init; } 8 | } -------------------------------------------------------------------------------- /PlikShare/Integrations/IIntegrationWithWorkspace.cs: -------------------------------------------------------------------------------- 1 | using PlikShare.Storages.Id; 2 | 3 | namespace PlikShare.Integrations; 4 | 5 | public interface IIntegrationWithWorkspace 6 | { 7 | public StorageExtId StorageExternalId { get; } 8 | } -------------------------------------------------------------------------------- /PlikShare/Integrations/IntegrationType.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Integrations; 2 | 3 | public enum IntegrationType 4 | { 5 | AwsTextract, 6 | OpenaiChatgpt 7 | } 8 | 9 | public static class IntegrationTypeExtensions 10 | { 11 | public static string GetWorkspaceNamePrefix(this IntegrationType type) 12 | { 13 | return type switch 14 | { 15 | IntegrationType.AwsTextract => "Textract", 16 | IntegrationType.OpenaiChatgpt => "ChatGpt", 17 | _ => throw new ArgumentOutOfRangeException(nameof(type), type, null) 18 | }; 19 | } 20 | } -------------------------------------------------------------------------------- /PlikShare/Integrations/OpenAi/ChatGpt/ChatGptDetails.cs: -------------------------------------------------------------------------------- 1 | using PlikShare.Storages.Id; 2 | 3 | namespace PlikShare.Integrations.OpenAi.ChatGpt; 4 | 5 | public class ChatGptDetails : IIntegrationWithWorkspace 6 | { 7 | public required string ApiKey { get; init; } 8 | public required StorageExtId StorageExternalId { get; init; } 9 | } -------------------------------------------------------------------------------- /PlikShare/Integrations/OpenAi/ChatGpt/TestConfiguration/Contracts/TestChatGptConfigurationRequestDto.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Integrations.OpenAi.ChatGpt.TestConfiguration.Contracts; 2 | 3 | public class TestChatGptConfigurationRequestDto 4 | { 5 | public required string ApiKey { get; init; } 6 | } 7 | 8 | public class TestChatGptConfigurationResponseDto 9 | { 10 | public required string Haiku { get; init; } 11 | } -------------------------------------------------------------------------------- /PlikShare/Integrations/UpdateName/Contracts/UpdateIntegrationNameRequestDto.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Integrations.UpdateName.Contracts; 2 | 3 | public class UpdateIntegrationNameRequestDto 4 | { 5 | public required string Name { get; init; } 6 | } -------------------------------------------------------------------------------- /PlikShare/Locks/CheckFileLocks/Contracts/CheckFileLocksRequestDto.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Locks.CheckFileLocks.Contracts; 2 | 3 | public class CheckFileLocksRequestDto 4 | { 5 | public required List ExternalIds { get; init; } 6 | } -------------------------------------------------------------------------------- /PlikShare/Locks/CheckFileLocks/Contracts/CheckFileLocksResponseDto.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Locks.CheckFileLocks.Contracts; 2 | 3 | public record CheckFileLocksResponseDto( 4 | List LockedExternalIds); -------------------------------------------------------------------------------- /PlikShare/Program.cs: -------------------------------------------------------------------------------- 1 | using PlikShare; 2 | 3 | var builder = WebApplication.CreateBuilder( 4 | new WebApplicationOptions() 5 | { 6 | WebRootPath = "wwwroot/browser" 7 | }); 8 | 9 | builder 10 | .Configuration 11 | .AddEnvironmentVariables(prefix: "PlikShare_"); 12 | 13 | Startup.SetupWebAppBuilder(builder); 14 | 15 | var app = builder.Build(); 16 | 17 | Startup.InitializeWebApp(app: app); 18 | 19 | app.Run(); 20 | -------------------------------------------------------------------------------- /PlikShare/Search/Get/Contracts/SearchRequestDto.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Search.Get.Contracts; 2 | 3 | public class SearchRequestDto 4 | { 5 | public required string[] WorkspaceExternalIds { get; init; } 6 | public required string[] BoxExternalIds { get; init; } 7 | public required string Phrase { get; init; } 8 | } -------------------------------------------------------------------------------- /PlikShare/Storages/Encryption/StorageEncryptionKey.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Storages.Encryption; 2 | 3 | /// 4 | /// Versioned encryption key used in storage encryption algorithms 5 | /// 6 | /// byte value of the given key version. Indexation starts from 0 7 | /// Input keying material for HKDM DeriveKey method used in AES_GCM storage encryption 8 | public record StorageEncryptionKey( 9 | byte Version, 10 | byte[] Ikm); -------------------------------------------------------------------------------- /PlikShare/Storages/Encryption/StorageManagedEncryptionDetails.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Storages.Encryption; 2 | 3 | public record StorageManagedEncryptionDetails( 4 | List Ikms); -------------------------------------------------------------------------------- /PlikShare/Storages/Entities/StorageType.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Storages.Entities; 2 | 3 | public class StorageType 4 | { 5 | public const string CloudflareR2 = "cloudflare-r2"; 6 | public const string AwsS3 = "aws-s3"; 7 | public const string DigitalOceanSpaces = "digitalocean-spaces"; 8 | public const string HardDrive = "hard-drive"; 9 | } -------------------------------------------------------------------------------- /PlikShare/Storages/Exceptions/FileNotFoundInStorageException.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Storages.Exceptions; 2 | 3 | public class FileNotFoundInStorageException: Exception 4 | { 5 | public FileNotFoundInStorageException() 6 | { 7 | 8 | } 9 | 10 | public FileNotFoundInStorageException(string message): base(message) 11 | { 12 | 13 | } 14 | } -------------------------------------------------------------------------------- /PlikShare/Storages/FileCopying/BulkInitiateCopyFiles/BulkInitiateCopyFilesQueueJobType.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Storages.FileCopying.BulkInitiateCopyFiles; 2 | 3 | public static class BulkInitiateCopyFilesQueueJobType 4 | { 5 | public const string Value = "bulk-initiate-copy-files"; 6 | } -------------------------------------------------------------------------------- /PlikShare/Storages/FileCopying/CopyFile/CopyFileQueueJobDefinition.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Storages.FileCopying.CopyFile; 2 | 3 | public class CopyFileQueueJobDefinition 4 | { 5 | public required int CopyFileQueueJobId { get; init; } 6 | } -------------------------------------------------------------------------------- /PlikShare/Storages/FileCopying/CopyFile/CopyFileQueueJobType.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Storages.FileCopying.CopyFile; 2 | 3 | public static class CopyFileQueueJobType 4 | { 5 | public const string Value = "copy-file"; 6 | } -------------------------------------------------------------------------------- /PlikShare/Storages/FileCopying/CopyFileQueueOnCompletedActionDefinition.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Storages.FileCopying; 2 | 3 | public class CopyFileQueueOnCompletedActionDefinition 4 | { 5 | public CopyFileQueueOnCompletedActionDefinition() 6 | { 7 | 8 | } 9 | 10 | public required string HandlerType { get; init; } 11 | public string? ActionHandlerDefinition { get; init; } = default; 12 | } -------------------------------------------------------------------------------- /PlikShare/Storages/FileCopying/CopyFileQueueStatus.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Storages.FileCopying; 2 | 3 | public enum CopyFileQueueStatus 4 | { 5 | Pending, 6 | Uploading, 7 | Failed, 8 | } -------------------------------------------------------------------------------- /PlikShare/Storages/FileEncryption.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | using PlikShare.Core.Encryption; 3 | using PlikShare.Storages.Encryption; 4 | 5 | namespace PlikShare.Storages; 6 | 7 | [ImmutableObject(true)] 8 | public sealed class FileEncryption 9 | { 10 | public required StorageEncryptionType EncryptionType { get; init; } 11 | public FileEncryptionMetadata? Metadata { get; init; } 12 | }; -------------------------------------------------------------------------------- /PlikShare/Storages/HardDrive/Create/Contracts/CreateHardDriveStorageRequestDto.cs: -------------------------------------------------------------------------------- 1 | using PlikShare.Storages.Encryption; 2 | using PlikShare.Storages.Id; 3 | 4 | namespace PlikShare.Storages.HardDrive.Create.Contracts; 5 | 6 | public record CreateHardDriveStorageRequestDto( 7 | string Name, 8 | string VolumePath, 9 | string FolderPath, 10 | StorageEncryptionType EncryptionType); 11 | 12 | public record CreateHardDriveStorageResponseDto( 13 | StorageExtId ExternalId); -------------------------------------------------------------------------------- /PlikShare/Storages/HardDrive/GetVolumes/Contracts/GetHardDriveVolumesResponseDto.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Storages.HardDrive.GetVolumes.Contracts; 2 | 3 | public record GetHardDriveVolumesResponseDto( 4 | HardDriveVolumeItemDto[] Items); 5 | 6 | public record HardDriveVolumeItemDto( 7 | string Path, 8 | string[] RestrictedFolderPaths); -------------------------------------------------------------------------------- /PlikShare/Storages/HardDrive/HardDriveDetailsEntity.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Storages.HardDrive; 2 | 3 | public record HardDriveDetailsEntity( 4 | string VolumePath, 5 | string FolderPath, 6 | string FullPath); -------------------------------------------------------------------------------- /PlikShare/Storages/S3/AwsS3/AwsS3DetailsEntity.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Storages.S3.AwsS3; 2 | 3 | public record AwsS3DetailsEntity( 4 | string AccessKey, 5 | string SecretAccessKey, 6 | string Region); -------------------------------------------------------------------------------- /PlikShare/Storages/S3/AwsS3/Create/Contracts/CreateAwsS3StorageRequestDto.cs: -------------------------------------------------------------------------------- 1 | using PlikShare.Storages.Encryption; 2 | using PlikShare.Storages.Id; 3 | 4 | namespace PlikShare.Storages.S3.AwsS3.Create.Contracts; 5 | 6 | public record CreateAwsS3StorageRequestDto( 7 | string Name, 8 | string AccessKey, 9 | string SecretAccessKey, 10 | string Region, 11 | StorageEncryptionType EncryptionType); 12 | 13 | public record CreateAwsS3StorageResponseDto( 14 | StorageExtId ExternalId); -------------------------------------------------------------------------------- /PlikShare/Storages/S3/AwsS3/UpdateDetails/Contracts/UpdateAwsS3StorageDetailsRequestDto.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Storages.S3.AwsS3.UpdateDetails.Contracts; 2 | 3 | public record UpdateAwsS3StorageDetailsRequestDto( 4 | string AccessKey, 5 | string SecretAccessKey, 6 | string Region); -------------------------------------------------------------------------------- /PlikShare/Storages/S3/CloudflareR2/CloudflareR2DetailsEntity.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Storages.S3.CloudflareR2; 2 | 3 | public record CloudflareR2DetailsEntity( 4 | string AccessKeyId, 5 | string SecretAccessKey, 6 | string Url); -------------------------------------------------------------------------------- /PlikShare/Storages/S3/CloudflareR2/Create/Contracts/CreateCloudflareR2StorageRequestDto.cs: -------------------------------------------------------------------------------- 1 | using PlikShare.Storages.Encryption; 2 | using PlikShare.Storages.Id; 3 | 4 | namespace PlikShare.Storages.S3.CloudflareR2.Create.Contracts; 5 | 6 | public record CreateCloudflareR2StorageRequestDto( 7 | string Name, 8 | string AccessKeyId, 9 | string SecretAccessKey, 10 | string Url, 11 | StorageEncryptionType EncryptionType); 12 | 13 | public record CreateCloudflareR2StorageResponseDto( 14 | StorageExtId ExternalId); -------------------------------------------------------------------------------- /PlikShare/Storages/S3/CloudflareR2/UpdateDetails/Contracts/UpdateCloudflareR2StorageDetailsRequestDto.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Storages.S3.CloudflareR2.UpdateDetails.Contracts; 2 | 3 | public record UpdateCloudflareR2StorageDetailsRequestDto( 4 | string AccessKeyId, 5 | string SecretAccessKey, 6 | string Url); -------------------------------------------------------------------------------- /PlikShare/Storages/S3/DigitalOcean/Create/Contracts/CreateDigitalOceanSpacesStorageRequestDto.cs: -------------------------------------------------------------------------------- 1 | using PlikShare.Storages.Encryption; 2 | using PlikShare.Storages.Id; 3 | 4 | namespace PlikShare.Storages.S3.DigitalOcean.Create.Contracts; 5 | 6 | public record CreateDigitalOceanSpacesStorageRequestDto( 7 | string Name, 8 | string AccessKey, 9 | string SecretKey, 10 | string Region, 11 | StorageEncryptionType EncryptionType); 12 | 13 | public record CreateDigitalOceanSpacesStorageResponseDto( 14 | StorageExtId ExternalId); -------------------------------------------------------------------------------- /PlikShare/Storages/S3/DigitalOcean/DigitalOceanSpacesDetailsEntity.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Storages.S3.DigitalOcean; 2 | 3 | public record DigitalOceanSpacesDetailsEntity( 4 | string AccessKey, 5 | string SecretKey, 6 | string Url); -------------------------------------------------------------------------------- /PlikShare/Storages/S3/DigitalOcean/UpdateDetails/Contracts/UpdateDigitalOceanSpacesStorageDetailsRequestDto.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Storages.S3.DigitalOcean.UpdateDetails.Contracts; 2 | 3 | public record UpdateDigitalOceanSpacesStorageDetailsRequestDto( 4 | string AccessKey, 5 | string SecretKey, 6 | string Region); -------------------------------------------------------------------------------- /PlikShare/Storages/StorageUploadDetails.cs: -------------------------------------------------------------------------------- 1 | using PlikShare.Uploads.Algorithm; 2 | 3 | namespace PlikShare.Storages; 4 | 5 | public class StorageUploadDetails 6 | { 7 | public required UploadAlgorithm Algorithm { get; init; } 8 | public required int FilePartsCount { get; init; } 9 | public required string S3UploadId { get; init; } 10 | public required string? PreSignedUploadLink { get; init; } 11 | public required bool WasMultiPartUploadInitiated { get; init; } 12 | public required FileEncryption FileEncryption { get; init; } 13 | } -------------------------------------------------------------------------------- /PlikShare/Storages/UpdateName/Contracts/UpdateStorageNameRequestDto.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Storages.UpdateName.Contracts; 2 | 3 | public record UpdateStorageNameRequestDto( 4 | string Name); -------------------------------------------------------------------------------- /PlikShare/Storages/Zip/Zip64ExtraField.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Storages.Zip; 2 | 3 | public class Zip64ExtraField 4 | { 5 | public const ushort HeaderId = 0x0001; // Identifier for ZIP64 extended information 6 | 7 | public long? UncompressedSize { get; init; } 8 | public long? CompressedSize { get; init; } 9 | public long? LocalHeaderOffset { get; init; } 10 | public uint? DiskStart { get; init; } 11 | } -------------------------------------------------------------------------------- /PlikShare/Storages/Zip/ZipEocdExtensions.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Storages.Zip; 2 | 3 | public static class ZipEocdExtensions 4 | { 5 | public static bool HasZip64Markers(this ZipEocdRecord eocd) 6 | { 7 | return eocd.NumberOfThisDisk == 0xFFFF 8 | || eocd.DiskWhereCentralDirectoryStarts == 0xFFFF 9 | || eocd.NumbersOfCentralDirectoryRecordsOnThisDisk == 0xFFFF 10 | || eocd.TotalNumberOfCentralDirectoryRecords == 0xFFFF 11 | || eocd.SizeOfCentralDirectoryInBytes == 0xFFFFFFFF 12 | || eocd.OffsetToStartCentralDirectory == 0xFFFFFFFF; 13 | } 14 | } -------------------------------------------------------------------------------- /PlikShare/Storages/Zip/ZipFileDto.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Storages.Zip; 2 | 3 | public record ZipFileDto( 4 | string FilePath, 5 | long CompressedSizeInBytes, 6 | long SizeInBytes, 7 | long OffsetToLocalFileHeader, 8 | ushort FileNameLength, 9 | ushort CompressionMethod, 10 | uint IndexInArchive); -------------------------------------------------------------------------------- /PlikShare/Uploads/Abort/QueueJob/AbortS3UploadQueueJobDefinition.cs: -------------------------------------------------------------------------------- 1 | using PlikShare.Files.Id; 2 | 3 | namespace PlikShare.Uploads.Abort.QueueJob; 4 | 5 | public class AbortS3UploadQueueJobDefinition 6 | { 7 | public required int StorageId{get; init;} 8 | public required string BucketName{get; init;} 9 | public required FileExtId FileExternalId{get; init;} 10 | public required string S3KeySecretPart{get; init;} 11 | public required string S3UploadId{get; init;} 12 | public required long FileSizeInBytes { get; init; } 13 | public required List PartETags { get; init; } 14 | }; -------------------------------------------------------------------------------- /PlikShare/Uploads/Abort/QueueJob/AbortS3UploadQueueJobType.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Uploads.Abort.QueueJob; 2 | 3 | public static class AbortS3UploadQueueJobType 4 | { 5 | public const string Value = "abort-s3-upload"; 6 | } -------------------------------------------------------------------------------- /PlikShare/Uploads/CompleteFileUpload/Contracts/CompleteFileUploadResponseDto.cs: -------------------------------------------------------------------------------- 1 | using PlikShare.Files.Id; 2 | 3 | namespace PlikShare.Uploads.CompleteFileUpload.Contracts; 4 | 5 | public record CompleteFileUploadResponseDto( 6 | FileExtId FileExternalId); -------------------------------------------------------------------------------- /PlikShare/Uploads/CompleteFileUpload/QueueJob/CompleteFileUploadQueueJobDefinition.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Uploads.CompleteFileUpload.QueueJob; 2 | 3 | public record CompleteFileUploadQueueJobDefinition( 4 | int FileUploadId); -------------------------------------------------------------------------------- /PlikShare/Uploads/CompleteFileUpload/QueueJob/CompleteS3UploadQueueJobType.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Uploads.CompleteFileUpload.QueueJob; 2 | 3 | public static class CompleteS3UploadQueueJobType 4 | { 5 | public const string Value = "complete-s3-upload"; 6 | } -------------------------------------------------------------------------------- /PlikShare/Uploads/Count/Contracts/GetUploadsCountResponse.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Uploads.Count.Contracts; 2 | 3 | public record GetUploadsCountResponse(int Count); -------------------------------------------------------------------------------- /PlikShare/Uploads/FilePartUpload/Complete/Contracts/CompleteFilePartUploadRequestDto.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Uploads.FilePartUpload.Complete.Contracts; 2 | 3 | public record CompleteFilePartUploadRequestDto( 4 | string ETag); -------------------------------------------------------------------------------- /PlikShare/Uploads/FilePartUpload/Initiate/Contracts/InitiateFilePartUploadResponseDto.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Uploads.FilePartUpload.Initiate.Contracts; 2 | 3 | public record InitiateFilePartUploadResponseDto( 4 | string UploadPreSignedUrl, 5 | long StartsAtByte, 6 | long EndsAtByte, 7 | bool IsCompleteFilePartUploadCallbackRequired); -------------------------------------------------------------------------------- /PlikShare/Uploads/GetDetails/Contracts/GetFileUploadDetailsResponseDto.cs: -------------------------------------------------------------------------------- 1 | using PlikShare.Uploads.Algorithm; 2 | 3 | namespace PlikShare.Uploads.GetDetails.Contracts; 4 | 5 | public class GetFileUploadDetailsResponseDto 6 | { 7 | public required List AlreadyUploadedPartNumbers { get; init; } 8 | public required UploadAlgorithm Algorithm { get; init; } 9 | public required int ExpectedPartsCount { get; init; } 10 | }; -------------------------------------------------------------------------------- /PlikShare/Users/Invite/IOneTimeInvitationCode.cs: -------------------------------------------------------------------------------- 1 | using PlikShare.Core.Utils; 2 | 3 | namespace PlikShare.Users.Invite; 4 | 5 | public interface IOneTimeInvitationCode 6 | { 7 | string Generate(); 8 | } 9 | 10 | public class OneTimeInvitationCode : IOneTimeInvitationCode 11 | { 12 | public string Generate() => Guid.NewGuid().ToBase62(); 13 | } -------------------------------------------------------------------------------- /PlikShare/Users/UpdateDefaultMaxWorkspaceSizeInBytes/Contracts/UpdateUserDefaultMaxWorkspaceSizeInBytesRequestDto.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Users.UpdateDefaultMaxWorkspaceSizeInBytes.Contracts; 2 | 3 | public class UpdateUserDefaultMaxWorkspaceSizeInBytesRequestDto 4 | { 5 | public required long? DefaultMaxWorkspaceSizeInBytes { get; init; } 6 | } -------------------------------------------------------------------------------- /PlikShare/Users/UpdateDefaultMaxWorkspaceTeamMembers/Contracts/UpdateUserDefaultMaxWorkspaceSizeInBytesRequestDto.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Users.UpdateDefaultMaxWorkspaceTeamMembers.Contracts; 2 | 3 | public class UpdateUserDefaultMaxWorkspaceTeamMembersRequestDto 4 | { 5 | public required int? DefaultMaxWorkspaceTeamMembers { get; init; } 6 | } -------------------------------------------------------------------------------- /PlikShare/Users/UpdateMaxWorkspaceNumber/Contracts/UpdateUserMaxWorkspaceNumberRequestDto.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Users.UpdateMaxWorkspaceNumber.Contracts; 2 | 3 | public class UpdateUserMaxWorkspaceNumberRequestDto 4 | { 5 | public required int? MaxWorkspaceNumber { get; init; } 6 | } -------------------------------------------------------------------------------- /PlikShare/Workspaces/ChangeOwner/Contracts/ChangeWorkspaceOwnerRequestDto.cs: -------------------------------------------------------------------------------- 1 | using PlikShare.Users.Id; 2 | 3 | namespace PlikShare.Workspaces.ChangeOwner.Contracts; 4 | 5 | public record ChangeWorkspaceOwnerRequestDto(UserExtId NewOwnerExternalId); -------------------------------------------------------------------------------- /PlikShare/Workspaces/CheckBucketStatus/Contracts/CheckWorkspaceBucketStatusRequestDto.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Workspaces.CheckBucketStatus.Contracts; 2 | 3 | public readonly record struct CheckWorkspaceBucketStatusResponseDto( 4 | bool IsBucketCreated); 5 | -------------------------------------------------------------------------------- /PlikShare/Workspaces/Create/Contracts/CreateWorkspaceRequestDto.cs: -------------------------------------------------------------------------------- 1 | using PlikShare.Storages.Id; 2 | 3 | namespace PlikShare.Workspaces.Create.Contracts; 4 | 5 | public record CreateWorkspaceRequestDto( 6 | StorageExtId StorageExternalId, 7 | string Name); -------------------------------------------------------------------------------- /PlikShare/Workspaces/Create/Contracts/CreateWorkspaceResponseDto.cs: -------------------------------------------------------------------------------- 1 | using PlikShare.Workspaces.Id; 2 | 3 | namespace PlikShare.Workspaces.Create.Contracts; 4 | 5 | public class CreateWorkspaceResponseDto 6 | { 7 | public required WorkspaceExtId ExternalId { get; init; } 8 | public required long? MaxSizeInBytes { get; init; } 9 | } -------------------------------------------------------------------------------- /PlikShare/Workspaces/CreateBucket/CreateWorkspaceBucketQueueJobDefinition.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Workspaces.CreateBucket; 2 | 3 | public record CreateWorkspaceBucketQueueJobDefinition( 4 | int WorkspaceId, 5 | string BucketName, 6 | int StorageId); -------------------------------------------------------------------------------- /PlikShare/Workspaces/CreateBucket/CreateWorkspaceBucketQueueJobType.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Workspaces.CreateBucket; 2 | 3 | public static class CreateWorkspaceBucketQueueJobType 4 | { 5 | public const string Value = "create-workspace-bucket"; 6 | } -------------------------------------------------------------------------------- /PlikShare/Workspaces/Delete/QueueJob/DeleteWorkspaceQueueJobDefinition.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Workspaces.Delete.QueueJob; 2 | 3 | public class DeleteWorkspaceQueueJobDefinition 4 | { 5 | public required int WorkspaceId { get; init; } 6 | public required DateTimeOffset DeletedAt { get; init; } 7 | } -------------------------------------------------------------------------------- /PlikShare/Workspaces/Delete/QueueJob/DeleteWorkspaceQueueJobType.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Workspaces.Delete.QueueJob; 2 | 3 | public static class DeleteWorkspaceQueueJobType 4 | { 5 | public const string Value = "delete-workspace"; 6 | } -------------------------------------------------------------------------------- /PlikShare/Workspaces/DeleteBucket/DeleteBucketQueueJobDefinition.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Workspaces.DeleteBucket; 2 | 3 | public class DeleteBucketQueueJobDefinition 4 | { 5 | public required string BucketName{get;init;} 6 | public required int StorageId { get; init; } 7 | } -------------------------------------------------------------------------------- /PlikShare/Workspaces/DeleteBucket/DeleteBucketQueueJobType.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Workspaces.DeleteBucket; 2 | 3 | public static class DeleteBucketQueueJobType 4 | { 5 | public const string Value = "delete-bucket"; 6 | } -------------------------------------------------------------------------------- /PlikShare/Workspaces/Members/AcceptInvitation/Contracts/AcceptWorkspaceInvitationResponseDto.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Workspaces.Members.AcceptInvitation.Contracts; 2 | 3 | public class AcceptWorkspaceInvitationResponseDto 4 | { 5 | public required long WorkspaceCurrentSizeInBytes { get; init; } 6 | public required long? WorkspaceMaxSizeInBytes { get; init; } 7 | } -------------------------------------------------------------------------------- /PlikShare/Workspaces/Members/CreateInvitation/Contracts/CreateWorkspaceMemberInvitationRequestDto.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Workspaces.Members.CreateInvitation.Contracts; 2 | 3 | public record CreateWorkspaceMemberInvitationRequestDto( 4 | List MemberEmails, 5 | bool AllowShare); -------------------------------------------------------------------------------- /PlikShare/Workspaces/Members/CreateInvitation/Contracts/CreateWorkspaceMemberInvitationResponseDto.cs: -------------------------------------------------------------------------------- 1 | using PlikShare.Users.Id; 2 | 3 | namespace PlikShare.Workspaces.Members.CreateInvitation.Contracts; 4 | 5 | public class CreateWorkspaceMemberInvitationResponseDto 6 | { 7 | public required List Members { get; set; } 8 | 9 | public record WorkspaceInvitationMember( 10 | string Email, 11 | UserExtId ExternalId); 12 | } -------------------------------------------------------------------------------- /PlikShare/Workspaces/Members/UpdatePermissions/Contracts/UpdateWorkspaceMemberPermissionsRequestDto.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Workspaces.Members.UpdatePermissions.Contracts; 2 | 3 | public class UpdateWorkspaceMemberPermissionsRequestDto 4 | { 5 | public bool AllowShare { get; set; } 6 | } -------------------------------------------------------------------------------- /PlikShare/Workspaces/Permissions/WorkspacePermissions.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Workspaces.Permissions; 2 | 3 | public readonly record struct WorkspacePermissions( 4 | bool AllowShare); -------------------------------------------------------------------------------- /PlikShare/Workspaces/UpdateCurrentSizeInBytes/QueueJob/UpdateWorkspaceCurrentSizeInBytesQueueJobDefinition.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Workspaces.UpdateCurrentSizeInBytes.QueueJob; 2 | 3 | public class UpdateWorkspaceCurrentSizeInBytesQueueJobDefinition 4 | { 5 | public required int WorkspaceId { get; init; } 6 | }; -------------------------------------------------------------------------------- /PlikShare/Workspaces/UpdateMaxSize/Contracts/UpdateWorkspaceMaxSizeDto.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Workspaces.UpdateMaxSize.Contracts; 2 | 3 | public class UpdateWorkspaceMaxSizeDto 4 | { 5 | public required long? MaxSizeInBytes { get; init; } 6 | } -------------------------------------------------------------------------------- /PlikShare/Workspaces/UpdateMaxTeamMembers/Contracts/UpdateWorkspaceMaxSizeDto.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Workspaces.UpdateMaxTeamMembers.Contracts; 2 | 3 | public class UpdateWorkspaceMaxTeamMembersRequestDto 4 | { 5 | public required int? MaxTeamMembers { get; init; } 6 | } -------------------------------------------------------------------------------- /PlikShare/Workspaces/UpdateName/Contracts/UpdateWorkspaceNameRequestDto.cs: -------------------------------------------------------------------------------- 1 | namespace PlikShare.Workspaces.UpdateName.Contracts; 2 | 3 | public record UpdateWorkspaceNameRequestDto( 4 | string Name); -------------------------------------------------------------------------------- /PlikShare/Workspaces/Validation/WorkspaceMembershipHttpContextExtensions.cs: -------------------------------------------------------------------------------- 1 | using PlikShare.Workspaces.Cache; 2 | 3 | namespace PlikShare.Workspaces.Validation; 4 | 5 | public static class WorkspaceMembershipHttpContextExtensions 6 | { 7 | public static WorkspaceMembershipContext GetWorkspaceMembershipDetails(this HttpContext httpContext) 8 | { 9 | var workspace = httpContext.Items[ValidateWorkspaceFilter.WorkspaceMembershipContext]; 10 | 11 | if (workspace is not WorkspaceMembershipContext context) 12 | { 13 | throw new InvalidOperationException( 14 | $"Cannot extract WorkspaceContext from HttpContext."); 15 | } 16 | 17 | return context; 18 | } 19 | } -------------------------------------------------------------------------------- /PlikShare/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | } 3 | -------------------------------------------------------------------------------- /assets/dashboard_printscreen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/damian-krychowski/plikshare/1b5717473495bb8e02108ac3409cec10eb8a9afe/assets/dashboard_printscreen.png -------------------------------------------------------------------------------- /assets/how_to_pronounce.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/damian-krychowski/plikshare/1b5717473495bb8e02108ac3409cec10eb8a9afe/assets/how_to_pronounce.png --------------------------------------------------------------------------------