mirror of
https://github.com/plankanban/planka.git
synced 2026-03-01 11:21:46 +03:00
Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
414418130d | ||
|
|
d83ea4b146 | ||
|
|
addad4378a | ||
|
|
b9967feeea | ||
|
|
dbcdd62bdf | ||
|
|
ff4177f27a | ||
|
|
f68e7d156e |
@@ -11,9 +11,13 @@ server/test
|
||||
server/.tmp
|
||||
server/.venv
|
||||
|
||||
server/views/index.ejs
|
||||
server/views/index.html
|
||||
|
||||
server/data/*
|
||||
!server/data/.gitkeep
|
||||
|
||||
server/terms/*
|
||||
!server/terms/_template
|
||||
!server/terms/cloud
|
||||
|
||||
client/dist
|
||||
|
||||
2
.github/workflows/build-and-test.yml
vendored
2
.github/workflows/build-and-test.yml
vendored
@@ -69,7 +69,7 @@ jobs:
|
||||
|
||||
- name: Seed database with terms signature
|
||||
run: |
|
||||
TERMS_SIGNATURE=$(sha256sum terms/self-hosted/en-US.md | awk '{print $1}')
|
||||
TERMS_SIGNATURE=$(sha256sum terms/_template/en-US.md | awk '{print $1}')
|
||||
PGPASSWORD=$POSTGRES_PASSWORD psql -h localhost -U $POSTGRES_USERNAME -d $POSTGRES_DATABASE -c "UPDATE user_account SET terms_signature = '$TERMS_SIGNATURE';"
|
||||
working-directory: ./server
|
||||
|
||||
|
||||
49
README.md
49
README.md
@@ -1,23 +1,27 @@
|
||||
# PLANKA
|
||||
<div align="center">
|
||||
|
||||
**Project mastering driven by fun**
|
||||

|
||||
|
||||
 [](https://github.com/plankanban/planka/pkgs/container/planka) [](https://github.com/plankanban/planka/graphs/contributors) [](https://discord.gg/WqqYNd7Jvt)
|
||||
# PLANKA
|
||||
|
||||

|
||||
_Project mastering driven by fun_
|
||||
|
||||
[**Client demo**](https://plankanban.github.io/planka) (without server features).
|
||||
 [](https://github.com/plankanban/planka/pkgs/container/planka) [](https://github.com/plankanban/planka/graphs/contributors) [](https://discord.gg/WqqYNd7Jvt)
|
||||
|
||||
> ⚠️ The demo GIF and client demo are based on **v1** and will be updated soon.
|
||||
[Install](https://docs.planka.cloud/docs/installation/docker/production-version/) · [Demo](https://planka.app) · [Docs](https://docs.planka.cloud/docs/welcome/) · [API](https://plankanban.github.io/planka/swagger-ui/) · [Cloud](https://planka.app/pricing) · [Pro version](https://planka.app/pro)
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
## Key Features
|
||||
|
||||
- **Collaborative Kanban Boards**: Create projects, boards, lists, cards, and manage tasks with an intuitive drag-and-drop interface
|
||||
- **Real-Time Updates**: Instant syncing across all users, no refresh needed
|
||||
- **Rich Markdown Support**: Write beautifully formatted card descriptions with a powerful markdown editor
|
||||
- **Flexible Notifications**: Get alerts through 100+ providers, fully customizable to your workflow
|
||||
- **Seamless Authentication**: Single sign-on with OpenID Connect integration
|
||||
- **Multilingual & Easy to Translate**: Full internationalization support for a global audience
|
||||
- **Collaborative Kanban Boards:** Create projects, boards, lists, cards, and manage tasks with an intuitive drag-and-drop interface
|
||||
- **Real-Time Updates:** Instant syncing across all users, no refresh needed
|
||||
- **Rich Markdown Support:** Write beautifully formatted card descriptions with a powerful markdown editor
|
||||
- **Flexible Notifications:** Get alerts through 100+ providers, fully customizable to your workflow
|
||||
- **Seamless Authentication:** Single sign-on with OpenID Connect integration
|
||||
- **Multilingual & Easy to Translate:** Full internationalization support for a global audience
|
||||
|
||||
## How to Deploy
|
||||
|
||||
@@ -25,20 +29,17 @@ PLANKA is easy to install using multiple methods - learn more in the [installati
|
||||
|
||||
For configuration and environment settings, see the [configuration section](https://docs.planka.cloud/docs/category/configuration/).
|
||||
|
||||
## Notes App Testing
|
||||
Interested in a hosted or [Pro version](https://planka.app/pro) of PLANKA? Check out the pricing on our [website](https://planka.app/pricing).
|
||||
|
||||
The Notes app testing version is available across multiple platforms.
|
||||
## Notes App
|
||||
|
||||
If you have an iOS device, you can join the TestFlight to try the app: [TestFlight](https://testflight.apple.com/join/5eJqTaJW).
|
||||
A testing version of the Notes app is now available on multiple platforms:
|
||||
|
||||
For Windows and Android, you can find the app here: [PLANKA Notes](https://planka-notes.hillerdaniel.de).
|
||||
|
||||
> ⚠️ The Notes app has currently been tested only with PLANKA v2.
|
||||
- **iOS:** Join the [TestFlight](https://testflight.apple.com/join/5eJqTaJW) to try the app
|
||||
- **Windows & Android:** Download the app [here](https://planka-notes.hillerdaniel.de)
|
||||
|
||||
## Contact
|
||||
|
||||
Interested in a hosted version of PLANKA? Email us at [github@planka.group](mailto:github@planka.group).
|
||||
|
||||
For any security issues, please do not create a public issue on GitHub - instead, report it privately by emailing [security@planka.group](mailto:security@planka.group).
|
||||
|
||||
**Note:** We do NOT offer any public support via email, please use GitHub.
|
||||
@@ -49,10 +50,10 @@ For any security issues, please do not create a public issue on GitHub - instead
|
||||
|
||||
PLANKA is [fair-code](https://faircode.io) distributed under the [Fair Use License](https://github.com/plankanban/planka/blob/master/LICENSES/PLANKA%20Community%20License%20EN.md) and [PLANKA Pro/Enterprise License](https://github.com/plankanban/planka/blob/master/LICENSES/PLANKA%20Commercial%20License%20EN.md).
|
||||
|
||||
- **Source Available**: The source code is always visible
|
||||
- **Self-Hostable**: Deploy and host it anywhere
|
||||
- **Extensible**: Customize with your own functionality
|
||||
- **Enterprise Licenses**: Available for additional features and support
|
||||
- **Source Available:** The source code is always visible
|
||||
- **Self-Hostable:** Deploy and host it anywhere
|
||||
- **Extensible:** Customize with your own functionality
|
||||
- **Enterprise Licenses:** Available for additional features and support
|
||||
|
||||
For more details, check the [License Guide](https://github.com/plankanban/planka/blob/master/LICENSES/PLANKA%20License%20Guide%20EN.md).
|
||||
|
||||
|
||||
BIN
assets/demo.gif
BIN
assets/demo.gif
Binary file not shown.
|
Before Width: | Height: | Size: 1.1 MiB After Width: | Height: | Size: 1.6 MiB |
BIN
assets/logo.png
Normal file
BIN
assets/logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 10 KiB |
@@ -15,13 +15,13 @@ type: application
|
||||
# This is the chart version. This version number should be incremented each time you make changes
|
||||
# to the chart and its templates, including the app version.
|
||||
# Versions are expected to follow Semantic Versioning (https://semver.org/)
|
||||
version: 2.0.0
|
||||
version: 2.0.1
|
||||
|
||||
# This is the version number of the application being deployed. This version number should be
|
||||
# incremented each time you make changes to the application. Versions are not expected to
|
||||
# follow Semantic Versioning. They should reflect the version the application is using.
|
||||
# It is recommended to use it with quotes.
|
||||
appVersion: "2.0.0"
|
||||
appVersion: "2.0.1"
|
||||
|
||||
dependencies:
|
||||
- alias: postgresql
|
||||
|
||||
@@ -68,7 +68,7 @@ helm install planka . --set secretkey=$SECRETKEY \
|
||||
|
||||
or create a values.yaml file like:
|
||||
|
||||
```yaml
|
||||
````yaml
|
||||
secretkey: "<InsertSecretKey>"
|
||||
# The admin section needs to be present for new instances of PLANKA, after the first start you can remove the lines starting with admin_. If you want the admin user to be unchangeable admin_email: has to stay
|
||||
# After changing the config you have to run ```helm upgrade planka . -f values.yaml```
|
||||
@@ -89,11 +89,11 @@ ingress:
|
||||
- path: /
|
||||
pathType: ImplementationSpecific
|
||||
|
||||
# Needed for HTTPS
|
||||
# Needed for HTTPS
|
||||
tls:
|
||||
- secretName: planka-tls # existing TLS secret in k8s
|
||||
hosts:
|
||||
- planka.example.dev
|
||||
- secretName: planka-tls # existing TLS secret in k8s
|
||||
hosts:
|
||||
- planka.example.dev
|
||||
```
|
||||
|
||||
```bash
|
||||
@@ -135,14 +135,14 @@ extraMounts:
|
||||
subPath: ca.crt
|
||||
readOnly: true
|
||||
configMap:
|
||||
name: ca-certificates # Must exist
|
||||
name: ca-certificates # Must exist
|
||||
|
||||
# Mount TLS certificates from existing Secret
|
||||
- name: tls-certs
|
||||
mountPath: /etc/ssl/private
|
||||
readOnly: true
|
||||
secret:
|
||||
secretName: planka-tls-secret # Must exist
|
||||
secretName: planka-tls-secret # Must exist
|
||||
items:
|
||||
- key: tls.crt
|
||||
path: server.crt
|
||||
@@ -178,11 +178,13 @@ extraMounts:
|
||||
A common use case is configuring OIDC with a self-hosted Keycloak instance that uses custom CA certificates.
|
||||
|
||||
First, create the CA certificate ConfigMap:
|
||||
|
||||
```bash
|
||||
kubectl create configmap ca-certificates --from-file=ca.crt=/path/to/your/ca.crt
|
||||
```
|
||||
|
||||
Then configure the chart:
|
||||
|
||||
```yaml
|
||||
# Mount custom CA certificate from existing ConfigMap
|
||||
extraMounts:
|
||||
@@ -225,6 +227,67 @@ extraEnv:
|
||||
key: api-key
|
||||
```
|
||||
|
||||
### Image Digest Pinning
|
||||
|
||||
For enhanced security and reproducibility, you can pin the container image using its SHA256 digest instead of relying solely on tags. This ensures you always deploy the exact same image, preventing tag mutations or accidental updates.
|
||||
|
||||
#### Finding the Image Digest
|
||||
|
||||
You can find the digest of a specific image tag using:
|
||||
|
||||
```bash
|
||||
docker inspect ghcr.io/plankanban/planka:latest --format='{{index .RepoDigests 0}}'
|
||||
# Output: ghcr.io/plankanban/planka@sha256:abc123def456...
|
||||
|
||||
# Or with skopeo
|
||||
skopeo inspect docker://ghcr.io/plankanban/planka:latest
|
||||
```
|
||||
|
||||
#### Usage
|
||||
|
||||
You can use digest pinning in several ways:
|
||||
|
||||
**Option 1: Digest with tag (recommended)**
|
||||
|
||||
Includes the tag for reference while using the digest for verification:
|
||||
|
||||
```bash
|
||||
helm install planka . --set secretkey=$SECRETKEY \
|
||||
--set image.tag=latest \
|
||||
--set image.digest=abc123def456... \
|
||||
--set admin_email="demo@demo.demo" \
|
||||
--set admin_password="demo" \
|
||||
--set admin_name="Demo Demo" \
|
||||
--set admin_username="demo"
|
||||
```
|
||||
|
||||
Or in values.yaml:
|
||||
|
||||
```yaml
|
||||
image:
|
||||
repository: ghcr.io/plankanban/planka
|
||||
tag: latest
|
||||
digest: "abc123def456ab89cd12ef34ab56cd78ef90ab12cd34ef56ab78cd90ef12ab34"
|
||||
```
|
||||
|
||||
**Option 2: Digest only**
|
||||
|
||||
If you prefer to pin only by digest without specifying a tag:
|
||||
|
||||
```yaml
|
||||
image:
|
||||
repository: ghcr.io/plankanban/planka
|
||||
tag: "" # Empty - digest alone identifies the image
|
||||
digest: "abc123def456ab89cd12ef34ab56cd78ef90ab12cd34ef56ab78cd90ef12ab34"
|
||||
```
|
||||
|
||||
#### Security Benefits
|
||||
|
||||
- **Immutability**: Ensures you always deploy the exact same image
|
||||
- **Supply Chain Security**: Protects against tag mutations or registry compromise
|
||||
- **Reproducibility**: Makes deployments fully reproducible across environments
|
||||
- **Audit Trail**: Provides clear image identity in deployment manifests
|
||||
|
||||
### Complete Example
|
||||
|
||||
See `values-example.yaml` for a comprehensive example that demonstrates all the advanced features including OIDC configuration with custom CA certificates.
|
||||
|
||||
@@ -39,7 +39,16 @@ spec:
|
||||
- name: {{ .Chart.Name }}
|
||||
securityContext:
|
||||
{{- toYaml .Values.securityContext | nindent 12 }}
|
||||
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
|
||||
{{- $imageTag := .Values.image.tag | default .Chart.AppVersion }}
|
||||
{{- if .Values.image.digest }}
|
||||
{{- if $imageTag }}
|
||||
image: "{{ .Values.image.repository }}:{{ $imageTag }}@sha256:{{ .Values.image.digest }}"
|
||||
{{- else }}
|
||||
image: "{{ .Values.image.repository }}@sha256:{{ .Values.image.digest }}"
|
||||
{{- end }}
|
||||
{{- else }}
|
||||
image: "{{ .Values.image.repository }}:{{ $imageTag }}"
|
||||
{{- end }}
|
||||
imagePullPolicy: {{ .Values.image.pullPolicy }}
|
||||
ports:
|
||||
- name: http
|
||||
|
||||
@@ -9,6 +9,10 @@ image:
|
||||
pullPolicy: IfNotPresent
|
||||
# Overrides the image tag whose default is the chart appVersion.
|
||||
tag: ""
|
||||
# Optional: specify the image digest for pinning by SHA256
|
||||
# When set, the image reference will include the digest for enhanced security
|
||||
# Example: "abc123def456..." (without sha256: prefix)
|
||||
digest: ""
|
||||
|
||||
imagePullSecrets: []
|
||||
nameOverride: ""
|
||||
|
||||
@@ -30,8 +30,8 @@ socket.connect = socket._connect; // eslint-disable-line no-underscore-dangle
|
||||
headers,
|
||||
url: `/api${url}`,
|
||||
},
|
||||
(_, { body, error }) => {
|
||||
if (error) {
|
||||
(body, { error }) => {
|
||||
if (body instanceof Error || error) {
|
||||
reject(body);
|
||||
} else {
|
||||
resolve(body);
|
||||
|
||||
@@ -1,3 +1,10 @@
|
||||
# [2.0.1] - 2026-02-17
|
||||
|
||||
### Fixed
|
||||
|
||||
* Improve connection reliability after the app is idle
|
||||
* Allow loading custom End User Terms of Service
|
||||
|
||||
## [2.0.0] - 2026-02-11
|
||||
|
||||
### Added
|
||||
|
||||
@@ -11,15 +11,12 @@ import { Button, Checkbox, Dropdown, Modal, Segment } from 'semantic-ui-react';
|
||||
import selectors from '../../../selectors';
|
||||
import entryActions from '../../../entry-actions';
|
||||
import { localeByLanguage } from '../../../locales';
|
||||
import TERMS_LANGUAGES from '../../../constants/TermsLanguages';
|
||||
import Markdown from '../Markdown';
|
||||
|
||||
import styles from './TermsModal.module.scss';
|
||||
|
||||
const LOCALES = TERMS_LANGUAGES.map((language) => localeByLanguage[language]);
|
||||
|
||||
const splitTermsAndConfirmations = (content) => {
|
||||
const separator = '\n---\n';
|
||||
const separator = '\n[confirmations]::\n---\n';
|
||||
const index = content.lastIndexOf(separator);
|
||||
|
||||
if (index === -1) {
|
||||
@@ -38,6 +35,8 @@ const splitTermsAndConfirmations = (content) => {
|
||||
};
|
||||
|
||||
const TermsModal = React.memo(() => {
|
||||
const { termsLanguages } = useSelector(selectors.selectBootstrap);
|
||||
|
||||
const {
|
||||
termsForm: { payload: terms, isSubmitting, isCancelling, isLanguageUpdating },
|
||||
} = useSelector(selectors.selectAuthenticateForm);
|
||||
@@ -46,6 +45,19 @@ const TermsModal = React.memo(() => {
|
||||
const [t] = useTranslation();
|
||||
const [acceptedConfirmationsSet, setAcceptedConfirmationsSet] = useState(new Set());
|
||||
|
||||
const locales = useMemo(
|
||||
() =>
|
||||
termsLanguages.map(
|
||||
(language) =>
|
||||
localeByLanguage[language] || {
|
||||
language,
|
||||
country: language.split('-')[1]?.toLowerCase(),
|
||||
name: language,
|
||||
},
|
||||
),
|
||||
[termsLanguages],
|
||||
);
|
||||
|
||||
const [content, confirmations] = useMemo(
|
||||
() => splitTermsAndConfirmations(terms.content),
|
||||
[terms.content],
|
||||
@@ -88,7 +100,7 @@ const TermsModal = React.memo(() => {
|
||||
<Dropdown
|
||||
fluid
|
||||
selection
|
||||
options={LOCALES.map((locale) => ({
|
||||
options={locales.map((locale) => ({
|
||||
value: locale.language,
|
||||
flag: locale.country,
|
||||
text: locale.name,
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
/*!
|
||||
* Copyright (c) 2024 PLANKA Software GmbH
|
||||
* Licensed under the Fair Use License: https://github.com/plankanban/planka/blob/master/LICENSE.md
|
||||
*/
|
||||
|
||||
export default ['de-DE', 'en-US'];
|
||||
@@ -1 +1 @@
|
||||
export default '2.0.0';
|
||||
export default '2.0.1';
|
||||
|
||||
@@ -4,6 +4,7 @@ services:
|
||||
restart: on-failure
|
||||
volumes:
|
||||
- data:/app/data
|
||||
# - ./terms:/app/terms/custom
|
||||
# Optionally override this to your user/group
|
||||
# user: 1000:1000
|
||||
# tmpfs:
|
||||
|
||||
@@ -21,7 +21,7 @@ echo "Success!"
|
||||
|
||||
# Restore Docker Volume
|
||||
echo -n "Importing data volume ... "
|
||||
docker run --rm --volumes-from "$PLANKA_DOCKER_CONTAINER_PLANKA" -v "$(pwd)/$PLANKA_BACKUP_ARCHIVE:/backup" ubuntu cp -rf /backup/data/. /app/public/data
|
||||
docker run --rm --volumes-from "$PLANKA_DOCKER_CONTAINER_PLANKA" -v "$(pwd)/$PLANKA_BACKUP_ARCHIVE:/backup" ubuntu cp -rf /backup/data/. /app/data
|
||||
echo "Success!"
|
||||
|
||||
echo -n "Cleaning up temporary files and folders ... "
|
||||
|
||||
4
package-lock.json
generated
4
package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "planka",
|
||||
"version": "2.0.0",
|
||||
"version": "2.0.1",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "planka",
|
||||
"version": "2.0.0",
|
||||
"version": "2.0.1",
|
||||
"hasInstallScript": true,
|
||||
"dependencies": {
|
||||
"concurrently": "^9.2.1",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "planka",
|
||||
"version": "2.0.0",
|
||||
"version": "2.0.1",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"client:build": "npm run build --prefix client",
|
||||
|
||||
@@ -20,6 +20,10 @@ test
|
||||
.tmp
|
||||
.venv
|
||||
|
||||
views/index.ejs
|
||||
views/index.html
|
||||
|
||||
data/*
|
||||
|
||||
terms/*
|
||||
!terms/_template
|
||||
!terms/cloud
|
||||
|
||||
6
server/.gitignore
vendored
6
server/.gitignore
vendored
@@ -134,7 +134,11 @@ swagger.json
|
||||
dist
|
||||
logs
|
||||
|
||||
views/index.ejs
|
||||
views/index.html
|
||||
|
||||
data/*
|
||||
!data/.gitkeep
|
||||
|
||||
terms/*
|
||||
!terms/_template
|
||||
!terms/cloud
|
||||
|
||||
@@ -57,6 +57,12 @@
|
||||
* format: uri
|
||||
* description: URL to the customer management panel (conditionally added for admins if configured)
|
||||
* example: https://panel.example.com
|
||||
* termsLanguages:
|
||||
* type: array
|
||||
* description: List of available language codes for terms localization
|
||||
* items:
|
||||
* type: string
|
||||
* example: [de-DE, en-US]
|
||||
* version:
|
||||
* type: string
|
||||
* description: Current version of the PLANKA application
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
* description: Language code for terms localization
|
||||
* schema:
|
||||
* type: string
|
||||
* enum: [de-DE, en-US]
|
||||
* example: en-US
|
||||
* responses:
|
||||
* 200:
|
||||
@@ -41,7 +40,6 @@
|
||||
* properties:
|
||||
* language:
|
||||
* type: string
|
||||
* enum: [de-DE, en-US]
|
||||
* description: Language code used
|
||||
* example: en-US
|
||||
* content:
|
||||
@@ -65,7 +63,6 @@ module.exports = {
|
||||
inputs: {
|
||||
language: {
|
||||
type: 'string',
|
||||
isIn: User.LANGUAGES,
|
||||
},
|
||||
},
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@ module.exports = {
|
||||
fn(inputs) {
|
||||
const data = {
|
||||
oidc: inputs.oidc,
|
||||
termsLanguages: sails.hooks.terms.getLanguages(),
|
||||
version: sails.config.custom.version,
|
||||
};
|
||||
|
||||
|
||||
@@ -12,25 +12,35 @@
|
||||
*/
|
||||
|
||||
const fsPromises = require('fs').promises;
|
||||
const path = require('path');
|
||||
const crypto = require('crypto');
|
||||
|
||||
const LANGUAGES = ['de-DE', 'en-US'];
|
||||
const DEFAULT_LANGUAGE = 'en-US';
|
||||
|
||||
const getContent = (language = DEFAULT_LANGUAGE) =>
|
||||
fsPromises.readFile(
|
||||
`${sails.config.appPath}/terms/${sails.config.custom.termsType}/${language}.md`,
|
||||
'utf8',
|
||||
);
|
||||
const PATH = path.join(sails.config.appPath, 'terms');
|
||||
const TEMPLATE_TYPE = '_template';
|
||||
|
||||
const hashContent = (content) => crypto.createHash('sha256').update(content).digest('hex');
|
||||
|
||||
module.exports = function defineTermsHook(sails) {
|
||||
let type;
|
||||
let languages;
|
||||
let defaultLanguage;
|
||||
let signature;
|
||||
|
||||
return {
|
||||
LANGUAGES,
|
||||
const getLanguages = async () => {
|
||||
const entries = await fsPromises.readdir(path.join(PATH, type), {
|
||||
withFileTypes: true,
|
||||
});
|
||||
|
||||
return entries
|
||||
.filter((entry) => entry.isFile() && path.extname(entry.name) === '.md')
|
||||
.map((entry) => path.basename(entry.name, '.md'))
|
||||
.sort();
|
||||
};
|
||||
|
||||
const getContent = (language) =>
|
||||
fsPromises.readFile(path.join(PATH, type, `${language}.md`), 'utf8');
|
||||
|
||||
return {
|
||||
/**
|
||||
* Runs when this Sails app loads/lifts.
|
||||
*/
|
||||
@@ -38,13 +48,32 @@ module.exports = function defineTermsHook(sails) {
|
||||
async initialize() {
|
||||
sails.log.info('Initializing custom hook (`terms`)');
|
||||
|
||||
const content = await getContent();
|
||||
type = sails.config.custom.termsType;
|
||||
|
||||
try {
|
||||
languages = await getLanguages();
|
||||
} catch (error) {
|
||||
/* empty */
|
||||
}
|
||||
|
||||
if (!languages || languages.length === 0) {
|
||||
sails.log.warn('Custom terms not found, falling back to template');
|
||||
|
||||
type = TEMPLATE_TYPE;
|
||||
languages = await getLanguages();
|
||||
}
|
||||
|
||||
defaultLanguage = languages.includes(sails.config.i18n.defaultLocale)
|
||||
? sails.config.i18n.defaultLocale
|
||||
: languages[0];
|
||||
|
||||
const content = await getContent(defaultLanguage);
|
||||
signature = hashContent(content);
|
||||
},
|
||||
|
||||
async getPayload(language = DEFAULT_LANGUAGE) {
|
||||
if (!LANGUAGES.includes(language)) {
|
||||
language = DEFAULT_LANGUAGE; // eslint-disable-line no-param-reassign
|
||||
async getPayload(language) {
|
||||
if (!language || !languages.includes(language)) {
|
||||
language = defaultLanguage; // eslint-disable-line no-param-reassign
|
||||
}
|
||||
|
||||
const content = await getContent(language);
|
||||
@@ -56,6 +85,10 @@ module.exports = function defineTermsHook(sails) {
|
||||
};
|
||||
},
|
||||
|
||||
getLanguages() {
|
||||
return languages;
|
||||
},
|
||||
|
||||
isSignatureValid(value) {
|
||||
return value === signature;
|
||||
},
|
||||
|
||||
@@ -113,7 +113,7 @@ module.exports.custom = {
|
||||
/* Internal */
|
||||
|
||||
internalAccessToken: process.env.INTERNAL_ACCESS_TOKEN,
|
||||
termsType: process.env.TERMS_TYPE || 'self-hosted',
|
||||
termsType: process.env.TERMS_TYPE || 'custom',
|
||||
customerPanelUrl: process.env.CUSTOMER_PANEL_URL,
|
||||
demoMode: process.env.DEMO_MODE === 'true',
|
||||
};
|
||||
|
||||
@@ -1,3 +1,11 @@
|
||||
# ⚠️ DIES IST NUR EINE BEISPIEL-VORLAGE
|
||||
|
||||
Wenn Sie Administrator dieser Instanz sind, können Sie diese Bedingungen an Ihre eigenen Bedürfnisse und rechtlichen Anforderungen anpassen.
|
||||
|
||||
Eine Anleitung zum Anpassen dieser Vorlage finden Sie in diesem [Guide](https://docs.planka.cloud/docs/configuration/customizing-end-user-terms/).
|
||||
|
||||
---
|
||||
|
||||
# Nutzungsbedingungen für Endbenutzer – On-Premise-Version
|
||||
|
||||
**Stand: 11. Februar 2026 – v1.0**
|
||||
@@ -76,6 +84,7 @@ Der Anbieter kann diese Nutzungsbedingungen mit Wirkung für die Zukunft ändern
|
||||
|
||||
*PLANKA Software GmbH · Lindauer Str. 4 · 87439 Kempten · Deutschland*
|
||||
|
||||
[confirmations]::
|
||||
---
|
||||
|
||||
✔️ **Ich habe diese Nutzungsbedingungen gelesen und akzeptiere sie**
|
||||
@@ -1,3 +1,11 @@
|
||||
# ⚠️ THIS IS ONLY A TEMPLATE
|
||||
|
||||
If you are the admin of this instance, you can customize these Terms to suit your own needs and legal requirements.
|
||||
|
||||
For guidance on updating this template, see this [guide](https://docs.planka.cloud/docs/configuration/customizing-end-user-terms/).
|
||||
|
||||
---
|
||||
|
||||
# End User Terms of Service – On-Premise Version
|
||||
|
||||
**Effective: February 11, 2026 – v1.0**
|
||||
@@ -76,6 +84,7 @@ The Provider may amend these End User Terms of Service with effect for the futur
|
||||
|
||||
*PLANKA Software GmbH · Lindauer Str. 4 · 87439 Kempten · Germany*
|
||||
|
||||
[confirmations]::
|
||||
---
|
||||
|
||||
✔️ **I have read and accept these End User Terms of Service**
|
||||
@@ -124,6 +124,7 @@ Die vollständige Datenschutzerklärung mit allen Details zu Sub-Auftragsverarbe
|
||||
|
||||
*PLANKA Software GmbH · Lindauer Str. 4 · 87439 Kempten · Deutschland*
|
||||
|
||||
[confirmations]::
|
||||
---
|
||||
|
||||
✔️ **Ich habe die Nutzungsbedingungen (Teil I) gelesen und akzeptiere sie**
|
||||
|
||||
@@ -124,6 +124,7 @@ The full Privacy Policy with complete details on sub-processors, technical measu
|
||||
|
||||
*PLANKA Software GmbH · Lindauer Str. 4 · 87439 Kempten · Germany*
|
||||
|
||||
[confirmations]::
|
||||
---
|
||||
|
||||
✔️ **I have read and accept the Terms of Service (Part I)**
|
||||
|
||||
@@ -1 +1 @@
|
||||
module.exports = '2.0.0';
|
||||
module.exports = '2.0.1';
|
||||
|
||||
Reference in New Issue
Block a user