diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -1,28 +1,32 @@
## Quickstart Instructions to try it out
* Make sure you have docker and docker-compose available.
-* Run 'make deploy' in the base directory.
+* Change to the base directory of this repository.
+* Run 'HOSTNAME=kolab.local ADMIN_PASSWORD="simple123" bin/configure.sh config.prod' to configure this deployment.
+* Run 'bin/deploy.sh' to start the deployment.
+* Run 'docker exec -w /src/kolabsrc/ kolab-webapp ./artisan user:password admin@kolab.local simple123' to set your admin password
* Add an /etc/hosts entry "127.0.0.1 kolab.local"
* navigate to https://kolab.local
-* login as "john@kolab.org" with password "simple123"
+* login as "admin@kolab.local" with password "simple123" (or whatever you have set), and create your users.
-# Setup env.local
+# Customization
-To customize the installation, create a file src/env.local to override setting in src/.env.example.
+To customize the installation, copy config.prod and adjust to your liking. You can then install the configuration using 'bin/configure.sh $YOURCONFIG',
+and afterwards 'bin/deploy.sh' again.
-The setup script with merge these settings into src/.env, which is what is ultimately used by the installation.
-
-Take a look at ansible/env.local for an example of typical modifications required for an installation.
+Please note that bin/deploy.sh will remove any existing data.
# Use the ansible setup
The ansible/ directory contains setup scripts to setup a fresh Fedora system with a kolab deployment.
Modify the Makefile with the required variables and then execute `make setup`.
-This will configure the remote system and execute bin/deploy.sh
+This will configure the remote system and execute the above steps.
### Update
+To update the containers without removing the data:
+
* git pull
* Run "bin/update.sh"
@@ -36,6 +40,3 @@
### Requirements
* docker
* openssl
-
-## TODO
-* Only seed admin user, but not all the development stuff?
diff --git a/ansible/Makefile b/ansible/Makefile
--- a/ansible/Makefile
+++ b/ansible/Makefile
@@ -2,9 +2,10 @@
FIREBASE_API_KEY=
HOSTNAME=
PUBLIC_IP=
+ADMIN_PASSWORD=
GIT_BRANCH=beta-release
setup:
touch ./hosts
echo "${HOSTNAME}" > ./hosts
- ansible-playbook -v --inventory=./hosts --extra-vars="hostname=${HOSTNAME} openexchangerates_api_key=${OX_API_KEY} firebase_api_key=${FIREBASE_API_KEY} public_ip=${PUBLIC_IP} git_branch=${GIT_BRANCH}" setup.yml
+ ansible-playbook -v --inventory=./hosts --extra-vars="hostname=${HOSTNAME} openexchangerates_api_key=${OX_API_KEY} firebase_api_key=${FIREBASE_API_KEY} public_ip=${PUBLIC_IP} admin_password=${ADMIN_PASSWORD} git_branch=${GIT_BRANCH}" setup.yml
diff --git a/ansible/env.local b/ansible/env.local
deleted file mode 100644
--- a/ansible/env.local
+++ /dev/null
@@ -1,43 +0,0 @@
-APP_DOMAIN={{ host }}
-APP_WEBSITE_DOMAIN={{ host }}
-APP_KEY=base64:FG6ECzyAMSmyX+eYwO/FW3bwnarbKkBhqtO65vlMb1E=
-APP_PUBLIC_URL=https://{{ host }}
-COTURN_STATIC_SECRET=uzYguvIl9tpZFMuQOE78DpOi6Jc7VFSD0UAnvgMsg5n4e74MgIf6vQvbc6LWzZjz
-COTURN_PUBLIC_IP='{{ public_ip }}'
-MEET_TURN_SERVER='turn:{{ public_ip }}:3478'
-MEET_WEBRTC_LISTEN_IP='{{ public_ip }}'
-MEET_PUBLIC_DOMAIN={{ host }}
-MEET_SERVER_URLS=https://{{ host }}/meetmedia/api/
-APP_URL=https://{{ host }}
-ASSET_URL=https://{{ host }}
-
-DB_HOST=mariadb
-REDIS_HOST=redis
-IMAP_URI=ssl://kolab:11993
-LDAP_HOSTS=kolab
-
-MOLLIE_KEY=
-STRIPE_KEY=
-STRIPE_PUBLIC_KEY=
-STRIPE_WEBHOOK_SECRET=
-
-OCTANE_HTTP_HOST={{ host }}
-OPENEXCHANGERATES_API_KEY={{ openexchangerates_api_key }}
-FIREBASE_API_KEY={{ firebase_api_key }}
-
-#Generated by php artisan passport:client --password, but can be left hardcoded (the seeder will pick it up)
-PASSPORT_PROXY_OAUTH_CLIENT_ID=942edef5-3dbd-4a14-8e3e-d5d59b727bee
-PASSPORT_PROXY_OAUTH_CLIENT_SECRET=L6L0n56ecvjjK0cJMjeeV1pPAeffUBO0YSSH63wf
-
-#Generated by php artisan passport:client --password, but can be left hardcoded (the seeder will pick it up)
-PASSPORT_COMPANIONAPP_OAUTH_CLIENT_ID=9566e018-f05d-425c-9915-420cdb9258bb
-PASSPORT_COMPANIONAPP_OAUTH_CLIENT_SECRET=XjgV6SU9shO0QFKaU6pQPRC5rJpyRezDJTSoGLgz
-
-APP_PASSPHRASE=simple123
-
-KOLAB_SSL_CERTIFICATE=/etc/letsencrypt/live/{{ host }}/cert.pem
-KOLAB_SSL_CERTIFICATE_FULLCHAIN=/etc/letsencrypt/live/{{ host }}/fullchain.pem
-KOLAB_SSL_CERTIFICATE_KEY=/etc/letsencrypt/live/{{ host }}/privkey.pem
-
-PROXY_SSL_CERTIFICATE=/etc/letsencrypt/live/{{ host }}/fullchain.pem
-PROXY_SSL_CERTIFICATE_KEY=/etc/letsencrypt/live/{{ host }}/privkey.pem
diff --git a/ansible/setup.yml b/ansible/setup.yml
--- a/ansible/setup.yml
+++ b/ansible/setup.yml
@@ -46,18 +46,19 @@
version: "{{ git_branch }}"
force: yes
- - name: "kolab env.local"
- vars:
- host: "{{ hostname }}"
- openexchangerates_api_key: "{{ openexchangerates_api_key }}"
- firebase_api_key: "{{ firebase_api_key }}"
- public_ip: "{{ public_ip }}"
- ansible.builtin.template:
- src: env.local
- dest: /home/kolab/kolab/src/env.local
- owner: kolab
- group: kolab
- mode: '0766'
+ - name: Run bin/configure
+ become: true
+ become_user: kolab
+ ansible.builtin.command: bin/configure.sh config.production
+ args:
+ chdir: /home/kolab/kolab
+ environment:
+ HOSTNAME: "{{ hostname }}"
+ OPENEXCHANGERATES_API_KEY: "{{ openexchangerates_api_key }}"
+ FIREBASE_API_KEY: "{{ firebase_api_key }}"
+ PUBLIC_IP: "{{ public_ip }}"
+ ADMIN_PASSWORD: "{{ admin_password }}"
+
- name: Permit receiving mail
firewalld:
diff --git a/bin/configure.sh b/bin/configure.sh
new file mode 100755
--- /dev/null
+++ b/bin/configure.sh
@@ -0,0 +1,76 @@
+#!/bin/bash
+
+# Uninstall the old config
+if [ -d config ]; then
+ echo "Uninstalling the old config."
+ find -L config/ -type f | while read file; do
+ file=$(echo $file | sed -e 's|^config||g')
+ file="./$file"
+
+ rm -v $file
+ done
+fi
+
+if [ "$1" == "" ]; then
+ echo "Failed to find the configuration folder, please pass one as argument (e.g. config.demo)."
+ exit 1
+fi
+
+if [ ! -d $1 ]; then
+ echo "Failed to find the configuration folder, please pass one as argument (e.g. config.demo)."
+ exit 1
+fi
+
+echo "Installing $1."
+# Link new config
+rm config
+ln -s $1 config
+
+# Install new config
+find -L config/ -type f | while read file; do
+ dir=$(dirname $file | sed -e 's|^config||g')
+ dir="./$dir"
+
+ if [ ! -d $dir ]; then
+ mkdir -p $dir
+ fi
+
+ cp -v $file $dir/
+done
+
+
+# Generate random secrets
+if ! grep -q "COTURN_STATIC_SECRET" .env; then
+ COTURN_STATIC_SECRET=$(openssl rand -hex 32);
+ echo "COTURN_STATIC_SECRET=${COTURN_STATIC_SECRET}" >> src/.env
+fi
+
+if ! grep -q "MEET_WEBHOOK_TOKEN" .env; then
+ MEET_WEBHOOK_TOKEN=$(openssl rand -hex 32);
+ echo "MEET_WEBHOOK_TOKEN=${MEET_WEBHOOK_TOKEN}" >> src/.env
+fi
+
+if ! grep -q "MEET_SERVER_TOKEN" .env; then
+ MEET_SERVER_TOKEN=$(openssl rand -hex 32);
+ echo "MEET_SERVER_TOKEN=${MEET_SERVER_TOKEN}" >> src/.env
+fi
+
+# Customize configuration
+sed -i \
+ -e "s/{{ host }}/${HOSTNAME}/g" \
+ -e "s/{{ openexchangerates_api_key }}/${OPENEXCHANGERATES_API_KEY}/g" \
+ -e "s/{{ firebase_api_key }}/${FIREBASE_API_KEY}/g" \
+ -e "s/{{ public_ip }}/${PUBLIC_IP}/g" \
+ -e "s/{{ admin_password }}/${ADMIN_PASSWORD}/g" \
+ src/.env
+
+if [ -f /etc/letsencrypt/live/${HOSTNAME}/cert.pem ]; then
+ echo "Using the available letsencrypt certificate for ${HOSTNAME}"
+ cat >> .env << EOF
+KOLAB_SSL_CERTIFICATE=/etc/letsencrypt/live/${HOSTNAME}/cert.pem
+KOLAB_SSL_CERTIFICATE_FULLCHAIN=/etc/letsencrypt/live/${HOSTNAME}/fullchain.pem
+KOLAB_SSL_CERTIFICATE_KEY=/etc/letsencrypt/live/${HOSTNAME}/privkey.pem
+PROXY_SSL_CERTIFICATE=/etc/letsencrypt/live/${HOSTNAME}/fullchain.pem
+PROXY_SSL_CERTIFICATE_KEY=/etc/letsencrypt/live/${HOSTNAME}/privkey.pem
+EOF
+fi
diff --git a/bin/deploy.sh b/bin/deploy.sh
--- a/bin/deploy.sh
+++ b/bin/deploy.sh
@@ -1,4 +1,2 @@
#!/bin/bash
bin/quickstart.sh --nodev
-
-docker exec -w /src/kolabsrc/ kolab-webapp ./artisan user:assign john@kolab.org beta
diff --git a/bin/quickstart.sh b/bin/quickstart.sh
--- a/bin/quickstart.sh
+++ b/bin/quickstart.sh
@@ -16,41 +16,25 @@
base_dir=$(dirname $(dirname $0))
-# Always reset .env with .env.example
-cp src/.env.example src/.env
-if [ -f "src/env.local" ]; then
- # Ensure there's a line ending
- echo "" >> src/.env
- cat src/env.local >> src/.env
-fi
export DOCKER_BUILDKIT=0
-COMPOSE_ARGS=
-if [ "$1" != "--nodev" ]; then
- COMPOSE_ARGS="-f docker-compose.yml -f docker-compose.local.yml"
-fi
-
docker-compose down --remove-orphans
docker volume rm kolab_mariadb || :
docker volume rm kolab_imap || :
docker volume rm kolab_ldap || :
-if [ "$1" != "--nodev" ]; then
- src/artisan octane:stop >/dev/null 2>&1 || :
- src/artisan horizon:terminate >/dev/null 2>&1 || :
-else
- # If we switch from an existing development setup to a compose deployment,
- # we don't have a nice way to terminate octane/horizon.
- # We can't use the artisan command because it will just block if redis is,
- # no longer available, so we just kill all artisan processes running.
- pkill -9 -f artisan || :
-fi
+# We can't use the following artisan commands because it will just block if redis is unavailable:
+# src/artisan octane:stop >/dev/null 2>&1 || :
+# src/artisan horizon:terminate >/dev/null 2>&1 || :
+# we therefore just kill all artisan processes running.
+pkill -9 -f artisan || :
+pkill -9 -f swoole || :
bin/regen-certs
docker-compose build coturn kolab mariadb meet pdns proxy redis haproxy
-docker-compose ${COMPOSE_ARGS} up -d coturn kolab mariadb meet pdns redis
+docker-compose up -d coturn kolab mariadb meet pdns redis
# Workaround until we have docker-compose --wait (https://github.com/docker/compose/pull/8777)
function wait_for_container {
@@ -154,4 +138,4 @@
popd
-docker-compose ${COMPOSE_ARGS} up --no-deps -d proxy haproxy
+docker-compose up --no-deps -d proxy haproxy
diff --git a/ci/Makefile b/ci/Makefile
--- a/ci/Makefile
+++ b/ci/Makefile
@@ -1,17 +1,9 @@
-HOSTNAME=ci.local
-PUBLIC_IP=127.0.0.1
-OPENEXCHANGERATES_API_KEY=dummy
-FIREBASE_API_KEY=dummy
PWD=$(shell pwd)
configure:
cd .. ; \
- cp ci/env.local src/env.local ; \
- sed -i 's/{{ host }}/${HOSTNAME}/g' src/env.local ; \
- sed -i 's/{{ public_ip }}/${PUBLIC_IP}/g' src/env.local ; \
- sed -i 's/{{ openexchangerates_api_key }}/${OPENEXCHANGERATES_API_KEY}/g' src/env.local ; \
- sed -i 's/{{ firebase_api_key }}/${FIREBASE_API_KEY}/g' src/env.local ;
+ bin/configure.sh config.demo ;
setup:
cd .. && bin/quickstart.sh --nodev
diff --git a/ci/env.local b/ci/env.local
deleted file mode 100644
--- a/ci/env.local
+++ /dev/null
@@ -1,49 +0,0 @@
-MFA_DSN=mysql://root:Welcome2KolabSystems@mariadb/roundcube
-APP_DOMAIN={{ host }}
-APP_WEBSITE_DOMAIN={{ host }}
-APP_KEY=base64:FG6ECzyAMSmyX+eYwO/FW3bwnarbKkBhqtO65vlMb1E=
-APP_PUBLIC_URL=https://{{ host }}
-COTURN_STATIC_SECRET=uzYguvIl9tpZFMuQOE78DpOi6Jc7VFSD0UAnvgMsg5n4e74MgIf6vQvbc6LWzZjz
-COTURN_PUBLIC_IP='{{ public_ip }}'
-MEET_TURN_SERVER='turn:{{ public_ip }}:3478'
-MEET_WEBRTC_LISTEN_IP='{{ public_ip }}'
-MEET_PUBLIC_DOMAIN={{ host }}
-MEET_SERVER_URLS=https://{{ host }}/meetmedia/api/
-MEET_LISTENING_HOST=172.18.0.1
-WEBMAIL_URL=/roundcubemail
-APP_URL=https://{{ host }}
-ASSET_URL=https://{{ host }}
-
-DB_HOST=mariadb
-REDIS_HOST=redis
-IMAP_URI=ssl://kolab:11993
-LDAP_HOSTS=kolab
-
-MOLLIE_KEY=
-STRIPE_KEY=
-STRIPE_PUBLIC_KEY=
-STRIPE_WEBHOOK_SECRET=
-
-OCTANE_HTTP_HOST={{ host }}
-OPENEXCHANGERATES_API_KEY={{ openexchangerates_api_key }}
-FIREBASE_API_KEY={{ firebase_api_key }}
-
-#Generated by php artisan passport:client --password, but can be left hardcoded (the seeder will pick it up)
-PASSPORT_PROXY_OAUTH_CLIENT_ID=942edef5-3dbd-4a14-8e3e-d5d59b727bee
-PASSPORT_PROXY_OAUTH_CLIENT_SECRET=L6L0n56ecvjjK0cJMjeeV1pPAeffUBO0YSSH63wf
-
-#Generated by php artisan passport:client --password, but can be left hardcoded (the seeder will pick it up)
-PASSPORT_COMPANIONAPP_OAUTH_CLIENT_ID=9566e018-f05d-425c-9915-420cdb9258bb
-PASSPORT_COMPANIONAPP_OAUTH_CLIENT_SECRET=XjgV6SU9shO0QFKaU6pQPRC5rJpyRezDJTSoGLgz
-
-APP_TENANT_ID=42
-APP_PASSPHRASE=simple123
-
-MAIL_DRIVER=log
-
-KOLAB_SSL_CERTIFICATE=/etc/pki/tls/certs/kolab.hosted.com.cert
-KOLAB_SSL_CERTIFICATE_FULLCHAIN=/etc/pki/tls/certs/kolab.hosted.com.chain.pem
-KOLAB_SSL_CERTIFICATE_KEY=/etc/pki/tls/certs/kolab.hosted.com.key
-
-PROXY_SSL_CERTIFICATE=/etc/certs/imap.hosted.com.cert
-PROXY_SSL_CERTIFICATE_KEY=/etc/certs/imap.hosted.com.key
diff --git a/config.demo/docker-compose.override.yml b/config.demo/docker-compose.override.yml
new file mode 100644
--- /dev/null
+++ b/config.demo/docker-compose.override.yml
@@ -0,0 +1,47 @@
+version: '3'
+services:
+ haproxy:
+ depends_on:
+ proxy:
+ condition: service_healthy
+ proxy:
+ depends_on:
+ kolab:
+ condition: service_healthy
+ webapp:
+ condition: service_healthy
+ build:
+ context: ./docker/proxy/
+ args:
+ APP_WEBSITE_DOMAIN: ${APP_WEBSITE_DOMAIN:?err}
+ SSL_CERTIFICATE: ${PROXY_SSL_CERTIFICATE:?err}
+ SSL_CERTIFICATE_KEY: ${PROXY_SSL_CERTIFICATE_KEY:?err}
+ healthcheck:
+ interval: 10s
+ test: "kill -0 $$(cat /run/nginx.pid)"
+ timeout: 5s
+ retries: 30
+ container_name: kolab-proxy
+ hostname: proxy
+ image: kolab-proxy
+ extra_hosts:
+ - "meet:${MEET_LISTENING_HOST}"
+ networks:
+ kolab:
+ ipv4_address: 172.18.0.7
+ tmpfs:
+ - /run
+ - /tmp
+ - /var/run
+ - /var/tmp
+ tty: true
+ volumes:
+ - ./docker/certs/:/etc/certs/:ro
+ - /etc/letsencrypt/:/etc/letsencrypt/:ro
+ ports:
+ # - "80:80"
+ - "443:443"
+ - "465:465"
+ - "587:587"
+ - "143:143"
+ - "993:993"
diff --git a/src/.env.example b/config.demo/src/.env
rename from src/.env.example
rename to config.demo/src/.env
--- a/src/.env.example
+++ b/config.demo/src/.env
@@ -3,7 +3,7 @@
APP_KEY=
APP_DEBUG=true
APP_URL=https://kolab.local
-#APP_PASSPHRASE=
+APP_PASSPHRASE=simple123
APP_PUBLIC_URL=https://kolab.local
APP_DOMAIN=kolab.local
APP_WEBSITE_DOMAIN=kolab.local
@@ -18,6 +18,7 @@
APP_WITH_FILES=1
APP_LDAP=1
+APP_IMAP=0
APP_HEADER_CSP="connect-src 'self'; child-src 'self'; font-src 'self'; form-action 'self' data:; frame-ancestors 'self'; img-src blob: data: 'self' *; media-src 'self'; object-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-eval' 'unsafe-inline'; default-src 'self';"
APP_HEADER_XFO=sameorigin
@@ -53,7 +54,7 @@
OPENEXCHANGERATES_API_KEY="from openexchangerates.org"
-MFA_DSN=mysql://roundcube:Welcome2KolabSystems@mariadb/roundcube
+MFA_DSN=mysql://roundcube:kolab@mariadb/roundcube
MFA_TOTP_DIGITS=6
MFA_TOTP_INTERVAL=30
MFA_TOTP_DIGEST=sha1
@@ -113,7 +114,7 @@
REDIS_PASSWORD=null
REDIS_PORT=6379
-OCTANE_HTTP_HOST=127.0.0.1
+OCTANE_HTTP_HOST=0.0.0.0
SWOOLE_PACKAGE_MAX_LENGTH=10485760
PAYMENT_PROVIDER=
@@ -183,3 +184,23 @@
PROXY_SSL_CERTIFICATE=/etc/certs/imap.hosted.com.cert
PROXY_SSL_CERTIFICATE_KEY=/etc/certs/imap.hosted.com.key
+
+APP_KEY=base64:FG6ECzyAMSmyX+eYwO/FW3bwnarbKkBhqtO65vlMb1E=
+COTURN_STATIC_SECRET=uzYguvIl9tpZFMuQOE78DpOi6Jc7VFSD0UAnvgMsg5n4e74MgIf6vQvbc6LWzZjz
+
+MOLLIE_KEY="from mollie"
+STRIPE_KEY="from stripe"
+STRIPE_PUBLIC_KEY="from stripe"
+STRIPE_WEBHOOK_SECRET="from stripe"
+
+OX_API_KEY="from openexchange"
+FIREBASE_API_KEY="from firebase"
+
+#Generated by php artisan passport:client --password, but can be left hardcoded (the seeder will pick it up)
+PASSPORT_PROXY_OAUTH_CLIENT_ID=942edef5-3dbd-4a14-8e3e-d5d59b727bee
+PASSPORT_PROXY_OAUTH_CLIENT_SECRET=L6L0n56ecvjjK0cJMjeeV1pPAeffUBO0YSSH63wf
+
+#Generated by php artisan passport:client --password, but can be left hardcoded (the seeder will pick it up)
+PASSPORT_COMPANIONAPP_OAUTH_CLIENT_ID=9566e018-f05d-425c-9915-420cdb9258bb
+PASSPORT_COMPANIONAPP_OAUTH_CLIENT_SECRET=XjgV6SU9shO0QFKaU6pQPRC5rJpyRezDJTSoGLgz
+
diff --git a/src/database/migrations/2021_01_26_150000_change_sku_descriptions.php b/config.demo/src/database/migrations/2021_01_26_150000_change_sku_descriptions.php
rename from src/database/migrations/2021_01_26_150000_change_sku_descriptions.php
rename to config.demo/src/database/migrations/2021_01_26_150000_change_sku_descriptions.php
diff --git a/src/database/migrations/2021_02_19_100000_transaction_amount_fix.php b/config.demo/src/database/migrations/2021_02_19_100000_transaction_amount_fix.php
rename from src/database/migrations/2021_02_19_100000_transaction_amount_fix.php
rename to config.demo/src/database/migrations/2021_02_19_100000_transaction_amount_fix.php
diff --git a/src/database/migrations/2021_12_15_100000_rename_beta_skus.php b/config.demo/src/database/migrations/2021_12_15_100000_rename_beta_skus.php
rename from src/database/migrations/2021_12_15_100000_rename_beta_skus.php
rename to config.demo/src/database/migrations/2021_12_15_100000_rename_beta_skus.php
diff --git a/config.demo/src/database/migrations/2022_05_13_090000_permissions_and_room_subscriptions.php b/config.demo/src/database/migrations/2022_05_13_090000_permissions_and_room_subscriptions.php
new file mode 100644
--- /dev/null
+++ b/config.demo/src/database/migrations/2022_05_13_090000_permissions_and_room_subscriptions.php
@@ -0,0 +1,57 @@
+ 'group-room',
+ 'name' => 'Group conference room',
+ 'description' => 'Shareable audio & video conference room',
+ 'cost' => 0,
+ 'units_free' => 0,
+ 'period' => 'monthly',
+ 'handler_class' => 'App\Handlers\GroupRoom',
+ 'active' => true,
+ ]);
+
+ \App\Sku::create([
+ 'title' => 'room',
+ 'name' => 'Standard conference room',
+ 'description' => 'Audio & video conference room',
+ 'cost' => 0,
+ 'units_free' => 0,
+ 'period' => 'monthly',
+ 'handler_class' => 'App\Handlers\Room',
+ 'active' => true,
+ ]);
+ }
+
+ /**
+ * Reverse the migrations.
+ */
+ public function down(): void
+ {
+ \App\Sku::where('title', 'room')->delete();
+ \App\Sku::where('title', 'group-room')->delete();
+
+ \App\Sku::create([
+ 'title' => 'meet',
+ 'name' => 'Voice & Video Conferencing (public beta)',
+ 'description' => 'Video conferencing tool',
+ 'cost' => 0,
+ 'units_free' => 0,
+ 'period' => 'monthly',
+ 'handler_class' => 'App\Handlers\Meet',
+ 'active' => true,
+ ]);
+ }
+};
diff --git a/src/database/migrations/2022_07_08_100000_fix_group_sku_name.php b/config.demo/src/database/migrations/2022_07_08_100000_fix_group_sku_name.php
rename from src/database/migrations/2022_07_08_100000_fix_group_sku_name.php
rename to config.demo/src/database/migrations/2022_07_08_100000_fix_group_sku_name.php
diff --git a/config.demo/src/database/migrations/2022_09_08_100001_plans_free_months.php b/config.demo/src/database/migrations/2022_09_08_100001_plans_free_months.php
new file mode 100644
--- /dev/null
+++ b/config.demo/src/database/migrations/2022_09_08_100001_plans_free_months.php
@@ -0,0 +1,26 @@
+update(['free_months' => 1]);
+ }
+
+ /**
+ * Reverse the migrations.
+ *
+ * @return void
+ */
+ public function down()
+ {
+ }
+};
diff --git a/config.demo/src/database/seeds/DatabaseSeeder.php b/config.demo/src/database/seeds/DatabaseSeeder.php
new file mode 100644
--- /dev/null
+++ b/config.demo/src/database/seeds/DatabaseSeeder.php
@@ -0,0 +1,32 @@
+call([
+ Seeds\IP4NetSeeder::class,
+ Seeds\TenantSeeder::class,
+ Seeds\DiscountSeeder::class,
+ Seeds\DomainSeeder::class,
+ Seeds\SkuSeeder::class,
+ Seeds\PackageSeeder::class,
+ Seeds\PlanSeeder::class,
+ Seeds\PowerDNSSeeder::class,
+ Seeds\UserSeeder::class,
+ Seeds\OauthClientSeeder::class,
+ Seeds\ResourceSeeder::class,
+ Seeds\SharedFolderSeeder::class,
+ Seeds\MeetRoomSeeder::class,
+ ]);
+ }
+}
diff --git a/src/database/seeds/local/DiscountSeeder.php b/config.demo/src/database/seeds/DiscountSeeder.php
rename from src/database/seeds/local/DiscountSeeder.php
rename to config.demo/src/database/seeds/DiscountSeeder.php
--- a/src/database/seeds/local/DiscountSeeder.php
+++ b/config.demo/src/database/seeds/DiscountSeeder.php
@@ -1,6 +1,6 @@
NS RRs refer to ns0{1,2}.
-WOAT_NS1=ns01.domain.tld
-WOAT_NS2=ns02.domain.tld
-
REDIS_HOST=redis
REDIS_PASSWORD=null
REDIS_PORT=6379
-OCTANE_HTTP_HOST=127.0.0.1
+OCTANE_HTTP_HOST={{ host }}
SWOOLE_PACKAGE_MAX_LENGTH=10485760
-PAYMENT_PROVIDER=
-MOLLIE_KEY=
-STRIPE_KEY=
-STRIPE_PUBLIC_KEY=
-STRIPE_WEBHOOK_SECRET=
-
MAIL_DRIVER=log
MAIL_MAILER=smtp
MAIL_HOST=smtp.mailtrap.io
@@ -139,24 +125,7 @@
DNS_STATIC="%s. MX 10 ext-mx01.mykolab.com."
DNS_COPY_FROM=null
-AWS_ACCESS_KEY_ID=
-AWS_SECRET_ACCESS_KEY=
-AWS_DEFAULT_REGION=us-east-1
-AWS_BUCKET=
-AWS_USE_PATH_STYLE_ENDPOINT=false
-
-PUSHER_APP_ID=
-PUSHER_APP_KEY=
-PUSHER_APP_SECRET=
-PUSHER_APP_CLUSTER=mt1
-
MIX_ASSET_PATH='/'
-MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
-MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"
-
-# Generate with ./artisan passport:client --password
-#PASSPORT_PROXY_OAUTH_CLIENT_ID=
-#PASSPORT_PROXY_OAUTH_CLIENT_SECRET=
PASSPORT_PRIVATE_KEY=
PASSPORT_PUBLIC_KEY=
@@ -183,3 +152,6 @@
PROXY_SSL_CERTIFICATE=/etc/certs/imap.hosted.com.cert
PROXY_SSL_CERTIFICATE_KEY=/etc/certs/imap.hosted.com.key
+
+OPENEXCHANGERATES_API_KEY={{ openexchangerates_api_key }}
+FIREBASE_API_KEY={{ firebase_api_key }}
diff --git a/config.prod/src/database/migrations b/config.prod/src/database/migrations
new file mode 120000
--- /dev/null
+++ b/config.prod/src/database/migrations
@@ -0,0 +1 @@
+../../../config.demo/src/database/migrations
\ No newline at end of file
diff --git a/config.prod/src/database/seeds/AdminSeeder.php b/config.prod/src/database/seeds/AdminSeeder.php
new file mode 100644
--- /dev/null
+++ b/config.prod/src/database/seeds/AdminSeeder.php
@@ -0,0 +1,86 @@
+ 'domain-hosting', 'tenant_id' => \config('app.tenant_id')])->first();
+ $skuGroupware = Sku::where(['title' => 'groupware', 'tenant_id' => \config('app.tenant_id')])->first();
+ $skuMailbox = Sku::where(['title' => 'mailbox', 'tenant_id' => \config('app.tenant_id')])->first();
+ $skuStorage = Sku::where(['title' => 'storage', 'tenant_id' => \config('app.tenant_id')])->first();
+
+ $packageKolab = Package::create(
+ [
+ 'title' => 'kolab',
+ 'name' => 'Groupware Account',
+ 'description' => 'A fully functional groupware account.',
+ 'discount_rate' => 0,
+ ]
+ );
+ $packageKolab->skus()->saveMany([
+ $skuMailbox,
+ $skuGroupware,
+ $skuStorage
+ ]);
+
+
+ $packageDomain = Package::create(
+ [
+ 'title' => 'domain-hosting',
+ 'name' => 'Domain Hosting',
+ 'description' => 'Use your own, existing domain.',
+ 'discount_rate' => 0,
+ ]
+ );
+ $packageDomain->skus()->saveMany([
+ $skuDomain
+ ]);
+
+
+
+ //Create primary domain
+ $appDomain = Domain::create(
+ [
+ 'namespace' => \config('app.domain'),
+ 'status' => DOMAIN::STATUS_CONFIRMED + Domain::STATUS_ACTIVE,
+ 'type' => Domain::TYPE_PUBLIC,
+ ]
+ );
+
+ //Create admin user
+ $admin = User::create(
+ [
+ 'email' => 'admin@' . \config('app.domain'),
+ 'password' => \App\Utils::generatePassphrase()
+ ]
+ );
+
+ $admin->setSettings(
+ [
+ 'first_name' => 'Admin',
+ ]
+ );
+
+ $appDomain->assignPackage($packageDomain, $admin);
+ $admin->assignPackage($packageKolab);
+ }
+}
+
diff --git a/config.prod/src/database/seeds/AppKeySeeder.php b/config.prod/src/database/seeds/AppKeySeeder.php
new file mode 100644
--- /dev/null
+++ b/config.prod/src/database/seeds/AppKeySeeder.php
@@ -0,0 +1,62 @@
+generateRandomKey();
+ $this->writeNewEnvironmentFileWith($key);
+ }
+
+ /**
+ * Generate a random key for the application.
+ *
+ * @return string
+ */
+ protected function generateRandomKey()
+ {
+ return 'base64:' . base64_encode(
+ Encrypter::generateKey(\config('app.cipher'))
+ );
+ }
+
+ /**
+ * Write a new environment file with the given key.
+ *
+ * @param string $key
+ * @return void
+ */
+ protected function writeNewEnvironmentFileWith($key)
+ {
+ file_put_contents(\app()->environmentFilePath(), preg_replace(
+ $this->keyReplacementPattern(),
+ 'APP_KEY=' . $key,
+ file_get_contents(\app()->environmentFilePath())
+ ));
+ }
+
+ /**
+ * Get a regex pattern that will match env APP_KEY with any random key.
+ *
+ * @return string
+ */
+ protected function keyReplacementPattern()
+ {
+ $escaped = preg_quote('=' . \config('app.key'), '/');
+ return "/^APP_KEY{$escaped}/m";
+ }
+}
+
diff --git a/config.prod/src/database/seeds/DatabaseSeeder.php b/config.prod/src/database/seeds/DatabaseSeeder.php
new file mode 100644
--- /dev/null
+++ b/config.prod/src/database/seeds/DatabaseSeeder.php
@@ -0,0 +1,24 @@
+call([
+ Seeds\AppKeySeeder::class,
+ Seeds\PassportSeeder::class,
+ Seeds\PowerDNSSeeder::class,
+ Seeds\SkuSeeder::class,
+ Seeds\AdminSeeder::class,
+ ]);
+ }
+}
diff --git a/config.prod/src/database/seeds/PassportSeeder.php b/config.prod/src/database/seeds/PassportSeeder.php
new file mode 100644
--- /dev/null
+++ b/config.prod/src/database/seeds/PassportSeeder.php
@@ -0,0 +1,103 @@
+getPublicKey());
+ file_put_contents($privateKey, (string) $key);
+
+ $this->writeNewEnvironmentFileWith('PASSPORT_PRIVATE_KEY', 'passport.private_key', $key);
+ $this->writeNewEnvironmentFileWith('PASSPORT_PUBLIC_KEY', 'passport.public_key', (string) $key->getPublicKey());
+
+ //Create a password grant client for the webapp
+ $secret = $this->generateRandomKey();
+
+ $client = Passport::client()->forceFill([
+ 'user_id' => null,
+ 'name' => "Kolab Password Grant Client",
+ 'secret' => $secret,
+ 'provider' => 'users',
+ 'redirect' => 'https://' . \config('app.website_domain'),
+ 'personal_access_client' => 0,
+ 'password_client' => 1,
+ 'revoked' => false,
+ ]);
+ $client->save();
+
+ $this->writeNewEnvironmentFileWith('PASSPORT_PROXY_OAUTH_CLIENT_ID', 'auth.proxy.client_id', $client->id);
+ $this->writeNewEnvironmentFileWith('PASSPORT_PROXY_OAUTH_CLIENT_SECRET', 'auth.proxy.client_secret', $secret);
+ }
+
+ /**
+ * Generate a random key for the application.
+ *
+ * @return string
+ */
+ protected function generateRandomKey()
+ {
+ return base64_encode(
+ Encrypter::generateKey(\config('app.cipher'))
+ );
+ }
+
+ /**
+ * Write a new environment file with the given key.
+ *
+ * @param string $key
+ * @param string $configKey
+ * @param string $value
+ * @return void
+ */
+ protected function writeNewEnvironmentFileWith($key, $configKey, $value)
+ {
+ $path = \app()->environmentFilePath();
+ $count = 0;
+ $line = "{$key}=\"{$value}\"";
+ $result = preg_replace(
+ $this->keyReplacementPattern($key, \config($configKey)),
+ $line,
+ file_get_contents($path),
+ -1,
+ $count
+ );
+ //Append if it doesn't exist
+ if ($count == 0) {
+ $result = $result . "\n$line";
+ }
+ file_put_contents($path, $result);
+ }
+
+ /**
+ * Get a regex pattern that will match env APP_KEY with any random key.
+ *
+ * @return string
+ */
+ protected function keyReplacementPattern($key, $value)
+ {
+ $escaped = preg_quote("={$value}", '/');
+ return "/^{$key}{$escaped}/m";
+ }
+}
diff --git a/config.prod/src/database/seeds/PowerDNSSeeder.php b/config.prod/src/database/seeds/PowerDNSSeeder.php
new file mode 100644
--- /dev/null
+++ b/config.prod/src/database/seeds/PowerDNSSeeder.php
@@ -0,0 +1,23 @@
+ '_woat.' . \config('app.domain')
+ ]
+ );
+ }
+}
diff --git a/src/database/seeds/production/SkuSeeder.php b/config.prod/src/database/seeds/SkuSeeder.php
rename from src/database/seeds/production/SkuSeeder.php
rename to config.prod/src/database/seeds/SkuSeeder.php
--- a/src/database/seeds/production/SkuSeeder.php
+++ b/config.prod/src/database/seeds/SkuSeeder.php
@@ -1,6 +1,6 @@
'mailbox',
'name' => 'User Mailbox',
'description' => 'Just a mailbox',
- 'cost' => 444,
+ 'cost' => 500,
'units_free' => 0,
'period' => 'monthly',
'handler_class' => 'App\Handlers\Mailbox',
@@ -66,8 +66,8 @@
'title' => 'storage',
'name' => 'Storage Quota',
'description' => 'Some wiggle room',
- 'cost' => 50,
- 'units_free' => 2,
+ 'cost' => 25,
+ 'units_free' => 5,
'period' => 'monthly',
'handler_class' => 'App\Handlers\Storage',
'active' => true,
@@ -76,7 +76,7 @@
'title' => 'groupware',
'name' => 'Groupware Features',
'description' => 'Groupware functions like Calendar, Tasks, Notes, etc.',
- 'cost' => 555,
+ 'cost' => 490,
'units_free' => 0,
'period' => 'monthly',
'handler_class' => 'App\Handlers\Groupware',
@@ -86,7 +86,7 @@
'title' => 'resource',
'name' => 'Resource',
'description' => 'Reservation taker',
- 'cost' => 0,
+ 'cost' => 101,
'period' => 'monthly',
'handler_class' => 'App\Handlers\Resource',
'active' => true,
@@ -98,7 +98,7 @@
'cost' => 89,
'period' => 'monthly',
'handler_class' => 'App\Handlers\SharedFolder',
- 'active' => false,
+ 'active' => true,
],
[
'title' => '2fa',
@@ -114,7 +114,7 @@
'title' => 'activesync',
'name' => 'Activesync',
'description' => 'Mobile synchronization',
- 'cost' => 100,
+ 'cost' => 0,
'units_free' => 0,
'period' => 'monthly',
'handler_class' => 'App\Handlers\Activesync',
@@ -123,7 +123,7 @@
[
'title' => 'beta',
'name' => 'Private Beta (invitation only)',
- 'description' => 'Access to the private beta program subscriptions',
+ 'description' => 'Access to the private beta program features',
'cost' => 0,
'units_free' => 0,
'period' => 'monthly',
@@ -151,7 +151,7 @@
'active' => true,
],
[
- 'title' => 'room',
+ 'title' => 'room',
'name' => 'Standard conference room',
'description' => 'Audio & video conference room',
'cost' => 0,
@@ -164,7 +164,7 @@
foreach ($skus as $sku) {
// Check existence because migration might have added this already
- if (!Sku::where('title', $sku['title'])->first()) {
+ if (!Sku::where('title', $sku['title'])->where('tenant_id', \config('app.tenant_id'))->first()) {
Sku::create($sku);
}
}
diff --git a/docker-compose.local.yml b/docker-compose.local.yml
deleted file mode 100644
--- a/docker-compose.local.yml
+++ /dev/null
@@ -1,21 +0,0 @@
-version: '3'
-services:
- kolab:
- ports:
- - "389:389"
- - "8880:8880"
- - "8443:8443"
- - "10143:10143"
- - "10587:10587"
- - "11143:11143"
- - "11993:11993"
- - "12143:12143"
- mariadb:
- ports:
- - "3306:3306"
- redis:
- ports:
- - "6379:6379"
- proxy:
- extra_hosts:
- - "webapp:127.0.0.1"
diff --git a/docker-compose.yml b/docker-compose.yml
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -34,23 +34,27 @@
environment:
- APP_DOMAIN=${APP_DOMAIN}
- LDAP_HOST=127.0.0.1
- - LDAP_ADMIN_BIND_DN="cn=Directory Manager"
- - LDAP_ADMIN_BIND_PW=Welcome2KolabSystems
+ - LDAP_ADMIN_BIND_DN=${LDAP_ADMIN_BIND_DN}
+ - LDAP_ADMIN_BIND_PW=${LDAP_ADMIN_BIND_PW}
+ - LDAP_SERVICE_BIND_PW=${LDAP_SERVICE_BIND_PW}
+ - LDAP_HOSTED_BIND_PW=${LDAP_HOSTED_BIND_PW}
- DB_HOST=mariadb
- - DB_ROOT_PASSWORD=Welcome2KolabSystems
+ - DB_ROOT_PASSWORD=${DB_PASSWORD}
- DB_HKCCP_DATABASE=${DB_DATABASE}
- DB_HKCCP_USERNAME=${DB_USERNAME}
- DB_HKCCP_PASSWORD=${DB_PASSWORD}
- DB_KOLAB_DATABASE=kolab
- DB_KOLAB_USERNAME=kolab
- - DB_KOLAB_PASSWORD=Welcome2KolabSystems
+ - DB_KOLAB_PASSWORD=${DB_PASSWORD}
- DB_RC_USERNAME=roundcube
- - DB_RC_PASSWORD=Welcome2KolabSystems
+ - DB_RC_PASSWORD=${DB_PASSWORD}
- SSL_CERTIFICATE=${KOLAB_SSL_CERTIFICATE:?err}
- SSL_CERTIFICATE_FULLCHAIN=${KOLAB_SSL_CERTIFICATE_FULLCHAIN:?err}
- SSL_CERTIFICATE_KEY=${KOLAB_SSL_CERTIFICATE_KEY:?err}
- IMAP_HOST=127.0.0.1
- IMAP_PORT=11993
+ - IMAP_ADMIN_LOGIN=${IMAP_ADMIN_LOGIN}
+ - IMAP_ADMIN_PASSWORD=${IMAP_ADMIN_PASSWORD}
- MAIL_HOST=127.0.0.1
- MAIL_PORT=10587
healthcheck:
@@ -90,7 +94,7 @@
mariadb:
container_name: kolab-mariadb
environment:
- - MARIADB_ROOT_PASSWORD=Welcome2KolabSystems
+ - MARIADB_ROOT_PASSWORD=${DB_PASSWORD}
- TZ="+02:00"
- DB_HKCCP_DATABASE=${DB_DATABASE}
- DB_HKCCP_USERNAME=${DB_USERNAME}
@@ -107,9 +111,6 @@
- ./docker/mariadb/mysql-init/:/docker-entrypoint-initdb.d/
- mariadb:/var/lib/mysql
haproxy:
- depends_on:
- proxy:
- condition: service_healthy
build:
context: ./docker/haproxy/
healthcheck:
@@ -134,6 +135,11 @@
pdns:
build:
context: ./docker/pdns/
+ args:
+ DB_HOST: ${DB_HOST:?err}
+ DB_DATABASE: ${DB_DATABASE:?err}
+ DB_USERNAME: ${DB_USERNAME:?err}
+ DB_PASSWORD: ${DB_PASSWORD:?err}
container_name: kolab-pdns
hostname: pdns
depends_on:
@@ -156,47 +162,6 @@
tty: true
volumes:
- /sys/fs/cgroup:/sys/fs/cgroup:ro
- proxy:
- depends_on:
- kolab:
- condition: service_healthy
- webapp:
- condition: service_healthy
- build:
- context: ./docker/proxy/
- args:
- APP_WEBSITE_DOMAIN: ${APP_WEBSITE_DOMAIN:?err}
- SSL_CERTIFICATE: ${PROXY_SSL_CERTIFICATE:?err}
- SSL_CERTIFICATE_KEY: ${PROXY_SSL_CERTIFICATE_KEY:?err}
- healthcheck:
- interval: 10s
- test: "kill -0 $$(cat /run/nginx.pid)"
- timeout: 5s
- retries: 30
- container_name: kolab-proxy
- hostname: proxy
- image: kolab-proxy
- extra_hosts:
- - "meet:${MEET_LISTENING_HOST}"
- networks:
- kolab:
- ipv4_address: 172.18.0.7
- tmpfs:
- - /run
- - /tmp
- - /var/run
- - /var/tmp
- tty: true
- volumes:
- - ./docker/certs/:/etc/certs/:ro
- - /etc/letsencrypt/:/etc/letsencrypt/:ro
- ports:
- # - "80:80"
- - "443:443"
- - "465:465"
- - "587:587"
- - "143:143"
- - "993:993"
redis:
build:
context: ./docker/redis/
@@ -212,8 +177,6 @@
- kolab
volumes:
- ./docker/redis/redis.conf:/usr/local/etc/redis/redis.conf:ro
- # ports:
- # - "6379:6379"
webapp:
build:
context: ./docker/webapp/
diff --git a/docker/kolab/kolab.conf b/docker/kolab/kolab.conf
--- a/docker/kolab/kolab.conf
+++ b/docker/kolab/kolab.conf
@@ -16,9 +16,9 @@
supported_controls = 0,2,3
base_dn = dc=mgmt,dc=com
bind_dn = cn=Directory Manager
-bind_pw = Welcome2KolabSystems
+bind_pw =
service_bind_dn = uid=kolab-service,ou=Special Users,dc=mgmt,dc=com
-service_bind_pw = Welcome2KolabSystems
+service_bind_pw =
user_base_dn = dc=hosted,dc=com
user_scope = sub
user_filter = (objectclass=inetorgperson)
@@ -45,7 +45,7 @@
auth_attributes = mail, uid
[kolab_smtp_access_policy]
-cache_uri = mysql://kolab:Welcome2KolabSystems@mariadb/kolab
+cache_uri = mysql://kolab:@mariadb/kolab
cache_retention = 86400
address_search_attrs = mail, alias
delegate_sender_header = True
@@ -59,14 +59,14 @@
hosted_root_dn = dc=hosted,dc=com
api_url = http://127.0.0.1:9080/kolab-webadmin/api
skin = default
-sql_uri = mysql://kolab:Welcome2KolabSystems@mariadb/kolab
+sql_uri = mysql://kolab:@mariadb/kolab
ssl_verify_peer = false
ssl_verify_host = false
[cyrus-imap]
uri = imaps://127.0.0.1:11993
admin_login = cyrus-admin
-admin_password = Welcome2KolabSystems
+admin_password =
[cyrus-sasl]
result_attribute = mail
diff --git a/docker/kolab/utils/settings.sh b/docker/kolab/utils/settings.sh
--- a/docker/kolab/utils/settings.sh
+++ b/docker/kolab/utils/settings.sh
@@ -4,21 +4,19 @@
export domain=${DOMAIN:-"mgmt.com"}
export domain_db=${DOMAIN_DB:-"mgmt_com"}
export ldap_host=${LDAP_HOST}
-export ldap_binddn=${LDAP_ADMIN_BIND_DN:-"cn=Directory Manager"}
-export ldap_bindpw=${LDAP_ADMIN_BIND_PW:-"Welcome2KolabSystems"}
+export ldap_binddn=${LDAP_ADMIN_BIND_DN}
+export ldap_bindpw=${LDAP_ADMIN_BIND_PW}
-export cyrus_admin=${IMAP_ADMIN_LOGIN:-"cyrus-admin"}
+export cyrus_admin=${IMAP_ADMIN_LOGIN}
export imap_host=${IMAP_HOST}
-export cyrus_admin_pw=${IMAP_ADMIN_PASSWORD:-"Welcome2KolabSystems"}
+export cyrus_admin_pw=${IMAP_ADMIN_PASSWORD}
-export kolab_service_pw=${LDAP_SERVICE_BIND_PW:-"Welcome2KolabSystems"}
-export hosted_kolab_service_pw=${LDAP_HOSTED_BIND_PW:-"Welcome2KolabSystems"}
+export kolab_service_pw=${LDAP_SERVICE_BIND_PW}
+export hosted_kolab_service_pw=${LDAP_HOSTED_BIND_PW}
export hosted_domain=${HOSTED_DOMAIN:-"hosted.com"}
export hosted_domain_db=${HOSTED_DOMAIN_DB:-"hosted_com"}
export hosted_domain_rootdn=${LDAP_HOSTED_ROOT_DN:-"dc=hosted,dc=com"}
export domain_base_dn=${LDAP_DOMAIN_BASE_DN:-"ou=Domains,dc=mgmt,dc=com"}
-
-export default_user_password=${DEFAULT_USER_PASSWORD:-"Welcome2KolabSystems"}
diff --git a/docker/pdns/Dockerfile b/docker/pdns/Dockerfile
--- a/docker/pdns/Dockerfile
+++ b/docker/pdns/Dockerfile
@@ -23,6 +23,17 @@
COPY pdns.conf /etc/pdns/pdns.conf
COPY recursor.conf /etc/pdns-recursor/recursor.conf
+ARG DB_HOST
+ARG DB_DATABASE
+ARG DB_USERNAME
+ARG DB_PASSWORD
+RUN sed -i -r \
+ -e "s|DB_HOST|$DB_HOST|g" \
+ -e "s|DB_DATABASE|$DB_DATABASE|g" \
+ -e "s|DB_USERNAME|$DB_USERNAME|g" \
+ -e "s|DB_PASSWORD|$DB_PASSWORD|g" \
+ /etc/pdns/pdns.conf
+
RUN systemctl disable systemd-resolved && systemctl enable pdns && systemctl enable pdns-recursor
# This is how we could run pdns without systemd
diff --git a/docker/pdns/pdns.conf b/docker/pdns/pdns.conf
--- a/docker/pdns/pdns.conf
+++ b/docker/pdns/pdns.conf
@@ -6,10 +6,10 @@
edns-subnet-processing
-gmysql-host=mariadb
-gmysql-dbname=kolabdev
-gmysql-password=kolab
-gmysql-user=kolabdev
+gmysql-host=DB_HOST
+gmysql-dbname=DB_DATABASE
+gmysql-password=DB_PASSWORD
+gmysql-user=DB_USERNAME
gmysql-activate-domain-key-query=UPDATE powerdns_cryptokeys SET active=1 WHERE domain_id=(SELECT id FROM domains WHERE name=?) AND powerdns_cryptokeys.id=?
gmysql-add-domain-key-query=INSERT INTO powerdns_cryptokeys (domain_id, flags, active, content) SELECT id, ?, ?, ? FROM powerdns_domains WHERE name=?
diff --git a/docker/tests/init.sh b/docker/tests/init.sh
--- a/docker/tests/init.sh
+++ b/docker/tests/init.sh
@@ -1,5 +1,6 @@
#!/bin/bash
#set -e
+rm -rf /src/kolabsrc
sudo cp -a /src/kolabsrc.orig /src/kolabsrc
sudo chmod 777 -R /src/kolabsrc
cd /src/kolabsrc
diff --git a/docker/webapp/init.sh b/docker/webapp/init.sh
--- a/docker/webapp/init.sh
+++ b/docker/webapp/init.sh
@@ -16,22 +16,12 @@
./artisan cache:clear
./artisan horizon:install
-if [ ! -f storage/oauth-public.key -o ! -f storage/oauth-private.key ]; then
- ./artisan passport:keys --force
-fi
-
-cat >> .env << EOF
-PASSPORT_PRIVATE_KEY="$(cat storage/oauth-private.key)"
-PASSPORT_PUBLIC_KEY="$(cat storage/oauth-public.key)"
-EOF
-
if [ ! -f 'resources/countries.php' ]; then
./artisan data:countries
fi
npm run dev
-rm -rf database/database.sqlite
./artisan db:ping --wait
php -dmemory_limit=512M ./artisan migrate:refresh --seed
./artisan data:import || :
diff --git a/src/.gitignore b/src/.gitignore
--- a/src/.gitignore
+++ b/src/.gitignore
@@ -24,4 +24,6 @@
composer.lock
resources/countries.php
resources/build/js/
+database/seeds/
+src/public/themes/active
cache
diff --git a/src/.s2i/bin/assemble b/src/.s2i/bin/assemble
--- a/src/.s2i/bin/assemble
+++ b/src/.s2i/bin/assemble
@@ -20,13 +20,6 @@
fix-permissions ./
-if [ -f ".env.local" ]; then
- # Ensure there's a line ending
- echo "---->> Append .env.local"
- echo "" >> .env
- cat .env.local >> .env
-fi
-
if [ -f "composer.json" ]; then
echo "--->> Detected composer.json, running install"
composer_install
diff --git a/src/database/migrations/2021_04_08_150000_signup_code_headers.php b/src/database/migrations/2021_04_08_150000_signup_code_headers.php
--- a/src/database/migrations/2021_04_08_150000_signup_code_headers.php
+++ b/src/database/migrations/2021_04_08_150000_signup_code_headers.php
@@ -2,7 +2,6 @@
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
-use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;
// phpcs:ignore
diff --git a/src/database/migrations/2021_07_12_100000_create_tenant_settings_table.php b/src/database/migrations/2021_07_12_100000_create_tenant_settings_table.php
--- a/src/database/migrations/2021_07_12_100000_create_tenant_settings_table.php
+++ b/src/database/migrations/2021_07_12_100000_create_tenant_settings_table.php
@@ -2,7 +2,6 @@
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
-use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;
// phpcs:ignore
diff --git a/src/database/migrations/2022_05_13_100000_permissions_and_room_subscriptions.php b/src/database/migrations/2022_05_13_100000_permissions_and_room_subscriptions.php
--- a/src/database/migrations/2022_05_13_100000_permissions_and_room_subscriptions.php
+++ b/src/database/migrations/2022_05_13_100000_permissions_and_room_subscriptions.php
@@ -38,54 +38,32 @@
);
// Create the new SKUs
- if (!\App\Sku::where('title', 'room')->first()) {
- $sku = \App\Sku::create([
- 'title' => 'group-room',
- 'name' => 'Group conference room',
- 'description' => 'Shareable audio & video conference room',
- 'cost' => 0,
- 'units_free' => 0,
- 'period' => 'monthly',
- 'handler_class' => 'App\Handlers\GroupRoom',
- 'active' => true,
- ]);
+ $sku = \App\Sku::where('title', 'room')->first();
- $sku = \App\Sku::create([
- 'title' => 'room',
- 'name' => 'Standard conference room',
- 'description' => 'Audio & video conference room',
- 'cost' => 0,
- 'units_free' => 0,
- 'period' => 'monthly',
- 'handler_class' => 'App\Handlers\Room',
- 'active' => true,
- ]);
+ // Create the entitlement for every existing room
+ foreach (\App\Meet\Room::get() as $room) {
+ $user = \App\User::find($room->user_id); // @phpstan-ignore-line
+ if (!$user) {
+ $room->forceDelete();
+ continue;
+ }
- // Create the entitlement for every existing room
- foreach (\App\Meet\Room::get() as $room) {
- $user = \App\User::find($room->user_id); // @phpstan-ignore-line
- if (!$user) {
- $room->forceDelete();
- continue;
- }
-
- // Set tenant_id
- if ($user->tenant_id) {
- $room->tenant_id = $user->tenant_id;
- $room->save();
- }
-
- $wallet = $user->wallets()->first();
-
- \App\Entitlement::create([
- 'wallet_id' => $wallet->id,
- 'sku_id' => $sku->id,
- 'cost' => 0,
- 'fee' => 0,
- 'entitleable_id' => $room->id,
- 'entitleable_type' => \App\Meet\Room::class
- ]);
+ // Set tenant_id
+ if ($user->tenant_id) {
+ $room->tenant_id = $user->tenant_id;
+ $room->save();
}
+
+ $wallet = $user->wallets()->first();
+
+ \App\Entitlement::create([
+ 'wallet_id' => $wallet->id,
+ 'sku_id' => $sku->id,
+ 'cost' => 0,
+ 'fee' => 0,
+ 'entitleable_id' => $room->id,
+ 'entitleable_type' => \App\Meet\Room::class
+ ]);
}
// Remove 'meet' SKU/entitlements
@@ -137,19 +115,6 @@
);
\App\Entitlement::where('entitleable_type', \App\Meet\Room::class)->forceDelete();
- \App\Sku::where('title', 'room')->delete();
- \App\Sku::where('title', 'group-room')->delete();
-
- \App\Sku::create([
- 'title' => 'meet',
- 'name' => 'Voice & Video Conferencing (public beta)',
- 'description' => 'Video conferencing tool',
- 'cost' => 0,
- 'units_free' => 0,
- 'period' => 'monthly',
- 'handler_class' => 'App\Handlers\Meet',
- 'active' => true,
- ]);
Schema::dropIfExists('permissions');
}
diff --git a/src/database/migrations/2022_09_08_100000_plans_free_months.php b/src/database/migrations/2022_09_08_100000_plans_free_months.php
--- a/src/database/migrations/2022_09_08_100000_plans_free_months.php
+++ b/src/database/migrations/2022_09_08_100000_plans_free_months.php
@@ -2,7 +2,6 @@
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
-use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
@@ -20,8 +19,6 @@
$table->tinyInteger('free_months')->unsigned()->default(0);
}
);
-
- DB::table('plans')->update(['free_months' => 1]);
}
/**
diff --git a/src/database/seeds/DatabaseSeeder.php b/src/database/seeds/DatabaseSeeder.php
deleted file mode 100644
--- a/src/database/seeds/DatabaseSeeder.php
+++ /dev/null
@@ -1,44 +0,0 @@
- $name) {
- $class = "Database\\Seeds\\$env\\$name";
- $seeders[$idx] = class_exists($class) ? $class : null;
- }
-
- $seeders = array_filter($seeders);
-
- $this->call($seeders);
- }
-}
diff --git a/src/database/seeds/production/DiscountSeeder.php b/src/database/seeds/production/DiscountSeeder.php
deleted file mode 100644
--- a/src/database/seeds/production/DiscountSeeder.php
+++ /dev/null
@@ -1,33 +0,0 @@
- 'Free Account',
- 'discount' => 100,
- 'active' => true,
- ]
- );
-
- Discount::create(
- [
- 'description' => 'Student or Educational Institution',
- 'discount' => 30,
- 'active' => true,
- ]
- );
- }
-}
diff --git a/src/database/seeds/production/DomainSeeder.php b/src/database/seeds/production/DomainSeeder.php
deleted file mode 100644
--- a/src/database/seeds/production/DomainSeeder.php
+++ /dev/null
@@ -1,52 +0,0 @@
- $domain,
- 'status' => Domain::STATUS_CONFIRMED + Domain::STATUS_ACTIVE,
- 'type' => Domain::TYPE_PUBLIC
- ]
- );
- }
- }
-}
diff --git a/src/database/seeds/production/PackageSeeder.php b/src/database/seeds/production/PackageSeeder.php
deleted file mode 100644
--- a/src/database/seeds/production/PackageSeeder.php
+++ /dev/null
@@ -1,86 +0,0 @@
- 'activesync']);
- $skuGroupware = Sku::firstOrCreate(['title' => 'groupware']);
- $skuMailbox = Sku::firstOrCreate(['title' => 'mailbox']);
- $skuStorage = Sku::firstOrCreate(['title' => 'storage']);
-
- $package = Package::create(
- [
- 'title' => 'kolab',
- 'name' => 'Groupware Account',
- 'description' => 'A fully functional groupware account.',
- 'discount_rate' => 0
- ]
- );
-
- $skus = [
- $skuMailbox,
- $skuGroupware,
- $skuStorage,
- $skuActiveSync
- ];
-
- $package->skus()->saveMany($skus);
-
- // This package contains 2 units of the storage SKU, which just so happens to also
- // be the number of SKU free units.
- $package->skus()->updateExistingPivot(
- $skuStorage,
- ['qty' => 2],
- false
- );
-
- $package = Package::create(
- [
- 'title' => 'lite',
- 'name' => 'Lite Account',
- 'description' => 'Just mail and no more.',
- 'discount_rate' => 0
- ]
- );
-
- $skus = [
- $skuMailbox,
- $skuStorage
- ];
-
- $package->skus()->saveMany($skus);
-
- $package->skus()->updateExistingPivot(
- Sku::firstOrCreate(['title' => 'storage']),
- ['qty' => 2],
- false
- );
-
- $package = Package::create(
- [
- 'title' => 'domain-hosting',
- 'name' => 'Domain Hosting',
- 'description' => 'Use your own, existing domain.',
- 'discount_rate' => 0
- ]
- );
-
- $skus = [
- Sku::firstOrCreate(['title' => 'domain-hosting'])
- ];
-
- $package->skus()->saveMany($skus);
- }
-}
diff --git a/src/database/seeds/production/PlanSeeder.php b/src/database/seeds/production/PlanSeeder.php
deleted file mode 100644
--- a/src/database/seeds/production/PlanSeeder.php
+++ /dev/null
@@ -1,76 +0,0 @@
-Everything you need to get started or try Kolab Now, including:
-
- - Perfect for anyone wanting to move to Kolab Now
- - Suite of online apps: Secure email, calendar, address book, files and more
- - Access for anywhere: Sync all your devices to your Kolab Now account
- - Secure hosting: Managed right here on our own servers in Switzerland
- - Start protecting your data today, no ads, no crawling, no compromise
- - An ideal replacement for services like Gmail, Office 365, etc…
-
-EOD;
-
- $plan = Plan::create(
- [
- 'title' => 'individual',
- 'name' => 'Individual Account',
- 'description' => $description,
- 'free_months' => 1,
- 'discount_qty' => 0,
- 'discount_rate' => 0
- ]
- );
-
- $packages = [
- Package::firstOrCreate(['title' => 'kolab'])
- ];
-
- $plan->packages()->saveMany($packages);
-
- $description = <<<'EOD'
-All the features of the Individual Account, with the following extras:
-
- - Perfect for anyone wanting to move a group or small business to Kolab Now
- - Recommended to support users from 1 to 100
- - Use your own personal domains with Kolab Now
- - Manage and add users through our online admin area
- - Flexible pricing based on user count
-
-EOD;
-
- $plan = Plan::create(
- [
- 'title' => 'group',
- 'name' => 'Group Account',
- 'description' => $description,
- 'free_months' => 1,
- 'discount_qty' => 0,
- 'discount_rate' => 0
- ]
- );
-
- $packages = [
- Package::firstOrCreate(['title' => 'domain-hosting']),
- Package::firstOrCreate(['title' => 'kolab']),
- ];
-
- $plan->packages()->saveMany($packages);
- }
-}