├── .editorconfig ├── .env ├── .eslintignore ├── .eslintrc.js ├── .gitignore ├── .gitlab-ci.yml ├── .gitlab └── issue_templates │ ├── Bug.md │ └── Issue.md ├── .prettierrc.js ├── LICENSE ├── LICENSE.md ├── README.md ├── index.html ├── maven ├── assembly │ └── bin.xml └── main │ └── resources │ └── version.properties ├── package.json ├── pom.xml ├── public ├── config │ └── config.js └── favicon.ico ├── src ├── App.vue ├── api.ts ├── apiv4.ts ├── assets │ └── images │ │ ├── app-store.svg │ │ ├── freeotp-app-icon.png │ │ ├── freeotp.svg │ │ ├── google-play.svg │ │ └── linshare-logo-white.svg ├── config.ts ├── core │ ├── components │ │ ├── hydrate-error.vue │ │ ├── icons │ │ │ ├── actor-icon.vue │ │ │ ├── archive-icon.vue │ │ │ ├── arrow-left-icon.vue │ │ │ ├── arrow-right-icon.vue │ │ │ ├── assign-icon.vue │ │ │ ├── assign-mime-icon.vue │ │ │ ├── building-icon.vue │ │ │ ├── calendar-icon.vue │ │ │ ├── cancel-cross-icon.vue │ │ │ ├── check-circle-icon.vue │ │ │ ├── chevron-down-fill-icon.vue │ │ │ ├── chevron-down-icon.vue │ │ │ ├── chevron-right-icon.vue │ │ │ ├── close-circle-icon.vue │ │ │ ├── close-icon.vue │ │ │ ├── creation-icon.vue │ │ │ ├── delete-icon.vue │ │ │ ├── delete-mime-icon.vue │ │ │ ├── detail-icon.vue │ │ │ ├── document-icon.vue │ │ │ ├── door-icon.vue │ │ │ ├── dot-icon.vue │ │ │ ├── edit-icon.vue │ │ │ ├── empty-icon.vue │ │ │ ├── file-icon.vue │ │ │ ├── filter-icon.vue │ │ │ ├── flag-france.vue │ │ │ ├── flag-russia.vue │ │ │ ├── flag-uk.vue │ │ │ ├── flag-vn.vue │ │ │ ├── folder-icon.vue │ │ │ ├── globe-icon.vue │ │ │ ├── group-domain-icon.vue │ │ │ ├── identifier-icon.vue │ │ │ ├── inconsistent-users.vue │ │ │ ├── info-icon.vue │ │ │ ├── light-bulb-icon.vue │ │ │ ├── lock-icon.vue │ │ │ ├── loggers-icon.vue │ │ │ ├── menu-icon.vue │ │ │ ├── music-icon.vue │ │ │ ├── my-contact.vue │ │ │ ├── my-drive.vue │ │ │ ├── my-technical-account.vue │ │ │ ├── my-users.vue │ │ │ ├── newsfeed-icon.vue │ │ │ ├── picture-icon.vue │ │ │ ├── plus-icon.vue │ │ │ ├── pollsquare-icon.vue │ │ │ ├── reload-icon.vue │ │ │ ├── replay-icon.vue │ │ │ ├── security-icon.vue │ │ │ ├── services-icon.vue │ │ │ ├── sort-icon.vue │ │ │ ├── status-icon.vue │ │ │ ├── success-icon.vue │ │ │ ├── switch-icon.vue │ │ │ ├── text-icon.vue │ │ │ ├── unlock-icon.vue │ │ │ ├── user-add-icon.vue │ │ │ ├── user-icon.vue │ │ │ ├── user-profile-icon.vue │ │ │ ├── users-icon.vue │ │ │ ├── video-icon.vue │ │ │ ├── view-icon.vue │ │ │ ├── view-mimes-icon.vue │ │ │ └── warning-icon.vue │ │ ├── language-selector.vue │ │ ├── ls-language-modal.vue │ │ ├── ls │ │ │ ├── ls-alert.vue │ │ │ ├── ls-button.vue │ │ │ ├── ls-collapse-panel.vue │ │ │ ├── ls-collapse.vue │ │ │ ├── ls-domain-treeview.vue │ │ │ ├── ls-modal.vue │ │ │ └── ls-tag.vue │ │ ├── moderator-select.vue │ │ ├── otp-input.vue │ │ ├── page-title.vue │ │ ├── size-input.vue │ │ ├── the-copyright.vue │ │ ├── the-footer.vue │ │ ├── the-header.vue │ │ ├── the-menu.vue │ │ ├── the-mobile-menu.vue │ │ ├── the-mobile-profile.vue │ │ ├── the-pagination.vue │ │ ├── the-profile.vue │ │ ├── the-subheader.vue │ │ ├── token-input.vue │ │ └── user-select.vue │ ├── constants │ │ ├── api-errors.ts │ │ ├── breakpoint.ts │ │ ├── emails.ts │ │ ├── index.ts │ │ ├── languages.ts │ │ ├── pagination.ts │ │ └── permissions.ts │ ├── hooks │ │ ├── useAdministrationPage.ts │ │ ├── useAntConfig.ts │ │ ├── useBreadcrumbs.ts │ │ ├── useConfigurationPages.ts │ │ ├── useLanguageModal.ts │ │ ├── useLegacyFeatures.ts │ │ ├── useMenu.ts │ │ ├── useNotification.ts │ │ ├── useProfile.ts │ │ ├── useRelativeTime.ts │ │ └── useUpgradeTaskPage.ts │ ├── layouts │ │ ├── administration-page.vue │ │ ├── home-page.vue │ │ └── upgrade-page.vue │ ├── pages │ │ └── configuration-entries.vue │ ├── plugins │ │ ├── antd │ │ │ └── index.ts │ │ └── i18n │ │ │ ├── formats.ts │ │ │ ├── index.ts │ │ │ └── locales │ │ │ ├── en.json │ │ │ ├── fr.json │ │ │ ├── index.ts │ │ │ ├── ru.json │ │ │ └── vi.json │ ├── router │ │ ├── coreRoutes.ts │ │ ├── index.ts │ │ └── routes.ts │ ├── services │ │ ├── I18nService.ts │ │ └── configuration-pages.ts │ ├── store │ │ ├── hydrate.ts │ │ └── index.ts │ ├── styles │ │ ├── fonts │ │ │ └── Inter │ │ │ │ ├── Inter-Black.woff │ │ │ │ ├── Inter-Black.woff2 │ │ │ │ ├── Inter-BlackItalic.woff │ │ │ │ ├── Inter-BlackItalic.woff2 │ │ │ │ ├── Inter-Bold.woff │ │ │ │ ├── Inter-Bold.woff2 │ │ │ │ ├── Inter-BoldItalic.woff │ │ │ │ ├── Inter-BoldItalic.woff2 │ │ │ │ ├── Inter-ExtraBold.woff │ │ │ │ ├── Inter-ExtraBold.woff2 │ │ │ │ ├── Inter-ExtraBoldItalic.woff │ │ │ │ ├── Inter-ExtraBoldItalic.woff2 │ │ │ │ ├── Inter-ExtraLight.woff │ │ │ │ ├── Inter-ExtraLight.woff2 │ │ │ │ ├── Inter-ExtraLightItalic.woff │ │ │ │ ├── Inter-ExtraLightItalic.woff2 │ │ │ │ ├── Inter-Italic.woff │ │ │ │ ├── Inter-Italic.woff2 │ │ │ │ ├── Inter-Light.woff │ │ │ │ ├── Inter-Light.woff2 │ │ │ │ ├── Inter-LightItalic.woff │ │ │ │ ├── Inter-LightItalic.woff2 │ │ │ │ ├── Inter-Medium.woff │ │ │ │ ├── Inter-Medium.woff2 │ │ │ │ ├── Inter-MediumItalic.woff │ │ │ │ ├── Inter-MediumItalic.woff2 │ │ │ │ ├── Inter-Regular.woff │ │ │ │ ├── Inter-Regular.woff2 │ │ │ │ ├── Inter-SemiBold.woff │ │ │ │ ├── Inter-SemiBold.woff2 │ │ │ │ ├── Inter-SemiBoldItalic.woff │ │ │ │ ├── Inter-SemiBoldItalic.woff2 │ │ │ │ ├── Inter-Thin.woff │ │ │ │ ├── Inter-Thin.woff2 │ │ │ │ ├── Inter-ThinItalic.woff │ │ │ │ ├── Inter-ThinItalic.woff2 │ │ │ │ ├── Inter-italic.var.woff2 │ │ │ │ ├── Inter-roman.var.woff2 │ │ │ │ ├── Inter.var.woff2 │ │ │ │ └── inter.less │ │ ├── main.less │ │ └── variables.less │ ├── types │ │ ├── APIError.ts │ │ ├── AppConfiguration.ts │ │ ├── Domain.ts │ │ ├── Filters.ts │ │ ├── PaginatedList.ts │ │ ├── Sort.ts │ │ ├── Status.ts │ │ ├── TimePeriod.ts │ │ └── Unit.ts │ └── utils │ │ ├── date.ts │ │ ├── functionality.ts │ │ ├── is-email.ts │ │ └── unitStorage.ts ├── env.d.ts ├── main.ts ├── modules │ ├── activities │ │ ├── components │ │ │ ├── README.md │ │ │ ├── activities-data-table.vue │ │ │ ├── activities-filters-list.vue │ │ │ └── activities-filters-modal.vue │ │ ├── hooks │ │ │ ├── README.md │ │ │ └── use-activities.ts │ │ ├── layouts │ │ │ └── activities-layout.vue │ │ ├── pages │ │ │ ├── README.md │ │ │ └── index-page.vue │ │ ├── router │ │ │ ├── README.md │ │ │ └── index.ts │ │ ├── services │ │ │ ├── README.md │ │ │ └── index.ts │ │ ├── store │ │ │ ├── README.md │ │ │ └── index.ts │ │ └── types │ │ │ ├── README.md │ │ │ └── index.ts │ ├── administration │ │ ├── pages │ │ │ ├── contact-list │ │ │ │ ├── components │ │ │ │ │ ├── contact-list-actions.vue │ │ │ │ │ ├── contact-list-table.vue │ │ │ │ │ ├── delete-contact-card.vue │ │ │ │ │ ├── delete-contact-fail-card.vue │ │ │ │ │ └── detail-page │ │ │ │ │ │ ├── contact-list-detail-action.vue │ │ │ │ │ │ ├── contact-list-detail-card.vue │ │ │ │ │ │ ├── contact-list-detail-header.vue │ │ │ │ │ │ ├── contact-list-email-table.vue │ │ │ │ │ │ └── delete-mail-card.vue │ │ │ │ ├── hooks │ │ │ │ │ └── useContactList.ts │ │ │ │ ├── pages │ │ │ │ │ ├── contact-list-detail-page.vue │ │ │ │ │ ├── contact-list-page.vue │ │ │ │ │ └── entries-page.vue │ │ │ │ ├── router │ │ │ │ │ └── index.ts │ │ │ │ ├── services │ │ │ │ │ └── contact-list-api.ts │ │ │ │ └── types │ │ │ │ │ └── Contact.ts │ │ │ ├── entries-page.vue │ │ │ └── technical-accounts │ │ │ │ ├── components │ │ │ │ ├── create-technical-account-card.vue │ │ │ │ ├── delete-technical-account-card.vue │ │ │ │ ├── detail-page │ │ │ │ │ ├── change-password-tab.vue │ │ │ │ │ ├── system-information-card.vue │ │ │ │ │ ├── technical-account-informations.vue │ │ │ │ │ ├── technical-account-permission-table.vue │ │ │ │ │ └── user-informations.vue │ │ │ │ └── technical-accounts-table.vue │ │ │ │ ├── hooks │ │ │ │ └── useTechnicalAccount.ts │ │ │ │ ├── pages │ │ │ │ ├── entries-page.vue │ │ │ │ ├── technical-account-detail.vue │ │ │ │ └── technical-accounts.vue │ │ │ │ ├── router │ │ │ │ └── index.ts │ │ │ │ ├── services │ │ │ │ └── technical-account-api.ts │ │ │ │ └── types │ │ │ │ └── TechnicalAccount.ts │ │ └── router │ │ │ └── index.ts │ ├── auth │ │ ├── components │ │ │ ├── key-creation.vue │ │ │ ├── key-removal.vue │ │ │ ├── oidc-callback.vue │ │ │ └── otp-setup-hint.vue │ │ ├── constants │ │ │ └── index.ts │ │ ├── hooks │ │ │ ├── use2FARequiredCheck.ts │ │ │ └── useChangePassword.ts │ │ ├── pages │ │ │ ├── login-page.vue │ │ │ ├── login-second-factor.vue │ │ │ ├── manage-change-password.vue │ │ │ └── manage-second-factor-authentication.vue │ │ ├── router │ │ │ ├── index.ts │ │ │ ├── requiresAuth.guard.ts │ │ │ └── requiresSecondFAEnabled.ts │ │ ├── services │ │ │ ├── auth-api.ts │ │ │ ├── basic.ts │ │ │ └── oidc.ts │ │ ├── store │ │ │ ├── auth2FAstore.ts │ │ │ └── index.ts │ │ └── types │ │ │ ├── ChangePassword.ts │ │ │ ├── OtpSetupHintConfigs.ts │ │ │ └── SecondFactorAuthentication.ts │ ├── configuration │ │ ├── components │ │ │ ├── config-domain-actions.vue │ │ │ ├── configuration-tabs.vue │ │ │ └── select-domain-modal.vue │ │ ├── layouts │ │ │ └── configuration-layout.vue │ │ ├── pages │ │ │ ├── detail │ │ │ │ ├── components │ │ │ │ │ └── domain-form.vue │ │ │ │ ├── pages │ │ │ │ │ └── detail-page.vue │ │ │ │ └── router │ │ │ │ │ └── index.ts │ │ │ ├── domain-group-providers │ │ │ │ ├── components │ │ │ │ │ └── readme.md │ │ │ │ ├── composables │ │ │ │ │ └── readme.md │ │ │ │ ├── hooks │ │ │ │ │ └── readme.md │ │ │ │ ├── pages │ │ │ │ │ ├── group-providers-page.vue │ │ │ │ │ └── readme.md │ │ │ │ ├── router │ │ │ │ │ ├── index.ts │ │ │ │ │ └── readme.md │ │ │ │ ├── services │ │ │ │ │ └── readme.md │ │ │ │ └── types │ │ │ │ │ └── readme.md │ │ │ ├── domain-policies │ │ │ │ ├── components │ │ │ │ │ ├── assign-domain-policy-card.vue │ │ │ │ │ ├── creation-domain-policy-modal.vue │ │ │ │ │ ├── delete-domain-policies-card.vue │ │ │ │ │ ├── delete-domain-policy-card.vue │ │ │ │ │ ├── delete-domain-policy-fail-card.vue │ │ │ │ │ ├── detail-page │ │ │ │ │ │ ├── domain-policy-detail-action.vue │ │ │ │ │ │ ├── domain-policy-detail-card.vue │ │ │ │ │ │ ├── domain-policy-detail-header.vue │ │ │ │ │ │ └── domain-policy-rules-table.vue │ │ │ │ │ ├── domain-policy-actions.vue │ │ │ │ │ ├── domain-policy-table.vue │ │ │ │ │ └── duplicate-domain-policy-card.vue │ │ │ │ ├── hooks │ │ │ │ │ └── useDomainPolicies.ts │ │ │ │ ├── pages │ │ │ │ │ ├── policies-page.vue │ │ │ │ │ └── policy-detail-page.vue │ │ │ │ ├── router │ │ │ │ │ └── index.ts │ │ │ │ ├── services │ │ │ │ │ └── domain-policies-api.ts │ │ │ │ └── types │ │ │ │ │ └── DomainPolicy.ts │ │ │ ├── domain-provider-management │ │ │ │ ├── components │ │ │ │ │ └── readme.md │ │ │ │ ├── composables │ │ │ │ │ └── readme.md │ │ │ │ ├── hooks │ │ │ │ │ └── readme.md │ │ │ │ ├── pages │ │ │ │ │ ├── domain-provider-management-page.vue │ │ │ │ │ └── readme.md │ │ │ │ ├── router │ │ │ │ │ ├── index.ts │ │ │ │ │ └── readme.md │ │ │ │ ├── services │ │ │ │ │ └── readme.md │ │ │ │ └── types │ │ │ │ │ └── readme.md │ │ │ ├── domain-user-providers │ │ │ │ ├── components │ │ │ │ │ └── readme.md │ │ │ │ ├── composables │ │ │ │ │ └── readme.md │ │ │ │ ├── hooks │ │ │ │ │ └── readme.md │ │ │ │ ├── pages │ │ │ │ │ ├── domain-user-providers-page.vue │ │ │ │ │ └── readme.md │ │ │ │ ├── router │ │ │ │ │ ├── index.ts │ │ │ │ │ └── readme.md │ │ │ │ ├── services │ │ │ │ │ └── readme.md │ │ │ │ └── types │ │ │ │ │ └── readme.md │ │ │ ├── domain-workspace-providers │ │ │ │ ├── components │ │ │ │ │ └── readme.md │ │ │ │ ├── composables │ │ │ │ │ └── readme.md │ │ │ │ ├── hooks │ │ │ │ │ └── readme.md │ │ │ │ ├── pages │ │ │ │ │ ├── domain-workspace-providers-page.vue │ │ │ │ │ └── readme.md │ │ │ │ ├── router │ │ │ │ │ ├── index.ts │ │ │ │ │ └── readme.md │ │ │ │ ├── services │ │ │ │ │ └── readme.md │ │ │ │ └── types │ │ │ │ │ └── readme.md │ │ │ ├── email-templates │ │ │ │ ├── components │ │ │ │ │ ├── email-activation │ │ │ │ │ │ ├── email-activation-actions.vue │ │ │ │ │ │ ├── email-activation-detail.vue │ │ │ │ │ │ └── email-activation-table.vue │ │ │ │ │ ├── email-configuration │ │ │ │ │ │ ├── assign-mail-configuration-card.vue │ │ │ │ │ │ ├── create-mail-configuration-card.vue │ │ │ │ │ │ ├── delete-mail-configuration-card.vue │ │ │ │ │ │ ├── delete-mail-configurations-card.vue │ │ │ │ │ │ ├── delete-mail-configurations-fail-card.vue │ │ │ │ │ │ ├── detail-page │ │ │ │ │ │ │ ├── email-configuration-content-table.vue │ │ │ │ │ │ │ ├── email-configuration-detail-action.vue │ │ │ │ │ │ │ ├── email-configuration-detail-card.vue │ │ │ │ │ │ │ ├── email-configuration-detail-header.vue │ │ │ │ │ │ │ └── system-information-card.vue │ │ │ │ │ │ ├── mail-configuration-actions.vue │ │ │ │ │ │ └── mail-configuration-table.vue │ │ │ │ │ ├── email-content │ │ │ │ │ │ ├── create-mail-content-card.vue │ │ │ │ │ │ ├── delete-mail-content-card.vue │ │ │ │ │ │ ├── delete-mail-contents-card.vue │ │ │ │ │ │ ├── delete-mail-contents-fail-card.vue │ │ │ │ │ │ ├── detail-page │ │ │ │ │ │ │ ├── email-content-detail-actions.vue │ │ │ │ │ │ │ ├── email-content-detail-card.vue │ │ │ │ │ │ │ ├── email-content-detail-header.vue │ │ │ │ │ │ │ ├── email-content-information-card.vue │ │ │ │ │ │ │ └── email-content-preview-card.vue │ │ │ │ │ │ ├── email-content-actions.vue │ │ │ │ │ │ └── email-content-table.vue │ │ │ │ │ ├── email-footer │ │ │ │ │ │ ├── create-mail-footer-card.vue │ │ │ │ │ │ ├── delete-mail-footer-card.vue │ │ │ │ │ │ ├── delete-mail-footers-card.vue │ │ │ │ │ │ ├── delete-mail-footers-fail-card.vue │ │ │ │ │ │ ├── detail-page │ │ │ │ │ │ │ ├── email-footer-detail-actions.vue │ │ │ │ │ │ │ ├── email-footer-detail-card.vue │ │ │ │ │ │ │ ├── email-footer-detail-header.vue │ │ │ │ │ │ │ └── email-footer-information-card.vue │ │ │ │ │ │ ├── email-footer-actions.vue │ │ │ │ │ │ └── email-footer-table.vue │ │ │ │ │ ├── email-layout │ │ │ │ │ │ ├── delete-mail-layout-card.vue │ │ │ │ │ │ ├── delete-mail-layouts-card.vue │ │ │ │ │ │ ├── delete-mail-layouts-fail-card.vue │ │ │ │ │ │ ├── detail-page │ │ │ │ │ │ │ ├── email-layout-detail-actions.vue │ │ │ │ │ │ │ ├── email-layout-detail-card.vue │ │ │ │ │ │ │ ├── email-layout-detail-header.vue │ │ │ │ │ │ │ └── email-layout-information-card.vue │ │ │ │ │ │ ├── email-layout-creation-modal.vue │ │ │ │ │ │ ├── email-layout-table.vue │ │ │ │ │ │ └── mail-layout-actions.vue │ │ │ │ │ └── email-templates-vertical-tabs.vue │ │ │ │ ├── hooks │ │ │ │ │ ├── useEmailTemplatesActivation.ts │ │ │ │ │ ├── useEmailTemplatesConfiguration.ts │ │ │ │ │ ├── useEmailTemplatesContent.ts │ │ │ │ │ ├── useEmailTemplatesFooter.ts │ │ │ │ │ └── useEmailTemplatesLayout.ts │ │ │ │ ├── pages │ │ │ │ │ ├── activation-page.vue │ │ │ │ │ ├── configuration-detail-page.vue │ │ │ │ │ ├── configuration-page.vue │ │ │ │ │ ├── content-detail-page.vue │ │ │ │ │ ├── content-page.vue │ │ │ │ │ ├── entries-page.vue │ │ │ │ │ ├── footer-detail-page.vue │ │ │ │ │ ├── footer-page.vue │ │ │ │ │ ├── layout-detail-page.vue │ │ │ │ │ └── layout-page.vue │ │ │ │ ├── router │ │ │ │ │ └── index.ts │ │ │ │ ├── services │ │ │ │ │ └── email-templates-api.ts │ │ │ │ ├── types │ │ │ │ │ ├── MailActivation.ts │ │ │ │ │ ├── MailConfiguration.ts │ │ │ │ │ ├── MailContent.ts │ │ │ │ │ ├── MailContext.ts │ │ │ │ │ ├── MailFooter.ts │ │ │ │ │ └── MailLayout.ts │ │ │ │ └── utils │ │ │ │ │ └── mail-content-types.ts │ │ │ ├── index-page.vue │ │ │ ├── parameters │ │ │ │ ├── components │ │ │ │ │ ├── domain-functionality-details.vue │ │ │ │ │ └── domain-functionality.vue │ │ │ │ ├── hooks │ │ │ │ │ └── useFunctionalities.ts │ │ │ │ ├── pages │ │ │ │ │ └── parameters-page.vue │ │ │ │ ├── router │ │ │ │ │ └── index.ts │ │ │ │ ├── services │ │ │ │ │ └── parameters-api.ts │ │ │ │ └── types │ │ │ │ │ └── Functionality.ts │ │ │ ├── providers │ │ │ │ ├── components │ │ │ │ │ ├── domain-group-provider-ldap-form.vue │ │ │ │ │ ├── domain-group-providers.vue │ │ │ │ │ ├── domain-management-warning.vue │ │ │ │ │ ├── domain-provider-management.vue │ │ │ │ │ ├── domain-user-provider-ldap-form.vue │ │ │ │ │ ├── domain-user-provider-oidc-form.vue │ │ │ │ │ ├── domain-user-provider-twake-form.vue │ │ │ │ │ ├── domain-user-providers.vue │ │ │ │ │ ├── domain-workspace-provider-ldap-form.vue │ │ │ │ │ └── domain-workspace-providers.vue │ │ │ │ ├── hooks │ │ │ │ │ └── use-providers.ts │ │ │ │ ├── pages │ │ │ │ │ └── providers-page.vue │ │ │ │ ├── router │ │ │ │ │ └── index.ts │ │ │ │ ├── services │ │ │ │ │ └── providers-api.ts │ │ │ │ └── types │ │ │ │ │ ├── Domain.ts │ │ │ │ │ ├── GroupProvider.ts │ │ │ │ │ ├── UserProvider.ts │ │ │ │ │ └── WorkspaceProvider.ts │ │ │ ├── public-keys │ │ │ │ ├── components │ │ │ │ │ └── readme.md │ │ │ │ ├── composables │ │ │ │ │ └── readme.md │ │ │ │ ├── hooks │ │ │ │ │ └── readme.md │ │ │ │ ├── pages │ │ │ │ │ ├── public-keys-page.vue │ │ │ │ │ └── readme.md │ │ │ │ ├── router │ │ │ │ │ ├── index.ts │ │ │ │ │ └── readme.md │ │ │ │ ├── services │ │ │ │ │ └── readme.md │ │ │ │ └── types │ │ │ │ │ └── readme.md │ │ │ ├── quota │ │ │ │ ├── components │ │ │ │ │ ├── allocation-within-the-current-domain.vue │ │ │ │ │ ├── domain-quota-and-used-space.vue │ │ │ │ │ ├── quota-doughnut-chart.vue │ │ │ │ │ ├── quota-input.vue │ │ │ │ │ ├── quota-visualize.vue │ │ │ │ │ └── subdomains-allocation-settings.vue │ │ │ │ ├── hooks │ │ │ │ │ └── useQuota.ts │ │ │ │ ├── pages │ │ │ │ │ └── quota-page.vue │ │ │ │ ├── router │ │ │ │ │ └── index.ts │ │ │ │ ├── services │ │ │ │ │ └── quota-api.ts │ │ │ │ └── types │ │ │ │ │ ├── Container.ts │ │ │ │ │ └── Quota.ts │ │ │ ├── remote-filters │ │ │ │ ├── components │ │ │ │ │ ├── group-filter-ldap.vue │ │ │ │ │ ├── group-filters-list.vue │ │ │ │ │ ├── user-filter-ldap.vue │ │ │ │ │ ├── user-filters-list.vue │ │ │ │ │ ├── workspace-filter-ldap.vue │ │ │ │ │ └── workspace-filters-list.vue │ │ │ │ ├── composables │ │ │ │ │ └── readme.md │ │ │ │ ├── hooks │ │ │ │ │ └── readme.md │ │ │ │ ├── pages │ │ │ │ │ └── remote-filters-page.vue │ │ │ │ ├── router │ │ │ │ │ └── index.ts │ │ │ │ ├── services │ │ │ │ │ ├── group-filter-api.ts │ │ │ │ │ ├── user-filter-api.ts │ │ │ │ │ └── workspace-filter-api.ts │ │ │ │ └── types │ │ │ │ │ ├── GroupFilters.ts │ │ │ │ │ ├── UserFilter.ts │ │ │ │ │ └── WorkspaceFilters.ts │ │ │ ├── remote-servers │ │ │ │ ├── components │ │ │ │ │ ├── remote-server-ldap-modal.vue │ │ │ │ │ └── remote-server-twake-modal.vue │ │ │ │ ├── hooks │ │ │ │ │ └── readme.md │ │ │ │ ├── pages │ │ │ │ │ └── remote-servers-page.vue │ │ │ │ ├── router │ │ │ │ │ └── index.ts │ │ │ │ ├── services │ │ │ │ │ └── remote-server-api.ts │ │ │ │ └── types │ │ │ │ │ └── RemoteServer.ts │ │ │ ├── type-mime-policies │ │ │ │ ├── components │ │ │ │ │ ├── assign-mime-policy-card.vue │ │ │ │ │ ├── delete-mime-policies-card.vue │ │ │ │ │ ├── delete-mime-policies-fail-card.vue │ │ │ │ │ ├── delete-mime-policy-card.vue │ │ │ │ │ ├── detail-page │ │ │ │ │ │ ├── mime-detail-card.vue │ │ │ │ │ │ ├── mime-detail-header.vue │ │ │ │ │ │ ├── mime-system-information.vue │ │ │ │ │ │ ├── mime-type-options.vue │ │ │ │ │ │ └── mime-types-table.vue │ │ │ │ │ ├── mime-policies-actions.vue │ │ │ │ │ ├── mime-policies-creation-modal.vue │ │ │ │ │ └── mime-policies-table.vue │ │ │ │ ├── hooks │ │ │ │ │ └── useMimePolicies.ts │ │ │ │ ├── pages │ │ │ │ │ ├── mime-policy-detail-page.vue │ │ │ │ │ └── type-mime-policies-page.vue │ │ │ │ ├── router │ │ │ │ │ └── index.ts │ │ │ │ ├── services │ │ │ │ │ └── mime-policies-api.ts │ │ │ │ └── types │ │ │ │ │ └── MimeType.ts │ │ │ └── welcome-messages │ │ │ │ ├── components │ │ │ │ ├── domain-welcome-message-form.vue │ │ │ │ ├── domain-welcome-message.vue │ │ │ │ ├── domain-welcome-messages-large-table.vue │ │ │ │ └── domain-welcome-messages-small-table.vue │ │ │ │ ├── composables │ │ │ │ └── readme.md │ │ │ │ ├── hooks │ │ │ │ └── useWelcomeMessages.ts │ │ │ │ ├── pages │ │ │ │ └── welcome-messages-page.vue │ │ │ │ ├── router │ │ │ │ └── index.ts │ │ │ │ ├── services │ │ │ │ └── welcome-messages-api.ts │ │ │ │ └── types │ │ │ │ └── WelcomeMessages.ts │ │ └── router │ │ │ └── index.ts │ ├── design-system │ │ ├── pages │ │ │ ├── data-entry-page.vue │ │ │ ├── feedback-page.vue │ │ │ ├── form-page.vue │ │ │ ├── general-page.vue │ │ │ ├── index-page.vue │ │ │ └── navigation-page.vue │ │ └── router │ │ │ └── index.ts │ ├── domain │ │ ├── components │ │ │ ├── domain-associated-list-modal.vue │ │ │ ├── domain-creation-form-modal.vue │ │ │ ├── domain-functionalities-list.vue │ │ │ ├── domain-functionality-details.vue │ │ │ ├── domain-functionality.vue │ │ │ ├── domains-tree-node.vue │ │ │ └── domains-tree.vue │ │ ├── hooks │ │ │ ├── useAssociatedDomainsModal.ts │ │ │ ├── useDomainDelete.ts │ │ │ └── useFunctionalities.ts │ │ ├── pages │ │ │ ├── domain-page.vue │ │ │ └── domain-providers-page.vue │ │ ├── router │ │ │ ├── index.ts │ │ │ ├── requiresDomainAccessibility.ts │ │ │ └── requiresDomainUpdate.ts │ │ ├── services │ │ │ └── domain-api.ts │ │ ├── store │ │ │ └── index.ts │ │ └── types │ │ │ ├── Domain.ts │ │ │ └── DomainTreeNode.ts │ ├── inconsistent-users │ │ ├── components │ │ │ ├── inconsistent-users-list.vue │ │ │ ├── inconsistent-users-migration-modal.vue │ │ │ ├── inconsistent-users-tabs.vue │ │ │ ├── profil-creation-modal.vue │ │ │ ├── user-diagnostic-quota.vue │ │ │ ├── users-diagnostic-detail-card.vue │ │ │ └── users-diagnostic-table.vue │ │ ├── hooks │ │ │ ├── useInconsistentUsers.ts │ │ │ └── useUsersDiagnostic.ts │ │ ├── pages │ │ │ ├── entries-page.vue │ │ │ ├── inconsistent-users-entries-page.vue │ │ │ ├── manage-diagnostic-users.vue │ │ │ └── manage-inconsistent-users.vue │ │ ├── router │ │ │ └── index.ts │ │ ├── services │ │ │ └── inconsistent-users-api.ts │ │ ├── store │ │ │ └── index.ts │ │ └── types │ │ │ ├── InconsistentUsers.ts │ │ │ └── UserDiagnotic.ts │ ├── password │ │ └── router │ │ │ └── index.ts │ ├── reporting │ │ ├── components │ │ │ ├── human-mime-type-icon.vue │ │ │ ├── mime-type-statistic.vue │ │ │ ├── reporting-filters-list.vue │ │ │ ├── reporting-filters-modal.vue │ │ │ ├── reporting-page.vue │ │ │ ├── reporting-shares-filters-list.vue │ │ │ ├── reporting-shares-filters-modal.vue │ │ │ ├── reporting-shares-page.vue │ │ │ ├── reporting-statistic-files-quantity.vue │ │ │ ├── reporting-statistic-generics-list.vue │ │ │ ├── reporting-statistic-generics-table.vue │ │ │ ├── reporting-statistic-generics.vue │ │ │ ├── reporting-statistic-most-uploaded.vue │ │ │ ├── reporting-statistic-storage-consumption.vue │ │ │ ├── reporting-statistic-summary.vue │ │ │ ├── reporting-statistic-total-storage.vue │ │ │ ├── reporting-statistic-user-used-storage-table.vue │ │ │ ├── reporting-statistic-user-used-storage.vue │ │ │ ├── reporting-storage-page.vue │ │ │ ├── top-shares-by-file-count.vue │ │ │ └── top-shares-by-file-size.vue │ │ ├── constants │ │ │ └── human-mime-type-color.ts │ │ ├── hooks │ │ │ ├── useMimeType.ts │ │ │ ├── useStorageConsumption.ts │ │ │ ├── useTopSharesFiles.ts │ │ │ └── useTopSharesFilesSize.ts │ │ ├── router │ │ │ └── index.ts │ │ ├── services │ │ │ └── statistic-api.ts │ │ ├── store │ │ │ └── index.ts │ │ └── types │ │ │ ├── AccountQuotaStatistic.ts │ │ │ ├── GenericStatistic.ts │ │ │ ├── MimeTypeStatistic.ts │ │ │ ├── StorageConsumptionStatistic.ts │ │ │ ├── TopSharesFileCount.ts │ │ │ └── TopSharesFileSize.ts │ ├── shared-spaces │ │ ├── components │ │ │ ├── member-large-table.vue │ │ │ ├── member-small-table.vue │ │ │ ├── shared-space-details.vue │ │ │ ├── shared-space-member-role-modal.vue │ │ │ ├── shared-space-members-add-modal.vue │ │ │ ├── shared-space-members-list-item.vue │ │ │ ├── shared-space-members-list.vue │ │ │ ├── shared-space-role-select.vue │ │ │ ├── shared-spaces-list.vue │ │ │ ├── workgroup-icon.vue │ │ │ └── workspace-icon.vue │ │ ├── hooks │ │ │ ├── useSharedSpaceMemberList.ts │ │ │ └── useSharedSpacesList.ts │ │ ├── pages │ │ │ ├── entries-page.vue │ │ │ └── manage-shared-spaces.vue │ │ ├── router │ │ │ └── index.ts │ │ ├── services │ │ │ └── shared-space-api.ts │ │ ├── store │ │ │ └── index.ts │ │ └── types │ │ │ ├── ShareSpaceList.ts │ │ │ ├── SharedSpace.ts │ │ │ ├── SharedSpaceAccount.ts │ │ │ ├── SharedSpaceMember.ts │ │ │ └── SharedSpaceRole.ts │ ├── upgrades │ │ ├── components │ │ │ ├── async-task-table.vue │ │ │ ├── retry-upgrade-task-card.vue │ │ │ ├── upgrade-list-actions.vue │ │ │ └── upgrade-list-table.vue │ │ ├── hooks │ │ │ └── useUpgradeTasks.ts │ │ ├── pages │ │ │ ├── upgrade-console.vue │ │ │ ├── upgrade-list-detail-page.vue │ │ │ └── upgrade-list-page.vue │ │ ├── router │ │ │ └── index.ts │ │ ├── services │ │ │ └── upgrade-task-api.ts │ │ └── types │ │ │ └── UpgradeTask.ts │ └── user │ │ ├── components │ │ ├── account-autocomplete-item.vue │ │ ├── current-user-guests-small-table.vue │ │ ├── current-user-guests.vue │ │ ├── guest-moderator-add-modal.vue │ │ ├── large-table.vue │ │ ├── search-form.vue │ │ ├── small-table.vue │ │ ├── user-guest-moderators.vue │ │ ├── user-locked-alert.vue │ │ ├── user-personal-space-quota.vue │ │ ├── user-profile.vue │ │ ├── user-restricted-contacts.vue │ │ └── user-shared-key-alert.vue │ │ ├── hooks │ │ ├── useGuest.ts │ │ ├── useGuestList.ts │ │ └── useUsersList.ts │ │ ├── pages │ │ ├── entries-page.vue │ │ ├── manage-users.vue │ │ └── user-detail.vue │ │ ├── router │ │ └── index.ts │ │ ├── services │ │ ├── guest-api.ts │ │ ├── user-api.ts │ │ └── user-utils.ts │ │ └── types │ │ ├── GuestList.ts │ │ ├── GuestModerator.ts │ │ ├── RestrictedContact.ts │ │ ├── User.ts │ │ ├── UserQuota.ts │ │ └── UsersList.ts ├── router.d.ts ├── shims-vue.d.ts └── window.d.ts ├── tsconfig.json └── vite.config.js /.editorconfig: -------------------------------------------------------------------------------- 1 | [*.{js,jsx,ts,tsx,vue}] 2 | indent_style = space 3 | indent_size = 2 4 | trim_trailing_whitespace = true 5 | insert_final_newline = true 6 | -------------------------------------------------------------------------------- /.env: -------------------------------------------------------------------------------- 1 | BACKEND_API_URL = 'https://admin.linshare-dev-on-commit.integration-linshare.org' 2 | ACCESS_TOKEN='7cQx7y-pw-WnXfHSNngm' 3 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist 3 | node 4 | maven 5 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | const defaultRules = { 2 | 'no-debugger': process.env.NODE_ENV !== 'development' ? 'error' : 'off', 3 | 'prettier/prettier': 'error', 4 | }; 5 | 6 | module.exports = { 7 | root: true, 8 | env: { 9 | browser: true, 10 | node: true, 11 | }, 12 | plugins: ['@typescript-eslint', 'prettier'], 13 | extends: ['eslint:recommended', 'prettier'], 14 | rules: defaultRules, 15 | parserOptions: { 16 | ecmaVersion: 2020, 17 | }, 18 | overrides: [ 19 | { 20 | files: ['vite.config.js'], 21 | parserOptions: { 22 | sourceType: 'module', 23 | }, 24 | }, 25 | { 26 | files: ['*.ts', '*.vue'], 27 | parser: 'vue-eslint-parser', 28 | parserOptions: { 29 | parser: '@typescript-eslint/parser', 30 | }, 31 | extends: [ 32 | 'eslint:recommended', 33 | 'plugin:@typescript-eslint/recommended', 34 | 'plugin:vue/vue3-recommended', 35 | 'prettier', 36 | ], 37 | rules: { 38 | ...defaultRules, 39 | 'no-undef': 'off', 40 | 'no-console': ['error', { allow: ['warn', 'error'] }], 41 | '@typescript-eslint/ban-ts-comment': 'off', 42 | '@typescript-eslint/no-explicit-any': 'off', 43 | '@typescript-eslint/no-unused-vars': 'off', 44 | 'vue/no-v-html': 'off', 45 | }, 46 | }, 47 | ], 48 | }; 49 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /dist 4 | 5 | 6 | # local env files 7 | .env.local 8 | .env.*.local 9 | node 10 | 11 | # Log files 12 | npm-debug.log* 13 | yarn-debug.log* 14 | yarn-error.log* 15 | pnpm-debug.log* 16 | # Editor directories and files 17 | .idea 18 | .vscode 19 | *.suo 20 | *.ntvs* 21 | *.njsproj 22 | *.sln 23 | *.sw? 24 | 25 | # npm file 26 | package-lock.json 27 | yarn.lock 28 | .yarn 29 | -------------------------------------------------------------------------------- /.gitlab-ci.yml: -------------------------------------------------------------------------------- 1 | stages: 2 | - build 3 | 4 | .curl-tpl: &curl-tpl 5 | variables: 6 | GIT_STRATEGY: none 7 | tags: 8 | - curl 9 | 10 | check_author: 11 | image: docker-registry.linagora.com:5000/lgs-releases/gitlab-integrity-checks:latest 12 | stage: build 13 | variables: 14 | GIT_DEPTH: "1" 15 | tags: 16 | - ultralight 17 | script: 18 | - check_author.py check "$GITLAB_USER_EMAIL" "$GITLAB_USER_NAME" --no-accents 19 | except: 20 | refs: 21 | - master@linagora/lgs/linshare/products/linshare-ui-admin 22 | - tags@linagora/lgs/linshare/products/linshare-ui-admin 23 | - /^release-.*/@linagora/lgs/linshare/products/linshare-ui-admin 24 | retry: 25 | max: 2 26 | when: 27 | - runner_system_failure 28 | - stuck_or_timeout_failure 29 | 30 | build: 31 | <<: *curl-tpl 32 | stage: build 33 | script: 34 | - echo skip 35 | retry: 36 | max: 2 37 | when: 38 | - runner_system_failure 39 | - stuck_or_timeout_failure 40 | -------------------------------------------------------------------------------- /.gitlab/issue_templates/Bug.md: -------------------------------------------------------------------------------- 1 | ## **Bug details** 2 | 3 | - **User detail:** 4 | 5 | 6 | - **Description:** 7 | 8 | 9 | - **Bug occurred time:** 10 | 11 | 12 | - **Environment(version):** 13 | 14 | 15 | - **API(optional)** 16 | 17 | 18 | - **Params/cURL(backend)(optional):** 19 | 20 | 21 | - **Steps to reproduce:** 22 | 23 | 24 | - **Expectation:** 25 | 26 | 27 | - **Image/Video envidence:** 28 | 29 | 30 | ## **Related issues** 31 | - **QA** 32 | 33 | 34 | - **Story** 35 | 36 | 37 | - **Tech** 38 | 39 | -------------------------------------------------------------------------------- /.gitlab/issue_templates/Issue.md: -------------------------------------------------------------------------------- 1 | ## Related issues 2 | - QA 3 | - Story 4 | - Tech 5 | ## Technical details 6 | -------------------------------------------------------------------------------- /.prettierrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | singleQuote: true, 3 | printWidth: 120 4 | }; 5 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # linshare-ui-admin 2 | 3 | ## Project setup 4 | ``` 5 | yarn 6 | ``` 7 | 8 | ### Compiles and hot-reloads for development 9 | ``` 10 | yarn run dev 11 | 12 | # Development with a custom backend API base url 13 | 14 | BACKEND_API_URL='https://example.linshare.org' yarn run dev 15 | ``` 16 | 17 | ### Compiles and minifies for production 18 | ``` 19 | yarn run build 20 | ``` 21 | 22 | 23 | ### Lints and fixes files 24 | ``` 25 | yarn run lint 26 | 27 | # Fix lint errors 28 | 29 | yarn run lint:fix 30 | ``` 31 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | LinShare Admin 9 | 10 | 11 | 12 | 15 |
16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /maven/assembly/bin.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | archive 4 | 5 | tar.bz2 6 | 7 | 8 | 9 | dist 10 | . 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /maven/main/resources/version.properties: -------------------------------------------------------------------------------- 1 | Implementation-Version=${project.version} 2 | Project-Version=${project.version} 3 | Compilation-Version=${sources.version} 4 | Compilation-Timestamp=${build.timestamp} 5 | -------------------------------------------------------------------------------- /public/config/config.js: -------------------------------------------------------------------------------- 1 | window.APP_CONFIGURATION = Object.freeze({ 2 | beta: true, 3 | legacyAppUrl: '/', 4 | oidcEnabled: false, 5 | oidcSetting: { 6 | authority: 'http://auth.linshare.local/', 7 | client_id: 'linshare', 8 | client_secret: 'linshare', 9 | scope: 'openid email profile', 10 | }, 11 | }); 12 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linagora/linshare-ui-admin/715bdfc967b504b51ccaf6c619239161cdccefcd/public/favicon.ico -------------------------------------------------------------------------------- /src/App.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 20 | 21 | 41 | -------------------------------------------------------------------------------- /src/assets/images/freeotp-app-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linagora/linshare-ui-admin/715bdfc967b504b51ccaf6c619239161cdccefcd/src/assets/images/freeotp-app-icon.png -------------------------------------------------------------------------------- /src/config.ts: -------------------------------------------------------------------------------- 1 | import AppConfiguration from '@/core/types/AppConfiguration'; 2 | 3 | export const DEFAULT_CONFIGURATION: AppConfiguration = { 4 | beta: true, 5 | legacyAppUrl: '/', 6 | homeRoute: '/administration', 7 | rootWelcomeMessageUuid: '4bc57114-c8c9-11e4-a859-37b5db95d856', 8 | oidcEnabled: false, 9 | appContext: '/new', 10 | oidcSetting: { 11 | authority: 'https://auth.linshare.local', 12 | client_id: 'linshare', 13 | client_secret: 'linshare', 14 | scope: 'openid email profile', 15 | loadUserInfo: true, 16 | }, 17 | }; 18 | 19 | const config: AppConfiguration = { 20 | ...DEFAULT_CONFIGURATION, 21 | ...window.APP_CONFIGURATION, 22 | }; 23 | 24 | export default config; 25 | -------------------------------------------------------------------------------- /src/core/components/hydrate-error.vue: -------------------------------------------------------------------------------- 1 | 18 | 19 | 28 | 29 | 40 | -------------------------------------------------------------------------------- /src/core/components/icons/actor-icon.vue: -------------------------------------------------------------------------------- 1 | 9 | 26 | -------------------------------------------------------------------------------- /src/core/components/icons/archive-icon.vue: -------------------------------------------------------------------------------- 1 | 18 | 19 | 27 | -------------------------------------------------------------------------------- /src/core/components/icons/arrow-right-icon.vue: -------------------------------------------------------------------------------- 1 | 9 | 16 | -------------------------------------------------------------------------------- /src/core/components/icons/assign-mime-icon.vue: -------------------------------------------------------------------------------- 1 | 18 | 19 | 28 | -------------------------------------------------------------------------------- /src/core/components/icons/cancel-cross-icon.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 27 | -------------------------------------------------------------------------------- /src/core/components/icons/check-circle-icon.vue: -------------------------------------------------------------------------------- 1 | 8 | 27 | -------------------------------------------------------------------------------- /src/core/components/icons/chevron-down-fill-icon.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 17 | -------------------------------------------------------------------------------- /src/core/components/icons/chevron-down-icon.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 17 | -------------------------------------------------------------------------------- /src/core/components/icons/chevron-right-icon.vue: -------------------------------------------------------------------------------- 1 | 9 | 16 | -------------------------------------------------------------------------------- /src/core/components/icons/close-circle-icon.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 19 | -------------------------------------------------------------------------------- /src/core/components/icons/close-icon.vue: -------------------------------------------------------------------------------- 1 | 8 | 16 | -------------------------------------------------------------------------------- /src/core/components/icons/creation-icon.vue: -------------------------------------------------------------------------------- 1 | 18 | 19 | 32 | -------------------------------------------------------------------------------- /src/core/components/icons/detail-icon.vue: -------------------------------------------------------------------------------- 1 | 18 | 19 | 27 | -------------------------------------------------------------------------------- /src/core/components/icons/dot-icon.vue: -------------------------------------------------------------------------------- 1 | 18 | 19 | 24 | -------------------------------------------------------------------------------- /src/core/components/icons/flag-france.vue: -------------------------------------------------------------------------------- 1 | 8 | 21 | -------------------------------------------------------------------------------- /src/core/components/icons/flag-russia.vue: -------------------------------------------------------------------------------- 1 | 8 | 32 | -------------------------------------------------------------------------------- /src/core/components/icons/flag-vn.vue: -------------------------------------------------------------------------------- 1 | 8 | 20 | -------------------------------------------------------------------------------- /src/core/components/icons/info-icon.vue: -------------------------------------------------------------------------------- 1 | 8 | 16 | -------------------------------------------------------------------------------- /src/core/components/icons/menu-icon.vue: -------------------------------------------------------------------------------- 1 | 8 | 16 | -------------------------------------------------------------------------------- /src/core/components/icons/newsfeed-icon.vue: -------------------------------------------------------------------------------- 1 | 8 | 16 | -------------------------------------------------------------------------------- /src/core/components/icons/plus-icon.vue: -------------------------------------------------------------------------------- 1 | 18 | 19 | 27 | -------------------------------------------------------------------------------- /src/core/components/icons/security-icon.vue: -------------------------------------------------------------------------------- 1 | 18 | 19 | 27 | -------------------------------------------------------------------------------- /src/core/components/icons/sort-icon.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 17 | -------------------------------------------------------------------------------- /src/core/components/icons/status-icon.vue: -------------------------------------------------------------------------------- 1 | 18 | 19 | 27 | -------------------------------------------------------------------------------- /src/core/components/icons/success-icon.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 27 | -------------------------------------------------------------------------------- /src/core/components/icons/switch-icon.vue: -------------------------------------------------------------------------------- 1 | 8 | 18 | -------------------------------------------------------------------------------- /src/core/components/icons/user-icon.vue: -------------------------------------------------------------------------------- 1 | 18 | 19 | 27 | -------------------------------------------------------------------------------- /src/core/components/icons/video-icon.vue: -------------------------------------------------------------------------------- 1 | 18 | 19 | 27 | -------------------------------------------------------------------------------- /src/core/components/icons/view-icon.vue: -------------------------------------------------------------------------------- 1 | 18 | 19 | 27 | -------------------------------------------------------------------------------- /src/core/components/icons/view-mimes-icon.vue: -------------------------------------------------------------------------------- 1 | 18 | 19 | 27 | -------------------------------------------------------------------------------- /src/core/components/ls/ls-alert.vue: -------------------------------------------------------------------------------- 1 | 8 | 16 | 58 | -------------------------------------------------------------------------------- /src/core/components/ls/ls-collapse-panel.vue: -------------------------------------------------------------------------------- 1 | 6 | 50 | -------------------------------------------------------------------------------- /src/core/components/ls/ls-collapse.vue: -------------------------------------------------------------------------------- 1 | 6 | 17 | -------------------------------------------------------------------------------- /src/core/components/ls/ls-modal.vue: -------------------------------------------------------------------------------- 1 | 8 | 15 | -------------------------------------------------------------------------------- /src/core/components/ls/ls-tag.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 16 | 17 | 35 | -------------------------------------------------------------------------------- /src/core/components/size-input.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 50 | -------------------------------------------------------------------------------- /src/core/components/the-copyright.vue: -------------------------------------------------------------------------------- 1 | 8 | -------------------------------------------------------------------------------- /src/core/components/the-footer.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 10 | 11 | 27 | -------------------------------------------------------------------------------- /src/core/constants/api-errors.ts: -------------------------------------------------------------------------------- 1 | export const ERRORS_REQUIRE_EXTRA_MESSAGE = [1006, 1007, 1008]; 2 | -------------------------------------------------------------------------------- /src/core/constants/breakpoint.ts: -------------------------------------------------------------------------------- 1 | export const LARGE_SCREEN_BREAK_POINT = '(min-width: 1069px)'; 2 | -------------------------------------------------------------------------------- /src/core/constants/emails.ts: -------------------------------------------------------------------------------- 1 | export const EMAIL_DEFAULT_UUID = { 2 | CONFIGURATION: '946b190d-4c95-485f-bfe6-d288a2de1edd', 3 | LAYOUT: '15044750-89d1-11e3-8d50-5404a683a462', 4 | FOOTER: 'e85f4a22-8cf2-11e3-8a7a-5404a683a462', 5 | }; 6 | -------------------------------------------------------------------------------- /src/core/constants/index.ts: -------------------------------------------------------------------------------- 1 | export const CONFIG = { 2 | API: { 3 | BASE_URL: 'linshare/webservice/rest/admin/v5', 4 | DEFAULT_HEADERS: { 5 | 'WWW-No-Authenticate': 'linshare', 6 | }, 7 | }, 8 | }; 9 | 10 | export const CONFIGV4 = { 11 | API: { 12 | BASE_URL: 'linshare/webservice/rest/admin/v4', 13 | DEFAULT_HEADERS: { 14 | 'WWW-No-Authenticate': 'linshare', 15 | }, 16 | }, 17 | }; 18 | 19 | export * from './languages'; 20 | export * from './permissions'; 21 | export * from './pagination'; 22 | export * from './api-errors'; 23 | -------------------------------------------------------------------------------- /src/core/constants/languages.ts: -------------------------------------------------------------------------------- 1 | export const LANGUAGES = { 2 | SUPPORTED_LANGUAGE: [ 3 | { 4 | name: 'English', 5 | key: 'us', 6 | language: 'en', 7 | }, 8 | { 9 | name: 'Français', 10 | key: 'fr', 11 | language: 'fr', 12 | }, 13 | { 14 | name: 'Tiếng Việt', 15 | key: 'vi', 16 | language: 'vi', 17 | }, 18 | { 19 | name: 'Pусский', 20 | key: 'ru', 21 | language: 'ru', 22 | }, 23 | ], 24 | DEFAULT: 'en', 25 | SUPPORTED_LOCALES: ['en', 'fr', 'ru', 'vi'], 26 | }; 27 | -------------------------------------------------------------------------------- /src/core/constants/pagination.ts: -------------------------------------------------------------------------------- 1 | export const DEFAULT_PAGE_SIZE = 10; 2 | -------------------------------------------------------------------------------- /src/core/constants/permissions.ts: -------------------------------------------------------------------------------- 1 | export const PERMISSIONS = Object.freeze({ 2 | DOMAINS: { 3 | VIEW: 'DOMAINS.VIEW', 4 | MANAGE_DOMAINS: 'DOMAINS.MANAGE_DOMAINS', 5 | FUNCTIONALITIES: 'DOMAINS.FUNCTIONALITIES', 6 | }, 7 | USERS: { 8 | VIEW: 'USERS.VIEW', 9 | MANAGE_USERS: 'USERS.MANAGE_USERS', 10 | INCONSISTENT_USERS: 'USERS.INCONSISTENT_USERS', 11 | TECHNICAL_ACCOUNTS: 'USERS.TECHNICAL_ACCOUNTS', 12 | }, 13 | WORKGROUPS: { 14 | VIEW: 'WORKGROUPS.VIEW', 15 | }, 16 | MAILING_LISTS: { 17 | VIEW: 'MAILING_LISTS.VIEW', 18 | }, 19 | HISTORY: { 20 | VIEW: 'HISTORY.VIEW', 21 | }, 22 | MAILS: { 23 | VIEW: 'MAILS.VIEW', 24 | CONFIGURATION: 'MAILS.CONFIGURATION', 25 | LAYOUT: 'MAILS.LAYOUT', 26 | FOOTER: 'MAILS.FOOTER', 27 | CONTENT: 'MAILS.CONTENT', 28 | ACTIVATION: 'MAILS.ACTIVATION', 29 | }, 30 | UPGRADE_TASKS: { 31 | VIEW: 'UPGRADE_TASKS.VIEW', 32 | }, 33 | }); 34 | -------------------------------------------------------------------------------- /src/core/hooks/useAdministrationPage.ts: -------------------------------------------------------------------------------- 1 | import { ref } from 'vue'; 2 | 3 | const actions = ref< 4 | { 5 | class: string; 6 | action: () => void; 7 | label: string; 8 | icon?: any; 9 | }[] 10 | >([]); 11 | 12 | export default function useAdministrationPage() { 13 | function setActions( 14 | items: { 15 | class: string; 16 | label: string; 17 | icon?: any; 18 | action: () => void; 19 | }[] 20 | ) { 21 | actions.value = items; 22 | } 23 | 24 | function addActions( 25 | items: { 26 | class: string; 27 | label: string; 28 | icon?: any; 29 | action: () => void; 30 | }[] 31 | ) { 32 | actions.value.push(...items); 33 | } 34 | 35 | return { 36 | actions, 37 | setActions, 38 | addActions, 39 | }; 40 | } 41 | -------------------------------------------------------------------------------- /src/core/hooks/useAntConfig.ts: -------------------------------------------------------------------------------- 1 | import { computed, ComputedRef } from 'vue'; 2 | import { useI18n } from 'vue-i18n'; 3 | import { LANGUAGES } from '@/core/constants'; 4 | import { Locale } from 'ant-design-vue/es/locale-provider'; 5 | import enUS from 'ant-design-vue/es/locale/en_US'; 6 | import frFR from 'ant-design-vue/es/locale/fr_FR'; 7 | import ruRU from 'ant-design-vue/es/locale/ru_RU'; 8 | import viVN from 'ant-design-vue/es/locale/vi_VN'; 9 | 10 | const keyToLocaleMap = new Map(); 11 | 12 | keyToLocaleMap.set('en', enUS); 13 | keyToLocaleMap.set('fr', frFR); 14 | keyToLocaleMap.set('ru', ruRU); 15 | keyToLocaleMap.set('vi', viVN); 16 | 17 | type AntConfig = { 18 | antdLocale: ComputedRef; 19 | }; 20 | 21 | export default function useAntConfig(): AntConfig { 22 | const { locale } = useI18n(); 23 | const antdLocale = computed(() => 24 | keyToLocaleMap.has(locale.value) ? keyToLocaleMap.get(locale.value) : keyToLocaleMap.get(LANGUAGES.DEFAULT) 25 | ); 26 | 27 | return { 28 | antdLocale, 29 | }; 30 | } 31 | -------------------------------------------------------------------------------- /src/core/hooks/useLanguageModal.ts: -------------------------------------------------------------------------------- 1 | import { ref, Ref } from 'vue'; 2 | 3 | type UsableLanguageModal = { 4 | languageVisible: Ref; 5 | toogleLanguage: (state: boolean) => void; 6 | }; 7 | const languageVisible = ref(false); 8 | 9 | export default function useLanguageModal(): UsableLanguageModal { 10 | const toogleLanguage = (state: boolean) => { 11 | languageVisible.value = state; 12 | }; 13 | 14 | return { 15 | languageVisible, 16 | toogleLanguage, 17 | }; 18 | } 19 | -------------------------------------------------------------------------------- /src/core/hooks/useMenu.ts: -------------------------------------------------------------------------------- 1 | import { ref, watch, Ref } from 'vue'; 2 | import { useRouter } from 'vue-router'; 3 | 4 | type UsableMenu = { 5 | current: Ref; 6 | visible: Ref; 7 | onClose: () => void; 8 | showDrawer: () => void; 9 | }; 10 | 11 | export default function useMenu(): UsableMenu { 12 | const { currentRoute } = useRouter(); 13 | const current = ref([currentRoute.value.path.split('/')[1]]); 14 | const visible = ref(false); 15 | 16 | const showDrawer = () => { 17 | visible.value = true; 18 | }; 19 | const onClose = () => { 20 | visible.value = false; 21 | }; 22 | 23 | watch(currentRoute, (newRoute) => { 24 | current.value = [newRoute.path.split('/')[1]]; 25 | }); 26 | return { 27 | visible, 28 | showDrawer, 29 | onClose, 30 | current, 31 | }; 32 | } 33 | -------------------------------------------------------------------------------- /src/core/hooks/useNotification.ts: -------------------------------------------------------------------------------- 1 | import { createVNode } from 'vue'; 2 | import { Modal } from 'ant-design-vue'; 3 | import { useI18n } from 'vue-i18n'; 4 | import { ExclamationCircleOutlined } from '@ant-design/icons-vue'; 5 | 6 | interface ModalOptions { 7 | title: string; 8 | content: string; 9 | okText?: string; 10 | cancelText?: string; 11 | onOk?: (...args: any[]) => any; 12 | } 13 | 14 | type UsableNotification = { 15 | infoModal: (options: ModalOptions) => void; 16 | confirmModal: (options: ModalOptions) => void; 17 | }; 18 | 19 | export default function useNotification(): UsableNotification { 20 | const { t } = useI18n(); 21 | 22 | const infoModal = (options: ModalOptions) => { 23 | Modal.info({ 24 | title: () => options.title, 25 | icon: () => createVNode(ExclamationCircleOutlined), 26 | content: () => options.content, 27 | okText: () => options.okText || t('GENERAL.OK'), 28 | onOk: options.onOk, 29 | }); 30 | }; 31 | 32 | const confirmModal = (options: ModalOptions) => { 33 | Modal.confirm({ 34 | title: () => options.title, 35 | icon: () => createVNode(ExclamationCircleOutlined), 36 | content: () => options.content, 37 | okText: () => options.okText || t('GENERAL.OK'), 38 | cancelText: () => options.cancelText || t('GENERAL.CANCEL'), 39 | onOk: options.onOk, 40 | }); 41 | }; 42 | 43 | return { 44 | infoModal, 45 | confirmModal, 46 | }; 47 | } 48 | -------------------------------------------------------------------------------- /src/core/hooks/useProfile.ts: -------------------------------------------------------------------------------- 1 | import { ref, watch, Ref } from 'vue'; 2 | import { useRouter } from 'vue-router'; 3 | 4 | type UsableProfile = { 5 | current: Ref; 6 | visible: Ref; 7 | onClose: () => void; 8 | showDrawer: () => void; 9 | }; 10 | 11 | export default function useProfile(): UsableProfile { 12 | const { currentRoute, push } = useRouter(); 13 | const current = ref([currentRoute.value.path.split('/')[1]]); 14 | const visible = ref(false); 15 | 16 | const showDrawer = () => { 17 | visible.value = true; 18 | }; 19 | const onClose = () => { 20 | visible.value = false; 21 | }; 22 | 23 | watch(currentRoute, (newRoute) => { 24 | current.value = [newRoute.path.split('/')[1]]; 25 | }); 26 | return { 27 | visible, 28 | showDrawer, 29 | onClose, 30 | current, 31 | }; 32 | } 33 | -------------------------------------------------------------------------------- /src/core/hooks/useRelativeTime.ts: -------------------------------------------------------------------------------- 1 | import { useI18n } from 'vue-i18n'; 2 | import { computed, ComputedRef } from 'vue'; 3 | interface Unit { 4 | max: number; 5 | value: number; 6 | name: Intl.RelativeTimeFormatUnit; 7 | } 8 | 9 | const UNITS: Unit[] = [ 10 | { max: 2760000, value: 60000, name: 'minute' }, 11 | { max: 72000000, value: 3600000, name: 'hour' }, 12 | { max: 518400000, value: 86400000, name: 'day' }, 13 | { max: 2419200000, value: 604800000, name: 'week' }, 14 | { max: 28512000000, value: 2592000000, name: 'month' }, 15 | { max: Infinity, value: 31536000000, name: 'year' }, 16 | ]; 17 | 18 | type UsableRelativeTime = ComputedRef | undefined; 19 | 20 | export default function useRelativeTime(from: Date | string | number): UsableRelativeTime { 21 | const { locale, t } = useI18n(); 22 | const { abs, round } = Math; 23 | const diff = +new Date(from) - +new Date(); 24 | 25 | if (abs(diff) < 60000) { 26 | return computed(() => t('GENERAL.JUST_NOW', locale.value)); 27 | } 28 | 29 | for (const unit of UNITS) { 30 | if (abs(diff) < unit.max) { 31 | return computed(() => new Intl.RelativeTimeFormat(locale.value).format(round(diff / unit.value), unit.name)); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/core/hooks/useUpgradeTaskPage.ts: -------------------------------------------------------------------------------- 1 | import { ref } from 'vue'; 2 | 3 | const actions = ref< 4 | { 5 | class: string; 6 | action: () => void; 7 | loading?: boolean; 8 | label: string; 9 | icon?: any; 10 | }[] 11 | >([]); 12 | 13 | export default function useUpgradeTaskPage() { 14 | function setActions( 15 | items: { 16 | class: string; 17 | label: string; 18 | icon?: any; 19 | action: () => void; 20 | }[] 21 | ) { 22 | actions.value = items; 23 | } 24 | 25 | function addActions( 26 | items: { 27 | class: string; 28 | label: string; 29 | icon?: any; 30 | action: () => void; 31 | }[] 32 | ) { 33 | actions.value.push(...items); 34 | } 35 | 36 | return { 37 | actions, 38 | setActions, 39 | addActions, 40 | }; 41 | } 42 | -------------------------------------------------------------------------------- /src/core/layouts/home-page.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | 24 | 25 | 55 | -------------------------------------------------------------------------------- /src/core/pages/configuration-entries.vue: -------------------------------------------------------------------------------- 1 | 6 | 14 | -------------------------------------------------------------------------------- /src/core/plugins/i18n/index.ts: -------------------------------------------------------------------------------- 1 | import { createI18n } from 'vue-i18n'; 2 | import i18nService from '@/core/services/I18nService'; 3 | import messages from '@/core/plugins/i18n/locales'; 4 | import { DATETIME_FORMATS as datetimeFormats } from './formats'; 5 | 6 | const locale = i18nService && i18nService.getLocale(); 7 | 8 | const i18n = createI18n({ 9 | legacy: false, 10 | globalInjection: true, 11 | missingWarn: false, 12 | fallbackWarn: false, 13 | datetimeFormats, 14 | locale, 15 | messages, 16 | }); 17 | 18 | export default i18n; 19 | -------------------------------------------------------------------------------- /src/core/plugins/i18n/locales/index.ts: -------------------------------------------------------------------------------- 1 | import en from './en.json'; 2 | import fr from './fr.json'; 3 | import ru from './ru.json'; 4 | import vi from './vi.json'; 5 | 6 | export default { 7 | en, 8 | fr, 9 | ru, 10 | vi, 11 | }; 12 | -------------------------------------------------------------------------------- /src/core/router/coreRoutes.ts: -------------------------------------------------------------------------------- 1 | import config from '@/config'; 2 | import { RouteRecordRaw } from 'vue-router'; 3 | import HomePage from '@/core/layouts/home-page.vue'; 4 | import { UpgradesRoute } from '@/modules/upgrades/router'; 5 | import { ReportingRoute } from '@/modules/reporting/router'; 6 | import { ActivitiesRoute } from '@/modules/activities/router'; 7 | import { ConfigurationRoute } from '@/modules/configuration/router'; 8 | import { AdministrationRoute } from '@/modules/administration/router'; 9 | import { ManageSecondFactorAuthenticationRoute, ManageChangePasswordRoute } from '@/modules/auth/router'; 10 | 11 | export const CoreRoutes: Array = [ 12 | { 13 | name: 'Home', 14 | path: '/', 15 | redirect: config.homeRoute, 16 | component: HomePage, 17 | meta: { 18 | requiresAuth: true, 19 | }, 20 | children: [ 21 | UpgradesRoute, 22 | ReportingRoute, 23 | ActivitiesRoute, 24 | ConfigurationRoute, 25 | AdministrationRoute, 26 | ManageSecondFactorAuthenticationRoute, 27 | ManageChangePasswordRoute, 28 | ], 29 | }, 30 | ]; 31 | -------------------------------------------------------------------------------- /src/core/router/index.ts: -------------------------------------------------------------------------------- 1 | import { createRouter, createWebHistory } from 'vue-router'; 2 | import routes from './routes'; 3 | import config from '@/config'; 4 | 5 | /** 6 | * We prefer hash routing for 2 reasons: 7 | * - Ease for webserver configuration as the app can be served under a subpath 8 | * - Callback uri for OIDC authentication is fixed in the app 9 | */ 10 | const router = createRouter({ 11 | history: createWebHistory(config.appContext), 12 | routes, 13 | }); 14 | 15 | export default router; 16 | -------------------------------------------------------------------------------- /src/core/router/routes.ts: -------------------------------------------------------------------------------- 1 | import { RouteRecordRaw } from 'vue-router'; 2 | import { LoginRoutes } from '@/modules/auth/router'; 3 | import { CoreRoutes } from '@/core/router/coreRoutes'; 4 | 5 | export default [...LoginRoutes, ...CoreRoutes] as Array; 6 | -------------------------------------------------------------------------------- /src/core/services/I18nService.ts: -------------------------------------------------------------------------------- 1 | import { LANGUAGES } from '@/core/constants'; 2 | 3 | /** 4 | * I18n service 5 | * 6 | * This service stores selected locale in LocalStorage. 7 | */ 8 | class I18nService { 9 | private localStorage: Storage; 10 | 11 | constructor() { 12 | if (!window.localStorage) { 13 | console.warn('Local storage is not supported by your browser. English will be used as the default language.'); 14 | } 15 | 16 | this.localStorage = window.localStorage; 17 | } 18 | 19 | setLocale(locale: string) { 20 | if (!this.localStorage) return; 21 | 22 | if (LANGUAGES.SUPPORTED_LOCALES.indexOf(locale) === -1) { 23 | console.warn(`The locale is not supported: ${locale}`); 24 | 25 | return; 26 | } 27 | 28 | localStorage.setItem('locale', locale); 29 | } 30 | 31 | getLocale(): string { 32 | if (!this.localStorage) return LANGUAGES.DEFAULT; 33 | 34 | return localStorage.getItem('locale') || LANGUAGES.DEFAULT; 35 | } 36 | } 37 | 38 | export default new I18nService(); 39 | -------------------------------------------------------------------------------- /src/core/store/index.ts: -------------------------------------------------------------------------------- 1 | import { defineStore } from 'pinia'; 2 | interface AppState { 3 | hydrating: boolean; 4 | hydrated: boolean; 5 | authenticating: boolean; 6 | authenticated: boolean; 7 | error: boolean; 8 | } 9 | 10 | export const useAppStore = defineStore('appStore', { 11 | state: (): AppState => ({ 12 | hydrated: false, 13 | hydrating: false, 14 | authenticating: false, 15 | authenticated: false, 16 | error: false, 17 | }), 18 | actions: { 19 | setHydrating(hydrating: boolean) { 20 | this.hydrating = hydrating; 21 | }, 22 | setHydrated(hydrated: boolean) { 23 | this.hydrated = hydrated; 24 | }, 25 | setAuthenticated(authenticated: boolean) { 26 | this.authenticated = authenticated; 27 | }, 28 | setAuthenticating(authenticating: boolean) { 29 | this.authenticating = authenticating; 30 | }, 31 | setError(errorState: boolean) { 32 | this.error = errorState; 33 | }, 34 | }, 35 | }); 36 | -------------------------------------------------------------------------------- /src/core/styles/fonts/Inter/Inter-Black.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linagora/linshare-ui-admin/715bdfc967b504b51ccaf6c619239161cdccefcd/src/core/styles/fonts/Inter/Inter-Black.woff -------------------------------------------------------------------------------- /src/core/styles/fonts/Inter/Inter-Black.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linagora/linshare-ui-admin/715bdfc967b504b51ccaf6c619239161cdccefcd/src/core/styles/fonts/Inter/Inter-Black.woff2 -------------------------------------------------------------------------------- /src/core/styles/fonts/Inter/Inter-BlackItalic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linagora/linshare-ui-admin/715bdfc967b504b51ccaf6c619239161cdccefcd/src/core/styles/fonts/Inter/Inter-BlackItalic.woff -------------------------------------------------------------------------------- /src/core/styles/fonts/Inter/Inter-BlackItalic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linagora/linshare-ui-admin/715bdfc967b504b51ccaf6c619239161cdccefcd/src/core/styles/fonts/Inter/Inter-BlackItalic.woff2 -------------------------------------------------------------------------------- /src/core/styles/fonts/Inter/Inter-Bold.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linagora/linshare-ui-admin/715bdfc967b504b51ccaf6c619239161cdccefcd/src/core/styles/fonts/Inter/Inter-Bold.woff -------------------------------------------------------------------------------- /src/core/styles/fonts/Inter/Inter-Bold.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linagora/linshare-ui-admin/715bdfc967b504b51ccaf6c619239161cdccefcd/src/core/styles/fonts/Inter/Inter-Bold.woff2 -------------------------------------------------------------------------------- /src/core/styles/fonts/Inter/Inter-BoldItalic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linagora/linshare-ui-admin/715bdfc967b504b51ccaf6c619239161cdccefcd/src/core/styles/fonts/Inter/Inter-BoldItalic.woff -------------------------------------------------------------------------------- /src/core/styles/fonts/Inter/Inter-BoldItalic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linagora/linshare-ui-admin/715bdfc967b504b51ccaf6c619239161cdccefcd/src/core/styles/fonts/Inter/Inter-BoldItalic.woff2 -------------------------------------------------------------------------------- /src/core/styles/fonts/Inter/Inter-ExtraBold.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linagora/linshare-ui-admin/715bdfc967b504b51ccaf6c619239161cdccefcd/src/core/styles/fonts/Inter/Inter-ExtraBold.woff -------------------------------------------------------------------------------- /src/core/styles/fonts/Inter/Inter-ExtraBold.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linagora/linshare-ui-admin/715bdfc967b504b51ccaf6c619239161cdccefcd/src/core/styles/fonts/Inter/Inter-ExtraBold.woff2 -------------------------------------------------------------------------------- /src/core/styles/fonts/Inter/Inter-ExtraBoldItalic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linagora/linshare-ui-admin/715bdfc967b504b51ccaf6c619239161cdccefcd/src/core/styles/fonts/Inter/Inter-ExtraBoldItalic.woff -------------------------------------------------------------------------------- /src/core/styles/fonts/Inter/Inter-ExtraBoldItalic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linagora/linshare-ui-admin/715bdfc967b504b51ccaf6c619239161cdccefcd/src/core/styles/fonts/Inter/Inter-ExtraBoldItalic.woff2 -------------------------------------------------------------------------------- /src/core/styles/fonts/Inter/Inter-ExtraLight.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linagora/linshare-ui-admin/715bdfc967b504b51ccaf6c619239161cdccefcd/src/core/styles/fonts/Inter/Inter-ExtraLight.woff -------------------------------------------------------------------------------- /src/core/styles/fonts/Inter/Inter-ExtraLight.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linagora/linshare-ui-admin/715bdfc967b504b51ccaf6c619239161cdccefcd/src/core/styles/fonts/Inter/Inter-ExtraLight.woff2 -------------------------------------------------------------------------------- /src/core/styles/fonts/Inter/Inter-ExtraLightItalic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linagora/linshare-ui-admin/715bdfc967b504b51ccaf6c619239161cdccefcd/src/core/styles/fonts/Inter/Inter-ExtraLightItalic.woff -------------------------------------------------------------------------------- /src/core/styles/fonts/Inter/Inter-ExtraLightItalic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linagora/linshare-ui-admin/715bdfc967b504b51ccaf6c619239161cdccefcd/src/core/styles/fonts/Inter/Inter-ExtraLightItalic.woff2 -------------------------------------------------------------------------------- /src/core/styles/fonts/Inter/Inter-Italic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linagora/linshare-ui-admin/715bdfc967b504b51ccaf6c619239161cdccefcd/src/core/styles/fonts/Inter/Inter-Italic.woff -------------------------------------------------------------------------------- /src/core/styles/fonts/Inter/Inter-Italic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linagora/linshare-ui-admin/715bdfc967b504b51ccaf6c619239161cdccefcd/src/core/styles/fonts/Inter/Inter-Italic.woff2 -------------------------------------------------------------------------------- /src/core/styles/fonts/Inter/Inter-Light.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linagora/linshare-ui-admin/715bdfc967b504b51ccaf6c619239161cdccefcd/src/core/styles/fonts/Inter/Inter-Light.woff -------------------------------------------------------------------------------- /src/core/styles/fonts/Inter/Inter-Light.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linagora/linshare-ui-admin/715bdfc967b504b51ccaf6c619239161cdccefcd/src/core/styles/fonts/Inter/Inter-Light.woff2 -------------------------------------------------------------------------------- /src/core/styles/fonts/Inter/Inter-LightItalic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linagora/linshare-ui-admin/715bdfc967b504b51ccaf6c619239161cdccefcd/src/core/styles/fonts/Inter/Inter-LightItalic.woff -------------------------------------------------------------------------------- /src/core/styles/fonts/Inter/Inter-LightItalic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linagora/linshare-ui-admin/715bdfc967b504b51ccaf6c619239161cdccefcd/src/core/styles/fonts/Inter/Inter-LightItalic.woff2 -------------------------------------------------------------------------------- /src/core/styles/fonts/Inter/Inter-Medium.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linagora/linshare-ui-admin/715bdfc967b504b51ccaf6c619239161cdccefcd/src/core/styles/fonts/Inter/Inter-Medium.woff -------------------------------------------------------------------------------- /src/core/styles/fonts/Inter/Inter-Medium.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linagora/linshare-ui-admin/715bdfc967b504b51ccaf6c619239161cdccefcd/src/core/styles/fonts/Inter/Inter-Medium.woff2 -------------------------------------------------------------------------------- /src/core/styles/fonts/Inter/Inter-MediumItalic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linagora/linshare-ui-admin/715bdfc967b504b51ccaf6c619239161cdccefcd/src/core/styles/fonts/Inter/Inter-MediumItalic.woff -------------------------------------------------------------------------------- /src/core/styles/fonts/Inter/Inter-MediumItalic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linagora/linshare-ui-admin/715bdfc967b504b51ccaf6c619239161cdccefcd/src/core/styles/fonts/Inter/Inter-MediumItalic.woff2 -------------------------------------------------------------------------------- /src/core/styles/fonts/Inter/Inter-Regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linagora/linshare-ui-admin/715bdfc967b504b51ccaf6c619239161cdccefcd/src/core/styles/fonts/Inter/Inter-Regular.woff -------------------------------------------------------------------------------- /src/core/styles/fonts/Inter/Inter-Regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linagora/linshare-ui-admin/715bdfc967b504b51ccaf6c619239161cdccefcd/src/core/styles/fonts/Inter/Inter-Regular.woff2 -------------------------------------------------------------------------------- /src/core/styles/fonts/Inter/Inter-SemiBold.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linagora/linshare-ui-admin/715bdfc967b504b51ccaf6c619239161cdccefcd/src/core/styles/fonts/Inter/Inter-SemiBold.woff -------------------------------------------------------------------------------- /src/core/styles/fonts/Inter/Inter-SemiBold.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linagora/linshare-ui-admin/715bdfc967b504b51ccaf6c619239161cdccefcd/src/core/styles/fonts/Inter/Inter-SemiBold.woff2 -------------------------------------------------------------------------------- /src/core/styles/fonts/Inter/Inter-SemiBoldItalic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linagora/linshare-ui-admin/715bdfc967b504b51ccaf6c619239161cdccefcd/src/core/styles/fonts/Inter/Inter-SemiBoldItalic.woff -------------------------------------------------------------------------------- /src/core/styles/fonts/Inter/Inter-SemiBoldItalic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linagora/linshare-ui-admin/715bdfc967b504b51ccaf6c619239161cdccefcd/src/core/styles/fonts/Inter/Inter-SemiBoldItalic.woff2 -------------------------------------------------------------------------------- /src/core/styles/fonts/Inter/Inter-Thin.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linagora/linshare-ui-admin/715bdfc967b504b51ccaf6c619239161cdccefcd/src/core/styles/fonts/Inter/Inter-Thin.woff -------------------------------------------------------------------------------- /src/core/styles/fonts/Inter/Inter-Thin.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linagora/linshare-ui-admin/715bdfc967b504b51ccaf6c619239161cdccefcd/src/core/styles/fonts/Inter/Inter-Thin.woff2 -------------------------------------------------------------------------------- /src/core/styles/fonts/Inter/Inter-ThinItalic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linagora/linshare-ui-admin/715bdfc967b504b51ccaf6c619239161cdccefcd/src/core/styles/fonts/Inter/Inter-ThinItalic.woff -------------------------------------------------------------------------------- /src/core/styles/fonts/Inter/Inter-ThinItalic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linagora/linshare-ui-admin/715bdfc967b504b51ccaf6c619239161cdccefcd/src/core/styles/fonts/Inter/Inter-ThinItalic.woff2 -------------------------------------------------------------------------------- /src/core/styles/fonts/Inter/Inter-italic.var.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linagora/linshare-ui-admin/715bdfc967b504b51ccaf6c619239161cdccefcd/src/core/styles/fonts/Inter/Inter-italic.var.woff2 -------------------------------------------------------------------------------- /src/core/styles/fonts/Inter/Inter-roman.var.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linagora/linshare-ui-admin/715bdfc967b504b51ccaf6c619239161cdccefcd/src/core/styles/fonts/Inter/Inter-roman.var.woff2 -------------------------------------------------------------------------------- /src/core/styles/fonts/Inter/Inter.var.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linagora/linshare-ui-admin/715bdfc967b504b51ccaf6c619239161cdccefcd/src/core/styles/fonts/Inter/Inter.var.woff2 -------------------------------------------------------------------------------- /src/core/types/AppConfiguration.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable camelcase */ 2 | export default interface AppConfiguration { 3 | beta: boolean; 4 | rootWelcomeMessageUuid: string; 5 | legacyAppUrl: string; 6 | homeRoute: string; 7 | appContext: string; 8 | oidcEnabled: boolean; 9 | oidcSetting: { 10 | authority: string; 11 | client_id: string; 12 | client_secret: string; 13 | scope: string; 14 | loadUserInfo: boolean; 15 | }; 16 | } 17 | -------------------------------------------------------------------------------- /src/core/types/Domain.ts: -------------------------------------------------------------------------------- 1 | export default interface Domain { 2 | name?: string; 3 | checked?: boolean; 4 | children?: Domain[]; 5 | type?: string; 6 | uuid: string; 7 | label?: string; 8 | identifier?: string; 9 | } 10 | -------------------------------------------------------------------------------- /src/core/types/Filters.ts: -------------------------------------------------------------------------------- 1 | export default interface Filters { 2 | [key: string]: string | boolean | undefined; 3 | } 4 | -------------------------------------------------------------------------------- /src/core/types/PaginatedList.ts: -------------------------------------------------------------------------------- 1 | export interface PaginatedList { 2 | data: T[]; 3 | total: number; 4 | totalPages: number; 5 | current: number; 6 | } 7 | -------------------------------------------------------------------------------- /src/core/types/Sort.ts: -------------------------------------------------------------------------------- 1 | export enum SORT_ORDER { 2 | ASC = 'ASC', 3 | DESC = 'DESC', 4 | } 5 | 6 | export default interface Sort { 7 | field?: string; 8 | order: SORT_ORDER; 9 | } 10 | -------------------------------------------------------------------------------- /src/core/types/Status.ts: -------------------------------------------------------------------------------- 1 | enum STATUS { 2 | LOADING = 'loading', 3 | SUCCESS = 'success', 4 | ERROR = 'error', 5 | } 6 | 7 | export { STATUS }; 8 | -------------------------------------------------------------------------------- /src/core/types/TimePeriod.ts: -------------------------------------------------------------------------------- 1 | export type TimePeriod = 2 | | 'ALL_TIME' 3 | | 'LAST_DAY' 4 | | 'LAST_7_DAYS' 5 | | 'LAST_30_DAYS' 6 | | 'LAST_6_MONTHS' 7 | | 'LAST_YEAR' 8 | | 'CUSTOM'; 9 | -------------------------------------------------------------------------------- /src/core/types/Unit.ts: -------------------------------------------------------------------------------- 1 | export type Unit = { 2 | name: string; 3 | value: string; 4 | factor: number; 5 | }; 6 | -------------------------------------------------------------------------------- /src/core/utils/functionality.ts: -------------------------------------------------------------------------------- 1 | import { 2 | Functionality, 3 | UnitSizeParameterValue, 4 | UnitTimeParameterValue, 5 | IntegerParameterValue, 6 | } from '../types/Functionality'; 7 | 8 | export function getMaximumParameter( 9 | functionality: Functionality | undefined 10 | ): UnitSizeParameterValue | UnitTimeParameterValue | IntegerParameterValue | null { 11 | if (!functionality) { 12 | return null; 13 | } 14 | 15 | const parameter = functionality.parameter; 16 | 17 | switch (parameter?.type) { 18 | case 'UNIT_SIZE_ALL': 19 | case 'UNIT_TIME_ALL': 20 | case 'INTEGER_ALL': 21 | return parameter.maximum; 22 | 23 | default: 24 | return null; 25 | } 26 | } 27 | 28 | export function isEnable(functionality: Functionality | undefined): boolean { 29 | if (!functionality) { 30 | return false; 31 | } 32 | return functionality?.activationPolicy.enable.value; 33 | } 34 | -------------------------------------------------------------------------------- /src/core/utils/is-email.ts: -------------------------------------------------------------------------------- 1 | export function isEmail(string: string): boolean { 2 | const emailRegex = /^\S+@\S+\.\S+$/; 3 | 4 | return emailRegex.test(string); 5 | } 6 | -------------------------------------------------------------------------------- /src/env.d.ts: -------------------------------------------------------------------------------- 1 | interface ImportMetaEnv extends Readonly> { 2 | readonly MODE: string; 3 | } 4 | 5 | interface ImportMeta { 6 | readonly env: ImportMetaEnv; 7 | } 8 | -------------------------------------------------------------------------------- /src/main.ts: -------------------------------------------------------------------------------- 1 | import { createApp } from 'vue'; 2 | import App from './App.vue'; 3 | import router from '@/core/router'; 4 | import i18n from '@/core/plugins/i18n'; 5 | import { createPinia } from 'pinia'; 6 | import useAntdComponents from '@/core/plugins/antd'; 7 | import { requiresAuthGuard } from '@/modules/auth/router/requiresAuth.guard'; 8 | import { requiresDomainAccessibility } from '@/modules/domain/router/requiresDomainAccessibility'; 9 | import { requiresDomainUpdate } from '@/modules/domain/router/requiresDomainUpdate'; 10 | 11 | requiresDomainUpdate(router); 12 | requiresAuthGuard(router); 13 | requiresDomainAccessibility(router); 14 | 15 | const app = createApp(App).use(router).use(i18n).use(createPinia()); 16 | 17 | useAntdComponents(app).mount('#app'); 18 | -------------------------------------------------------------------------------- /src/modules/activities/components/README.md: -------------------------------------------------------------------------------- 1 | Component folder -------------------------------------------------------------------------------- /src/modules/activities/hooks/README.md: -------------------------------------------------------------------------------- 1 | Hooks folder -------------------------------------------------------------------------------- /src/modules/activities/pages/README.md: -------------------------------------------------------------------------------- 1 | Pages folder -------------------------------------------------------------------------------- /src/modules/activities/pages/index-page.vue: -------------------------------------------------------------------------------- 1 | 6 | 9 | -------------------------------------------------------------------------------- /src/modules/activities/router/README.md: -------------------------------------------------------------------------------- 1 | Router folder -------------------------------------------------------------------------------- /src/modules/activities/router/index.ts: -------------------------------------------------------------------------------- 1 | import { RouteRecordRaw } from 'vue-router'; 2 | 3 | export const ActivitiesRoute: RouteRecordRaw = { 4 | name: 'Activities', 5 | path: 'activities', 6 | component: () => import('../layouts/activities-layout.vue'), 7 | meta: { 8 | label: 'NAVIGATOR.ACTIVITIES', 9 | requiresAuth: true, 10 | uiBeta: true, 11 | }, 12 | children: [ 13 | { 14 | name: 'ActivitiesEntries', 15 | path: '', 16 | component: () => import('../pages/index-page.vue'), 17 | }, 18 | ], 19 | }; 20 | -------------------------------------------------------------------------------- /src/modules/activities/services/README.md: -------------------------------------------------------------------------------- 1 | Service folder -------------------------------------------------------------------------------- /src/modules/activities/services/index.ts: -------------------------------------------------------------------------------- 1 | import api from '@/api'; 2 | import type { PaginatedList } from '@/core/types/PaginatedList'; 3 | import { ActivityLogParameters } from '@/modules/activities/types'; 4 | 5 | async function getActivitiesLogs( 6 | domainUuid: string, 7 | includeNestedDomains: boolean, 8 | beginDate: string | undefined, 9 | endDate: string | undefined, 10 | action?: string, 11 | type?: string, 12 | domain?: string, 13 | size?: number, 14 | page?: number, 15 | sortField?: string, 16 | sortOrder?: string, 17 | actorEmail?: string, 18 | resourceName?: string 19 | ): Promise> { 20 | const queryUrl = `domains/${domainUuid}/audit`; 21 | 22 | return await api.get(queryUrl, { 23 | params: { 24 | includeNestedDomains, 25 | beginDate, 26 | endDate, 27 | action, 28 | type, 29 | domain, 30 | size, 31 | page, 32 | sortField, 33 | sortOrder, 34 | actorEmail, 35 | resourceName, 36 | }, 37 | }); 38 | } 39 | 40 | export { getActivitiesLogs }; 41 | -------------------------------------------------------------------------------- /src/modules/activities/store/README.md: -------------------------------------------------------------------------------- 1 | Store folder -------------------------------------------------------------------------------- /src/modules/activities/types/README.md: -------------------------------------------------------------------------------- 1 | Type folder -------------------------------------------------------------------------------- /src/modules/administration/pages/contact-list/components/contact-list-actions.vue: -------------------------------------------------------------------------------- 1 | 11 | 17 | 47 | -------------------------------------------------------------------------------- /src/modules/administration/pages/contact-list/pages/entries-page.vue: -------------------------------------------------------------------------------- 1 | 8 | 19 | -------------------------------------------------------------------------------- /src/modules/administration/pages/contact-list/types/Contact.ts: -------------------------------------------------------------------------------- 1 | import Domain from '@/core/types/Domain'; 2 | import User from '@/modules/user/types/User'; 3 | import Filters from '@/core/types/Filters'; 4 | import { SORT_ORDER } from '@/core/types/Sort'; 5 | 6 | export interface Contact { 7 | identifier: string; 8 | description: string; 9 | owner: User; 10 | contacts: ContactInfo[]; 11 | uuid: string; 12 | domainId: string; 13 | domainLabel: string; 14 | domain: Domain; 15 | public: boolean; 16 | } 17 | 18 | export interface ContactInfo { 19 | mail?: string; 20 | email?: string; 21 | firstName: string; 22 | lastName: string; 23 | } 24 | 25 | export interface ContactListFilters extends Filters { 26 | domainUuid?: string; 27 | ownerUuid?: string; 28 | memberMail?: string; 29 | } 30 | 31 | export interface ContactListParameters { 32 | domainUuid?: string; 33 | ownerUuid?: string; 34 | memberMail?: string; 35 | page?: number; 36 | size?: number; 37 | sortOrder?: SORT_ORDER; 38 | sortField?: string; 39 | } 40 | -------------------------------------------------------------------------------- /src/modules/administration/pages/technical-accounts/components/detail-page/user-informations.vue: -------------------------------------------------------------------------------- 1 | 14 | 19 | 34 | -------------------------------------------------------------------------------- /src/modules/administration/pages/technical-accounts/pages/entries-page.vue: -------------------------------------------------------------------------------- 1 | 8 | 19 | -------------------------------------------------------------------------------- /src/modules/administration/pages/technical-accounts/services/technical-account-api.ts: -------------------------------------------------------------------------------- 1 | import apiv4 from '@/apiv4'; 2 | import { TechnicalAccount, TechnicalAccountCreation, TechnicalAccountDetails } from '../types/TechnicalAccount'; 3 | 4 | async function getTechnicalAccountsList(): Promise { 5 | return await apiv4.get(`/technical_accounts`); 6 | } 7 | 8 | async function createTechnicalAccount(payload: TechnicalAccountCreation): Promise { 9 | return await apiv4.post(`technical_accounts`, payload); 10 | } 11 | 12 | async function getTechnicalAccountDetail(uuid: string | string[]): Promise { 13 | return await apiv4.get(`/technical_accounts/${uuid}`); 14 | } 15 | 16 | async function updateTechnicalAccount(payload: TechnicalAccountDetails): Promise { 17 | return await apiv4.put(`/technical_accounts`, payload); 18 | } 19 | 20 | async function deleteTechnicalAccount(payload: TechnicalAccount): Promise { 21 | return await apiv4.delete(`technical_accounts`, { data: payload }); 22 | } 23 | 24 | async function changeTechnicalAccountPassword(uuid: string | string[], payload: { newPwd: string; oldPwd: string }) { 25 | return await apiv4.post(`/technical_accounts/${uuid}/change_password`, payload); 26 | } 27 | 28 | export { 29 | getTechnicalAccountsList, 30 | createTechnicalAccount, 31 | getTechnicalAccountDetail, 32 | updateTechnicalAccount, 33 | deleteTechnicalAccount, 34 | changeTechnicalAccountPassword, 35 | }; 36 | -------------------------------------------------------------------------------- /src/modules/auth/components/oidc-callback.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 29 | 30 | 43 | -------------------------------------------------------------------------------- /src/modules/auth/constants/index.ts: -------------------------------------------------------------------------------- 1 | export const OTP_DEFAULT_CONFIGURATION = { 2 | type: 'totp', 3 | digits: 6, 4 | issuer: 'LinShare', 5 | algorithm: 'SHA1', 6 | period: 30, 7 | }; 8 | 9 | export const OTP_APP_INSTALL_LINKS = { 10 | googlePlay: 'https://play.google.com/store/apps/details?id=org.fedorahosted.freeotp', 11 | appStore: 'https://apps.apple.com/us/app/freeotp-authenticator/id872559395', 12 | }; 13 | -------------------------------------------------------------------------------- /src/modules/auth/router/requiresAuth.guard.ts: -------------------------------------------------------------------------------- 1 | import { Router } from 'vue-router'; 2 | import { useAppStore } from '@/core/store'; 3 | import { hydrate } from '@/core/store/hydrate'; 4 | import { useAuthStore } from '@/modules/auth/store'; 5 | 6 | let firstLoad = true; 7 | 8 | export const requiresAuthGuard = async (router: Router): Promise => { 9 | router.beforeEach(async (to) => { 10 | const requiresAuth = to.matched.some((record) => record.meta.requiresAuth); 11 | 12 | if (!requiresAuth) { 13 | return; 14 | } 15 | 16 | if (firstLoad) { 17 | firstLoad = false; 18 | const authStore = useAuthStore(); 19 | const appStore = useAppStore(); 20 | try { 21 | appStore.setAuthenticating(true); 22 | await authStore.fetchLoggedUser(); 23 | appStore.setAuthenticated(true); 24 | } catch (error) { 25 | return { name: 'Login' }; 26 | } finally { 27 | appStore.setAuthenticating(false); 28 | } 29 | await hydrate(); 30 | } 31 | }); 32 | }; 33 | -------------------------------------------------------------------------------- /src/modules/auth/router/requiresSecondFAEnabled.ts: -------------------------------------------------------------------------------- 1 | import { isEnable } from '@/core/utils/functionality'; 2 | import { Router } from 'vue-router'; 3 | import { useAuthStore } from '../store'; 4 | 5 | export const requiresSecondFAEnabled = (router: Router): void => { 6 | router.beforeEach((to) => { 7 | const authStore = useAuthStore(); 8 | 9 | if (to.name === 'ManageSecondFactorAuthentication') { 10 | return isEnable(authStore.functionalities.SECOND_FACTOR_AUTHENTICATION) || '/'; 11 | } 12 | }); 13 | }; 14 | -------------------------------------------------------------------------------- /src/modules/auth/services/auth-api.ts: -------------------------------------------------------------------------------- 1 | import { AxiosRequestConfig } from 'axios'; 2 | import api from '@/api'; 3 | import SecondFactorAuthentication from '../types/SecondFactorAuthentication'; 4 | import ChangePassword from '../types/ChangePassword'; 5 | import User from '@/modules/user/types/User'; 6 | 7 | async function getAuthorizedUser(config?: AxiosRequestConfig): Promise { 8 | return await api.get('authentication/authorized', config); 9 | } 10 | 11 | async function get2FAStatus(uuid: string): Promise { 12 | return await api.get(`authentication/2fa/${uuid}`); 13 | } 14 | 15 | async function create2FAKey(): Promise { 16 | return await api.post('authentication/2fa'); 17 | } 18 | 19 | async function logOut(): Promise { 20 | return await api.get('authentication/logout'); 21 | } 22 | 23 | async function remove2FAKey(uuid: string): Promise { 24 | return await api.delete(`authentication/2fa/${uuid}`); 25 | } 26 | 27 | async function changePassword(payload: { oldPwd: string; newPwd: string }): Promise { 28 | return await api.post('authentication/change_password/', payload); 29 | } 30 | 31 | export { create2FAKey, get2FAStatus, getAuthorizedUser, logOut, remove2FAKey, changePassword }; 32 | -------------------------------------------------------------------------------- /src/modules/auth/services/basic.ts: -------------------------------------------------------------------------------- 1 | import { useAuthStore } from '@/modules/auth/store'; 2 | import { useAppStore } from '@/core/store'; 3 | import { hydrate, dehydrate } from '@/core/store/hydrate'; 4 | import { logOut } from './auth-api'; 5 | import { AxiosRequestConfig } from 'axios'; 6 | 7 | export interface LoginCredentials { 8 | email: string; 9 | password: string; 10 | otp?: string; 11 | } 12 | 13 | interface AuthRequestConfig extends AxiosRequestConfig { 14 | headers: { 15 | 'x-linShare-2fa-pin'?: string; 16 | }; 17 | } 18 | 19 | export async function login(credentials: LoginCredentials): Promise { 20 | const params: AuthRequestConfig = { 21 | auth: { 22 | username: credentials.email, 23 | password: credentials.password, 24 | }, 25 | headers: {}, 26 | }; 27 | 28 | if (credentials.otp) { 29 | params.headers['x-linShare-2fa-pin'] = credentials.otp; 30 | } 31 | 32 | const authStore = useAuthStore(); 33 | const appStore = useAppStore(); 34 | await authStore.fetchLoggedUser(params); 35 | appStore.setAuthenticated(true); 36 | hydrate(); 37 | } 38 | 39 | export async function logout(): Promise { 40 | await logOut(); 41 | await dehydrate(); 42 | } 43 | -------------------------------------------------------------------------------- /src/modules/auth/store/auth2FAstore.ts: -------------------------------------------------------------------------------- 1 | import { defineStore } from 'pinia'; 2 | 3 | interface Auth2FAState { 4 | email: string; 5 | password: string; 6 | redirect?: string; 7 | } 8 | 9 | export const useAuth2FAStore = defineStore('useAuth2FAStore', { 10 | state: (): Auth2FAState => ({ 11 | email: '', 12 | password: '', 13 | redirect: '', 14 | }), 15 | actions: { 16 | setCredentials(email: string, password: string, redirect = ''): void { 17 | this.email = email; 18 | this.password = password; 19 | this.redirect = redirect; 20 | }, 21 | dehydrate(): void { 22 | this.email = ''; 23 | this.password = ''; 24 | this.redirect = ''; 25 | }, 26 | }, 27 | }); 28 | -------------------------------------------------------------------------------- /src/modules/auth/types/ChangePassword.ts: -------------------------------------------------------------------------------- 1 | export default interface ChangePasswordType { 2 | oldPwd: string; 3 | newPwd: string; 4 | } 5 | -------------------------------------------------------------------------------- /src/modules/auth/types/OtpSetupHintConfigs.ts: -------------------------------------------------------------------------------- 1 | export default interface OtpSetupHintConfigs { 2 | secret: string; 3 | issuer: string; 4 | account: string; 5 | type: string; 6 | digits: number; 7 | algorithm: string; 8 | period: number; 9 | } 10 | -------------------------------------------------------------------------------- /src/modules/auth/types/SecondFactorAuthentication.ts: -------------------------------------------------------------------------------- 1 | export default interface SecondFactorAuthentication { 2 | uuid: string; 3 | canDeleteIt: boolean; 4 | creationDate: number; 5 | enabled: boolean; 6 | required: boolean; 7 | sharedKey?: string; 8 | } 9 | -------------------------------------------------------------------------------- /src/modules/configuration/pages/detail/router/index.ts: -------------------------------------------------------------------------------- 1 | import { RouteRecordRaw } from 'vue-router'; 2 | import DetailPage from '../pages/detail-page.vue'; 3 | export const ConfigurationDomainDetailRoutes: RouteRecordRaw[] = [ 4 | { 5 | name: 'ConfigurationDomainDetail', 6 | path: ':domainUuid/detail', 7 | component: DetailPage, 8 | meta: { 9 | requiresAuth: true, 10 | parentRoute: 'Configuration', 11 | label: 'NAVIGATOR.DETAILS', 12 | }, 13 | children: [], 14 | }, 15 | ]; 16 | -------------------------------------------------------------------------------- /src/modules/configuration/pages/domain-group-providers/components/readme.md: -------------------------------------------------------------------------------- 1 | This directory to store component files of configuration/domain-group-providers module -------------------------------------------------------------------------------- /src/modules/configuration/pages/domain-group-providers/composables/readme.md: -------------------------------------------------------------------------------- 1 | This directory is to store the files that declare the composable methods of configuration/domain-group-providers module -------------------------------------------------------------------------------- /src/modules/configuration/pages/domain-group-providers/hooks/readme.md: -------------------------------------------------------------------------------- 1 | This directory is to store the files that declare the methods used in the hook of configuration/domain-group-providers module -------------------------------------------------------------------------------- /src/modules/configuration/pages/domain-group-providers/pages/group-providers-page.vue: -------------------------------------------------------------------------------- 1 | 2 | 12 | -------------------------------------------------------------------------------- /src/modules/configuration/pages/domain-group-providers/pages/readme.md: -------------------------------------------------------------------------------- 1 | This directory to store vue page files of configuration/domain-group-providers module ( the file will be import in the routes) -------------------------------------------------------------------------------- /src/modules/configuration/pages/domain-group-providers/router/index.ts: -------------------------------------------------------------------------------- 1 | import { RouteRecordRaw } from 'vue-router'; 2 | import GroupProvidersPage from '../pages/group-providers-page.vue'; 3 | export const ConfigurationDomainGroupProvidersRoutes: RouteRecordRaw[] = [ 4 | { 5 | name: 'ConfigurationDomainGroupProviders', 6 | path: ':domainUuid/domain-group-providers', 7 | component: GroupProvidersPage, 8 | meta: { 9 | requiresAuth: true, 10 | parentRoute: 'Configuration', 11 | }, 12 | children: [], 13 | }, 14 | ]; 15 | -------------------------------------------------------------------------------- /src/modules/configuration/pages/domain-group-providers/router/readme.md: -------------------------------------------------------------------------------- 1 | This directory to store route config files of configuration/domain-group-providers module -------------------------------------------------------------------------------- /src/modules/configuration/pages/domain-group-providers/services/readme.md: -------------------------------------------------------------------------------- 1 | This directory to store services files of configuration/domain-group-providers module -------------------------------------------------------------------------------- /src/modules/configuration/pages/domain-group-providers/types/readme.md: -------------------------------------------------------------------------------- 1 | This directory is for storing type declaration files of configuration/domain-group-providers module -------------------------------------------------------------------------------- /src/modules/configuration/pages/domain-policies/router/index.ts: -------------------------------------------------------------------------------- 1 | import { RouteRecordRaw } from 'vue-router'; 2 | import DomainPoliciesPage from '@/modules/configuration/pages/domain-policies/pages/policies-page.vue'; 3 | export const CONFIGURATION_DOMAIN_POLICIES_ROUTE_NAMES = { 4 | POLICIES: 'ConfigurationDomainPolicies', 5 | POLICY_DETAIL: 'ConfigurationDomainPoliciesDetail', 6 | }; 7 | 8 | export const ConfigurationDomainPoliciesRoutes: RouteRecordRaw[] = [ 9 | { 10 | name: CONFIGURATION_DOMAIN_POLICIES_ROUTE_NAMES.POLICIES, 11 | path: ':domainUuid/domain-policies', 12 | component: DomainPoliciesPage, 13 | meta: { 14 | requiresAuth: true, 15 | parentRoute: 'Configuration', 16 | label: 'NAVIGATOR.CONFIGURATION_DOMAIN_POLICIES', 17 | }, 18 | children: [], 19 | }, 20 | { 21 | name: CONFIGURATION_DOMAIN_POLICIES_ROUTE_NAMES.POLICY_DETAIL, 22 | path: ':domainUuid/domain-policies/:id', 23 | component: () => import('@/modules/configuration/pages/domain-policies/pages/policy-detail-page.vue'), 24 | meta: { 25 | requiresAuth: true, 26 | parentRoute: CONFIGURATION_DOMAIN_POLICIES_ROUTE_NAMES.POLICIES, 27 | label: 'NAVIGATOR.CONFIGURATION_DOMAIN_POLICIES_DETAILS', 28 | }, 29 | children: [], 30 | }, 31 | ]; 32 | -------------------------------------------------------------------------------- /src/modules/configuration/pages/domain-policies/types/DomainPolicy.ts: -------------------------------------------------------------------------------- 1 | import Domain from '@/core/types/Domain'; 2 | 3 | export interface DomainPolicy { 4 | identifier: string; 5 | label: string; 6 | description: string; 7 | accessPolicy: { 8 | rules: DomainPolicyRule[]; 9 | }; 10 | assigned?: boolean; 11 | creationDate?: number; 12 | modificationDate?: number; 13 | } 14 | 15 | export interface DomainPolicyRule { 16 | type: 'ALLOW' | 'ALLOW_ALL' | 'DENY' | 'DENY_ALL'; 17 | domain: Domain; 18 | } 19 | -------------------------------------------------------------------------------- /src/modules/configuration/pages/domain-provider-management/components/readme.md: -------------------------------------------------------------------------------- 1 | This directory to store component files of configuration/domain-provider-management module -------------------------------------------------------------------------------- /src/modules/configuration/pages/domain-provider-management/composables/readme.md: -------------------------------------------------------------------------------- 1 | This directory is to store the files that declare the composable methods of configuration/domain-provider-management module -------------------------------------------------------------------------------- /src/modules/configuration/pages/domain-provider-management/hooks/readme.md: -------------------------------------------------------------------------------- 1 | This directory is to store the files that declare the methods used in the hook of configuration/domain-provider-management module -------------------------------------------------------------------------------- /src/modules/configuration/pages/domain-provider-management/pages/domain-provider-management-page.vue: -------------------------------------------------------------------------------- 1 | 2 | 12 | -------------------------------------------------------------------------------- /src/modules/configuration/pages/domain-provider-management/pages/readme.md: -------------------------------------------------------------------------------- 1 | This directory to store vue page files of configuration/domain-provider-management module ( the file will be import in the routes) -------------------------------------------------------------------------------- /src/modules/configuration/pages/domain-provider-management/router/index.ts: -------------------------------------------------------------------------------- 1 | import { RouteRecordRaw } from 'vue-router'; 2 | import ProviderManagementPage from '../pages/domain-provider-management-page.vue'; 3 | export const ConfigurationDomainProviderManagementRoutes: RouteRecordRaw[] = [ 4 | { 5 | name: 'ConfigurationDomainProviderManagement', 6 | path: ':domainUuid/domain-provider-management', 7 | component: ProviderManagementPage, 8 | meta: { 9 | requiresAuth: true, 10 | parentRoute: 'Configuration', 11 | }, 12 | children: [], 13 | }, 14 | ]; 15 | -------------------------------------------------------------------------------- /src/modules/configuration/pages/domain-provider-management/router/readme.md: -------------------------------------------------------------------------------- 1 | This directory to store route config files of configuration/domain-provider-management module -------------------------------------------------------------------------------- /src/modules/configuration/pages/domain-provider-management/services/readme.md: -------------------------------------------------------------------------------- 1 | This directory to store services files of configuration/domain-provider-management module -------------------------------------------------------------------------------- /src/modules/configuration/pages/domain-provider-management/types/readme.md: -------------------------------------------------------------------------------- 1 | This directory is for storing type declaration files of configuration/domain-provider-management module -------------------------------------------------------------------------------- /src/modules/configuration/pages/domain-user-providers/components/readme.md: -------------------------------------------------------------------------------- 1 | This directory to store component files of configuration/domain-user-providers module -------------------------------------------------------------------------------- /src/modules/configuration/pages/domain-user-providers/composables/readme.md: -------------------------------------------------------------------------------- 1 | This directory is to store the files that declare the composable methods of configuration/domain-user-providers module -------------------------------------------------------------------------------- /src/modules/configuration/pages/domain-user-providers/hooks/readme.md: -------------------------------------------------------------------------------- 1 | This directory is to store the files that declare the methods used in the hook of configuration/domain-user-providers module -------------------------------------------------------------------------------- /src/modules/configuration/pages/domain-user-providers/pages/domain-user-providers-page.vue: -------------------------------------------------------------------------------- 1 | 2 | 12 | -------------------------------------------------------------------------------- /src/modules/configuration/pages/domain-user-providers/pages/readme.md: -------------------------------------------------------------------------------- 1 | This directory to store vue page files of configuration/domain-user-providers module ( the file will be import in the routes) -------------------------------------------------------------------------------- /src/modules/configuration/pages/domain-user-providers/router/index.ts: -------------------------------------------------------------------------------- 1 | import { RouteRecordRaw } from 'vue-router'; 2 | import DomainUserProvidersPage from '../pages/domain-user-providers-page.vue'; 3 | export const ConfigurationDomainDomainUserProvidersRoutes: RouteRecordRaw[] = [ 4 | { 5 | name: 'ConfigurationDomainDomainUserProviders', 6 | path: ':domainUuid/domain-user-providers', 7 | component: DomainUserProvidersPage, 8 | meta: { 9 | requiresAuth: true, 10 | parentRoute: 'Configuration', 11 | }, 12 | children: [], 13 | }, 14 | ]; 15 | -------------------------------------------------------------------------------- /src/modules/configuration/pages/domain-user-providers/router/readme.md: -------------------------------------------------------------------------------- 1 | This directory to store route config files of configuration/domain-user-providers module -------------------------------------------------------------------------------- /src/modules/configuration/pages/domain-user-providers/services/readme.md: -------------------------------------------------------------------------------- 1 | This directory to store services files of configuration/domain-user-providers module -------------------------------------------------------------------------------- /src/modules/configuration/pages/domain-user-providers/types/readme.md: -------------------------------------------------------------------------------- 1 | This directory is for storing type declaration files of configuration/domain-user-providers module -------------------------------------------------------------------------------- /src/modules/configuration/pages/domain-workspace-providers/components/readme.md: -------------------------------------------------------------------------------- 1 | This directory to store component files of configuration/domain-workspace-providers module -------------------------------------------------------------------------------- /src/modules/configuration/pages/domain-workspace-providers/composables/readme.md: -------------------------------------------------------------------------------- 1 | This directory is to store the files that declare the composable methods of configuration/domain-workspace-providers module -------------------------------------------------------------------------------- /src/modules/configuration/pages/domain-workspace-providers/hooks/readme.md: -------------------------------------------------------------------------------- 1 | This directory is to store the files that declare the methods used in the hook of configuration/domain-workspace-providers module -------------------------------------------------------------------------------- /src/modules/configuration/pages/domain-workspace-providers/pages/domain-workspace-providers-page.vue: -------------------------------------------------------------------------------- 1 | 2 | 12 | -------------------------------------------------------------------------------- /src/modules/configuration/pages/domain-workspace-providers/pages/readme.md: -------------------------------------------------------------------------------- 1 | This directory to store vue page files of configuration/domain-workspace-providers module ( the file will be import in the routes) -------------------------------------------------------------------------------- /src/modules/configuration/pages/domain-workspace-providers/router/index.ts: -------------------------------------------------------------------------------- 1 | import { RouteRecordRaw } from 'vue-router'; 2 | import DomainWorkspaceProvidersPage from '../pages/domain-workspace-providers-page.vue'; 3 | export const ConfigurationDomainDomainWorkspaceProvidersRoutes: RouteRecordRaw[] = [ 4 | { 5 | name: 'ConfigurationDomainDomainWorkspaceProviders', 6 | path: ':domainUuid/domain-workspace-providers', 7 | component: DomainWorkspaceProvidersPage, 8 | meta: { 9 | requiresAuth: true, 10 | parentRoute: 'Configuration', 11 | }, 12 | children: [], 13 | }, 14 | ]; 15 | -------------------------------------------------------------------------------- /src/modules/configuration/pages/domain-workspace-providers/router/readme.md: -------------------------------------------------------------------------------- 1 | This directory to store route config files of configuration/domain-workspace-providers module -------------------------------------------------------------------------------- /src/modules/configuration/pages/domain-workspace-providers/services/readme.md: -------------------------------------------------------------------------------- 1 | This directory to store services files of configuration/domain-workspace-providers module -------------------------------------------------------------------------------- /src/modules/configuration/pages/domain-workspace-providers/types/readme.md: -------------------------------------------------------------------------------- 1 | This directory is for storing type declaration files of configuration/domain-workspace-providers module -------------------------------------------------------------------------------- /src/modules/configuration/pages/email-templates/pages/entries-page.vue: -------------------------------------------------------------------------------- 1 | 11 | 14 | 30 | -------------------------------------------------------------------------------- /src/modules/configuration/pages/email-templates/types/MailActivation.ts: -------------------------------------------------------------------------------- 1 | export interface MailActivation { 2 | identifier: string; 3 | domain: string; 4 | activationPolicy: { 5 | policy: string; 6 | status: boolean; 7 | defaultStatus: boolean; 8 | parentAllowUpdate: boolean; 9 | system: boolean; 10 | }; 11 | configurationPolicy: { 12 | policy: string; 13 | status: boolean; 14 | defaultStatus: boolean; 15 | parentAllowUpdate: boolean; 16 | system: boolean; 17 | }; 18 | delegationPolicy: { 19 | policy: string; 20 | status: boolean; 21 | defaultStatus: boolean; 22 | parentAllowUpdate: boolean; 23 | system: boolean; 24 | }; 25 | enable: boolean; 26 | } 27 | -------------------------------------------------------------------------------- /src/modules/configuration/pages/email-templates/types/MailConfiguration.ts: -------------------------------------------------------------------------------- 1 | export type MailFooterLangs = { [key: string]: MailLang }; 2 | export interface MailConfiguration { 3 | creationDate?: number; 4 | domain: string; 5 | domainName: string; 6 | mailContentLangs: MailLang[]; 7 | mailFooterLangs: MailFooterLangs; 8 | mailLayout: string; 9 | modificationDate: number; 10 | name: string; 11 | readonly: string; 12 | uuid: string; 13 | visible: boolean; 14 | assigned?: boolean; 15 | selectLanguage?: string; 16 | } 17 | 18 | export interface MailLang { 19 | language: string; 20 | mailConfig: string; 21 | mailContent: string; 22 | mailContentType: string; 23 | mailFooter?: string; 24 | readonly: boolean; 25 | uuid: string; 26 | mailContentDomainName?: string; 27 | mailContentName?: string; 28 | mailContentModificationDate?: string | number; 29 | legend: string; 30 | } 31 | 32 | export interface MailLangDetail { 33 | description: string; 34 | domain: string; 35 | domainLabel?: string; 36 | visible: boolean; 37 | mailContentType: string; 38 | subject: string; 39 | body: string; 40 | creationDate: number; 41 | modificationDate: number; 42 | uuid: string; 43 | readonly: boolean; 44 | messagesFrench: string; 45 | messagesEnglish: string; 46 | messagesRussian: string; 47 | } 48 | -------------------------------------------------------------------------------- /src/modules/configuration/pages/email-templates/types/MailContent.ts: -------------------------------------------------------------------------------- 1 | export interface MailContent { 2 | description: string; 3 | domain: string; 4 | domainName?: string; 5 | domainLabel: string; 6 | visible: boolean; 7 | footer: string; 8 | creationDate: number; 9 | modificationDate: number; 10 | uuid: string; 11 | plaintext: boolean; 12 | readonly: boolean; 13 | messagesFrench: string; 14 | messagesEnglish: string; 15 | messagesRussian: string; 16 | messagesVietnamese: string; 17 | body: string; 18 | mailContentType: string; 19 | subject: string; 20 | context?: number; 21 | config?: string; 22 | } 23 | -------------------------------------------------------------------------------- /src/modules/configuration/pages/email-templates/types/MailContext.ts: -------------------------------------------------------------------------------- 1 | export interface MailContext { 2 | mailType: string; 3 | variables: { 4 | name: string; 5 | type: string; 6 | stringValue: string; 7 | variables: { 8 | name: string; 9 | type: string; 10 | stringValue: string; 11 | }[]; 12 | }[]; 13 | } 14 | -------------------------------------------------------------------------------- /src/modules/configuration/pages/email-templates/types/MailFooter.ts: -------------------------------------------------------------------------------- 1 | export interface MailFooter { 2 | description: string; 3 | domain: string; 4 | domainName?: string; 5 | visible: boolean; 6 | footer: string; 7 | creationDate: number; 8 | modificationDate: number; 9 | uuid: string; 10 | plaintext: boolean; 11 | readonly: boolean; 12 | messagesFrench: string; 13 | messagesEnglish: string; 14 | messagesRussian: string; 15 | messagesVietnamese: string; 16 | } 17 | -------------------------------------------------------------------------------- /src/modules/configuration/pages/email-templates/types/MailLayout.ts: -------------------------------------------------------------------------------- 1 | export interface MailLayout { 2 | uuid: string; 3 | domain: string; 4 | domainName: string; 5 | description: string; 6 | layout: string; 7 | visible: boolean; 8 | creationDate: number; 9 | modificationDate: number; 10 | readonly: boolean; 11 | messagesFrench: string; 12 | messagesEnglish: string; 13 | messagesRussian: string; 14 | messagesVietnamese: string; 15 | assigned?: boolean; 16 | } 17 | -------------------------------------------------------------------------------- /src/modules/configuration/pages/parameters/hooks/useFunctionalities.ts: -------------------------------------------------------------------------------- 1 | import { computed, ComputedRef, Ref } from 'vue'; 2 | import { useI18n } from 'vue-i18n'; 3 | import { Functionality } from '@/modules/configuration/pages/parameters/types/Functionality'; 4 | 5 | type UsableFunctionalities = { 6 | getTranslatedText: (functionality: Functionality, key: string) => string; 7 | }; 8 | 9 | export default function useFunctionalities(): UsableFunctionalities { 10 | const { t } = useI18n(); 11 | 12 | function getTranslatedText(functionality: Functionality, key: string): string { 13 | const i18nKey = `FUNCTIONALITIES.DETAILS.${functionality.identifier}.${key}`; 14 | const i18nValue = t(i18nKey); 15 | 16 | return i18nValue === i18nKey ? t(`FUNCTIONALITIES.DEFAULT.${key}`) : i18nValue; 17 | } 18 | 19 | return { 20 | getTranslatedText, 21 | }; 22 | } 23 | -------------------------------------------------------------------------------- /src/modules/configuration/pages/parameters/router/index.ts: -------------------------------------------------------------------------------- 1 | import { RouteRecordRaw } from 'vue-router'; 2 | import ParametersPage from '../pages/parameters-page.vue'; 3 | import ParametersDetailsPage from '../components/domain-functionality-details.vue'; 4 | export const ConfigurationDomainParametersRoutes: RouteRecordRaw[] = [ 5 | { 6 | name: 'ConfigurationDomainParameters', 7 | path: ':domainUuid/parameters', 8 | component: ParametersPage, 9 | meta: { 10 | requiresAuth: true, 11 | parentRoute: 'Configuration', 12 | label: 'NAVIGATOR.FUNCTIONALITIES', 13 | }, 14 | children: [], 15 | }, 16 | { 17 | name: 'DomainFunctionality', 18 | path: ':domainUuid/parameters/:identifier', 19 | component: ParametersDetailsPage, 20 | meta: { 21 | parentRoute: 'ConfigurationDomainParameters', 22 | requiresAuth: true, 23 | label: 'NAVIGATOR.FUNCTIONALITIES', 24 | }, 25 | children: [], 26 | beforeEnter: (to) => { 27 | to.meta.label = to.params.identifier; 28 | }, 29 | }, 30 | ]; 31 | -------------------------------------------------------------------------------- /src/modules/configuration/pages/parameters/services/parameters-api.ts: -------------------------------------------------------------------------------- 1 | import api from '@/api'; 2 | import { Functionality } from '@/modules/configuration/pages/parameters/types/Functionality'; 3 | 4 | async function getFunctionalties( 5 | domainUuid: string, 6 | options?: { includeSubs?: boolean; parent?: string } 7 | ): Promise { 8 | return await api.get(`domains/${domainUuid}/functionalities`, { 9 | params: { 10 | subs: options?.includeSubs, 11 | parentIdentifier: options?.parent, 12 | }, 13 | }); 14 | } 15 | 16 | async function getFunctionality(domainUuid: string, identifier: string): Promise { 17 | return await api.get(`domains/${domainUuid}/functionalities/${identifier}`); 18 | } 19 | 20 | async function updateFunctionality(domainUuid: string, functionality: Functionality): Promise { 21 | return await api.put(`domains/${domainUuid}/functionalities/${functionality.identifier}`, functionality); 22 | } 23 | 24 | export { getFunctionalties, getFunctionality, updateFunctionality }; 25 | -------------------------------------------------------------------------------- /src/modules/configuration/pages/providers/components/domain-management-warning.vue: -------------------------------------------------------------------------------- 1 | 12 | -------------------------------------------------------------------------------- /src/modules/configuration/pages/providers/components/domain-provider-management.vue: -------------------------------------------------------------------------------- 1 | 29 | 30 | 36 | -------------------------------------------------------------------------------- /src/modules/configuration/pages/providers/hooks/use-providers.ts: -------------------------------------------------------------------------------- 1 | import { storeToRefs } from 'pinia'; 2 | import { useAuthStore } from '@/modules/auth/store'; 3 | import { useDomainStore } from '@/modules/domain/store'; 4 | import { findDomainPage, canAccessPage } from '@/core/services/configuration-pages'; 5 | 6 | export default function useProviders() { 7 | const authStore = useAuthStore(); 8 | const domainStore = useDomainStore(); 9 | const { loggedUser } = storeToRefs(authStore); 10 | const { currentDomain } = storeToRefs(domainStore); 11 | 12 | function isPageAccessible(name: string) { 13 | const page = findDomainPage(name); 14 | 15 | return page && canAccessPage(page, loggedUser.value?.role, currentDomain.value.type); 16 | } 17 | 18 | return { isPageAccessible }; 19 | } 20 | -------------------------------------------------------------------------------- /src/modules/configuration/pages/providers/pages/providers-page.vue: -------------------------------------------------------------------------------- 1 | 5 | 6 | 37 | -------------------------------------------------------------------------------- /src/modules/configuration/pages/providers/types/Domain.ts: -------------------------------------------------------------------------------- 1 | export enum DOMAIN_TYPE { 2 | ROOT = 'ROOTDOMAIN', 3 | TOP = 'TOPDOMAIN', 4 | SUB = 'SUBDOMAIN', 5 | GUEST = 'GUESTDOMAIN', 6 | } 7 | 8 | export default interface Domain { 9 | uuid: string; 10 | name: string; 11 | description?: string; 12 | language?: 'RUSSIAN' | 'ENGLISH' | 'FRENCH' | 'VIETNAMESE'; 13 | creationDate?: number; 14 | modificationDate?: number; 15 | defaultEmailLanguage?: string; 16 | defaultUserRole?: string; 17 | type?: DOMAIN_TYPE; 18 | parent?: Partial; 19 | domainPolicy?: { 20 | name: string; 21 | uuid: string; 22 | }; 23 | mailConfiguration?: { 24 | name: string; 25 | uuid: string; 26 | }; 27 | mimePolicy?: { 28 | name: string; 29 | uuid: string; 30 | }; 31 | welcomeMessage?: { 32 | name: string; 33 | uuid: string; 34 | }; 35 | } 36 | 37 | export const EMPTY_DOMAIN: Domain = { 38 | uuid: '', 39 | name: '', 40 | }; 41 | -------------------------------------------------------------------------------- /src/modules/configuration/pages/providers/types/GroupProvider.ts: -------------------------------------------------------------------------------- 1 | export interface LDAPGroupProvider { 2 | uuid?: string; 3 | creationDate?: number; 4 | modificationDate?: number; 5 | type?: 'LDAP_PROVIDER'; 6 | ldapServer: { 7 | uuid: string; 8 | name: string; 9 | }; 10 | groupFilter: { 11 | uuid: string; 12 | name: string; 13 | }; 14 | baseDn: string; 15 | searchInOtherDomains: boolean; 16 | } 17 | 18 | export const EMPTY_PROVIDER: LDAPGroupProvider = { 19 | ldapServer: { 20 | uuid: '', 21 | name: '', 22 | }, 23 | groupFilter: { 24 | uuid: '', 25 | name: '', 26 | }, 27 | baseDn: '', 28 | searchInOtherDomains: false, 29 | }; 30 | -------------------------------------------------------------------------------- /src/modules/configuration/pages/providers/types/UserProvider.ts: -------------------------------------------------------------------------------- 1 | export interface OIDCUserProvider { 2 | uuid: string; 3 | creationDate?: number; 4 | modificationDate?: number; 5 | type?: 'OIDC_PROVIDER'; 6 | domainDiscriminator?: string; 7 | checkExternalUserID?: boolean; 8 | useAccessClaim?: boolean; 9 | useRoleClaim?: boolean; 10 | useEmailLocaleClaim?: boolean; 11 | } 12 | 13 | export interface LDAPUserProvider { 14 | uuid: string; 15 | creationDate?: number; 16 | modificationDate?: number; 17 | type?: 'LDAP_PROVIDER'; 18 | ldapServer?: { 19 | uuid: string; 20 | name: string; 21 | }; 22 | userFilter?: { 23 | uuid: string; 24 | name: string; 25 | }; 26 | baseDn?: string; 27 | } 28 | 29 | export interface TwakeUserProvider { 30 | uuid: string; 31 | creationDate?: number; 32 | modificationDate?: number; 33 | type?: 'TWAKE_PROVIDER' | 'TWAKE_GUEST_PROVIDER'; 34 | twakeServer: { 35 | uuid: string; 36 | name: string; 37 | }; 38 | twakeCompanyId: string; 39 | } 40 | 41 | type UserProvider = OIDCUserProvider | LDAPUserProvider | TwakeUserProvider; 42 | 43 | export const EMPTY_PROVIDER = { 44 | uuid: '', 45 | }; 46 | 47 | export default UserProvider; 48 | -------------------------------------------------------------------------------- /src/modules/configuration/pages/providers/types/WorkspaceProvider.ts: -------------------------------------------------------------------------------- 1 | export interface LDAPWorkspaceProvider { 2 | uuid?: string; 3 | creationDate?: number; 4 | modificationDate?: number; 5 | type?: 'LDAP_PROVIDER'; 6 | ldapServer: { 7 | uuid: string; 8 | name: string; 9 | }; 10 | workSpaceFilter: { 11 | uuid: string; 12 | name: string; 13 | }; 14 | baseDn: string; 15 | searchInOtherDomains: boolean; 16 | } 17 | 18 | export const EMPTY_PROVIDER: LDAPWorkspaceProvider = { 19 | ldapServer: { 20 | uuid: '', 21 | name: '', 22 | }, 23 | workSpaceFilter: { 24 | uuid: '', 25 | name: '', 26 | }, 27 | baseDn: '', 28 | searchInOtherDomains: false, 29 | }; 30 | -------------------------------------------------------------------------------- /src/modules/configuration/pages/public-keys/components/readme.md: -------------------------------------------------------------------------------- 1 | This directory to store component files of configuration/public-keys module -------------------------------------------------------------------------------- /src/modules/configuration/pages/public-keys/composables/readme.md: -------------------------------------------------------------------------------- 1 | This directory is to store the files that declare the composable methods of configuration/public-keys module -------------------------------------------------------------------------------- /src/modules/configuration/pages/public-keys/hooks/readme.md: -------------------------------------------------------------------------------- 1 | This directory is to store the files that declare the methods used in the hook of configuration/public-keys module -------------------------------------------------------------------------------- /src/modules/configuration/pages/public-keys/pages/public-keys-page.vue: -------------------------------------------------------------------------------- 1 | 2 | 12 | -------------------------------------------------------------------------------- /src/modules/configuration/pages/public-keys/pages/readme.md: -------------------------------------------------------------------------------- 1 | This directory to store vue page files of configuration/public-keys module ( the file will be import in the routes) -------------------------------------------------------------------------------- /src/modules/configuration/pages/public-keys/router/index.ts: -------------------------------------------------------------------------------- 1 | import { RouteRecordRaw } from 'vue-router'; 2 | import PublicKeysPage from '../pages/public-keys-page.vue'; 3 | export const ConfigurationDomainPublicKeysRoutes: RouteRecordRaw[] = [ 4 | { 5 | name: 'ConfigurationDomainPublicKeys', 6 | path: ':domainUuid/public-keys', 7 | component: PublicKeysPage, 8 | meta: { 9 | requiresAuth: true, 10 | parentRoute: 'Configuration', 11 | label: 'NAVIGATOR.PUBLIC_KEYS', 12 | }, 13 | children: [], 14 | }, 15 | ]; 16 | -------------------------------------------------------------------------------- /src/modules/configuration/pages/public-keys/router/readme.md: -------------------------------------------------------------------------------- 1 | This directory to store route config files of configuration/public-keys module -------------------------------------------------------------------------------- /src/modules/configuration/pages/public-keys/services/readme.md: -------------------------------------------------------------------------------- 1 | This directory to store services files of configuration/public-keys module -------------------------------------------------------------------------------- /src/modules/configuration/pages/public-keys/types/readme.md: -------------------------------------------------------------------------------- 1 | This directory is for storing type declaration files of configuration/public-keys module -------------------------------------------------------------------------------- /src/modules/configuration/pages/quota/router/index.ts: -------------------------------------------------------------------------------- 1 | import { RouteRecordRaw } from 'vue-router'; 2 | import QuotaPage from '../pages/quota-page.vue'; 3 | export const ConfigurationDomainQuotaRoutes: RouteRecordRaw[] = [ 4 | { 5 | name: 'ConfigurationDomainQuota', 6 | path: ':domainUuid/quota', 7 | component: QuotaPage, 8 | meta: { 9 | requiresAuth: true, 10 | parentRoute: 'Configuration', 11 | label: 'NAVIGATOR.QUOTA', 12 | }, 13 | children: [], 14 | }, 15 | ]; 16 | -------------------------------------------------------------------------------- /src/modules/configuration/pages/quota/services/quota-api.ts: -------------------------------------------------------------------------------- 1 | import { AxiosRequestConfig } from 'axios'; 2 | import apiv4 from '@/apiv4'; 3 | import Quota from '../types/Quota'; 4 | import ContainerQuota from '../types/Container'; 5 | 6 | async function getQuotaInformations(domainUuid: string) { 7 | return await apiv4.get(`quotas/domains/${domainUuid}`); 8 | } 9 | 10 | async function getQuotaUuid(domainUuid: string) { 11 | return await apiv4.get(`domains/${domainUuid}?parent=false&tree=true`); 12 | } 13 | 14 | async function updateQuota(domainUuid: StringConstructor, quota: Quota): Promise { 15 | return await apiv4.put(`quotas/domains/${domainUuid}`, quota); 16 | } 17 | 18 | async function updateSubdomainQuota(containerUuid: string, ContainerQuota: ContainerQuota): Promise { 19 | return await apiv4.put(`quotas/containers/${containerUuid}`, ContainerQuota); 20 | } 21 | 22 | async function getContainerInformations(containerUuid: string) { 23 | return await apiv4.get(`quotas/containers/${containerUuid}`); 24 | } 25 | 26 | export { getQuotaInformations, updateQuota, getQuotaUuid, getContainerInformations, updateSubdomainQuota }; 27 | -------------------------------------------------------------------------------- /src/modules/configuration/pages/quota/types/Container.ts: -------------------------------------------------------------------------------- 1 | export default interface QuotaContainer { 2 | accountQuota: number; 3 | accountQuotaOverride: boolean; 4 | batchModificationDate: number; 5 | creationDate: number; 6 | defaultAccountQuota: number; 7 | defaultAccountQuotaOverride: boolean; 8 | defaultMaxFileSize: number; 9 | defaultMaxFileSizeOverride: boolean; 10 | defaultQuota: number; 11 | defaultQuotaOverride: boolean; 12 | domain: { 13 | identifier: string; 14 | label: string; 15 | type: string; 16 | }; 17 | maintenance: boolean; 18 | maxFileSize: number; 19 | maxFileSizeOverride: boolean; 20 | modificationDate: number; 21 | quota: number; 22 | quotaOverride: boolean; 23 | type: string; 24 | usedSpace: number; 25 | uuid: string; 26 | yersterdayUsedSpace: number; 27 | } 28 | 29 | export const EMPTY_CONTAINER: QuotaContainer = { 30 | accountQuota: 0, 31 | accountQuotaOverride: false, 32 | batchModificationDate: 0, 33 | creationDate: 0, 34 | defaultAccountQuota: 0, 35 | defaultAccountQuotaOverride: false, 36 | defaultMaxFileSize: 0, 37 | defaultMaxFileSizeOverride: false, 38 | defaultQuota: 0, 39 | defaultQuotaOverride: false, 40 | domain: { 41 | identifier: '', 42 | label: '', 43 | type: '', 44 | }, 45 | maintenance: false, 46 | maxFileSize: 0, 47 | maxFileSizeOverride: false, 48 | modificationDate: 0, 49 | quota: 0, 50 | quotaOverride: false, 51 | type: '', 52 | usedSpace: 0, 53 | uuid: '', 54 | yersterdayUsedSpace: 0, 55 | }; 56 | -------------------------------------------------------------------------------- /src/modules/configuration/pages/quota/types/Quota.ts: -------------------------------------------------------------------------------- 1 | export default interface DomainQuota { 2 | creationDate?: number; 3 | domain?: { 4 | label?: string; 5 | identifier?: string; 6 | type?: string; 7 | }; 8 | parentDomain?: { 9 | label?: string; 10 | identifier?: string; 11 | type?: string; 12 | }; 13 | currentValueForSubdomains?: number; 14 | defaultDomainShared?: boolean; 15 | defaultDomainSharedOverride?: boolean; 16 | defaultQuota: number; 17 | defaultQuotaOverride?: boolean; 18 | maintenance?: boolean; 19 | modificationDate?: number; 20 | quota: number; 21 | quotaOverride?: boolean; 22 | usedSpace: number; 23 | uuid: string; 24 | yersterdayUsedSpace?: number; 25 | batchModificationDate?: number; 26 | domainShared?: boolean; 27 | domainSharedOverride?: boolean; 28 | containerUuids?: string[]; 29 | } 30 | 31 | export const EMPTY_QUOTA: DomainQuota = { 32 | creationDate: 0, 33 | currentValueForSubdomains: 0, 34 | defaultDomainShared: false, 35 | defaultDomainSharedOverride: false, 36 | defaultQuota: 0, 37 | defaultQuotaOverride: false, 38 | maintenance: false, 39 | modificationDate: 0, 40 | quota: 0, 41 | quotaOverride: false, 42 | usedSpace: 0, 43 | uuid: '', 44 | yersterdayUsedSpace: 0, 45 | domainShared: false, 46 | domainSharedOverride: false, 47 | }; 48 | -------------------------------------------------------------------------------- /src/modules/configuration/pages/remote-filters/composables/readme.md: -------------------------------------------------------------------------------- 1 | This directory is to store the files that declare the composable methods of configuration/remote-filter-list module -------------------------------------------------------------------------------- /src/modules/configuration/pages/remote-filters/hooks/readme.md: -------------------------------------------------------------------------------- 1 | This directory is to store the files that declare the methods used in the hook of configuration/remote-filter-list module -------------------------------------------------------------------------------- /src/modules/configuration/pages/remote-filters/pages/remote-filters-page.vue: -------------------------------------------------------------------------------- 1 | 31 | 32 | 36 | -------------------------------------------------------------------------------- /src/modules/configuration/pages/remote-filters/services/group-filter-api.ts: -------------------------------------------------------------------------------- 1 | import api from '@/api'; 2 | import { LDAPGroupFilter } from '../types/GroupFilters'; 3 | import Domain from '@/modules/domain/types/Domain'; 4 | 5 | async function listGroupFilters(listModel?: boolean): Promise { 6 | return await api.get('group_filters', { 7 | params: { model: listModel }, 8 | }); 9 | } 10 | 11 | async function createGroupFilter(filter: Omit): Promise { 12 | return await api.post('group_filters', filter); 13 | } 14 | 15 | async function updateGroupFilter(filter: LDAPGroupFilter): Promise { 16 | return await api.put(`group_filters/${filter.uuid}`, filter); 17 | } 18 | 19 | async function getGroupFilter(uuid: string | string[]): Promise { 20 | return await api.get(`group_filters/${uuid}`); 21 | } 22 | 23 | async function getGroupFilterAssociatedDomains(uuid: string | string[]): Promise { 24 | return await api.get(`group_filters/${uuid}/domains`); 25 | } 26 | 27 | async function deleteGroupFilter(uuid: string | string[]): Promise { 28 | return await api.delete(`group_filters/${uuid}`); 29 | } 30 | 31 | export { 32 | createGroupFilter, 33 | deleteGroupFilter, 34 | getGroupFilter, 35 | getGroupFilterAssociatedDomains, 36 | listGroupFilters, 37 | updateGroupFilter, 38 | }; 39 | -------------------------------------------------------------------------------- /src/modules/configuration/pages/remote-filters/services/user-filter-api.ts: -------------------------------------------------------------------------------- 1 | import api from '@/api'; 2 | import Domain from '@/modules/domain/types/Domain'; 3 | import UserFilter from '../types/UserFilter'; 4 | 5 | async function listUserFilters(listModel?: boolean): Promise { 6 | return await api.get('user_filters', { 7 | params: { 8 | model: listModel, 9 | }, 10 | }); 11 | } 12 | 13 | async function createUserFilter(filter: Partial): Promise { 14 | return await api.post('user_filters', filter); 15 | } 16 | 17 | async function updateUserFilter(uuid: string | string[], filter: Partial): Promise { 18 | return await api.put(`user_filters/${uuid}`, filter); 19 | } 20 | 21 | async function getUserFilter(uuid: string | string[]): Promise { 22 | return await api.get(`user_filters/${uuid}`); 23 | } 24 | 25 | async function getAssociatedDomains(uuid: string | string[]): Promise { 26 | return await api.get(`user_filters/${uuid}/domains`); 27 | } 28 | 29 | async function deleteUserFilter(uuid: string | string[]): Promise { 30 | return await api.delete(`user_filters/${uuid}`); 31 | } 32 | 33 | export { listUserFilters, createUserFilter, updateUserFilter, getUserFilter, getAssociatedDomains, deleteUserFilter }; 34 | -------------------------------------------------------------------------------- /src/modules/configuration/pages/remote-filters/services/workspace-filter-api.ts: -------------------------------------------------------------------------------- 1 | import api from '@/api'; 2 | import Domain from '@/modules/domain/types/Domain'; 3 | import { LDAPWorkspaceFilter } from '../types/WorkspaceFilters'; 4 | 5 | async function listWorkspaceFilters(listModel?: boolean): Promise { 6 | return await api.get('workspace_filters', { 7 | params: { 8 | model: listModel, 9 | }, 10 | }); 11 | } 12 | 13 | async function createWorkspaceFilter(filter: LDAPWorkspaceFilter): Promise { 14 | return await api.post('workspace_filters', filter); 15 | } 16 | 17 | async function updateWorkspaceFilter(filter: LDAPWorkspaceFilter): Promise { 18 | return await api.put(`workspace_filters/${filter.uuid}`, filter); 19 | } 20 | 21 | async function getWorkspaceFilter(uuid: string | string[]): Promise { 22 | return await api.get(`workspace_filters/${uuid}`); 23 | } 24 | 25 | async function getWorkspaceFilterAssociatedDomains(uuid: string | string[]): Promise { 26 | return await api.get(`workspace_filters/${uuid}/domains`); 27 | } 28 | 29 | async function deleteWorkspaceFilter(uuid: string | string[]): Promise { 30 | return await api.delete(`workspace_filters/${uuid}`); 31 | } 32 | 33 | export { 34 | createWorkspaceFilter, 35 | deleteWorkspaceFilter, 36 | getWorkspaceFilter, 37 | getWorkspaceFilterAssociatedDomains, 38 | listWorkspaceFilters, 39 | updateWorkspaceFilter, 40 | }; 41 | -------------------------------------------------------------------------------- /src/modules/configuration/pages/remote-filters/types/GroupFilters.ts: -------------------------------------------------------------------------------- 1 | export interface LDAPGroupFilter { 2 | uuid: string; 3 | name: string; 4 | description?: string; 5 | type: 'LDAP'; 6 | creationDate?: number; 7 | modificationDate?: number; 8 | searchPageSize: number; 9 | searchAllGroupsQuery: string; 10 | searchGroupQuery: string; 11 | groupPrefixToRemove: string; 12 | groupNameAttribute: string; 13 | groupMemberAttribute: string; 14 | memberMailAttribute: string; 15 | memberFirstNameAttribute: string; 16 | memberLastNameAttribute: string; 17 | } 18 | 19 | export const EMPTY_LDAP_GROUP_FILTER: LDAPGroupFilter = { 20 | uuid: '', 21 | name: '', 22 | groupMemberAttribute: '', 23 | groupPrefixToRemove: '', 24 | memberFirstNameAttribute: '', 25 | memberLastNameAttribute: '', 26 | memberMailAttribute: '', 27 | groupNameAttribute: '', 28 | searchAllGroupsQuery: '', 29 | searchGroupQuery: '', 30 | searchPageSize: 1, 31 | type: 'LDAP', 32 | }; 33 | -------------------------------------------------------------------------------- /src/modules/configuration/pages/remote-filters/types/UserFilter.ts: -------------------------------------------------------------------------------- 1 | export enum USER_FILTER_TYPE { 2 | LDAP = 'LDAP', 3 | } 4 | 5 | export default interface UserFilter { 6 | uuid: string; 7 | name: string; 8 | description: string; 9 | type: USER_FILTER_TYPE; 10 | creationDate: number; 11 | modificationDate: number; 12 | authenticationQuery: string; 13 | searchUserQuery: string; 14 | autoCompleteCommandOnAllAttributes: string; 15 | autoCompleteCommandOnFirstAndLastName: string; 16 | userMailAttribute: string; 17 | userFirstNameAttribute: string; 18 | userLastNameAttribute: string; 19 | userUidAttribute: string; 20 | searchPageSize: number; 21 | searchSizeLimit: number; 22 | completionPageSize: number; 23 | completionSizeLimit: number; 24 | } 25 | -------------------------------------------------------------------------------- /src/modules/configuration/pages/remote-filters/types/WorkspaceFilters.ts: -------------------------------------------------------------------------------- 1 | export interface LDAPWorkspaceFilter { 2 | uuid: string; 3 | name: string; 4 | description?: string; 5 | type: 'LDAP'; 6 | creationDate?: number; 7 | modificationDate?: number; 8 | searchPageSize: number; 9 | searchAllGroupsQuery: string; 10 | searchGroupQuery: string; 11 | groupPrefixToRemove: string; 12 | groupNameAttribute: string; 13 | groupMemberAttribute: string; 14 | memberMailAttribute: string; 15 | memberFirstNameAttribute: string; 16 | memberLastNameAttribute: string; 17 | } 18 | 19 | export const EMPTY_FILTER: LDAPWorkspaceFilter = { 20 | uuid: '', 21 | name: '', 22 | groupMemberAttribute: '', 23 | groupPrefixToRemove: '', 24 | memberFirstNameAttribute: '', 25 | memberLastNameAttribute: '', 26 | memberMailAttribute: '', 27 | groupNameAttribute: '', 28 | searchAllGroupsQuery: '', 29 | searchGroupQuery: '', 30 | searchPageSize: 1, 31 | type: 'LDAP', 32 | }; 33 | -------------------------------------------------------------------------------- /src/modules/configuration/pages/remote-servers/hooks/readme.md: -------------------------------------------------------------------------------- 1 | This directory is to store the files that declare the methods used in the hook of configuration/remote-servers module -------------------------------------------------------------------------------- /src/modules/configuration/pages/remote-servers/router/index.ts: -------------------------------------------------------------------------------- 1 | import { RouteRecordRaw } from 'vue-router'; 2 | import RemoteServersPage from '../pages/remote-servers-page.vue'; 3 | export const ConfigurationDomainRemoteServersRoutes: RouteRecordRaw[] = [ 4 | { 5 | name: 'ConfigurationDomainRemoteServers', 6 | path: ':domainUuid/remote-servers', 7 | component: RemoteServersPage, 8 | meta: { 9 | requiresAuth: true, 10 | parentRoute: 'Configuration', 11 | label: 'NAVIGATOR.REMOTE_SERVERS', 12 | }, 13 | children: [], 14 | }, 15 | ]; 16 | -------------------------------------------------------------------------------- /src/modules/configuration/pages/remote-servers/services/remote-server-api.ts: -------------------------------------------------------------------------------- 1 | import api from '@/api'; 2 | import RemoteServer from '@/modules/remote-server/types/RemoteServer'; 3 | import Domain from '@/modules/domain/types/Domain'; 4 | 5 | async function listRemoteServers(): Promise { 6 | return await api.get('remote_servers'); 7 | } 8 | 9 | async function createRemoteServer(payload: Omit): Promise { 10 | return await api.post('remote_servers', payload); 11 | } 12 | 13 | async function updateRemoteServer(payload: RemoteServer): Promise { 14 | return await api.put(`remote_servers/${payload.uuid}`, payload); 15 | } 16 | 17 | async function getAssociatedDomains(uuid: string): Promise { 18 | return await api.get(`remote_servers/${uuid}/domains`); 19 | } 20 | 21 | async function deleteRemoteServer(uuid: string): Promise { 22 | return await api.delete(`remote_servers/${uuid}`); 23 | } 24 | 25 | export { listRemoteServers, createRemoteServer, updateRemoteServer, getAssociatedDomains, deleteRemoteServer }; 26 | -------------------------------------------------------------------------------- /src/modules/configuration/pages/remote-servers/types/RemoteServer.ts: -------------------------------------------------------------------------------- 1 | export interface LDAPRemoteServer { 2 | uuid: string; 3 | name: string; 4 | url: string; 5 | creationDate?: number; 6 | modificationDate?: number; 7 | bindDn?: string; 8 | bindPassword?: string; 9 | serverType: 'LDAP'; 10 | } 11 | 12 | export interface TwakeRemoteServer { 13 | uuid: string; 14 | name: string; 15 | url: string; 16 | creationDate?: number; 17 | modificationDate?: number; 18 | clientId?: string; 19 | clientSecret?: string; 20 | serverType: 'TWAKE'; 21 | } 22 | 23 | type RemoteServer = LDAPRemoteServer | TwakeRemoteServer; 24 | 25 | export const EMPTY_LDAP_SERVER: LDAPRemoteServer = { 26 | uuid: '', 27 | name: '', 28 | url: '', 29 | serverType: 'LDAP', 30 | }; 31 | 32 | export const EMPTY_TWAKE_SERVER: TwakeRemoteServer = { 33 | uuid: '', 34 | name: '', 35 | url: '', 36 | serverType: 'TWAKE', 37 | }; 38 | 39 | export default RemoteServer; 40 | -------------------------------------------------------------------------------- /src/modules/configuration/pages/type-mime-policies/router/index.ts: -------------------------------------------------------------------------------- 1 | import { RouteRecordRaw } from 'vue-router'; 2 | import TypeMimePoliciesPage from '../pages/type-mime-policies-page.vue'; 3 | 4 | export const CONFIGURATION_MIME_POLICIES_ROUTE_NAMES = { 5 | ENTRIES: 'ConfigurationDomainTypeMimePolicies', 6 | DETAIL: 'ConfigurationDomainTypeMimePolicyDetail', 7 | }; 8 | 9 | export const ConfigurationDomainTypeMimePoliciesRoutes: RouteRecordRaw[] = [ 10 | { 11 | name: CONFIGURATION_MIME_POLICIES_ROUTE_NAMES.ENTRIES, 12 | path: ':domainUuid/type-mime-policies', 13 | component: TypeMimePoliciesPage, 14 | meta: { 15 | requiresAuth: true, 16 | parentRoute: 'Configuration', 17 | label: 'NAVIGATOR.TYPE_MIME', 18 | }, 19 | children: [], 20 | }, 21 | { 22 | name: CONFIGURATION_MIME_POLICIES_ROUTE_NAMES.DETAIL, 23 | path: ':domainUuid/type-mime-policies/:mimePolicyUuid', 24 | component: () => import('@/modules/configuration/pages/type-mime-policies/pages/mime-policy-detail-page.vue'), 25 | meta: { 26 | requiresAuth: true, 27 | parentRoute: CONFIGURATION_MIME_POLICIES_ROUTE_NAMES.ENTRIES, 28 | label: 'NAVIGATOR.TYPE_MIME_DETAILS', 29 | }, 30 | children: [], 31 | }, 32 | ]; 33 | -------------------------------------------------------------------------------- /src/modules/configuration/pages/type-mime-policies/types/MimeType.ts: -------------------------------------------------------------------------------- 1 | export interface MimePolicy { 2 | uuid: string; 3 | creationDate?: number; 4 | name: string; 5 | modificationDate: number; 6 | domainId: string; 7 | domainName: string; 8 | mimeTypes: MimeType[]; 9 | assigned?: boolean; 10 | unknownTypeAllowed: boolean; 11 | } 12 | 13 | export interface MimeType { 14 | uuid: string; 15 | mimeType: string; 16 | extensions: string; 17 | enable: boolean; 18 | creationDate: number; 19 | modificationDate: number; 20 | } 21 | -------------------------------------------------------------------------------- /src/modules/configuration/pages/welcome-messages/composables/readme.md: -------------------------------------------------------------------------------- 1 | This directory is to store the files that declare the composable methods of configuration/welcome-messages module -------------------------------------------------------------------------------- /src/modules/configuration/pages/welcome-messages/types/WelcomeMessages.ts: -------------------------------------------------------------------------------- 1 | export default interface WelcomeMessage { 2 | uuid: string; 3 | creationDate?: number; 4 | name: string; 5 | modificationDate?: number; 6 | description?: string; 7 | domain?: { 8 | uuid: string; 9 | name: string; 10 | }; 11 | entries: Record; 12 | assignedToCurrentDomain?: boolean; 13 | readOnly?: boolean; 14 | } 15 | 16 | export const EMPTY_WELCOME_MESSAGE: WelcomeMessage = { 17 | uuid: '', 18 | name: '', 19 | entries: { 20 | VIETNAMESE: '', 21 | ENGLISH: '', 22 | FRENCH: '', 23 | RUSSIAN: '', 24 | }, 25 | }; 26 | -------------------------------------------------------------------------------- /src/modules/design-system/pages/data-entry-page.vue: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /src/modules/design-system/pages/feedback-page.vue: -------------------------------------------------------------------------------- 1 | 9 | 12 | 20 | -------------------------------------------------------------------------------- /src/modules/design-system/pages/general-page.vue: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /src/modules/design-system/pages/index-page.vue: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /src/modules/design-system/pages/navigation-page.vue: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /src/modules/design-system/router/index.ts: -------------------------------------------------------------------------------- 1 | import { RouteRecordRaw } from 'vue-router'; 2 | import DesignSystemPage from '../pages/index-page.vue'; 3 | 4 | export const DesignSystemRoutes: RouteRecordRaw[] = [ 5 | { 6 | name: 'DesignSystem', 7 | path: 'design-system', 8 | component: DesignSystemPage, 9 | meta: { 10 | requiresAuth: false, 11 | }, 12 | children: [ 13 | { 14 | name: 'DataEntryPage', 15 | path: 'data-entry', 16 | component: () => import('../pages/data-entry-page.vue'), 17 | }, 18 | { 19 | name: 'FeedbackPage', 20 | path: 'feedback', 21 | component: () => import('../pages/feedback-page.vue'), 22 | }, 23 | { 24 | name: 'FormPage', 25 | path: 'form', 26 | component: () => import('../pages/form-page.vue'), 27 | }, 28 | { 29 | name: 'GeneralPage', 30 | path: 'general', 31 | component: () => import('../pages/general-page.vue'), 32 | }, 33 | { 34 | name: 'NavigationPage', 35 | path: 'navigation', 36 | component: () => import('../pages/navigation-page.vue'), 37 | }, 38 | { 39 | name: 'DomainSelected', 40 | path: 'domains/:domainUuid/quota', 41 | component: () => import('../pages/navigation-page.vue'), 42 | }, 43 | ], 44 | }, 45 | ]; 46 | -------------------------------------------------------------------------------- /src/modules/domain/components/domain-associated-list-modal.vue: -------------------------------------------------------------------------------- 1 | 22 | 23 | 34 | 35 | 44 | -------------------------------------------------------------------------------- /src/modules/domain/hooks/useAssociatedDomainsModal.ts: -------------------------------------------------------------------------------- 1 | import { reactive, ref, UnwrapRef, watchEffect } from 'vue'; 2 | import Domain from '../types/Domain'; 3 | 4 | export interface AssociatedDomainModalState { 5 | loading: boolean; 6 | visible: boolean; 7 | list: Domain[]; 8 | } 9 | 10 | type UsableAssociatedDomainsModal = { 11 | hide: () => void; 12 | show: (uuid: string) => void; 13 | modal: UnwrapRef<{ loading: boolean; visible: boolean; list: Domain[] }>; 14 | }; 15 | 16 | export default function useAssociatedDomainsModal( 17 | fetcher: (uuid: string) => Promise 18 | ): UsableAssociatedDomainsModal { 19 | const targetUuid = ref(''); 20 | const modal = reactive({ 21 | loading: false, 22 | visible: false, 23 | list: [], 24 | }); 25 | 26 | watchEffect(() => { 27 | if (!targetUuid.value) return; 28 | 29 | modal.loading = true; 30 | fetcher(targetUuid.value) 31 | .then((domains) => { 32 | modal.list = domains; 33 | }) 34 | .finally(() => { 35 | modal.loading = false; 36 | }); 37 | }); 38 | 39 | function show(uuid: string) { 40 | targetUuid.value = uuid; 41 | modal.visible = true; 42 | } 43 | 44 | function hide() { 45 | modal.visible = false; 46 | } 47 | 48 | return { 49 | hide, 50 | show, 51 | modal, 52 | }; 53 | } 54 | -------------------------------------------------------------------------------- /src/modules/domain/hooks/useFunctionalities.ts: -------------------------------------------------------------------------------- 1 | import { computed, ComputedRef, Ref } from 'vue'; 2 | import { useI18n } from 'vue-i18n'; 3 | import { Functionality } from '@/core/types/Functionality'; 4 | 5 | type UsableFunctionalities = { 6 | getTranslatedText: (functionality: Functionality, key: string) => string; 7 | }; 8 | 9 | export default function useFunctionalities(): UsableFunctionalities { 10 | const { t } = useI18n(); 11 | 12 | function getTranslatedText(functionality: Functionality, key: string): string { 13 | const i18nKey = `FUNCTIONALITIES.DETAILS.${functionality.identifier}.${key}`; 14 | const i18nValue = t(i18nKey); 15 | 16 | return i18nValue === i18nKey ? t(`FUNCTIONALITIES.DEFAULT.${key}`) : i18nValue; 17 | } 18 | 19 | return { 20 | getTranslatedText, 21 | }; 22 | } 23 | -------------------------------------------------------------------------------- /src/modules/domain/pages/domain-page.vue: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /src/modules/domain/pages/domain-providers-page.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 19 | -------------------------------------------------------------------------------- /src/modules/domain/router/requiresDomainAccessibility.ts: -------------------------------------------------------------------------------- 1 | import { storeToRefs } from 'pinia'; 2 | import { Router } from 'vue-router'; 3 | import { useDomainStore } from '@/modules/domain/store'; 4 | import { useAuthStore } from '@/modules/auth/store'; 5 | import { findDomainPage, canAccessPage } from '@/core/services/configuration-pages'; 6 | 7 | export const requiresDomainAccessibility = (router: Router): void => { 8 | router.beforeEach((to) => { 9 | if (!to.name || !to.fullPath.includes('/configuration')) { 10 | return; 11 | } 12 | const domainStore = useDomainStore(); 13 | const authStore = useAuthStore(); 14 | const { currentDomain } = storeToRefs(domainStore); 15 | const { loggedUser } = storeToRefs(authStore); 16 | const page = findDomainPage(to.name); 17 | 18 | if (page && !canAccessPage(page, loggedUser.value?.role, currentDomain.value.type) && !to.meta?.noAccessibility) { 19 | return '/'; 20 | } 21 | }); 22 | }; 23 | -------------------------------------------------------------------------------- /src/modules/domain/router/requiresDomainUpdate.ts: -------------------------------------------------------------------------------- 1 | import { Router } from 'vue-router'; 2 | import { storeToRefs } from 'pinia'; 3 | import { useAppStore } from '@/core/store'; 4 | import { useDomainStore } from '@/modules/domain/store'; 5 | /** 6 | * This guard will detect if a domain uuid is present in the url 7 | * and therefore set the current domain uuid accordingly. 8 | * 9 | * It should be registered before requiresAuthGuard where the 10 | * hydration is triggered. 11 | */ 12 | export const requiresDomainUpdate = (router: Router): void => { 13 | router.beforeEach((to, from) => { 14 | const domainStore = useDomainStore(); 15 | const appStore = useAppStore(); 16 | const domainUuid = to.params.domainUuid as string; 17 | const { currentDomain } = storeToRefs(domainStore); 18 | const hydrated = appStore.hydrated; 19 | 20 | if (!domainUuid || domainUuid === currentDomain.value.uuid) { 21 | return; 22 | } 23 | 24 | domainStore.setCurrentDomainUuid(domainUuid); 25 | 26 | if (hydrated && !from.path.includes('/configuration')) { 27 | domainStore.fetchDomain(); 28 | } 29 | }); 30 | }; 31 | -------------------------------------------------------------------------------- /src/modules/domain/services/domain-api.ts: -------------------------------------------------------------------------------- 1 | import { AxiosRequestConfig } from 'axios'; 2 | import api from '@/api'; 3 | import apiv4 from '@/apiv4'; 4 | 5 | import Domain from '@/modules/domain/types/Domain'; 6 | import DomainTreeNode from '../types/DomainTreeNode'; 7 | import { PaginatedList } from '@/core/types/PaginatedList'; 8 | 9 | async function listDomainsR2(config?: AxiosRequestConfig): Promise> { 10 | return api.get('domains/r2', config); 11 | } 12 | 13 | async function getDomains(config?: AxiosRequestConfig): Promise { 14 | return await api.get('domains', config); 15 | } 16 | async function getDomainsV4(config?: AxiosRequestConfig): Promise { 17 | return await apiv4.get('domains', config); 18 | } 19 | 20 | async function getDomain(uuid: string, configs?: AxiosRequestConfig): Promise { 21 | return await api.get(`domains/${uuid}`, configs); 22 | } 23 | 24 | async function updateDomain(domain: Domain): Promise { 25 | return await api.put(`domains/${domain.uuid}`, domain); 26 | } 27 | 28 | async function createDomain(domain: Omit, dedicatedDomainPolicy = false): Promise { 29 | return await api.post('domains', domain, { 30 | params: { dedicatedDomainPolicy }, 31 | }); 32 | } 33 | 34 | async function deleteDomain(domain: Domain): Promise { 35 | return await api.delete(`domains/${domain.uuid}`); 36 | } 37 | 38 | export { createDomain, getDomainsV4, deleteDomain, getDomain, getDomains, listDomainsR2, updateDomain }; 39 | -------------------------------------------------------------------------------- /src/modules/domain/types/Domain.ts: -------------------------------------------------------------------------------- 1 | export enum DOMAIN_TYPE { 2 | ROOT = 'ROOTDOMAIN', 3 | TOP = 'TOPDOMAIN', 4 | SUB = 'SUBDOMAIN', 5 | GUEST = 'GUESTDOMAIN', 6 | } 7 | 8 | export default interface Domain { 9 | uuid: string; 10 | name: string; 11 | description?: string; 12 | language?: 'RUSSIAN' | 'ENGLISH' | 'FRENCH' | 'VIETNAMESE'; 13 | creationDate?: number; 14 | modificationDate?: number; 15 | defaultEmailLanguage?: string; 16 | defaultUserRole?: string; 17 | type?: DOMAIN_TYPE; 18 | parent?: Partial; 19 | domainPolicy?: { 20 | name: string; 21 | uuid: string; 22 | }; 23 | mailConfiguration?: { 24 | name: string; 25 | uuid: string; 26 | }; 27 | mimePolicy?: { 28 | name: string; 29 | uuid: string; 30 | }; 31 | welcomeMessage?: { 32 | name: string; 33 | uuid: string; 34 | }; 35 | } 36 | 37 | export const EMPTY_DOMAIN: Domain = { 38 | uuid: '', 39 | name: '', 40 | }; 41 | -------------------------------------------------------------------------------- /src/modules/domain/types/DomainTreeNode.ts: -------------------------------------------------------------------------------- 1 | import { DOMAIN_TYPE } from './Domain'; 2 | 3 | export default interface DomainTreeNode { 4 | uuid: string; 5 | name: string; 6 | type?: DOMAIN_TYPE; 7 | children?: DomainTreeNode[]; 8 | checked?: boolean; 9 | } 10 | 11 | export const EMPTY_DOMAIN_NODE: DomainTreeNode = { 12 | uuid: '', 13 | name: '', 14 | }; 15 | -------------------------------------------------------------------------------- /src/modules/inconsistent-users/pages/entries-page.vue: -------------------------------------------------------------------------------- 1 | 8 | 19 | -------------------------------------------------------------------------------- /src/modules/inconsistent-users/pages/inconsistent-users-entries-page.vue: -------------------------------------------------------------------------------- 1 | 11 | 14 | 24 | -------------------------------------------------------------------------------- /src/modules/inconsistent-users/router/index.ts: -------------------------------------------------------------------------------- 1 | import { RouteRecordRaw } from 'vue-router'; 2 | 3 | export const INCONSISTENT_USERS_ROUTE_NAMES = { 4 | ENTRIES: 'InconsistentUsers', 5 | DIAGNOSIC: 'InconsistentUsersDiagnostic', 6 | INCONSISTENT_LIST: 'InconsistentUserList', 7 | }; 8 | 9 | export const InconsistentUsersRoutes: Array = [ 10 | { 11 | name: INCONSISTENT_USERS_ROUTE_NAMES.ENTRIES, 12 | path: 'inconsistent-users', 13 | component: () => import('../pages/inconsistent-users-entries-page.vue'), 14 | meta: { 15 | parentRoute: 'AdministrationEntries', 16 | label: 'INCONSISTENT_USERS_ROUTE_NAMES.ENTRIES', 17 | requiresAuth: true, 18 | }, 19 | children: [ 20 | { 21 | name: INCONSISTENT_USERS_ROUTE_NAMES.DIAGNOSIC, 22 | path: 'diagnostic', 23 | component: () => import('../pages/manage-diagnostic-users.vue'), 24 | meta: { 25 | label: 'ADMINISTRATION.NAVIGATOR.DIAGNOSIC', 26 | requiresAuth: true, 27 | }, 28 | }, 29 | { 30 | name: INCONSISTENT_USERS_ROUTE_NAMES.INCONSISTENT_LIST, 31 | path: 'inconsistent', 32 | component: () => import('../pages/manage-inconsistent-users.vue'), 33 | meta: { 34 | label: 'ADMINISTRATION.NAVIGATOR.INCONSISTENT_USERS', 35 | requiresAuth: true, 36 | }, 37 | }, 38 | ], 39 | }, 40 | ]; 41 | -------------------------------------------------------------------------------- /src/modules/inconsistent-users/store/index.ts: -------------------------------------------------------------------------------- 1 | import Domain from '@/modules/domain/types/Domain'; 2 | import dayjs, { Dayjs } from 'dayjs'; 3 | import { defineStore } from 'pinia'; 4 | 5 | export type ReportingCategory = 'WHOLE_DOMAIN' | 'SHARED_SPACE' | 'MY_SPACE'; 6 | 7 | interface ReportingStore { 8 | domains: Domain[]; 9 | category: ReportingCategory; 10 | beginDate: Dayjs | null; 11 | endDate: Dayjs | null; 12 | } 13 | 14 | export const useReportingStore = defineStore('reportingStore', { 15 | state: (): ReportingStore => ({ 16 | domains: [], 17 | category: 'WHOLE_DOMAIN', 18 | beginDate: dayjs().subtract(7, 'days'), 19 | endDate: dayjs(), 20 | }), 21 | }); 22 | -------------------------------------------------------------------------------- /src/modules/inconsistent-users/types/InconsistentUsers.ts: -------------------------------------------------------------------------------- 1 | import Filters from '@/core/types/Filters'; 2 | import { SORT_ORDER } from '@/core/types/Sort'; 3 | export interface InconsistentUsers { 4 | creationDate?: number; 5 | domain: string; 6 | domainName: string; 7 | externalMailLocale: string; 8 | locale: string; 9 | modificationDate: number; 10 | uuid: string; 11 | accountType: string; 12 | canCreateGuest: boolean; 13 | canUpload: boolean; 14 | firstName: string; 15 | lastName: string; 16 | mail: string; 17 | role: string; 18 | } 19 | 20 | export interface InconsistentUsersListFilters extends Filters { 21 | domains?: string; 22 | firstName?: string; 23 | lastName?: string; 24 | email?: string; 25 | } 26 | 27 | export interface InconsistentUsersListParameters { 28 | domainId?: string; 29 | firstName?: string; 30 | lastName?: string; 31 | mail?: string; 32 | page?: number; 33 | size?: number; 34 | sortOrder?: SORT_ORDER; 35 | sortField?: string; 36 | } 37 | -------------------------------------------------------------------------------- /src/modules/password/router/index.ts: -------------------------------------------------------------------------------- 1 | import { NavigationGuard, RouteRecordRaw } from 'vue-router'; 2 | import { useAuthStore } from '@/modules/auth/store'; 3 | const checkCredentials: NavigationGuard = (to) => { 4 | if (!to.params.email || !to.params.password) { 5 | return '/login'; 6 | } 7 | }; 8 | 9 | const checkLoggedIn: NavigationGuard = (to) => { 10 | const authStore = useAuthStore(); 11 | if (authStore.loggedUser) { 12 | return '/administration'; 13 | } 14 | }; 15 | 16 | export const LoginRoutes: Array = [ 17 | { 18 | name: 'Login', 19 | path: '/login', 20 | props: true, 21 | component: () => import('../pages/login-page.vue'), 22 | beforeEnter: [checkLoggedIn], 23 | }, 24 | { 25 | name: 'LoginUsingSecondFactorAuthentication', 26 | path: '/login/2fa', 27 | component: () => import('../pages/login-second-factor.vue'), 28 | props: true, 29 | beforeEnter: [checkCredentials], 30 | }, 31 | { 32 | name: 'OIDCCallback', 33 | path: '/oidc/callback', 34 | component: () => import('../components/oidc-callback.vue'), 35 | }, 36 | ]; 37 | 38 | export const ManageSecondFactorAuthenticationRoute: RouteRecordRaw = { 39 | name: 'ManageSecondFactorAuthentication', 40 | path: '/second_factor_authentication', 41 | component: () => import('../pages/manage-second-factor-authentication.vue'), 42 | meta: { 43 | requiresAuth: true, 44 | }, 45 | }; 46 | -------------------------------------------------------------------------------- /src/modules/reporting/components/reporting-page.vue: -------------------------------------------------------------------------------- 1 | 8 | 16 | 23 | -------------------------------------------------------------------------------- /src/modules/reporting/components/reporting-statistic-most-uploaded.vue: -------------------------------------------------------------------------------- 1 | 15 | 16 | 31 | 32 | 40 | -------------------------------------------------------------------------------- /src/modules/reporting/constants/human-mime-type-color.ts: -------------------------------------------------------------------------------- 1 | export const HUMAN_MIME_TYPE_COLOR: Record = { 2 | archive: '#ea3c3c', 3 | audio: '#30cd60', 4 | document: '#007aff', 5 | encrypted: '#ff008a', 6 | image: '#ffa940', 7 | pdf: '#007aff', 8 | text: '#30cd60', 9 | video: '#ffa940', 10 | others: '#007aff', 11 | }; 12 | -------------------------------------------------------------------------------- /src/modules/reporting/router/index.ts: -------------------------------------------------------------------------------- 1 | import { RouteRecordRaw } from 'vue-router'; 2 | 3 | export const ReportingRoute: RouteRecordRaw = { 4 | name: 'Reporting', 5 | path: 'reporting', 6 | component: () => import('../components/reporting-page.vue'), 7 | meta: { 8 | requiresAuth: true, 9 | uiBeta: true, 10 | }, 11 | }; 12 | -------------------------------------------------------------------------------- /src/modules/reporting/store/index.ts: -------------------------------------------------------------------------------- 1 | import Domain from '@/modules/domain/types/Domain'; 2 | import dayjs, { Dayjs } from 'dayjs'; 3 | import { defineStore } from 'pinia'; 4 | 5 | export type ReportingCategory = 'WHOLE_DOMAIN' | 'SHARED_SPACE' | 'MY_SPACE'; 6 | 7 | interface ReportingStorageStore { 8 | domains: Domain[]; 9 | category: ReportingCategory; 10 | beginDate: Dayjs | null; 11 | endDate: Dayjs | null; 12 | } 13 | 14 | interface ReportingSharesStore { 15 | domains: Domain[]; 16 | beginDate: Dayjs | null; 17 | endDate: Dayjs | null; 18 | top: number; 19 | } 20 | 21 | export const useReportingStore = defineStore('reportingStore', { 22 | state: (): ReportingStorageStore => ({ 23 | domains: [], 24 | category: 'WHOLE_DOMAIN', 25 | beginDate: dayjs().subtract(7, 'days'), 26 | endDate: dayjs(), 27 | }), 28 | }); 29 | 30 | export const useReportingSharesStore = defineStore('reportingSharesStore', { 31 | state: (): ReportingSharesStore => ({ 32 | domains: [], 33 | beginDate: dayjs().subtract(1, 'days'), 34 | endDate: dayjs(), 35 | top: 50, 36 | }), 37 | }); 38 | -------------------------------------------------------------------------------- /src/modules/reporting/types/AccountQuotaStatistic.ts: -------------------------------------------------------------------------------- 1 | export interface AccountQuotaStatistic { 2 | uuid: string; 3 | creationDate: number; 4 | statisticDate: number; 5 | domain: { 6 | uuid: string; 7 | name: string; 8 | }; 9 | account: { 10 | uuid: string; 11 | name: string; 12 | email: string; 13 | }; 14 | parentDomain: { 15 | uuid: string; 16 | name: string; 17 | }; 18 | quota: number; 19 | quotaOverride: boolean; 20 | usedSpace: number; 21 | yesterdayUsedSpace: number; 22 | maintenance: boolean; 23 | batchModificationDate: number; 24 | domainShared: boolean; 25 | domainSharedOverride: boolean; 26 | maxFileSize: number; 27 | maxFileSizeOverride: boolean; 28 | } 29 | -------------------------------------------------------------------------------- /src/modules/reporting/types/MimeTypeStatistic.ts: -------------------------------------------------------------------------------- 1 | export interface MimeTypeStatistic { 2 | uuid: string; 3 | value: number; 4 | totalSize: number; 5 | domainUuid: string; 6 | type: 'DAILY'; 7 | mimeType: string; 8 | humanMimeType: HumanMimeType; 9 | creationDate: number; 10 | statisticDate: number; 11 | } 12 | 13 | export type HumanMimeType = 14 | | 'audio' 15 | | 'video' 16 | | 'text' 17 | | 'image' 18 | | 'pdf' 19 | | 'archive' 20 | | 'encrypted' 21 | | 'document' 22 | | 'others'; 23 | 24 | export type StatisticByHumanMimeType = Record< 25 | HumanMimeType, 26 | { 27 | totalSize: number; 28 | totalCount: number; 29 | } 30 | >; 31 | 32 | export type StatisticByMimeType = Record< 33 | string, 34 | { 35 | humanMimeType: HumanMimeType; 36 | totalSize: number; 37 | totalCount: number; 38 | } 39 | >; 40 | -------------------------------------------------------------------------------- /src/modules/reporting/types/StorageConsumptionStatistic.ts: -------------------------------------------------------------------------------- 1 | export type StorageConsumptionStatisticByDate = Record< 2 | string, 3 | { 4 | countOfAddedFiles: number; 5 | countOfDeletedFiles: number; 6 | countOfFiles: number; 7 | sumOfAddedFiles: number; 8 | sumOfDeletedFiles: number; 9 | diffOperationSum: number; 10 | actualOperationSum: number; 11 | } 12 | >; 13 | 14 | export type StorageConsumtptionStatisticType = 15 | | 'USER_DAILY_STAT' 16 | | 'USER_WEEKLY_STAT' 17 | | 'USER_MONTHLY_STAT' 18 | | 'WORK_GROUP_DAILY_STAT' 19 | | 'WORK_GROUP_WEEKLY_STAT' 20 | | 'WORK_GROUP_MONTHLY_STAT' 21 | | 'DOMAIN_DAILY_STAT' 22 | | 'DOMAIN_WEEKLY_STAT' 23 | | 'DOMAIN_MONTHLY_STAT'; 24 | 25 | export interface StorageConsumptionStatistic { 26 | creationDate: number; 27 | statisticDate: number; 28 | domain: { 29 | uuid: string; 30 | name: string; 31 | }; 32 | statisticType: StorageConsumtptionStatisticType; 33 | countOfAddedFiles: number; 34 | countOfDeletedFiles: number; 35 | countOfFiles: number; 36 | sumOfAddedFiles: number; 37 | sumOfDeletedFiles: number; 38 | diffOperationSum: number; 39 | actualOperationSum: number; 40 | account: { 41 | uuid: string; 42 | name: string; 43 | }; 44 | } 45 | -------------------------------------------------------------------------------- /src/modules/reporting/types/TopSharesFileCount.ts: -------------------------------------------------------------------------------- 1 | export interface TopSharesFileCountItem { 2 | recipientType: string; 3 | recipientUuid: string; 4 | recipientMail: string; 5 | domainUuid: string; 6 | domainLabel: string; 7 | shareCount: number; 8 | shareTotalSize: number; 9 | } 10 | 11 | export interface TopSharesFileCount { 12 | pageNumber: number; 13 | pageSize: number; 14 | pageResponse: { 15 | total: number; 16 | totalPages: number; 17 | content: TopSharesFileCountItem[]; 18 | first: boolean; 19 | last: boolean; 20 | }; 21 | total: number; 22 | data: TopSharesFileCountItem[]; 23 | defaultPageRequest: { 24 | sort: { 25 | empty: boolean; 26 | sorted: boolean; 27 | unsorted: boolean; 28 | }; 29 | offset: number; 30 | pageNumber: number; 31 | pageSize: number; 32 | paged: boolean; 33 | unpaged: boolean; 34 | }; 35 | } 36 | -------------------------------------------------------------------------------- /src/modules/reporting/types/TopSharesFileSize.ts: -------------------------------------------------------------------------------- 1 | export interface TopSharesFileSizeItem { 2 | recipientType: string; 3 | recipientUuid: string; 4 | recipientMail: string; 5 | domainUuid: string; 6 | domainLabel: string; 7 | shareCount: number; 8 | shareTotalSize: number; 9 | } 10 | 11 | export interface TopSharesFileSize { 12 | pageNumber: number; 13 | pageSize: number; 14 | pageResponse: { 15 | total: number; 16 | totalPages: number; 17 | content: TopSharesFileSizeItem[]; 18 | first: boolean; 19 | last: boolean; 20 | }; 21 | total: number; 22 | data: TopSharesFileSizeItem[]; 23 | defaultPageRequest: { 24 | sort: { 25 | empty: boolean; 26 | sorted: boolean; 27 | unsorted: boolean; 28 | }; 29 | offset: number; 30 | pageNumber: number; 31 | pageSize: number; 32 | paged: boolean; 33 | unpaged: boolean; 34 | }; 35 | } 36 | -------------------------------------------------------------------------------- /src/modules/shared-spaces/pages/entries-page.vue: -------------------------------------------------------------------------------- 1 | 8 | 19 | -------------------------------------------------------------------------------- /src/modules/shared-spaces/router/index.ts: -------------------------------------------------------------------------------- 1 | import { RouteRecordRaw } from 'vue-router'; 2 | import SharedSpacesListEntries from '@/modules/shared-spaces/pages/entries-page.vue'; 3 | 4 | export const MY_SHARED_SPACES_ROUTE_NAMES = { 5 | ENTRIES: 'AdministrationSharedSpacesListEntries', 6 | SHARE_SPACES_LIST: 'AdministrationSharedSpacesList', 7 | SHARE_SPACES_DETAIL: 'AdministrationSharedSpaceDetails', 8 | }; 9 | export const SharedSpacesRoutes: Array = [ 10 | { 11 | name: MY_SHARED_SPACES_ROUTE_NAMES.ENTRIES, 12 | path: 'sharedspaces', 13 | component: SharedSpacesListEntries, 14 | meta: { 15 | requiresAuth: true, 16 | parentRoute: 'AdministrationEntries', 17 | label: 'NAVIGATOR.ADMINISTRATION_CONTACT_LIST', 18 | }, 19 | children: [ 20 | { 21 | name: MY_SHARED_SPACES_ROUTE_NAMES.SHARE_SPACES_LIST, 22 | path: '', 23 | component: () => import('../pages/manage-shared-spaces.vue'), 24 | meta: { 25 | label: 'NAVIGATOR.MY_SHARED_SPACES', 26 | parentRoute: 'AdministrationEntries', 27 | requiresAuth: true, 28 | }, 29 | }, 30 | { 31 | name: MY_SHARED_SPACES_ROUTE_NAMES.SHARE_SPACES_DETAIL, 32 | path: ':id', 33 | component: () => import('../components/shared-space-details.vue'), 34 | meta: { 35 | label: 'NAVIGATOR.SHARED_SPACE_DETAILS', 36 | parentRoute: MY_SHARED_SPACES_ROUTE_NAMES.SHARE_SPACES_LIST, 37 | requiresAuth: true, 38 | }, 39 | }, 40 | ], 41 | }, 42 | ]; 43 | -------------------------------------------------------------------------------- /src/modules/shared-spaces/store/index.ts: -------------------------------------------------------------------------------- 1 | import { defineStore } from 'pinia'; 2 | import { getSharedSpaceRoles } from '../services/shared-space-api'; 3 | import { SHARED_SPACE_TYPE } from '../types/SharedSpace'; 4 | import type SharedSpaceRole from '../types/SharedSpaceRole'; 5 | 6 | export interface SharedSpaceState { 7 | roles: SharedSpaceRole[]; 8 | } 9 | 10 | export const useSharedSpacesStore = defineStore('sharedSpacesStore', { 11 | state: (): SharedSpaceState => ({ 12 | roles: [], 13 | }), 14 | getters: { 15 | getRolesByType: 16 | (state) => 17 | (type: SHARED_SPACE_TYPE): SharedSpaceRole[] => 18 | state.roles.filter((role) => role.type === type), 19 | }, 20 | actions: { 21 | async fetchRoles() { 22 | try { 23 | const workgroupRoles = await getSharedSpaceRoles(SHARED_SPACE_TYPE.WORKGROUP); 24 | const workspaceRoles = await getSharedSpaceRoles(SHARED_SPACE_TYPE.WORKSPACE); 25 | 26 | this.roles = [...workgroupRoles, ...workspaceRoles]; 27 | } catch { 28 | this.roles = []; 29 | } 30 | }, 31 | }, 32 | }); 33 | -------------------------------------------------------------------------------- /src/modules/shared-spaces/types/ShareSpaceList.ts: -------------------------------------------------------------------------------- 1 | import { SORT_ORDER } from '@/core/types/Sort'; 2 | import Filters from '@/core/types/Filters'; 3 | 4 | export interface SharedSpaceListFilters extends Filters { 5 | name?: string; 6 | account?: string; 7 | nodeType?: string; 8 | domains?: string; 9 | } 10 | 11 | export interface SharedSpaceListParameters { 12 | name?: string; 13 | account?: string; 14 | nodeType?: string; 15 | domains?: string; 16 | page?: number; 17 | size?: number; 18 | sortOrder?: SORT_ORDER; 19 | sortField?: string; 20 | } 21 | -------------------------------------------------------------------------------- /src/modules/shared-spaces/types/SharedSpace.ts: -------------------------------------------------------------------------------- 1 | export enum SHARED_SPACE_TYPE { 2 | WORKGROUP = 'WORK_GROUP', 3 | WORKSPACE = 'WORK_SPACE', 4 | } 5 | export default interface SharedSpace { 6 | uuid: string; 7 | name: string; 8 | domainUuid?: string; 9 | parentUuid?: string; 10 | parentName?: string; 11 | creationDate?: number; 12 | modificationDate?: number; 13 | nodeType?: SHARED_SPACE_TYPE; 14 | author?: { 15 | name: string; 16 | mail: string; 17 | uuid: string; 18 | }; 19 | } 20 | 21 | export const EMPTY_SHARED_SPACE: SharedSpace = { 22 | uuid: '', 23 | name: '', 24 | }; 25 | -------------------------------------------------------------------------------- /src/modules/shared-spaces/types/SharedSpaceAccount.ts: -------------------------------------------------------------------------------- 1 | export default interface SharedSpaceAccount { 2 | uuid: string; 3 | firstName: string; 4 | lastName: string; 5 | mail: string; 6 | } 7 | -------------------------------------------------------------------------------- /src/modules/shared-spaces/types/SharedSpaceMember.ts: -------------------------------------------------------------------------------- 1 | import SharedSpace, { SHARED_SPACE_TYPE } from './SharedSpace'; 2 | import SharedSpaceAccount from './SharedSpaceAccount'; 3 | import SharedSpaceRole from './SharedSpaceRole'; 4 | import { SORT_ORDER } from '@/core/types/Sort'; 5 | import Filters from '@/core/types/Filters'; 6 | 7 | export interface SharedSpaceMember { 8 | uuid: string; 9 | type?: SHARED_SPACE_TYPE; 10 | nested?: boolean; 11 | node: Partial; 12 | nestedRole?: Omit; 13 | role: Omit; 14 | account: SharedSpaceAccount; 15 | creationDate?: number; 16 | modificationDate?: number; 17 | } 18 | 19 | export interface SharedSpaceMembersListParameter { 20 | pattern?: string; 21 | type?: string; 22 | roles?: string; 23 | accountUuid?: string; 24 | page?: number; 25 | size?: number; 26 | sortOrder?: SORT_ORDER; 27 | sortField?: string; 28 | } 29 | 30 | export interface MemberListFilters extends Filters { 31 | pattern?: string; 32 | type?: string; 33 | role?: string; 34 | accountUuid?: string; 35 | } 36 | 37 | export const EMPTY_SHARED_SPACE_MEMBER: SharedSpaceMember = { 38 | uuid: '', 39 | node: {}, 40 | role: { 41 | name: '', 42 | type: 'WORK_GROUP', 43 | uuid: '', 44 | }, 45 | account: { 46 | firstName: '', 47 | lastName: '', 48 | mail: '', 49 | uuid: '', 50 | }, 51 | }; 52 | -------------------------------------------------------------------------------- /src/modules/shared-spaces/types/SharedSpaceRole.ts: -------------------------------------------------------------------------------- 1 | export default interface SharedSpaceRole { 2 | uuid: string; 3 | name: string; 4 | enabled?: boolean; 5 | type: 'WORK_SPACE' | 'WORK_GROUP'; 6 | } 7 | -------------------------------------------------------------------------------- /src/modules/upgrades/components/upgrade-list-actions.vue: -------------------------------------------------------------------------------- 1 | 21 | 32 | 57 | -------------------------------------------------------------------------------- /src/modules/upgrades/services/upgrade-task-api.ts: -------------------------------------------------------------------------------- 1 | import apiv4 from '@/apiv4'; 2 | import { UpgradeTask, ConsoleInfos } from '../types/UpgradeTask'; 3 | 4 | async function getUpgradeTaskList(): Promise { 5 | return await apiv4.get(`upgrade_tasks`); 6 | } 7 | async function getUpgradeTaskDetail(uuid: string): Promise { 8 | return await apiv4.get(`upgrade_tasks/${uuid}/async_tasks`); 9 | } 10 | 11 | async function upgradeTaskinformations(taskIdentifier: string | string[]): Promise { 12 | return await apiv4.get(`upgrade_tasks/${taskIdentifier}`); 13 | } 14 | 15 | async function upgradeTaskRetry(taskIdentifier: string): Promise { 16 | return await apiv4.put(`upgrade_tasks/${taskIdentifier}?force=true`); 17 | } 18 | 19 | async function getConsoleInformations( 20 | taskIdentifier: string | string[], 21 | uuid: string | string[] 22 | ): Promise { 23 | return await apiv4.get(`upgrade_tasks/${taskIdentifier}/async_tasks/${uuid}/console`); 24 | } 25 | 26 | export { getUpgradeTaskList, getUpgradeTaskDetail, getConsoleInformations, upgradeTaskRetry, upgradeTaskinformations }; 27 | -------------------------------------------------------------------------------- /src/modules/upgrades/types/UpgradeTask.ts: -------------------------------------------------------------------------------- 1 | export interface UpgradeTask { 2 | identifier: string; 3 | taskGroup: string; 4 | parentIdentifier: string; 5 | taskOrder: number; 6 | status: string; 7 | priority: string; 8 | creationDate: number; 9 | modificationDate: number; 10 | asyncTaskUuid: string; 11 | } 12 | export interface ConsoleInfos { 13 | message: string; 14 | criticity: string; 15 | asyncTask: string; 16 | upgradeTask: string; 17 | creationDate: number; 18 | } 19 | export interface AsyncTask { 20 | uuid: string; 21 | status: string; 22 | errorMsg: string; 23 | errorName: string; 24 | errorCode: string; 25 | frequency: string; 26 | fileName: string; 27 | resourceUuid: string; 28 | creationDate: number; 29 | modificationDate: number; 30 | transfertDuration: number; 31 | waitingDuration: number; 32 | processingDuration: number; 33 | } 34 | -------------------------------------------------------------------------------- /src/modules/user/components/account-autocomplete-item.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 26 | 27 | 62 | -------------------------------------------------------------------------------- /src/modules/user/hooks/useGuest.ts: -------------------------------------------------------------------------------- 1 | import { addTime, isAfter, isBefore, isValid } from '@/core/utils/date'; 2 | import { getMaximumParameter } from '@/core/utils/functionality'; 3 | import { storeToRefs } from 'pinia'; 4 | import { useAuthStore } from '@/modules/auth/store'; 5 | import User from '../types/User'; 6 | 7 | type UsableGuest = { 8 | getMaxExpirationDate: (user: User) => Date; 9 | isValidExpirationDate: (user: User, date: Date) => boolean; 10 | }; 11 | 12 | export function useGuest(): UsableGuest { 13 | const authStore = useAuthStore(); 14 | const { functionalities } = storeToRefs(authStore); 15 | 16 | function getMaxExpirationDate(guest: User): Date { 17 | const max = getMaximumParameter(functionalities.value.GUESTS__EXPIRATION); 18 | 19 | if (max?.type !== 'UNIT_TIME') { 20 | return new Date(NaN); 21 | } 22 | 23 | return addTime(guest.creationDate, max.value, max.unit); 24 | } 25 | 26 | function isValidExpirationDate(guest: User, date: Date | number): boolean { 27 | const maxExpirationDate = getMaxExpirationDate(guest); 28 | 29 | if (isBefore(date, new Date())) { 30 | return false; 31 | } 32 | 33 | if (maxExpirationDate && isValid(maxExpirationDate) && isAfter(date, maxExpirationDate)) { 34 | return false; 35 | } 36 | 37 | return true; 38 | } 39 | 40 | return { 41 | getMaxExpirationDate, 42 | isValidExpirationDate, 43 | }; 44 | } 45 | -------------------------------------------------------------------------------- /src/modules/user/pages/entries-page.vue: -------------------------------------------------------------------------------- 1 | 8 | 19 | -------------------------------------------------------------------------------- /src/modules/user/router/index.ts: -------------------------------------------------------------------------------- 1 | import { RouteRecordRaw } from 'vue-router'; 2 | import UserListsEntries from '@/modules/user/pages/entries-page.vue'; 3 | 4 | export const MY_USERS_ROUTE_NAMES = { 5 | ENTRIES: 'AdministrationUserListsEntries', 6 | USER_LIST: 'UsersList', 7 | USER_DETAIL: 'UserDetail', 8 | }; 9 | export const UserRoutes: Array = [ 10 | { 11 | name: MY_USERS_ROUTE_NAMES.ENTRIES, 12 | path: 'users', 13 | component: UserListsEntries, 14 | meta: { 15 | requiresAuth: true, 16 | parentRoute: 'AdministrationEntries', 17 | label: 'NAVIGATOR.ADMINISTRATION_CONTACT_LIST', 18 | }, 19 | children: [ 20 | { 21 | name: MY_USERS_ROUTE_NAMES.USER_LIST, 22 | path: '', 23 | component: () => import('../pages/manage-users.vue'), 24 | meta: { 25 | parentRoute: 'AdministrationEntries', 26 | label: 'NAVIGATOR.MANAGE_USERS', 27 | requiresAuth: true, 28 | }, 29 | }, 30 | { 31 | name: MY_USERS_ROUTE_NAMES.USER_DETAIL, 32 | path: ':id', 33 | component: () => import('../pages/user-detail.vue'), 34 | meta: { 35 | parentRoute: 'UsersList', 36 | label: 'NAVIGATOR.USER_DETAILS', 37 | requiresAuth: true, 38 | }, 39 | }, 40 | ], 41 | }, 42 | ]; 43 | -------------------------------------------------------------------------------- /src/modules/user/services/guest-api.ts: -------------------------------------------------------------------------------- 1 | import api from '@/api'; 2 | import GuestModerator from '../types/GuestModerator'; 3 | 4 | async function listGuestModerators(guestUuid: string): Promise { 5 | return await api.get(`guests/${guestUuid}/moderators`); 6 | } 7 | 8 | async function createGuestModerator(guestUuid: string, moderator: GuestModerator): Promise { 9 | return await api.post(`guests/${guestUuid}/moderators`, moderator); 10 | } 11 | 12 | async function removeGuestModerator(guestUuid: string, moderator: GuestModerator): Promise { 13 | return await api.delete(`guests/${guestUuid}/moderators/${moderator.uuid}`, { data: moderator }); 14 | } 15 | 16 | async function updateGuestModerator(guestUuid: string, moderator: GuestModerator): Promise { 17 | return await api.put(`guests/${guestUuid}/moderators/${moderator.uuid}`, moderator); 18 | } 19 | 20 | export { createGuestModerator, listGuestModerators, removeGuestModerator, updateGuestModerator }; 21 | -------------------------------------------------------------------------------- /src/modules/user/services/user-utils.ts: -------------------------------------------------------------------------------- 1 | import User from '../types/User'; 2 | 3 | export function getUserFullName(user: User): string { 4 | return `${user.firstName || ''} ${user.lastName || ''}`; 5 | } 6 | -------------------------------------------------------------------------------- /src/modules/user/types/GuestList.ts: -------------------------------------------------------------------------------- 1 | import { SORT_ORDER } from '@/core/types/Sort'; 2 | import Filters from '@/core/types/Filters'; 3 | 4 | export interface GuestListFilters extends Filters { 5 | firstName?: string; 6 | pattern?: string; 7 | role?: string; 8 | } 9 | 10 | export interface GuestListParameters { 11 | uuid?: string; 12 | pattern?: string; 13 | role?: string; 14 | page?: number; 15 | size?: number; 16 | sortOrder?: SORT_ORDER; 17 | sortField?: string; 18 | } 19 | 20 | export interface Guest { 21 | canUpload: boolean; 22 | comment: string; 23 | creationDate: number; 24 | domain: string; 25 | expirationDate: number; 26 | externalMailLocale: string; 27 | firstName: string; 28 | lastName: string; 29 | locale: string; 30 | mail: string; 31 | modificationDate: number; 32 | restricted: boolean; 33 | uuid: string; 34 | } 35 | -------------------------------------------------------------------------------- /src/modules/user/types/GuestModerator.ts: -------------------------------------------------------------------------------- 1 | export enum GUEST_MODERATOR_ROLE { 2 | ADMIN = 'ADMIN', 3 | SIMPLE = 'SIMPLE', 4 | } 5 | 6 | export default interface GuestModerator { 7 | uuid: string; 8 | role: GUEST_MODERATOR_ROLE; 9 | creationDate?: number; 10 | modificationDate?: number; 11 | account: { 12 | uuid: string; 13 | name?: string; 14 | email?: string; 15 | domain?: { 16 | uuid: string; 17 | name: string; 18 | }; 19 | }; 20 | guest: { 21 | uuid: string; 22 | name?: string; 23 | email?: string; 24 | domain?: { 25 | uuid: string; 26 | name: string; 27 | }; 28 | }; 29 | } 30 | -------------------------------------------------------------------------------- /src/modules/user/types/RestrictedContact.ts: -------------------------------------------------------------------------------- 1 | export default interface RestrictedContact { 2 | uuid: string; 3 | firstName: string; 4 | lastName: string; 5 | mail: string; 6 | domain: { 7 | uuid: string; 8 | name: string; 9 | }; 10 | } 11 | -------------------------------------------------------------------------------- /src/modules/user/types/User.ts: -------------------------------------------------------------------------------- 1 | export enum ACCOUNT_ROLE { 2 | SIMPLE = 'SIMPLE', 3 | ADMIN = 'ADMIN', 4 | SYSTEM = 'SYSTEM', 5 | SUPERADMIN = 'SUPERADMIN', 6 | DELEGATION = 'DELEGATION', 7 | UPLOAD_REQUEST = 'UPLOAD_REQUEST', 8 | SAFE = 'SAFE', 9 | ANONYMOUS = 'ANONYMOUS', 10 | } 11 | 12 | export default interface User { 13 | uuid: string; 14 | mail: string; 15 | firstName: string; 16 | lastName: string; 17 | locked: boolean; 18 | canUpload: boolean; 19 | canCreateGuest: boolean; 20 | comment: string; 21 | externalMailLocale: string; 22 | creationDate: number; 23 | modificationDate: number; 24 | expirationDate?: number; 25 | secondFAUuid: string; 26 | secondFAEnabled: boolean; 27 | quotaUuid: string; 28 | author: { 29 | uuid: string; 30 | email: string; 31 | name: string; 32 | }; 33 | domain: { 34 | name: string; 35 | uuid: string; 36 | label?: string; 37 | }; 38 | accountType: 'INTERNAL' | 'GUEST' | 'TECHNICAL_ACCOUNT' | 'THREAD' | 'ROOT' | 'SYSTEM'; 39 | role: ACCOUNT_ROLE; 40 | restricted: boolean; 41 | authWithOIDC: boolean; 42 | name?: string; 43 | } 44 | -------------------------------------------------------------------------------- /src/modules/user/types/UserQuota.ts: -------------------------------------------------------------------------------- 1 | import User from './User'; 2 | 3 | export default interface UserQuota { 4 | account: Partial; 5 | creationDate: number; 6 | defaultMaxFileSize: number; 7 | defaultQuota: number; 8 | maintenance: boolean; 9 | maxFileSize: number; 10 | modificationDate: number; 11 | realTimeUsedSpace: number; 12 | quota: number; 13 | uuid: string; 14 | usedSpace: number; 15 | yersterdayUsedSpace: number; 16 | } 17 | -------------------------------------------------------------------------------- /src/modules/user/types/UsersList.ts: -------------------------------------------------------------------------------- 1 | import Filters from '@/core/types/Filters'; 2 | import { SORT_ORDER } from '@/core/types/Sort'; 3 | 4 | export interface UsersListFilters extends Filters { 5 | domain?: string; 6 | firstName?: string; 7 | lastName?: string; 8 | mail?: string; 9 | role?: string; 10 | type?: string; 11 | restricted?: boolean; 12 | canCreateGuest?: boolean; 13 | canUpload?: boolean; 14 | } 15 | 16 | export interface UsersListParameters { 17 | domain?: string; 18 | firstName?: string; 19 | lastName?: string; 20 | mail?: string; 21 | role?: string; 22 | type?: string; 23 | restricted?: boolean; 24 | canCreateGuest?: boolean; 25 | canUpload?: boolean; 26 | page?: number; 27 | size?: number; 28 | sortOrder?: SORT_ORDER; 29 | sortField?: string; 30 | } 31 | 32 | export interface ModeratorsListParameters { 33 | pattern?: string; 34 | accountType?: string; 35 | domain?: string; 36 | } 37 | -------------------------------------------------------------------------------- /src/router.d.ts: -------------------------------------------------------------------------------- 1 | import 'vue-router'; 2 | 3 | declare module 'vue-router' { 4 | interface RouteMeta { 5 | requiresAuth?: boolean; 6 | uiBeta?: boolean; // Use a different background color 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/shims-vue.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*.vue' { 2 | import type { DefineComponent } from 'vue'; 3 | const component: DefineComponent<{}, {}, any>; // eslint-disable-line 4 | export default component; 5 | } 6 | -------------------------------------------------------------------------------- /src/window.d.ts: -------------------------------------------------------------------------------- 1 | import AppConfiguration from './core/types/AppConfiguration'; 2 | 3 | declare global { 4 | interface Window { 5 | APP_CONFIGURATION: AppConfiguration; 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "esnext", 4 | "module": "esnext", 5 | "strict": true, 6 | "jsx": "preserve", 7 | "importHelpers": true, 8 | "moduleResolution": "node", 9 | "skipLibCheck": true, 10 | "esModuleInterop": true, 11 | "allowSyntheticDefaultImports": true, 12 | "resolveJsonModule": true, 13 | "sourceMap": true, 14 | "baseUrl": ".", 15 | "paths": { 16 | "@/*": [ 17 | "src/*" 18 | ] 19 | }, 20 | "lib": [ 21 | "esnext", 22 | "dom", 23 | "dom.iterable", 24 | "scripthost" 25 | ] 26 | }, 27 | "include": [ 28 | "src/**/*.ts", 29 | "src/**/*.tsx", 30 | "src/**/*.vue", 31 | "tests/**/*.ts", 32 | "tests/**/*.tsx" 33 | ], 34 | "exclude": [ 35 | "node_modules" 36 | ] 37 | } 38 | -------------------------------------------------------------------------------- /vite.config.js: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite'; 2 | import vue from '@vitejs/plugin-vue'; 3 | import path from 'path'; 4 | 5 | export default defineConfig({ 6 | plugins: [vue()], 7 | base: './', 8 | resolve: { 9 | alias: [ 10 | { find: '@', replacement: path.resolve(__dirname, 'src') }, 11 | { find: /^~/, replacement: '' }, 12 | ], 13 | }, 14 | css: { 15 | preprocessorOptions: { 16 | less: { 17 | additionalData: '@import "@/core/styles/variables.less";', 18 | javascriptEnabled: true, 19 | }, 20 | }, 21 | }, 22 | server: { 23 | port: 20082, 24 | proxy: { 25 | '^/linshare': { 26 | target: process.env.BACKEND_API_URL || 'http://localhost:28080', 27 | changeOrigin: true, 28 | secure: false, 29 | }, 30 | }, 31 | }, 32 | }); 33 | --------------------------------------------------------------------------------