diff --git a/.env b/.env --- a/.env +++ b/.env @@ -1 +1 @@ -src/.env \ No newline at end of file +config/env \ No newline at end of file diff --git a/bin/configure.sh b/bin/configure.sh new file mode 100755 --- /dev/null +++ b/bin/configure.sh @@ -0,0 +1,26 @@ +#!/bin/bash + +if [ ! -d config ]; then + echo "Failed to find a configuration folder. Use e.g. 'ln -s config.local config'" + exit 1 +fi + +rm -f src/resources/themes/active +if [ -d config/theme ]; then + cp -r config/theme src/resources/themes/active +else + ln -s ../default src/resources/themes/active +fi + +rm -rf src/database/seeds +cp -rL config/seeds src/database/seeds + +if [ -d config/seed-migrations ]; then + rm -rf src/database/seed-migrations + cp -rL config/seed-migrations src/database/seed-migrations +fi + +rm -f .env +ln -s config/env .env +rm -f src/.env +cp config/env src/.env diff --git a/bin/quickstart.sh b/bin/quickstart.sh --- a/bin/quickstart.sh +++ b/bin/quickstart.sh @@ -16,14 +16,7 @@ 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 @@ -37,17 +30,13 @@ 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 || : +bin/configure.sh 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 @@ -147,7 +136,7 @@ pushd ${base_dir}/src/ rm -rf database/database.sqlite ./artisan db:ping --wait -php -dmemory_limit=512M ./artisan migrate:refresh --seed +php -dmemory_limit=512M ./artisan migrate:refresh --path=/database/migrations --path=/database/seed-migrations --seed ./artisan data:import || : nohup ./artisan octane:start --host=$(grep OCTANE_HTTP_HOST .env | tail -n1 | sed "s/OCTANE_HTTP_HOST=//") > octane.out & nohup ./artisan horizon > horizon.out & diff --git a/config.local/README.md b/config.local/README.md new file mode 100644 --- /dev/null +++ b/config.local/README.md @@ -0,0 +1,7 @@ + + +src/resources/themes/$theme + +# Custom Theme + +Add to theme subdirectory diff --git a/src/.env.example b/config.local/env rename from src/.env.example rename to config.local/env --- a/src/.env.example +++ b/config.local/env @@ -7,7 +7,7 @@ APP_PUBLIC_URL=https://kolab.local APP_DOMAIN=kolab.local APP_WEBSITE_DOMAIN=kolab.local -APP_THEME=default +APP_THEME=active APP_TENANT_ID=5 APP_LOCALE=en APP_LOCALES= @@ -187,3 +187,29 @@ 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 + +APP_LDAP=1 + +MOLLIE_KEY=test_9A9yMAm7KKsWUGrRnd6y2pUBrBjPWc +STRIPE_KEY=sk_test_TJGHJIymaUklGhCouWeYrJPV +STRIPE_PUBLIC_KEY=pk_test_oVKmR8lEIzVa6gDRZOET0vcF +STRIPE_WEBHOOK_SECRET=whsec_lKDxl4kAvwgRvmmPuwX3t80s0YPy289W + +# Do we need this or is localhost fine? +#OCTANE_HTTP_HOST=kolab.local +OX_API_KEY=2e706a1510e64d00816adfa40de8a679 +FIREBASE_API_KEY=AAAAozVvJlM:APA91bEO9PiIGl4_jCYagUc5KZQjM9yK8Fc6sJPSLzW1T6yVdLD6A1h48YO8AiOVqHwy1His0B_U_2_pMKq2K5QEev6E5Ljz0hy8PHXoslco57f5bpd9cVQdtYLF_M1dPY6z2fw9KWkf + +#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 diff --git a/src/database/migrations/2021_01_26_150000_change_sku_descriptions.php b/config.local/seed-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.local/seed-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.local/seed-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.local/seed-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.local/seed-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.local/seed-migrations/2021_12_15_100000_rename_beta_skus.php diff --git a/config.local/seed-migrations/2022_05_13_090000_permissions_and_room_subscriptions.php b/config.local/seed-migrations/2022_05_13_090000_permissions_and_room_subscriptions.php new file mode 100644 --- /dev/null +++ b/config.local/seed-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.local/seed-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.local/seed-migrations/2022_07_08_100000_fix_group_sku_name.php diff --git a/config.local/seed-migrations/2022_09_08_100001_plans_free_months.php b/config.local/seed-migrations/2022_09_08_100001_plans_free_months.php new file mode 100644 --- /dev/null +++ b/config.local/seed-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.local/seeds/DatabaseSeeder.php b/config.local/seeds/DatabaseSeeder.php new file mode 100644 --- /dev/null +++ b/config.local/seeds/DatabaseSeeder.php @@ -0,0 +1,32 @@ +call([ + Local\IP4NetSeeder::class, + Local\TenantSeeder::class, + Local\DiscountSeeder::class, + Local\DomainSeeder::class, + Local\SkuSeeder::class, + Local\PackageSeeder::class, + Local\PlanSeeder::class, + Local\PowerDNSSeeder::class, + Local\UserSeeder::class, + Local\OauthClientSeeder::class, + Local\ResourceSeeder::class, + Local\SharedFolderSeeder::class, + Local\MeetRoomSeeder::class, + ]); + } +} diff --git a/src/database/seeds/local/DiscountSeeder.php b/config.local/seeds/DiscountSeeder.php rename from src/database/seeds/local/DiscountSeeder.php rename to config.local/seeds/DiscountSeeder.php diff --git a/src/database/seeds/local/DomainSeeder.php b/config.local/seeds/DomainSeeder.php rename from src/database/seeds/local/DomainSeeder.php rename to config.local/seeds/DomainSeeder.php diff --git a/src/database/seeds/local/IP4NetSeeder.php b/config.local/seeds/IP4NetSeeder.php rename from src/database/seeds/local/IP4NetSeeder.php rename to config.local/seeds/IP4NetSeeder.php diff --git a/src/database/seeds/local/MeetRoomSeeder.php b/config.local/seeds/MeetRoomSeeder.php rename from src/database/seeds/local/MeetRoomSeeder.php rename to config.local/seeds/MeetRoomSeeder.php diff --git a/src/database/seeds/local/OauthClientSeeder.php b/config.local/seeds/OauthClientSeeder.php rename from src/database/seeds/local/OauthClientSeeder.php rename to config.local/seeds/OauthClientSeeder.php diff --git a/src/database/seeds/local/PackageSeeder.php b/config.local/seeds/PackageSeeder.php rename from src/database/seeds/local/PackageSeeder.php rename to config.local/seeds/PackageSeeder.php diff --git a/src/database/seeds/local/PlanSeeder.php b/config.local/seeds/PlanSeeder.php rename from src/database/seeds/local/PlanSeeder.php rename to config.local/seeds/PlanSeeder.php diff --git a/src/database/seeds/local/PowerDNSSeeder.php b/config.local/seeds/PowerDNSSeeder.php rename from src/database/seeds/local/PowerDNSSeeder.php rename to config.local/seeds/PowerDNSSeeder.php diff --git a/src/database/seeds/local/ResourceSeeder.php b/config.local/seeds/ResourceSeeder.php rename from src/database/seeds/local/ResourceSeeder.php rename to config.local/seeds/ResourceSeeder.php diff --git a/src/database/seeds/local/SharedFolderSeeder.php b/config.local/seeds/SharedFolderSeeder.php rename from src/database/seeds/local/SharedFolderSeeder.php rename to config.local/seeds/SharedFolderSeeder.php diff --git a/src/database/seeds/local/SkuSeeder.php b/config.local/seeds/SkuSeeder.php rename from src/database/seeds/local/SkuSeeder.php rename to config.local/seeds/SkuSeeder.php diff --git a/src/database/seeds/local/TenantSeeder.php b/config.local/seeds/TenantSeeder.php rename from src/database/seeds/local/TenantSeeder.php rename to config.local/seeds/TenantSeeder.php diff --git a/src/database/seeds/local/UserSeeder.php b/config.local/seeds/UserSeeder.php rename from src/database/seeds/local/UserSeeder.php rename to config.local/seeds/UserSeeder.php diff --git a/config.production/seeds/DatabaseSeeder.php b/config.production/seeds/DatabaseSeeder.php new file mode 100644 --- /dev/null +++ b/config.production/seeds/DatabaseSeeder.php @@ -0,0 +1,24 @@ +call([ + Local\DomainSeeder::class, + Local\DiscountSeeder::class, + Local\SkuSeeder::class, + Local\PackageSeeder::class, + Local\PlanSeeder::class, + ]); + } +} diff --git a/src/database/seeds/production/DiscountSeeder.php b/config.production/seeds/DiscountSeeder.php rename from src/database/seeds/production/DiscountSeeder.php rename to config.production/seeds/DiscountSeeder.php diff --git a/src/database/seeds/production/DomainSeeder.php b/config.production/seeds/DomainSeeder.php rename from src/database/seeds/production/DomainSeeder.php rename to config.production/seeds/DomainSeeder.php diff --git a/src/database/seeds/production/PackageSeeder.php b/config.production/seeds/PackageSeeder.php rename from src/database/seeds/production/PackageSeeder.php rename to config.production/seeds/PackageSeeder.php diff --git a/src/database/seeds/production/PlanSeeder.php b/config.production/seeds/PlanSeeder.php rename from src/database/seeds/production/PlanSeeder.php rename to config.production/seeds/PlanSeeder.php diff --git a/src/database/seeds/production/SkuSeeder.php b/config.production/seeds/SkuSeeder.php rename from src/database/seeds/production/SkuSeeder.php rename to config.production/seeds/SkuSeeder.php diff --git a/docker/webapp/init.sh b/docker/webapp/init.sh --- a/docker/webapp/init.sh +++ b/docker/webapp/init.sh @@ -32,7 +32,7 @@ rm -rf database/database.sqlite ./artisan db:ping --wait -php -dmemory_limit=512M ./artisan migrate:refresh --seed +php -dmemory_limit=512M ./artisan migrate:refresh --path=/database/migrations --path=/database/seed-migrations --seed ./artisan data:import || : nohup ./artisan horizon >/dev/null 2>&1 & ./artisan octane:start --host=$(grep OCTANE_HTTP_HOST .env | tail -n1 | sed "s/OCTANE_HTTP_HOST=//") diff --git a/src/.gitignore b/src/.gitignore --- a/src/.gitignore +++ b/src/.gitignore @@ -24,4 +24,7 @@ composer.lock resources/countries.php resources/build/js/ +database/seeds/ +database/seed-migrations/ +src/public/themes/active cache 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 @@ -8,6 +8,10 @@ { /** * Run the migrations. + * FIXME: This migratoin is problematic in that it contains a seed-migration, but we can't untangle it easily. + * We use old data to migrate the seed, and then drop the old data. + * I suppose we could externalize the creation of the new skus into a seed-migration, + * and then do the migration over to the new sku in this migration. */ public function up(): void { @@ -38,54 +42,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 +119,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); - } -}