Skip to content

Commit

Permalink
Allow self-hosted instances to disable data deletion, and turn off ab…
Browse files Browse the repository at this point in the history
…ility to show author (#555)
  • Loading branch information
antoinejaussoin authored Jul 16, 2023
1 parent e6eef4b commit fbb4680
Show file tree
Hide file tree
Showing 19 changed files with 242 additions and 90 deletions.
4 changes: 3 additions & 1 deletion .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -61,4 +61,6 @@ GA4_SECRET=
GA4_MEASUREMENT_ID=G-XXXXXXXXXX
OPEN_AI_API_KEY=sk-xxxx
OPEN_AI_FREE_LIMIT=5
OPEN_AI_PAID_LIMIT=1000
OPEN_AI_PAID_LIMIT=1000
DISABLE_DATA_DELETION=true
DISABLE_REVEAL_NAMES=true
2 changes: 2 additions & 0 deletions backend/src/admin/router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ export default function getRouter(io: Server) {
disableAnonymous: config.DISABLE_ANONYMOUS_LOGIN,
disablePasswords: config.DISABLE_PASSWORD_LOGIN,
disablePasswordRegistration: config.DISABLE_PASSWORD_REGISTRATION,
disableAccountDeletion: config.DISABLE_ACCOUNT_DELETION,
disableShowAuthor: config.DISABLE_SHOW_AUTHOR,
ai: !!config.OPEN_AI_API_KEY,
oAuth: {
google: !!config.GOOGLE_KEY && !!config.GOOGLE_SECRET,
Expand Down
2 changes: 2 additions & 0 deletions backend/src/common/payloads.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ export interface BackendCapabilities {
disableAnonymous: boolean;
disablePasswords: boolean;
disablePasswordRegistration: boolean;
disableAccountDeletion: boolean;
disableShowAuthor: boolean;
ai: boolean;
}

Expand Down
2 changes: 2 additions & 0 deletions backend/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,8 @@ const config: BackendConfig = {
OPEN_AI_API_KEY: defaults('OPEN_AI_API_KEY', ''),
OPEN_AI_FREE_LIMIT: defaultsNumber('OPEN_AI_FREE_LIMIT', 5),
OPEN_AI_PAID_LIMIT: defaultsNumber('OPEN_AI_PAID_LIMIT', 100),
DISABLE_ACCOUNT_DELETION: defaultsBool('DISABLE_ACCOUNT_DELETION', false),
DISABLE_SHOW_AUTHOR: defaultsBool('DISABLE_SHOW_AUTHOR', false),
};

export default config;
2 changes: 2 additions & 0 deletions backend/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ export interface BackendConfig {
OPEN_AI_API_KEY: string;
OPEN_AI_FREE_LIMIT: number;
OPEN_AI_PAID_LIMIT: number;
DISABLE_ACCOUNT_DELETION: boolean;
DISABLE_SHOW_AUTHOR: boolean;
}

export type LicenceMetadata = {
Expand Down
2 changes: 2 additions & 0 deletions docs/docs/self-hosting/optionals.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ services:
DISABLE_ANONYMOUS_LOGIN: 'false' # Set to true to disable anonymous accounts
DISABLE_PASSWORD_LOGIN: 'false' # Set to true to disable password accounts (email accounts).
DISABLE_PASSWORD_REGISTRATION: 'false' # Set to true to disable password accounts registration (but not login!)
DISABLE_ACCOUNT_DELETION: 'false' # Set to true to disable data deletion (GDPR)
DISABLE_SHOW_AUTHOR: 'false' # Set to true to disable the ability to reveal names, even for board owners

# -- AI - Open AI: Set these to enable AI capabilities. This is optional. --
OPEN_AI_API_KEY: '' # To activate AI capabilities, you need to get an API key from https://platform.openai.com/account/api-keys
Expand Down
6 changes: 6 additions & 0 deletions docs/docs/self-hosting/quick-start/ComposeView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ type ComposeViewSettings = {
disableAnon: boolean;
disablePassword: boolean;
disableRegistration: boolean;
disableAccountDeletion: boolean;
disableShowAuthor: boolean;
useSendgrid: boolean;
useSmtp: boolean;
sendgridKey: string;
Expand Down Expand Up @@ -60,6 +62,8 @@ export default function ComposeView({
disableAnon,
disablePassword,
disableRegistration,
disableAccountDeletion,
disableShowAuthor,
useSendgrid,
useSmtp,
sendgridKey,
Expand All @@ -81,6 +85,8 @@ export default function ComposeView({
p(disableAnon, 'DISABLE_ANONYMOUS_LOGIN', 'true'),
p(disablePassword, 'DISABLE_PASSWORD_LOGIN', 'true'),
p(disableRegistration, 'DISABLE_PASSWORD_REGISTRATION', 'true'),
p(disableAccountDeletion, 'DISABLE_ACCOUNT_DELETION', 'true'),
p(disableShowAuthor, 'DISABLE_SHOW_AUTHOR', 'true'),
p(useSendgrid, 'SENDGRID_API_KEY', sendgridKey),
p(useSendgrid, 'SENDGRID_SENDER', sendgridSender),
p(useSmtp, 'MAIL_SMTP_HOST', smtpHost),
Expand Down
26 changes: 26 additions & 0 deletions docs/docs/self-hosting/quick-start/Editor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,14 @@ export default function Editor() {
);
const [disableRegistration, setDisablePasswordRegistration] =
usePersistedState('disable-password-reg', false);
const [disableAccountDeletion, setDisableAccountDeletion] = usePersistedState(
'disable-delete-account',
false
);
const [disableShowAuthor, setDisableShowAuthor] = usePersistedState(
'disable-show-author',
false
);
const [useSendgrid, setUseSendgrid] = usePersistedState(
'use-sendgrid',
false
Expand Down Expand Up @@ -176,6 +184,22 @@ export default function Editor() {
value={disableRegistration || disablePassword}
onChange={setDisablePasswordRegistration}
/>
<FieldToggle
id="disable-delete-data"
label="Disable Delete Account (RGPD)?"
description="Users won't be able to delete their account or data."
toggleLabel="Disable Delete Account"
value={disableAccountDeletion}
onChange={setDisableAccountDeletion}
/>
<FieldToggle
id="disable-show-author"
label="Disable the ability to show the author of a card"
description="The option to show the author of a card will not be available, for anyone, including the owner of a board."
toggleLabel="Disable Show Author"
value={disableShowAuthor}
onChange={setDisableShowAuthor}
/>
</div>
</Accordion>
<Accordion title="Email settings">
Expand Down Expand Up @@ -317,6 +341,8 @@ export default function Editor() {
disableAnon,
disablePassword,
disableRegistration,
disableAccountDeletion,
disableShowAuthor,
useSendgrid,
useSmtp,
sendgridKey,
Expand Down
2 changes: 2 additions & 0 deletions frontend/src/common/payloads.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ export interface BackendCapabilities {
disableAnonymous: boolean;
disablePasswords: boolean;
disablePasswordRegistration: boolean;
disableAccountDeletion: boolean;
disableShowAuthor: boolean;
ai: boolean;
}

Expand Down
40 changes: 22 additions & 18 deletions frontend/src/global/state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,27 @@ import { selector } from 'recoil';
import { BackendCapabilities } from 'common';
import { fetchBackendCapabilities } from 'api';

const defaultBackendCapabilities: BackendCapabilities = {
adminEmail: '',
licenced: true,
selfHosted: false,
disableAnonymous: false,
disablePasswords: false,
disablePasswordRegistration: false,
disableAccountDeletion: false,
disableShowAuthor: false,
oAuth: {
google: false,
github: false,
twitter: false,
microsoft: false,
slack: false,
okta: false,
},
emailAvailable: false,
ai: false,
};

export const backendCapabilitiesState = selector<BackendCapabilities>({
key: 'BACKEND_CAPABILITIES',
get: async () => {
Expand All @@ -11,23 +32,6 @@ export const backendCapabilitiesState = selector<BackendCapabilities>({
return data;
}

return {
adminEmail: '',
licenced: true,
selfHosted: false,
disableAnonymous: false,
disablePasswords: false,
disablePasswordRegistration: false,
oAuth: {
google: false,
github: false,
twitter: false,
microsoft: false,
slack: false,
okta: false,
},
emailAvailable: false,
ai: false,
};
return defaultBackendCapabilities;
},
});
41 changes: 39 additions & 2 deletions frontend/src/testing/index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { PropsWithChildren, useEffect } from 'react';
import { render, RenderOptions, RenderResult } from '@testing-library/react';
import { FullUser, Session, defaultOptions } from 'common';
import { vi } from 'vitest';
import { BackendCapabilities, FullUser, Session, defaultOptions } from 'common';
import {
DragDropContext,
Droppable,
Expand Down Expand Up @@ -57,10 +58,46 @@ export const initialSession: Session = {
demo: false,
};

const capabilities: BackendCapabilities = {
adminEmail: '[email protected]',
ai: false,
disableAccountDeletion: false,
disableAnonymous: false,
disablePasswordRegistration: false,
disablePasswords: false,
disableShowAuthor: false,
emailAvailable: true,
licenced: true,
oAuth: {
github: false,
google: false,
microsoft: false,
okta: false,
slack: false,
twitter: false,
},
selfHosted: false,
slackClientId: 'xxx',
};
// fetchBackendCapabilities
vi.mock('../api/index', () => {
return {
fetchBackendCapabilities: () => {
return Promise.resolve(capabilities);
},
};
});

export function AllTheProviders({ children }: PropsWithChildren<{}>) {
return (
<RecoilRoot initializeState={(snap) => snap.set(userState, user)}>
<RecoilRoot
initializeState={(snap) => {
snap.set(userState, user);
}}
>
{/* <I18nextProvider i18n={i18n}> */}
<Inner>{children}</Inner>
{/* </I18nextProvider> */}
</RecoilRoot>
);
}
Expand Down
42 changes: 22 additions & 20 deletions frontend/src/views/account/AccountPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -238,28 +238,30 @@ function AccountPage() {
</Section>
) : null}

<Section title={t('AccountPage.deleteAccount.title')!} danger>
<Alert severity="error">
{t('AccountPage.deleteAccount.warning')}
</Alert>
{capabilities.disableAccountDeletion ? null : (
<Section title={t('AccountPage.deleteAccount.title')!} danger>
<Alert severity="error">
{t('AccountPage.deleteAccount.warning')}
</Alert>

<Button
color="error"
variant="contained"
onClick={handleDeleteModalOpen}
style={{ marginTop: 20 }}
data-cy="delete-account-button"
>
{t('AccountPage.deleteAccount.deleteData')}
</Button>
<Button
color="error"
variant="contained"
onClick={handleDeleteModalOpen}
style={{ marginTop: 20 }}
data-cy="delete-account-button"
>
{t('AccountPage.deleteAccount.deleteData')}
</Button>

<DeleteModal
open={deleteModalOpen}
user={user}
onDelete={handleDeleteModalClose}
onClose={handleDeleteModalClose}
/>
</Section>
<DeleteModal
open={deleteModalOpen}
user={user}
onDelete={handleDeleteModalClose}
onClose={handleDeleteModalClose}
/>
</Section>
)}
</Page>
</>
);
Expand Down
Loading

0 comments on commit fbb4680

Please sign in to comment.