mirror of
https://github.com/hcengineering/platform.git
synced 2026-08-17 18:05:42 +02:00
feat: Anonymous guest permissions (#10726)
* Anonymous guest permissions Signed-off-by: Artem Savchenko <armisav@gmail.com> * Fix channels dropdown Signed-off-by: Artem Savchenko <armisav@gmail.com> * Update guest layout Signed-off-by: Artem Savchenko <armisav@gmail.com> --------- Signed-off-by: Artem Savchenko <armisav@gmail.com>
This commit is contained in:
@@ -310,7 +310,7 @@ services:
|
||||
- PAYMENT_URL=http://huly.local:3040
|
||||
- COMMUNICATION_API_ENABLED=true
|
||||
- BACKUP_URL=http://huly.local:4039/api/backup,
|
||||
- EXCLUDED_APPLICATIONS_FOR_ANONYMOUS=["chunter", "notification"]
|
||||
- EXCLUDED_APPLICATIONS_FOR_ANONYMOUS=[]
|
||||
# - DISABLE_SIGNUP=true
|
||||
- OTEL_EXPORTER_OTLP_ENDPOINT=http://jaeger:4318/v1/traces
|
||||
- PULSE_URL=ws://huly.local:8099/ws
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
"BACKUP_URL": "http://huly.local:4039/api/backup",
|
||||
"PULSE_URL": "ws://huly.local:8099/ws",
|
||||
"HULYLAKE_URL": "http://huly.local:8096",
|
||||
"EXCLUDED_APPLICATIONS_FOR_ANONYMOUS": "[\"chunter\", \"notification\"]",
|
||||
"EXCLUDED_APPLICATIONS_FOR_ANONYMOUS": "[]",
|
||||
"ANALYTICS_COLLECTOR_URL": "http://huly.local:4017",
|
||||
"LINK_PREVIEW_URL": "http://huly.local:4041"
|
||||
}
|
||||
|
||||
@@ -947,6 +947,20 @@ export function createModel (builder: Builder): void {
|
||||
card.ids.ModulePermissionGroup
|
||||
)
|
||||
|
||||
builder.createDoc(
|
||||
core.class.ModulePermissionGroup,
|
||||
core.space.Model,
|
||||
{
|
||||
application: card.app.Card,
|
||||
role: AccountRole.ReadOnlyGuest,
|
||||
permissions: [],
|
||||
spaceClass: card.class.CardSpace,
|
||||
enabled: false,
|
||||
order: 20
|
||||
},
|
||||
card.ids.ModulePermissionGroupReadOnlyGuest
|
||||
)
|
||||
|
||||
builder.mixin(card.class.Card, core.class.Class, view.mixin.ClassFilters, {
|
||||
filters: ['space'],
|
||||
ignoreKeys: ['parent']
|
||||
|
||||
@@ -83,6 +83,20 @@ export function createModel (builder: Builder): void {
|
||||
chunter.ids.ModulePermissionGroup
|
||||
)
|
||||
|
||||
builder.createDoc(
|
||||
core.class.ModulePermissionGroup,
|
||||
core.space.Model,
|
||||
{
|
||||
application: chunter.app.Chunter,
|
||||
role: AccountRole.ReadOnlyGuest,
|
||||
permissions: [],
|
||||
spaceClass: chunter.class.ChunterSpace,
|
||||
enabled: true,
|
||||
order: 15
|
||||
},
|
||||
chunter.ids.ModulePermissionGroupReadOnlyGuest
|
||||
)
|
||||
|
||||
builder.createDoc(
|
||||
workbench.class.Widget,
|
||||
core.space.Model,
|
||||
|
||||
@@ -95,7 +95,8 @@ export default mergeIds(chunterId, chunter, {
|
||||
},
|
||||
ids: {
|
||||
ChunterNotificationGroup: '' as Ref<NotificationGroup>,
|
||||
ModulePermissionGroup: '' as Ref<Doc>
|
||||
ModulePermissionGroup: '' as Ref<Doc>,
|
||||
ModulePermissionGroupReadOnlyGuest: '' as Ref<Doc>
|
||||
},
|
||||
space: {
|
||||
General: '' as Ref<Channel>,
|
||||
|
||||
@@ -1124,6 +1124,20 @@ export function createModel (builder: Builder): void {
|
||||
},
|
||||
documents.ids.ModulePermissionGroup
|
||||
)
|
||||
|
||||
builder.createDoc(
|
||||
core.class.ModulePermissionGroup,
|
||||
core.space.Model,
|
||||
{
|
||||
application: documents.app.Documents,
|
||||
role: AccountRole.ReadOnlyGuest,
|
||||
permissions: [],
|
||||
spaceClass: documents.class.OrgSpace,
|
||||
enabled: false,
|
||||
order: 42
|
||||
},
|
||||
documents.ids.ModulePermissionGroupReadOnlyGuest
|
||||
)
|
||||
definePermissions(builder)
|
||||
defineNotifications(builder)
|
||||
defineSearch(builder)
|
||||
|
||||
@@ -93,6 +93,7 @@ export default mergeIds(documentsId, documents, {
|
||||
StateNotification: '' as Ref<NotificationType>
|
||||
},
|
||||
ids: {
|
||||
ModulePermissionGroup: '' as Ref<Doc>
|
||||
ModulePermissionGroup: '' as Ref<Doc>,
|
||||
ModulePermissionGroupReadOnlyGuest: '' as Ref<Doc>
|
||||
}
|
||||
})
|
||||
|
||||
@@ -553,6 +553,20 @@ export function createModel (builder: Builder): void {
|
||||
},
|
||||
document.ids.ModulePermissionGroup
|
||||
)
|
||||
|
||||
builder.createDoc(
|
||||
core.class.ModulePermissionGroup,
|
||||
core.space.Model,
|
||||
{
|
||||
application: document.app.Documents,
|
||||
role: AccountRole.ReadOnlyGuest,
|
||||
permissions: [],
|
||||
spaceClass: document.class.Teamspace,
|
||||
enabled: false,
|
||||
order: 40
|
||||
},
|
||||
document.ids.ModulePermissionGroupReadOnlyGuest
|
||||
)
|
||||
definePermissions(builder)
|
||||
|
||||
builder.createDoc(core.class.DomainIndexConfiguration, core.space.Model, {
|
||||
|
||||
@@ -62,7 +62,8 @@ export default mergeIds(documentId, document, {
|
||||
Other: '' as Ref<TagCategory>
|
||||
},
|
||||
ids: {
|
||||
ModulePermissionGroup: '' as Ref<Doc>
|
||||
ModulePermissionGroup: '' as Ref<Doc>,
|
||||
ModulePermissionGroupReadOnlyGuest: '' as Ref<Doc>
|
||||
},
|
||||
string: {
|
||||
ConfigDescription: '' as IntlString,
|
||||
|
||||
@@ -855,5 +855,19 @@ export function createModel (builder: Builder): void {
|
||||
},
|
||||
drive.ids.ModulePermissionGroup
|
||||
)
|
||||
|
||||
builder.createDoc(
|
||||
core.class.ModulePermissionGroup,
|
||||
core.space.Model,
|
||||
{
|
||||
application: drive.app.Drive,
|
||||
role: AccountRole.ReadOnlyGuest,
|
||||
permissions: [],
|
||||
spaceClass: drive.class.Drive,
|
||||
enabled: false,
|
||||
order: 60
|
||||
},
|
||||
drive.ids.ModulePermissionGroupReadOnlyGuest
|
||||
)
|
||||
definePermissions(builder)
|
||||
}
|
||||
|
||||
@@ -102,7 +102,8 @@ export default mergeIds(driveId, drive, {
|
||||
RestoreFileVersion: '' as ViewAction
|
||||
},
|
||||
ids: {
|
||||
ModulePermissionGroup: '' as Ref<Doc>
|
||||
ModulePermissionGroup: '' as Ref<Doc>,
|
||||
ModulePermissionGroupReadOnlyGuest: '' as Ref<Doc>
|
||||
},
|
||||
string: {
|
||||
Grid: '' as IntlString,
|
||||
|
||||
@@ -280,6 +280,20 @@ export function createModel (builder: Builder): void {
|
||||
love.ids.ModulePermissionGroup
|
||||
)
|
||||
|
||||
builder.createDoc(
|
||||
core.class.ModulePermissionGroup,
|
||||
core.space.Model,
|
||||
{
|
||||
application: love.app.Love,
|
||||
role: AccountRole.ReadOnlyGuest,
|
||||
permissions: [],
|
||||
spaceClass: love.class.Office,
|
||||
enabled: false,
|
||||
order: 50
|
||||
},
|
||||
love.ids.ModulePermissionGroupReadOnlyGuest
|
||||
)
|
||||
|
||||
builder.createDoc(
|
||||
workbench.class.Widget,
|
||||
core.space.Model,
|
||||
|
||||
@@ -51,7 +51,8 @@ export default mergeIds(loveId, love, {
|
||||
Settings: '' as Ref<Doc>,
|
||||
LoveNotificationGroup: '' as Ref<NotificationGroup>,
|
||||
MeetingMinutesChatNotification: '' as Ref<NotificationType>,
|
||||
ModulePermissionGroup: '' as Ref<Doc>
|
||||
ModulePermissionGroup: '' as Ref<Doc>,
|
||||
ModulePermissionGroupReadOnlyGuest: '' as Ref<Doc>
|
||||
},
|
||||
function: {
|
||||
MeetingMinutesTitleProvider: '' as Resource<(client: Client, ref: Ref<Doc>, doc?: Doc) => Promise<string>>
|
||||
|
||||
@@ -216,6 +216,20 @@ export function createModel (builder: Builder): void {
|
||||
testManagement.ids.ModulePermissionGroup
|
||||
)
|
||||
|
||||
builder.createDoc(
|
||||
core.class.ModulePermissionGroup,
|
||||
core.space.Model,
|
||||
{
|
||||
application: testManagement.app.TestManagement,
|
||||
role: AccountRole.ReadOnlyGuest,
|
||||
permissions: [],
|
||||
spaceClass: testManagement.class.TestProject,
|
||||
enabled: false,
|
||||
order: 70
|
||||
},
|
||||
testManagement.ids.ModulePermissionGroupReadOnlyGuest
|
||||
)
|
||||
|
||||
builder.mixin(testManagement.class.TestCase, core.class.Class, view.mixin.ObjectIcon, {
|
||||
component: testManagement.component.TestCaseStatusPresenter
|
||||
})
|
||||
|
||||
@@ -50,6 +50,7 @@ export default mergeIds(testManagementId, testManganement, {
|
||||
RunTestPlanButton: '' as AnyComponent
|
||||
},
|
||||
ids: {
|
||||
ModulePermissionGroup: '' as Ref<Doc>
|
||||
ModulePermissionGroup: '' as Ref<Doc>,
|
||||
ModulePermissionGroupReadOnlyGuest: '' as Ref<Doc>
|
||||
}
|
||||
})
|
||||
|
||||
@@ -682,6 +682,20 @@ export function createModel (builder: Builder): void {
|
||||
tracker.ids.ModulePermissionGroup
|
||||
)
|
||||
|
||||
builder.createDoc(
|
||||
core.class.ModulePermissionGroup,
|
||||
core.space.Model,
|
||||
{
|
||||
application: tracker.app.Tracker,
|
||||
role: AccountRole.ReadOnlyGuest,
|
||||
permissions: [],
|
||||
spaceClass: tracker.class.Project,
|
||||
enabled: true,
|
||||
order: 10
|
||||
},
|
||||
tracker.ids.ModulePermissionGroupReadOnlyGuest
|
||||
)
|
||||
|
||||
builder.createDoc(
|
||||
chunter.class.ChatMessageViewlet,
|
||||
core.space.Model,
|
||||
|
||||
@@ -82,6 +82,7 @@ export default mergeIds(trackerId, tracker, {
|
||||
BaseProjectType: '' as Ref<ProjectType>,
|
||||
GuestIssueClassPermission: '' as Ref<Doc>,
|
||||
ModulePermissionGroup: '' as Ref<Doc>,
|
||||
ModulePermissionGroupReadOnlyGuest: '' as Ref<Doc>,
|
||||
IssueUpdatedActivityViewlet: '' as Ref<DocUpdateMessageViewlet>,
|
||||
IssueCreatedActivityViewlet: '' as Ref<DocUpdateMessageViewlet>,
|
||||
IssueRemovedActivityViewlet: '' as Ref<DocUpdateMessageViewlet>,
|
||||
|
||||
@@ -923,6 +923,20 @@ function defineSettings (builder: Builder): void {
|
||||
},
|
||||
training.ids.ModulePermissionGroup
|
||||
)
|
||||
|
||||
builder.createDoc(
|
||||
core.class.ModulePermissionGroup,
|
||||
core.space.Model,
|
||||
{
|
||||
application: training.app.Training,
|
||||
role: AccountRole.ReadOnlyGuest,
|
||||
permissions: [],
|
||||
spaceClass: core.class.TypedSpace,
|
||||
enabled: false,
|
||||
order: 25
|
||||
},
|
||||
training.ids.ModulePermissionGroupReadOnlyGuest
|
||||
)
|
||||
}
|
||||
|
||||
const columns = {
|
||||
|
||||
@@ -35,7 +35,8 @@ export default mergeIds(trainingId, training, {
|
||||
},
|
||||
ids: {
|
||||
GuestTrainingAttemptClassPermission: '' as Ref<Doc>,
|
||||
ModulePermissionGroup: '' as Ref<Doc>
|
||||
ModulePermissionGroup: '' as Ref<Doc>,
|
||||
ModulePermissionGroupReadOnlyGuest: '' as Ref<Doc>
|
||||
},
|
||||
|
||||
// TODO: Move function resources declarations to plugins/*-resources
|
||||
|
||||
@@ -80,10 +80,11 @@
|
||||
background-color: var(--global-accent-BackgroundColor);
|
||||
|
||||
.icon {
|
||||
color: var(--global-on-nuance-TextColor);
|
||||
color: var(--global-on-accent-TextColor);
|
||||
}
|
||||
span {
|
||||
color: var(--global-on-nuance-TextColor);
|
||||
color: var(--global-on-accent-TextColor);
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
&:checked + .switcher-element.subtle {
|
||||
|
||||
@@ -226,7 +226,8 @@ const cardPlugin = plugin(cardId, {
|
||||
ids: {
|
||||
CardWidget: '' as Ref<Doc>,
|
||||
GuestCardClassPermission: '' as Ref<Doc>,
|
||||
ModulePermissionGroup: '' as Ref<Doc>
|
||||
ModulePermissionGroup: '' as Ref<Doc>,
|
||||
ModulePermissionGroupReadOnlyGuest: '' as Ref<Doc>
|
||||
},
|
||||
component: {
|
||||
LabelsPresenter: '' as AnyComponent,
|
||||
|
||||
@@ -212,9 +212,12 @@
|
||||
"OfficeDefaultSettings": "Výchozí nastavení pro jednací místnosti",
|
||||
"DefaultStartWithTranscription": "Povolit přepis v nových kancelářích",
|
||||
"DefaultStartWithRecording": "Povolit záznam v nových kancelářích",
|
||||
"GuestPermissionsSettings": "Oprávnění hostů",
|
||||
"GuestPermissionsModulePermissions": "Oprávnění modulů",
|
||||
"GuestPermissionsModulePermissionsHint": "Vyberte, které moduly mohou hosté používat, a níže upravte oprávnění pro jednotlivé aplikace.",
|
||||
"GuestPermissionsSettings": "Hosté",
|
||||
"GuestPermissionsApplicationPermissions": "Oprávnění aplikací",
|
||||
"GuestPermissionsApplicationPermissionsHint": "Vyberte, které aplikace mohou hosté používat, a níže upravte oprávnění pro jednotlivé aplikace.",
|
||||
"GuestPermissionsTabGuest": "Host",
|
||||
"GuestPermissionsTabAnonymousGuest": "Anonymní host",
|
||||
"GuestPermissionsAnonymousApplicationHint": "Přístup k aplikacím pro anonymní (pouze pro čtení) hosty. Které aplikace uvidí, může záviset i na konfiguraci nasazení.",
|
||||
"ImportDocumentPermission": "Importovat dokumenty",
|
||||
"ImportDocumentDescription": "Umožňuje uživatelům importovat dokumenty do pracovního prostoru",
|
||||
"SelectUsers": "Vybrat uživatele",
|
||||
|
||||
@@ -214,9 +214,12 @@
|
||||
"OfficeDefaultSettings": "Standardeinstellungen für Besprechungsräume",
|
||||
"DefaultStartWithTranscription": "Transkription in neuen Büroräumen aktivieren",
|
||||
"DefaultStartWithRecording": "Aufnahme in neuen Büroräumen aktivieren",
|
||||
"GuestPermissionsSettings": "Gastberechtigungen",
|
||||
"GuestPermissionsModulePermissions": "Modulberechtigungen",
|
||||
"GuestPermissionsModulePermissionsHint": "Wählen Sie, welche Module Gäste nutzen dürfen, und passen Sie unten die Berechtigungen für jede App an.",
|
||||
"GuestPermissionsSettings": "Gäste",
|
||||
"GuestPermissionsApplicationPermissions": "Anwendungsberechtigungen",
|
||||
"GuestPermissionsApplicationPermissionsHint": "Wählen Sie, welche Anwendungen Gäste nutzen dürfen, und passen Sie unten die Berechtigungen für jede Anwendung an.",
|
||||
"GuestPermissionsTabGuest": "Gast",
|
||||
"GuestPermissionsTabAnonymousGuest": "Anonymer Gast",
|
||||
"GuestPermissionsAnonymousApplicationHint": "Anwendungszugriff für anonyme (nur lesende) Gäste. Welche Anwendungen sie sehen, kann auch von der Bereitstellungskonfiguration abhängen.",
|
||||
"ImportDocumentPermission": "Dokumente importieren",
|
||||
"ImportDocumentDescription": "Gewährt Benutzern die Möglichkeit, Dokumente in den Arbeitsbereich zu importieren",
|
||||
"SelectUsers": "Benutzer auswählen",
|
||||
|
||||
@@ -215,9 +215,12 @@
|
||||
"OfficeDefaultSettings": "Default settings for meeting rooms",
|
||||
"DefaultStartWithTranscription": "Enable transcription in new office rooms",
|
||||
"DefaultStartWithRecording": "Enable recording in new office rooms",
|
||||
"GuestPermissionsSettings": "Guest permissions",
|
||||
"GuestPermissionsModulePermissions": "Module permissions",
|
||||
"GuestPermissionsModulePermissionsHint": "Choose which modules guests can use, then adjust permissions for each app below.",
|
||||
"GuestPermissionsSettings": "Guests",
|
||||
"GuestPermissionsApplicationPermissions": "Application permissions",
|
||||
"GuestPermissionsApplicationPermissionsHint": "Choose which applications guests can use, then adjust permissions for each application below.",
|
||||
"GuestPermissionsTabGuest": "Guest",
|
||||
"GuestPermissionsTabAnonymousGuest": "Anonymous guest",
|
||||
"GuestPermissionsAnonymousApplicationHint": "Application access for anonymous (read-only) guests. Which applications they see can also depend on deployment configuration.",
|
||||
"ImportDocumentPermission": "Import documents",
|
||||
"ImportDocumentDescription": "Grants users ability to import documents into the workspace",
|
||||
"SelectUsers": "Select users",
|
||||
|
||||
@@ -205,9 +205,12 @@
|
||||
"OfficeDefaultSettings": "Configuración predeterminada para salas de reuniones",
|
||||
"DefaultStartWithTranscription": "Habilitar transcripción en nuevas oficinas",
|
||||
"DefaultStartWithRecording": "Habilitar grabación en nuevas oficinas",
|
||||
"GuestPermissionsSettings": "Permisos de invitados",
|
||||
"GuestPermissionsModulePermissions": "Permisos de módulos",
|
||||
"GuestPermissionsModulePermissionsHint": "Elija qué módulos pueden usar los invitados y luego ajuste los permisos de cada aplicación a continuación.",
|
||||
"GuestPermissionsSettings": "Invitados",
|
||||
"GuestPermissionsApplicationPermissions": "Permisos de aplicaciones",
|
||||
"GuestPermissionsApplicationPermissionsHint": "Elija qué aplicaciones pueden usar los invitados y luego ajuste los permisos de cada aplicación a continuación.",
|
||||
"GuestPermissionsTabGuest": "Invitado",
|
||||
"GuestPermissionsTabAnonymousGuest": "Invitado anónimo",
|
||||
"GuestPermissionsAnonymousApplicationHint": "Acceso a aplicaciones para invitados anónimos (solo lectura). Las aplicaciones que ven también pueden depender de la configuración de despliegue.",
|
||||
"ImportDocumentPermission": "Importar documentos",
|
||||
"ImportDocumentDescription": "Otorga a los usuarios la capacidad de importar documentos al espacio de trabajo",
|
||||
"SelectUsers": "Seleccionar usuarios",
|
||||
|
||||
@@ -214,9 +214,12 @@
|
||||
"OfficeDefaultSettings": "Paramètres par défaut pour les salles de réunion",
|
||||
"DefaultStartWithTranscription": "Activer la transcription dans les nouveaux bureaux",
|
||||
"DefaultStartWithRecording": "Activer l'enregistrement dans les nouveaux bureaux",
|
||||
"GuestPermissionsSettings": "Permissions des invités",
|
||||
"GuestPermissionsModulePermissions": "Permissions des modules",
|
||||
"GuestPermissionsModulePermissionsHint": "Choisissez les modules accessibles aux invités, puis ajustez les permissions pour chaque application ci-dessous.",
|
||||
"GuestPermissionsSettings": "Invités",
|
||||
"GuestPermissionsApplicationPermissions": "Permissions des applications",
|
||||
"GuestPermissionsApplicationPermissionsHint": "Choisissez les applications accessibles aux invités, puis ajustez les permissions pour chaque application ci-dessous.",
|
||||
"GuestPermissionsTabGuest": "Invité",
|
||||
"GuestPermissionsTabAnonymousGuest": "Invité anonyme",
|
||||
"GuestPermissionsAnonymousApplicationHint": "Accès aux applications pour les invités anonymes (lecture seule). Les applications visibles peuvent aussi dépendre de la configuration de déploiement.",
|
||||
"ImportDocumentPermission": "Importer des documents",
|
||||
"ImportDocumentDescription": "Accorde aux utilisateurs la possibilité d'importer des documents dans l'espace de travail",
|
||||
"SelectUsers": "Sélectionner des utilisateurs",
|
||||
|
||||
@@ -214,9 +214,12 @@
|
||||
"OfficeDefaultSettings": "Impostazioni predefinite per le sale riunioni",
|
||||
"DefaultStartWithTranscription": "Abilita trascrizione nelle nuove stanze dell'ufficio",
|
||||
"DefaultStartWithRecording": "Abilita registrazione nelle nuove stanze dell'ufficio",
|
||||
"GuestPermissionsSettings": "Permessi ospite",
|
||||
"GuestPermissionsModulePermissions": "Permessi dei moduli",
|
||||
"GuestPermissionsModulePermissionsHint": "Scegli quali moduli possono usare gli ospiti, poi regola i permessi per ogni app qui sotto.",
|
||||
"GuestPermissionsSettings": "Ospiti",
|
||||
"GuestPermissionsApplicationPermissions": "Permessi delle applicazioni",
|
||||
"GuestPermissionsApplicationPermissionsHint": "Scegli quali applicazioni possono usare gli ospiti, poi regola i permessi per ogni applicazione qui sotto.",
|
||||
"GuestPermissionsTabGuest": "Ospite",
|
||||
"GuestPermissionsTabAnonymousGuest": "Ospite anonimo",
|
||||
"GuestPermissionsAnonymousApplicationHint": "Accesso alle applicazioni per ospiti anonimi (sola lettura). Le applicazioni visibili possono dipendere anche dalla configurazione di distribuzione.",
|
||||
"ImportDocumentPermission": "Importa documenti",
|
||||
"ImportDocumentDescription": "Concede agli utenti la possibilità di importare documenti nell'area di lavoro",
|
||||
"SelectUsers": "Seleziona utenti",
|
||||
|
||||
@@ -214,9 +214,12 @@
|
||||
"OfficeDefaultSettings": "会議室のデフォルト設定",
|
||||
"DefaultStartWithTranscription": "新しいオフィスルームで文字起こしを有効にする",
|
||||
"DefaultStartWithRecording": "新しいオフィスルームで録画を有効にする",
|
||||
"GuestPermissionsSettings": "ゲストの権限",
|
||||
"GuestPermissionsModulePermissions": "モジュールの権限",
|
||||
"GuestPermissionsModulePermissionsHint": "ゲストが利用できるモジュールを選び、その下で各アプリの権限を調整します。",
|
||||
"GuestPermissionsSettings": "ゲスト",
|
||||
"GuestPermissionsApplicationPermissions": "アプリケーションの権限",
|
||||
"GuestPermissionsApplicationPermissionsHint": "ゲストが利用できるアプリケーションを選び、その下で各アプリケーションの権限を調整します。",
|
||||
"GuestPermissionsTabGuest": "ゲスト",
|
||||
"GuestPermissionsTabAnonymousGuest": "匿名ゲスト",
|
||||
"GuestPermissionsAnonymousApplicationHint": "匿名(読み取り専用)ゲストのアプリケーションアクセス。表示されるアプリケーションはデプロイ設定にも依存する場合があります。",
|
||||
"ImportDocumentPermission": "ドキュメントをインポート",
|
||||
"ImportDocumentDescription": "ユーザーにワークスペースにドキュメントをインポートする機能を付与します",
|
||||
"SelectUsers": "ユーザーを選択",
|
||||
|
||||
@@ -205,9 +205,12 @@
|
||||
"OfficeDefaultSettings": "Configurações padrão para salas de reunião",
|
||||
"DefaultStartWithTranscription": "Habilitar transcrição em novos escritórios",
|
||||
"DefaultStartWithRecording": "Habilitar gravação em novos escritórios",
|
||||
"GuestPermissionsSettings": "Permissões de convidados",
|
||||
"GuestPermissionsModulePermissions": "Permissões de módulos",
|
||||
"GuestPermissionsModulePermissionsHint": "Escolha quais módulos os convidados podem usar e, em seguida, ajuste as permissões de cada aplicativo abaixo.",
|
||||
"GuestPermissionsSettings": "Convidados",
|
||||
"GuestPermissionsApplicationPermissions": "Permissões de aplicativos",
|
||||
"GuestPermissionsApplicationPermissionsHint": "Escolha quais aplicativos os convidados podem usar e, em seguida, ajuste as permissões de cada aplicativo abaixo.",
|
||||
"GuestPermissionsTabGuest": "Convidado",
|
||||
"GuestPermissionsTabAnonymousGuest": "Convidado anônimo",
|
||||
"GuestPermissionsAnonymousApplicationHint": "Acesso a aplicativos para convidados anônimos (somente leitura). Os aplicativos visíveis também podem depender da configuração de implantação.",
|
||||
"ImportDocumentPermission": "Importar documentos",
|
||||
"ImportDocumentDescription": "Concede aos usuários a capacidade de importar documentos para o espaço de trabalho",
|
||||
"SelectUsers": "Selecionar usuários",
|
||||
|
||||
@@ -205,9 +205,12 @@
|
||||
"OfficeDefaultSettings": "Configurações padrão para salas de reunião",
|
||||
"DefaultStartWithTranscription": "Habilitar transcrição em novos escritórios",
|
||||
"DefaultStartWithRecording": "Habilitar gravação em novos escritórios",
|
||||
"GuestPermissionsSettings": "Permissões de convidados",
|
||||
"GuestPermissionsModulePermissions": "Permissões de módulos",
|
||||
"GuestPermissionsModulePermissionsHint": "Escolha quais módulos os convidados podem usar e, em seguida, ajuste as permissões de cada aplicação abaixo.",
|
||||
"GuestPermissionsSettings": "Convidados",
|
||||
"GuestPermissionsApplicationPermissions": "Permissões de aplicações",
|
||||
"GuestPermissionsApplicationPermissionsHint": "Escolha quais aplicações os convidados podem usar e, em seguida, ajuste as permissões de cada aplicação abaixo.",
|
||||
"GuestPermissionsTabGuest": "Convidado",
|
||||
"GuestPermissionsTabAnonymousGuest": "Convidado anónimo",
|
||||
"GuestPermissionsAnonymousApplicationHint": "Acesso a aplicações para convidados anónimos (só leitura). As aplicações visíveis também podem depender da configuração de implementação.",
|
||||
"ImportDocumentPermission": "Importar documentos",
|
||||
"ImportDocumentDescription": "Concede aos usuários a capacidade de importar documentos para o espaço de trabalho",
|
||||
"SelectUsers": "Selecionar usuários",
|
||||
|
||||
@@ -215,9 +215,12 @@
|
||||
"OfficeDefaultSettings": "Настройки по умолчанию для переговорных",
|
||||
"DefaultStartWithTranscription": "Включить транскрипцию в новых комнатах",
|
||||
"DefaultStartWithRecording": "Включить запись в новых комнатах",
|
||||
"GuestPermissionsSettings": "Права гостей",
|
||||
"GuestPermissionsModulePermissions": "Права модулей",
|
||||
"GuestPermissionsModulePermissionsHint": "Выберите, какие модули доступны гостям, затем настройте права для каждого приложения ниже.",
|
||||
"GuestPermissionsSettings": "Гости",
|
||||
"GuestPermissionsApplicationPermissions": "Права приложений",
|
||||
"GuestPermissionsApplicationPermissionsHint": "Выберите, какие приложения доступны гостям, затем настройте права для каждого приложения ниже.",
|
||||
"GuestPermissionsTabGuest": "Гость",
|
||||
"GuestPermissionsTabAnonymousGuest": "Анонимный гость",
|
||||
"GuestPermissionsAnonymousApplicationHint": "Доступ к приложениям для анонимных гостей (только чтение). Видимые приложения также могут зависеть от конфигурации развёртывания.",
|
||||
"ImportDocumentPermission": "Импорт документов",
|
||||
"ImportDocumentDescription": "Предоставляет пользователям возможность импортировать документы в рабочее пространство",
|
||||
"SelectUsers": "Выбрать пользователей",
|
||||
|
||||
@@ -214,9 +214,12 @@
|
||||
"OfficeDefaultSettings": "Toplantı odaları için varsayılan ayarlar",
|
||||
"DefaultStartWithTranscription": "Yeni ofis odalarında transkripsiyonu etkinleştir",
|
||||
"DefaultStartWithRecording": "Yeni ofis odalarında kaydı etkinleştir",
|
||||
"GuestPermissionsSettings": "Misafir izinleri",
|
||||
"GuestPermissionsModulePermissions": "Modül izinleri",
|
||||
"GuestPermissionsModulePermissionsHint": "Misafirlerin hangi modülleri kullanabileceğini seçin, ardından her uygulama için izinleri aşağıdan ayarlayın.",
|
||||
"GuestPermissionsSettings": "Misafirler",
|
||||
"GuestPermissionsApplicationPermissions": "Uygulama izinleri",
|
||||
"GuestPermissionsApplicationPermissionsHint": "Misafirlerin hangi uygulamaları kullanabileceğini seçin, ardından her uygulama için izinleri aşağıdan ayarlayın.",
|
||||
"GuestPermissionsTabGuest": "Misafir",
|
||||
"GuestPermissionsTabAnonymousGuest": "Anonim misafir",
|
||||
"GuestPermissionsAnonymousApplicationHint": "Anonim (salt okunur) misafirler için uygulama erişimi. Gördükleri uygulamalar da dağıtım yapılandırmasına bağlı olabilir.",
|
||||
"ImportDocumentPermission": "Belgeleri içe aktar",
|
||||
"ImportDocumentDescription": "Kullanıcılara çalışma alanına belge içe aktarma yeteneği verir",
|
||||
"SelectUsers": "Kullanıcıları seç",
|
||||
|
||||
@@ -214,9 +214,12 @@
|
||||
"OfficeDefaultSettings": "会议室的默认设置",
|
||||
"DefaultStartWithTranscription": "在新办公室启用转录",
|
||||
"DefaultStartWithRecording": "在新办公室启用录制",
|
||||
"GuestPermissionsSettings": "访客权限",
|
||||
"GuestPermissionsModulePermissions": "模块权限",
|
||||
"GuestPermissionsModulePermissionsHint": "选择访客可以使用哪些模块,然后在下方调整每个应用的权限。",
|
||||
"GuestPermissionsSettings": "访客",
|
||||
"GuestPermissionsApplicationPermissions": "应用权限",
|
||||
"GuestPermissionsApplicationPermissionsHint": "选择访客可以使用哪些应用,然后在下方调整每个应用的权限。",
|
||||
"GuestPermissionsTabGuest": "访客",
|
||||
"GuestPermissionsTabAnonymousGuest": "匿名访客",
|
||||
"GuestPermissionsAnonymousApplicationHint": "匿名(只读)访客的应用访问。他们可见的应用也可能取决于部署配置。",
|
||||
"ImportDocumentPermission": "导入文档",
|
||||
"ImportDocumentDescription": "授予用户将文档导入工作区的权限",
|
||||
"SelectUsers": "选择用户",
|
||||
|
||||
@@ -13,30 +13,16 @@
|
||||
// limitations under the License.
|
||||
-->
|
||||
<script lang="ts">
|
||||
import card, { Card } from '@hcengineering/card'
|
||||
import chat from '@hcengineering/chat'
|
||||
import communication, { GuestCommunicationSettings } from '@hcengineering/communication'
|
||||
import contact, { AvatarType, ensureEmployeeForPerson } from '@hcengineering/contact'
|
||||
import { AvatarType } from '@hcengineering/contact'
|
||||
import { EditableAvatar, getAccountClient } from '@hcengineering/contact-resources'
|
||||
import core, {
|
||||
type Account,
|
||||
AccountRole,
|
||||
AccountUuid,
|
||||
Configuration,
|
||||
getCurrentAccount,
|
||||
pickPrimarySocialId,
|
||||
readOnlyGuestAccountUuid,
|
||||
Ref,
|
||||
WorkspaceAccountPermission
|
||||
} from '@hcengineering/core'
|
||||
import core, { Configuration, WorkspaceAccountPermission } from '@hcengineering/core'
|
||||
import { loginId } from '@hcengineering/login'
|
||||
import { translateCB } from '@hcengineering/platform'
|
||||
import { createQuery, getClient, MessageBox, uiContext } from '@hcengineering/presentation'
|
||||
import { createQuery, getClient, MessageBox } from '@hcengineering/presentation'
|
||||
import { WorkspaceSetting } from '@hcengineering/setting'
|
||||
import {
|
||||
Breadcrumb,
|
||||
Button,
|
||||
Component,
|
||||
deviceOptionsStore as deviceInfo,
|
||||
DropdownLabels,
|
||||
type DropdownTextItem,
|
||||
@@ -65,8 +51,6 @@
|
||||
let oldName: string
|
||||
let name: string = ''
|
||||
let workspaceUrl = ''
|
||||
let allowReadOnlyGuests: boolean
|
||||
let allowGuestSignUp: boolean
|
||||
let passwordAgingRule: number | undefined = undefined
|
||||
|
||||
const accountClient = getAccountClient()
|
||||
@@ -87,8 +71,6 @@
|
||||
workspaceUrl = res.url
|
||||
oldName = res.name
|
||||
name = oldName
|
||||
allowReadOnlyGuests = res.allowReadOnlyGuest ?? false
|
||||
allowGuestSignUp = res.allowGuestSignUp ?? false
|
||||
passwordAgingRule = res.passwordAgingRule ?? undefined
|
||||
loading = false
|
||||
}
|
||||
@@ -166,40 +148,6 @@
|
||||
}
|
||||
)
|
||||
|
||||
async function handleToggleReadonlyAccess (e: CustomEvent<boolean>): Promise<void> {
|
||||
const enabled = e.detail
|
||||
const guestUserInfo = await accountClient.updateAllowReadOnlyGuests(enabled)
|
||||
allowReadOnlyGuests = enabled
|
||||
if (guestUserInfo !== undefined) {
|
||||
const guestAccount: Account = {
|
||||
uuid: guestUserInfo.guestPerson.uuid as AccountUuid,
|
||||
role: AccountRole.ReadOnlyGuest,
|
||||
primarySocialId: pickPrimarySocialId(guestUserInfo.guestSocialIds)._id,
|
||||
socialIds: guestUserInfo.guestSocialIds.map((si) => si._id),
|
||||
fullSocialIds: guestUserInfo.guestSocialIds
|
||||
}
|
||||
const myAccount = getCurrentAccount()
|
||||
const ctx = uiContext.newChild('connect', {})
|
||||
await ensureEmployeeForPerson(
|
||||
ctx,
|
||||
myAccount,
|
||||
guestAccount,
|
||||
client,
|
||||
guestUserInfo.guestSocialIds,
|
||||
guestUserInfo.guestPerson
|
||||
)
|
||||
} else {
|
||||
const readonlyEmployee = await client.findOne(contact.mixin.Employee, { personUuid: readOnlyGuestAccountUuid })
|
||||
if (readonlyEmployee !== undefined) {
|
||||
await client.update(readonlyEmployee, { active: false })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function handleToggleGuestSignUp (e: CustomEvent<boolean>): Promise<void> {
|
||||
await accountClient.updateAllowGuestSignUp(e.detail)
|
||||
}
|
||||
|
||||
async function changePasswordAgingRules (val: number | undefined): Promise<void> {
|
||||
passwordAgingRule = Math.max(val ?? 1, 1)
|
||||
await accountClient.updatePasswordAgingRule(passwordAgingRule)
|
||||
@@ -253,29 +201,6 @@
|
||||
}
|
||||
)
|
||||
|
||||
let existingGuestChatSettings: GuestCommunicationSettings | undefined = undefined
|
||||
const query = createQuery()
|
||||
|
||||
$: query.query(communication.class.GuestCommunicationSettings, {}, (settings) => {
|
||||
existingGuestChatSettings = settings[0]
|
||||
})
|
||||
|
||||
async function onAllowedCardsChange (value: Ref<Card>[]): Promise<void> {
|
||||
if (existingGuestChatSettings === undefined) {
|
||||
await client.createDoc(communication.class.GuestCommunicationSettings, core.space.Workspace, {
|
||||
allowedCards: value,
|
||||
enabled: true
|
||||
})
|
||||
} else {
|
||||
await client.updateDoc(
|
||||
communication.class.GuestCommunicationSettings,
|
||||
core.space.Workspace,
|
||||
existingGuestChatSettings._id,
|
||||
{ allowedCards: value, enabled: true }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const onSelected = (e: CustomEvent<string>): void => {
|
||||
selected = e.detail
|
||||
localStorage.setItem('firstDayOfWeek', `${e.detail}`)
|
||||
@@ -373,43 +298,6 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex-col flex-gap-4 mt-6">
|
||||
<div class="title"><Label label={settingsRes.string.GuestAccess} /></div>
|
||||
<div class="flex-row-center flex-gap-4">
|
||||
<Label label={settingsRes.string.GuestAccessDescription} />
|
||||
<Toggle
|
||||
on={allowReadOnlyGuests}
|
||||
on:change={(e) => {
|
||||
void handleToggleReadonlyAccess(e)
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="flex-row-center flex-gap-4">
|
||||
<Label label={settingsRes.string.GuestSignUpDescription} />
|
||||
<Toggle
|
||||
disabled={!allowReadOnlyGuests}
|
||||
on={allowGuestSignUp}
|
||||
on:change={(e) => {
|
||||
void handleToggleGuestSignUp(e)
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="flex-row-center flex-gap-4">
|
||||
<Label label={settingsRes.string.GuestChannelsDescription} />
|
||||
<Component
|
||||
is={card.component.CardArrayEditor}
|
||||
props={{
|
||||
_class: chat.masterTag.Thread,
|
||||
value: existingGuestChatSettings !== undefined ? existingGuestChatSettings.allowedCards : [],
|
||||
label: settingsRes.string.GuestChannelsArrayLabel,
|
||||
onChange: onAllowedCardsChange
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex-col flex-gap-4 mt-6">
|
||||
<div class="title"><Label label={settingsRes.string.AccessControl} /></div>
|
||||
<div class="w-32">
|
||||
|
||||
@@ -12,27 +12,89 @@
|
||||
// limitations under the License.
|
||||
-->
|
||||
<script lang="ts">
|
||||
import core, { ModulePermissionGroup, type Doc, type Permission, type Ref } from '@hcengineering/core'
|
||||
import card, { Card } from '@hcengineering/card'
|
||||
import chat from '@hcengineering/chat'
|
||||
import communication, { GuestCommunicationSettings } from '@hcengineering/communication'
|
||||
import contact, { ensureEmployeeForPerson } from '@hcengineering/contact'
|
||||
import { getAccountClient } from '@hcengineering/contact-resources'
|
||||
import core, {
|
||||
type Account,
|
||||
AccountRole,
|
||||
AccountUuid,
|
||||
ModulePermissionGroup,
|
||||
getCurrentAccount,
|
||||
pickPrimarySocialId,
|
||||
readOnlyGuestAccountUuid,
|
||||
type Doc,
|
||||
type Permission,
|
||||
type Ref
|
||||
} from '@hcengineering/core'
|
||||
import { getEmbeddedLabel, getMetadata, type IntlString } from '@hcengineering/platform'
|
||||
import { createQuery, getClient } from '@hcengineering/presentation'
|
||||
import { createQuery, getClient, uiContext } from '@hcengineering/presentation'
|
||||
import workbench, { type Application } from '@hcengineering/workbench'
|
||||
import { Breadcrumb, Header, Icon, Label, Loading, Scroller, Toggle } from '@hcengineering/ui'
|
||||
import {
|
||||
Breadcrumb,
|
||||
Component,
|
||||
defineSeparators,
|
||||
Header,
|
||||
Icon,
|
||||
Label,
|
||||
Loading,
|
||||
NavItem,
|
||||
Scroller,
|
||||
Separator,
|
||||
Toggle,
|
||||
twoPanelsSeparators
|
||||
} from '@hcengineering/ui'
|
||||
import setting from '@hcengineering/setting'
|
||||
import { onMount } from 'svelte'
|
||||
import settingsRes from '../plugin'
|
||||
|
||||
let loadingSettings = true
|
||||
let loadingPermissions = true
|
||||
let workspaceAppsReady = false
|
||||
let loadingWorkspaceGuest = true
|
||||
|
||||
let allowReadOnlyGuests = false
|
||||
let allowGuestSignUp = false
|
||||
let existingGuestChatSettings: GuestCommunicationSettings | undefined = undefined
|
||||
|
||||
const accountClient = getAccountClient()
|
||||
|
||||
let moduleGroups: ModulePermissionGroup[] = []
|
||||
let permissionsMap: Map<Ref<Permission>, Permission> = new Map<Ref<Permission>, Permission>()
|
||||
let hiddenApplicationIds: Array<Ref<Application>> = []
|
||||
|
||||
const excludedApplicationIds = getMetadata(workbench.metadata.ExcludedApplications) ?? []
|
||||
const communicationApiEnabled = getMetadata(communication.metadata.Enabled) === true
|
||||
|
||||
let guestPermissionsTab: 'guest' | 'anonymous' = 'guest'
|
||||
|
||||
const client = getClient()
|
||||
const moduleGroupsQuery = createQuery()
|
||||
const permissionsQuery = createQuery()
|
||||
const hiddenAppsQuery = createQuery()
|
||||
const guestCommunicationQuery = createQuery()
|
||||
|
||||
onMount(() => {
|
||||
void (async (): Promise<void> => {
|
||||
try {
|
||||
const res = await accountClient.getWorkspaceInfo()
|
||||
allowReadOnlyGuests = res.allowReadOnlyGuest ?? false
|
||||
allowGuestSignUp = res.allowGuestSignUp ?? false
|
||||
} finally {
|
||||
loadingWorkspaceGuest = false
|
||||
}
|
||||
})()
|
||||
})
|
||||
|
||||
$: {
|
||||
if (communicationApiEnabled) {
|
||||
guestCommunicationQuery.query(communication.class.GuestCommunicationSettings, {}, (settings) => {
|
||||
existingGuestChatSettings = settings[0]
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
$: moduleGroupsQuery.query(core.class.ModulePermissionGroup, {}, (res) => {
|
||||
moduleGroups = res as unknown as ModulePermissionGroup[]
|
||||
@@ -62,13 +124,20 @@
|
||||
workspaceApplications.map((application) => [application._id as Ref<Doc>, application])
|
||||
)
|
||||
|
||||
$: loading = loadingSettings || loadingPermissions || !workspaceAppsReady
|
||||
$: loading = loadingSettings || loadingPermissions || !workspaceAppsReady || loadingWorkspaceGuest
|
||||
|
||||
/** Ignore permission groups for applications not enabled in this workspace. */
|
||||
$: visibleModuleGroups = moduleGroups.filter((group) => applicationsMap.has(group.application))
|
||||
$: modulePermissionsRole = guestPermissionsTab === 'guest' ? AccountRole.Guest : AccountRole.ReadOnlyGuest
|
||||
|
||||
/** Module permission groups for the selected tab (Guest vs anonymous read-only). */
|
||||
$: visibleModuleGroups = moduleGroups.filter(
|
||||
(group) => applicationsMap.has(group.application) && group.role === modulePermissionsRole
|
||||
)
|
||||
|
||||
$: sortedVisibleModuleGroups = [...visibleModuleGroups].sort((a, b) => (a.order ?? Infinity) - (b.order ?? Infinity))
|
||||
|
||||
/** Anonymous (read-only guest) module rows are view-only until workspace allows anonymous guests. */
|
||||
$: anonymousModulePermissionsReadOnly = guestPermissionsTab === 'anonymous' && !allowReadOnlyGuests
|
||||
|
||||
function getApplicationLabel (applicationId: Ref<Doc>): IntlString {
|
||||
return applicationsMap.get(applicationId)?.label ?? getEmbeddedLabel(applicationId)
|
||||
}
|
||||
@@ -90,6 +159,7 @@
|
||||
permissionId: Ref<Permission>,
|
||||
enabled: boolean
|
||||
): Promise<void> {
|
||||
if (anonymousModulePermissionsReadOnly) return
|
||||
if (!isModuleEnabled(group)) return
|
||||
const disabled = getDisabledPermissions(group)
|
||||
if (enabled) {
|
||||
@@ -103,6 +173,7 @@
|
||||
}
|
||||
|
||||
async function toggleModule (group: ModulePermissionGroup, enabled: boolean): Promise<void> {
|
||||
if (anonymousModulePermissionsReadOnly) return
|
||||
await client.updateDoc(core.class.ModulePermissionGroup, core.space.Model, group._id, {
|
||||
enabled
|
||||
} as any)
|
||||
@@ -137,12 +208,89 @@
|
||||
onPermissionToggle(group, permissionId, ev)
|
||||
}
|
||||
}
|
||||
|
||||
async function handleToggleReadonlyAccess (e: CustomEvent<boolean>): Promise<void> {
|
||||
const enabled = e.detail
|
||||
const guestUserInfo = await accountClient.updateAllowReadOnlyGuests(enabled)
|
||||
allowReadOnlyGuests = enabled
|
||||
if (guestUserInfo !== undefined) {
|
||||
const guestAccount: Account = {
|
||||
uuid: guestUserInfo.guestPerson.uuid as AccountUuid,
|
||||
role: AccountRole.ReadOnlyGuest,
|
||||
primarySocialId: pickPrimarySocialId(guestUserInfo.guestSocialIds)._id,
|
||||
socialIds: guestUserInfo.guestSocialIds.map((si) => si._id),
|
||||
fullSocialIds: guestUserInfo.guestSocialIds
|
||||
}
|
||||
const myAccount = getCurrentAccount()
|
||||
const ctx = uiContext.newChild('connect', {})
|
||||
await ensureEmployeeForPerson(
|
||||
ctx,
|
||||
myAccount,
|
||||
guestAccount,
|
||||
client,
|
||||
guestUserInfo.guestSocialIds,
|
||||
guestUserInfo.guestPerson
|
||||
)
|
||||
} else {
|
||||
const readonlyEmployee = await client.findOne(contact.mixin.Employee, { personUuid: readOnlyGuestAccountUuid })
|
||||
if (readonlyEmployee !== undefined) {
|
||||
await client.update(readonlyEmployee, { active: false })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function handleToggleGuestSignUp (e: CustomEvent<boolean>): Promise<void> {
|
||||
await accountClient.updateAllowGuestSignUp(e.detail)
|
||||
allowGuestSignUp = e.detail
|
||||
}
|
||||
|
||||
async function onAllowedCardsChange (value: Ref<Card>[]): Promise<void> {
|
||||
if (existingGuestChatSettings === undefined) {
|
||||
await client.createDoc(communication.class.GuestCommunicationSettings, core.space.Workspace, {
|
||||
allowedCards: value,
|
||||
enabled: true
|
||||
})
|
||||
} else {
|
||||
await client.updateDoc(
|
||||
communication.class.GuestCommunicationSettings,
|
||||
core.space.Workspace,
|
||||
existingGuestChatSettings._id,
|
||||
{ allowedCards: value, enabled: true }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
defineSeparators('guestPermissionsSettings', twoPanelsSeparators)
|
||||
</script>
|
||||
|
||||
<div class="hulyComponent">
|
||||
<Header adaptive={'disabled'}>
|
||||
<Breadcrumb label={setting.string.GuestPermissionsSettings} size={'large'} isCurrent />
|
||||
</Header>
|
||||
<div class="hulyComponent-content__container columns">
|
||||
<div class="hulyComponent-content__column navigation py-2">
|
||||
<Scroller shrink>
|
||||
<NavItem
|
||||
icon={contact.icon.Person}
|
||||
label={setting.string.GuestPermissionsTabGuest}
|
||||
selected={guestPermissionsTab === 'guest'}
|
||||
on:click={() => {
|
||||
guestPermissionsTab = 'guest'
|
||||
}}
|
||||
/>
|
||||
<NavItem
|
||||
icon={contact.icon.Persona}
|
||||
label={setting.string.GuestPermissionsTabAnonymousGuest}
|
||||
selected={guestPermissionsTab === 'anonymous'}
|
||||
on:click={() => {
|
||||
guestPermissionsTab = 'anonymous'
|
||||
}}
|
||||
/>
|
||||
</Scroller>
|
||||
</div>
|
||||
|
||||
<Separator name={'guestPermissionsSettings'} index={0} color={'var(--theme-divider-color)'} />
|
||||
|
||||
<div class="hulyComponent-content__column content">
|
||||
{#if loading}
|
||||
<div class="w-full h-full flex-col-center justify-center">
|
||||
@@ -151,17 +299,81 @@
|
||||
{:else}
|
||||
<Scroller align={'center'} padding={'var(--spacing-3)'} bottomPadding={'var(--spacing-3)'}>
|
||||
<div class="hulyComponent-content guestPermissionsRoot flex-col">
|
||||
{#if guestPermissionsTab === 'anonymous'}
|
||||
<section class="section">
|
||||
<div class="sectionHeader">
|
||||
<div class="sectionTitle">
|
||||
<Label label={setting.string.GuestPermissionsModulePermissions} />
|
||||
<Label label={settingsRes.string.GuestAccess} />
|
||||
</div>
|
||||
</div>
|
||||
<div class="guestAccessBlock">
|
||||
<div class="guestAccessRow">
|
||||
<div class="guestAccessRow-label">
|
||||
<Label label={settingsRes.string.GuestAccessDescription} />
|
||||
</div>
|
||||
<div class="guestAccessRow-toggleCell">
|
||||
<Toggle
|
||||
on={allowReadOnlyGuests}
|
||||
on:change={(e) => {
|
||||
void handleToggleReadonlyAccess(e)
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="guestAccessRow">
|
||||
<div class="guestAccessRow-label">
|
||||
<Label label={settingsRes.string.GuestSignUpDescription} />
|
||||
</div>
|
||||
<div class="guestAccessRow-toggleCell">
|
||||
<Toggle
|
||||
disabled={!allowReadOnlyGuests}
|
||||
on={allowGuestSignUp}
|
||||
on:change={(e) => {
|
||||
void handleToggleGuestSignUp(e)
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
{#if communicationApiEnabled}
|
||||
<div class="guestAccessRow guestAccessRow--editor">
|
||||
<div class="guestAccessRow-label">
|
||||
<Label label={settingsRes.string.GuestChannelsDescription} />
|
||||
</div>
|
||||
<div class="guestAccessRow-editorCell">
|
||||
<div class="guestAccessRow-editorInner">
|
||||
<Component
|
||||
is={card.component.CardArrayEditor}
|
||||
props={{
|
||||
_class: chat.masterTag.Thread,
|
||||
value:
|
||||
existingGuestChatSettings !== undefined ? existingGuestChatSettings.allowedCards : [],
|
||||
label: settingsRes.string.GuestChannelsArrayLabel,
|
||||
onChange: onAllowedCardsChange
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</section>
|
||||
{/if}
|
||||
|
||||
<section class="section">
|
||||
<div class="sectionHeader">
|
||||
<div class="sectionTitle">
|
||||
<Label label={setting.string.GuestPermissionsApplicationPermissions} />
|
||||
</div>
|
||||
<div class="sectionHint">
|
||||
<Label label={setting.string.GuestPermissionsModulePermissionsHint} />
|
||||
{#if guestPermissionsTab === 'anonymous'}
|
||||
<Label label={setting.string.GuestPermissionsAnonymousApplicationHint} />
|
||||
{:else}
|
||||
<Label label={setting.string.GuestPermissionsApplicationPermissionsHint} />
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="cardStack">
|
||||
<div class="cardStack" class:cardStack-readonly={anonymousModulePermissionsReadOnly}>
|
||||
{#each sortedVisibleModuleGroups as group}
|
||||
{@const app = getApplication(group.application)}
|
||||
{@const moduleOn = isModuleEnabled(group)}
|
||||
@@ -186,7 +398,11 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="permissionModuleCard-toggleCell">
|
||||
<Toggle on={moduleOn} on:change={handleAccessToggle(group)} />
|
||||
<Toggle
|
||||
disabled={anonymousModulePermissionsReadOnly}
|
||||
on={moduleOn}
|
||||
on:change={handleAccessToggle(group)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -199,7 +415,7 @@
|
||||
</div>
|
||||
<div class="permissionRow-toggleCell">
|
||||
<Toggle
|
||||
disabled={!moduleOn}
|
||||
disabled={!moduleOn || anonymousModulePermissionsReadOnly}
|
||||
on={isPermissionActive(group, permissionId)}
|
||||
on:change={handlePermissionToggle(group, permissionId)}
|
||||
/>
|
||||
@@ -220,8 +436,12 @@
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style lang="scss">
|
||||
/* Matches packages/ui Toggle width; shared with permission rows and guest access */
|
||||
$toggleTrackWidth: 2.25rem;
|
||||
|
||||
.guestPermissionsRoot {
|
||||
max-width: 40rem;
|
||||
width: 100%;
|
||||
@@ -229,6 +449,65 @@
|
||||
gap: 2rem;
|
||||
}
|
||||
|
||||
.guestAccessBlock {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0;
|
||||
padding-right: 1rem;
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
.guestAccessRow {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 1fr) #{$toggleTrackWidth};
|
||||
align-items: center;
|
||||
column-gap: 0.75rem;
|
||||
min-height: 2.5rem;
|
||||
padding: 0.625rem 0 0.625rem 0.25rem;
|
||||
}
|
||||
|
||||
.guestAccessRow:not(:first-child) {
|
||||
border-top: 1px solid var(--theme-navpanel-divider);
|
||||
}
|
||||
|
||||
.guestAccessRow--editor {
|
||||
align-items: start;
|
||||
min-height: auto;
|
||||
padding-top: 0.75rem;
|
||||
padding-bottom: 0.75rem;
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
/* Same two columns as toggle rows; editor sits in col 2 and grows left so its right edge matches toggles */
|
||||
.guestAccessRow--editor .guestAccessRow-editorCell {
|
||||
grid-column: 2;
|
||||
grid-row: 1;
|
||||
justify-self: end;
|
||||
align-self: start;
|
||||
width: max-content;
|
||||
max-width: min(22rem, calc(100vw - 3rem));
|
||||
min-width: 0;
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
.guestAccessRow-editorInner {
|
||||
min-width: 0;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.guestAccessRow-label {
|
||||
min-width: 0;
|
||||
color: var(--theme-content-color);
|
||||
}
|
||||
|
||||
.guestAccessRow-toggleCell {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: $toggleTrackWidth;
|
||||
justify-self: end;
|
||||
}
|
||||
|
||||
.section {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@@ -252,9 +531,6 @@
|
||||
color: var(--theme-halfcontent-color);
|
||||
}
|
||||
|
||||
/* Matches packages/ui Toggle width for a single aligned column */
|
||||
$toggleTrackWidth: 2.25rem;
|
||||
|
||||
.cardStack {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@@ -262,6 +538,10 @@
|
||||
padding-top: 0.5rem;
|
||||
}
|
||||
|
||||
.cardStack-readonly {
|
||||
opacity: 0.85;
|
||||
}
|
||||
|
||||
.appIcon {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@@ -334,11 +614,6 @@
|
||||
color: var(--theme-content-color);
|
||||
}
|
||||
|
||||
.permissionModuleCard-meta {
|
||||
font-size: 0.75rem;
|
||||
color: var(--theme-halfcontent-color);
|
||||
}
|
||||
|
||||
.permissionRows {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
@@ -312,8 +312,11 @@ export default plugin(settingId, {
|
||||
DefaultStartWithTranscription: '' as IntlString,
|
||||
DefaultStartWithRecording: '' as IntlString,
|
||||
GuestPermissionsSettings: '' as IntlString,
|
||||
GuestPermissionsModulePermissions: '' as IntlString,
|
||||
GuestPermissionsModulePermissionsHint: '' as IntlString,
|
||||
GuestPermissionsApplicationPermissions: '' as IntlString,
|
||||
GuestPermissionsApplicationPermissionsHint: '' as IntlString,
|
||||
GuestPermissionsTabGuest: '' as IntlString,
|
||||
GuestPermissionsTabAnonymousGuest: '' as IntlString,
|
||||
GuestPermissionsAnonymousApplicationHint: '' as IntlString,
|
||||
MailboxErrorInvalidName: '' as IntlString,
|
||||
MailboxErrorDomainNotFound: '' as IntlString,
|
||||
MailboxErrorNameRulesViolated: '' as IntlString,
|
||||
|
||||
@@ -62,8 +62,8 @@
|
||||
if (g.enabled ?? true) return false
|
||||
const role = getCurrentAccount().role
|
||||
if (role === g.role) return true
|
||||
// DocGuest / ReadOnlyGuest should also respect Guest module disables.
|
||||
return (role === AccountRole.DocGuest || role === AccountRole.ReadOnlyGuest) && g.role === AccountRole.Guest
|
||||
// DocGuest should also respect Guest module disables.
|
||||
return role === AccountRole.DocGuest && g.role === AccountRole.Guest
|
||||
})
|
||||
.map((g) => g.application as Ref<Application>)
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user