Compare commits

..

No commits in common. "main" and "c502694e59ba064e62011aa83d64e94bae4983c8" have entirely different histories.

819 changed files with 25554 additions and 40066 deletions

View File

@ -13,7 +13,7 @@ insert_final_newline = true
trim_trailing_whitespace = true trim_trailing_whitespace = true
max_line_length = 120 max_line_length = 120
[{.babelrc,package.json,.eslintrc.json,.prettierrc.json}] [{.babelrc,package.json}]
indent_size = 2 indent_size = 2
[docker/**.conf] [docker/**.conf]
@ -27,8 +27,6 @@ max_line_length = unset
indent_size = 2 indent_size = 2
[*.js] [*.js]
indent_size = 2
max_line_length = unset
quote_type = single quote_type = single
[{LICENSE,db/*.sql}] [{LICENSE,db/*.sql}]

View File

@ -1,3 +0,0 @@
/public
/node_modules
/vendor

View File

@ -1,10 +0,0 @@
{
"parser": "@babel/eslint-parser",
"extends": ["plugin:editorconfig/all", "prettier"],
"plugins": ["editorconfig"],
"rules": {
"prefer-arrow-callback": "error",
"prefer-template": "error",
"no-var": "error"
}
}

5
.gitignore vendored
View File

@ -26,10 +26,8 @@ _vimrc_local.vim
# Project files # Project files
/config/config.php /config/config.php
/config/lang/
/public/*.xml
/public/coverage
/test/coverage /test/coverage
/public/coverage
/coverage /coverage
/unittests.xml /unittests.xml
/resources/lang/*/*.mo /resources/lang/*/*.mo
@ -42,4 +40,3 @@ _vimrc_local.vim
/public/assets /public/assets
/package-lock.json /package-lock.json
/yarn-error.log /yarn-error.log
/.yarn-cache

View File

@ -12,7 +12,6 @@ variables:
DOCROOT: /var/www/ DOCROOT: /var/www/
stages: stages:
- prepare
- validate - validate
- build - build
- test - test
@ -21,90 +20,44 @@ stages:
- deploy-production - deploy-production
- stop - stop
.use_cache: &use_cache
cache:
key: "$CI_JOB_NAME-$CI_COMMIT_REF_SLUG"
paths:
- .yarn-cache/
- vendor/
# for jobs that depend on composer
.use_composer: &use_composer
<<: *use_cache
needs:
- composer install
before_script:
- composer install --no-ansi --no-progress
# for jobs that depend on yarn
.use_yarn: &use_yarn
<<: *use_cache
needs:
- yarn install
before_script:
- yarn install --check-frontend --cache-folder .yarn-cache
# #
# Preparation # Validation
# #
composer validate: check-style:
image: composer:latest image: composer:latest
stage: prepare stage: validate
before_script:
- composer --no-ansi global config --no-plugins allow-plugins.dealerdirect/phpcodesniffer-composer-installer true
- composer --no-ansi global require slevomat/coding-standard squizlabs/php_codesniffer
- export PATH=$PATH:$COMPOSER_HOME/vendor/bin
script:
- phpcs -p --no-colors --basepath="$PWD"
check-editorconfig:
image: mstruebing/editorconfig-checker
stage: validate
script:
- ec -v
validate-composer:
image: composer:latest
stage: validate
script: script:
- composer --no-ansi validate --strict - composer --no-ansi validate --strict
composer install: validate-yarn:
<<: *use_cache
image: composer:latest
stage: prepare
needs:
- composer audit
- composer validate
script:
- composer install --no-ansi --no-progress
composer audit:
image: php:latest
stage: prepare
needs:
- composer validate
before_script:
- curl -Ls https://github.com/symfony/cli/releases/latest/download/symfony_linux_amd64.gz | gzip -d > /bin/symfony
- chmod +x /bin/symfony
script:
- symfony check:security --no-ansi
yarn-validate:
image: node:alpine image: node:alpine
stage: prepare stage: validate
before_script: before_script:
- yarn global add package-json-validator - yarn global add package-json-validator
- export PATH=$PATH:~/.yarn/bin - export PATH=$PATH:~/.yarn/bin
script: script:
- pjv - pjv
yarn install:
<<: *use_cache
image: node:alpine
stage: prepare
needs:
- yarn-validate
- yarn audit
script:
- yarn install --check-frontend --cache-folder .yarn-cache
yarn audit:
image: node:alpine
stage: prepare
needs:
- yarn-validate
script:
- yarn audit
generate-version: generate-version:
image: alpine image: alpine
stage: prepare stage: validate
artifacts: artifacts:
name: "${CI_JOB_NAME}_${CI_JOB_ID}_version" name: "${CI_JOB_NAME}_${CI_JOB_ID}_version"
expire_in: 1 day expire_in: 1 day
@ -113,64 +66,10 @@ generate-version:
before_script: before_script:
- apk add -q git - apk add -q git
script: script:
- > - VERSION="$(git describe --abbrev=0 --tags)-${CI_COMMIT_REF_NAME}+${CI_PIPELINE_ID}.${CI_COMMIT_SHORT_SHA}"
VERSION="$(\
git describe --exact-match --tags HEAD 2> /dev/null\
|| (\
(git describe --abbrev=0 --tags | tr -d '\n')\
&& echo "-${CI_COMMIT_REF_NAME}+${CI_PIPELINE_ID}.${CI_COMMIT_SHORT_SHA}"\
)\
)"
- echo "${VERSION}" - echo "${VERSION}"
- echo -n "${VERSION}" > storage/app/VERSION - echo -n "${VERSION}" > storage/app/VERSION
#
# Validation
#
phpcs:
<<: *use_composer
image: composer:latest
stage: validate
script:
# tell phpcs the PHP version to check against
# we are using the min suppported version here
- ./vendor/bin/phpcs --config-set php_version 80100
- ./vendor/bin/phpcs -p --no-colors --basepath="$PWD"
phpstan:
<<: *use_composer
image: composer:latest
stage: validate
script:
- ./vendor/bin/phpstan --no-progress
yarn check:
<<: *use_yarn
image: node:alpine
stage: validate
script:
- yarn check
yarn lint:
<<: *use_yarn
image: node:alpine
stage: validate
script:
# Install git, so that tools can use .gitignore.
# Not done in before_script because of <<: *use_yarn.
- apk add --no-cache git
- yarn lint
translations lint:
image: alpine
stage: prepare
before_script:
- apk add gettext
script:
- find resources/lang -type f -name '*.po' -exec sh -c 'msgfmt "${1%.*}.po" -o"${1%.*}.mo"' shell {} \;
- '[[ $(find resources/lang -type f -name "*.po" | wc -l) == $(find resources/lang -type f -name "*.mo" | wc -l) ]]'
# #
# Build # Build
# #
@ -188,25 +87,39 @@ build-image:
<<: *container_definition <<: *container_definition
stage: build stage: build
needs: needs:
- phpcs - check-editorconfig
- phpstan - check-style
- composer validate
- yarn check
- yarn lint
- translations lint
- generate-version - generate-version
- validate-composer
- validate-yarn
dependencies: dependencies:
- generate-version - generate-version
script: script:
- /kaniko/executor --context ${CI_PROJECT_DIR} - /kaniko/executor --context ${CI_PROJECT_DIR}
--dockerfile ${CI_PROJECT_DIR}/docker/Dockerfile --dockerfile ${CI_PROJECT_DIR}/docker/Dockerfile
--destination "${TEST_IMAGE}" --destination "${TEST_IMAGE}"
--cache=true
# #
# Test # Test
# #
audit-composer:
image: php:latest
stage: test
needs: [ ]
before_script:
- curl -Ls https://github.com/symfony/cli/releases/latest/download/symfony_linux_amd64.gz | gzip -d > /bin/symfony
- chmod +x /bin/symfony
script:
- symfony check:security --no-ansi
audit-yarn:
image: node:alpine
stage: test
needs: [ ]
script:
- yarn audit
test: test:
image: image:
name: ${TEST_IMAGE} name: ${TEST_IMAGE}
@ -235,11 +148,10 @@ test:
- ./bin/migrate - ./bin/migrate
script: script:
- >- - >-
php -d memory_limit=1024M -d pcov.enabled=1 -d pcov.directory=. vendor/bin/phpunit -vvv --colors=never php -d pcov.enabled=1 -d pcov.directory=. vendor/bin/phpunit -vvv --colors=never
--coverage-text --coverage-html "${HOMEDIR}/coverage/" --coverage-text --coverage-html "${HOMEDIR}/coverage/"
--log-junit "${HOMEDIR}/unittests.xml" --log-junit "${HOMEDIR}/unittests.xml"
after_script: after_script:
- sed -i 's~/var/www/~~' unittests.xml
- '"${DOCROOT}/bin/migrate" down' - '"${DOCROOT}/bin/migrate" down'
dump-database: dump-database:
@ -260,9 +172,6 @@ dump-database:
- cd "${DOCROOT}" - cd "${DOCROOT}"
- ./bin/migrate - ./bin/migrate
script: script:
- >-
mysql -h "${MYSQL_HOST}" -u "${MYSQL_USER}" -p"${MYSQL_PASSWORD}" "${MYSQL_DATABASE}"
-e 'UPDATE users SET api_key="" WHERE name="admin"'
- >- - >-
mysqldump -h "${MYSQL_HOST}" -u "${MYSQL_USER}" -p"${MYSQL_PASSWORD}" "${MYSQL_DATABASE}" mysqldump -h "${MYSQL_HOST}" -u "${MYSQL_USER}" -p"${MYSQL_PASSWORD}" "${MYSQL_DATABASE}"
> "${HOMEDIR}/initial-install.sql" > "${HOMEDIR}/initial-install.sql"
@ -292,11 +201,7 @@ release-image:
- test - test
dependencies: [ ] dependencies: [ ]
script: script:
- echo -e "FROM ${TEST_IMAGE}" - echo -e "FROM ${TEST_IMAGE}" | /kaniko/executor --dockerfile /dev/stdin --destination "${RELEASE_IMAGE}"
| /kaniko/executor
--dockerfile /dev/stdin
--destination "${RELEASE_IMAGE}"
--cache=true
only: only:
- main - main
@ -313,8 +218,8 @@ build-release-file:
stage: release stage: release
needs: needs:
- build-image - build-image
- yarn audit - audit-yarn
- composer audit - audit-composer
- test - test
- dump-database - dump-database
- generate-assets - generate-assets
@ -369,7 +274,6 @@ deploy:
dependencies: *deploy_needs dependencies: *deploy_needs
environment: environment:
name: rsync-staging name: rsync-staging
deployment_tier: development
only: only:
- main - main
script: script:
@ -392,10 +296,7 @@ deploy:
- test - test
- build-image - build-image
before_script: before_script:
- &kubectl_deployment_script |- - &kubectl_deployment_script if [[ -z "${KUBE_INGRESS_BASE_DOMAIN}" ]]; then echo "Skipping deployment"; exit; fi
if [[ -z "${KUBE_INGRESS_BASE_DOMAIN}" ]]; then echo "Skipping deployment"; exit; fi
if [[ -n "${KUBE_CONTEXT}" ]]; then kubectl config use-context "${KUBE_CONTEXT}"; fi
if [[ -z "${KUBE_NAMESPACE}" ]]; then export KUBE_NAMESPACE=${CI_PROJECT_PATH_SLUG}-${CI_ENVIRONMENT_SLUG}; fi
.deploy_k8s: &deploy_k8s .deploy_k8s: &deploy_k8s
<<: *kubectl_deployment <<: *kubectl_deployment
@ -410,12 +311,8 @@ deploy:
# CI_ENVIRONMENT_URL is the URL configured in the GitLab environment # CI_ENVIRONMENT_URL is the URL configured in the GitLab environment
- export CI_ENVIRONMENT_URL="${CI_ENVIRONMENT_URL:-https://${CI_PROJECT_PATH_SLUG}.${KUBE_INGRESS_BASE_DOMAIN}/}" - export CI_ENVIRONMENT_URL="${CI_ENVIRONMENT_URL:-https://${CI_PROJECT_PATH_SLUG}.${KUBE_INGRESS_BASE_DOMAIN}/}"
- export CI_IMAGE=$RELEASE_IMAGE - export CI_IMAGE=$RELEASE_IMAGE
- export CI_INGRESS_CLASS=${CI_INGRESS_CLASS:-traefik}
- export CI_INGRESS_MATCH=${CI_INGRESS_MATCH:-$( if [[ "$CI_INGRESS_CLASS" == "nginx" ]]; then echo '/?(.*)'; fi )}
- export CI_INGRESS_TRAEFIK_ENTRYPOINT=${CI_INGRESS_TRAEFIK_ENTRYPOINT:-websecure}
- export CI_INGRESS_DOMAIN=$(echo "$CI_ENVIRONMENT_URL" | grep -oP '(?:https?://)?\K([^/]+)' | head -n1) - export CI_INGRESS_DOMAIN=$(echo "$CI_ENVIRONMENT_URL" | grep -oP '(?:https?://)?\K([^/]+)' | head -n1)
- export CI_INGRESS_PATH=$(echo "$CI_ENVIRONMENT_URL" | grep -oP '(?:https?://)?(?:[^/])+\K(.*)') - export CI_INGRESS_PATH=$(echo "$CI_ENVIRONMENT_URL" | grep -oP '(?:https?://)?(?:[^/])+\K(.*)')
- '[[ "${CI_INGRESS_PATH}" == /* ]] || export CI_INGRESS_PATH="/${CI_INGRESS_PATH}"'
- export CI_KUBE_NAMESPACE=$KUBE_NAMESPACE - export CI_KUBE_NAMESPACE=$KUBE_NAMESPACE
# Any available storage class like default, local-path (if you know what you are doing ;), longhorn etc. # Any available storage class like default, local-path (if you know what you are doing ;), longhorn etc.
- export CI_PVC_SC=${CI_PVC_SC:-"${CI_PVC_SC_LOCAL:-local-path}"} - export CI_PVC_SC=${CI_PVC_SC:-"${CI_PVC_SC_LOCAL:-local-path}"}
@ -424,24 +321,19 @@ deploy:
- export CI_CLUSTER_ISSUER=${CI_CLUSTER_ISSUER:-letsencrypt} - export CI_CLUSTER_ISSUER=${CI_CLUSTER_ISSUER:-letsencrypt}
- export CI_SETUP_ADMIN_PASSWORD=${CI_SETUP_ADMIN_PASSWORD} - export CI_SETUP_ADMIN_PASSWORD=${CI_SETUP_ADMIN_PASSWORD}
- echo "Generating config"
- cp deployment.tpl.yaml deployment.yaml - cp deployment.tpl.yaml deployment.yaml
- >- - >-
for env in ${!CI_*}; do for env in ${!CI_*}; do
sed -i "s#<${env}>#$( echo "${!env}" | head -n1 | sed -e 's~\\~\\\\~' -e 's~#~\\#~' )#g" deployment.yaml; sed -i "s#<${env}>#$( echo "${!env}" | head -n1 | sed -e 's~\\~\\\\~' -e 's~#~\\#~' )#g" deployment.yaml;
done done
- echo "Checking namespace ${CI_KUBE_NAMESPACE}"
- kubectl get namespace "${CI_KUBE_NAMESPACE}" > /dev/null 2>&1 || kubectl create namespace "${CI_KUBE_NAMESPACE}"
- echo "Deploying to ${CI_ENVIRONMENT_URL}" - echo "Deploying to ${CI_ENVIRONMENT_URL}"
- kubectl -n "${CI_KUBE_NAMESPACE}" diff -f deployment.yaml || true - kubectl apply -f deployment.yaml
- kubectl -n "${CI_KUBE_NAMESPACE}" apply -f deployment.yaml
- >- - >-
kubectl -n "${CI_KUBE_NAMESPACE}" wait --for=condition=Ready pods --timeout=${CI_WAIT_TIMEOUT:-5}m kubectl -n $CI_KUBE_NAMESPACE wait --for=condition=Ready pods --timeout=${CI_WAIT_TIMEOUT:-5}m
-l app=$CI_PROJECT_PATH_SLUG -l tier=database -l app=$CI_PROJECT_PATH_SLUG -l tier=database
- >- - >-
kubectl -n "${CI_KUBE_NAMESPACE}" wait --for=condition=Ready pods --timeout=${CI_WAIT_TIMEOUT:-5}m kubectl -n $CI_KUBE_NAMESPACE wait --for=condition=Ready pods --timeout=${CI_WAIT_TIMEOUT:-5}m
-l app=$CI_PROJECT_PATH_SLUG -l tier=application -l commit=$CI_COMMIT_SHORT_SHA -l app=$CI_PROJECT_PATH_SLUG -l tier=application -l commit=$CI_COMMIT_SHORT_SHA
.deploy_k8s_stop: &deploy_k8s_stop .deploy_k8s_stop: &deploy_k8s_stop
@ -452,8 +344,7 @@ deploy:
GIT_STRATEGY: none GIT_STRATEGY: none
when: manual when: manual
script: script:
- TARGETS=all,ingress,pvc,certificate - kubectl delete all,ingress,pvc -l app=$CI_PROJECT_PATH_SLUG -l environment=$CI_ENVIRONMENT_SLUG
- kubectl -n "${KUBE_NAMESPACE}" delete $TARGETS -l app=$CI_PROJECT_PATH_SLUG -l environment=$CI_ENVIRONMENT_SLUG
deploy-k8s-review: deploy-k8s-review:
<<: *deploy_k8s <<: *deploy_k8s
@ -462,7 +353,6 @@ deploy-k8s-review:
on_stop: stop-k8s-review on_stop: stop-k8s-review
auto_stop_in: 1 week auto_stop_in: 1 week
url: https://${CI_PROJECT_PATH_SLUG}-review.${KUBE_INGRESS_BASE_DOMAIN}/${CI_COMMIT_REF_SLUG} url: https://${CI_PROJECT_PATH_SLUG}-review.${KUBE_INGRESS_BASE_DOMAIN}/${CI_COMMIT_REF_SLUG}
deployment_tier: development
variables: variables:
CI_REPLICAS_REVIEW: 1 CI_REPLICAS_REVIEW: 1
CI_APP_NAME: review/${CI_COMMIT_REF_NAME} CI_APP_NAME: review/${CI_COMMIT_REF_NAME}
@ -476,7 +366,6 @@ stop-k8s-review:
environment: environment:
name: review/${CI_COMMIT_REF_NAME} name: review/${CI_COMMIT_REF_NAME}
action: stop action: stop
deployment_tier: development
# #
# Deploy production # Deploy production
@ -487,8 +376,8 @@ deploy-production:
stage: deploy-production stage: deploy-production
needs: needs:
- test - test
- yarn audit - audit-yarn
- composer audit - audit-composer
- build-image - build-image
- generate-assets - generate-assets
dependencies: dependencies:
@ -496,7 +385,6 @@ deploy-production:
- generate-assets - generate-assets
environment: environment:
name: rsync-production name: rsync-production
deployment_tier: production
when: manual when: manual
only: only:
- main - main
@ -516,8 +404,8 @@ deploy-k8s-production:
stage: deploy-production stage: deploy-production
needs: needs:
- release-image - release-image
- yarn audit - audit-yarn
- composer audit - audit-composer
environment: environment:
name: production name: production
on_stop: stop-k8s-production on_stop: stop-k8s-production

View File

@ -4,11 +4,9 @@
<file>config</file> <file>config</file>
<file>db</file> <file>db</file>
<file>includes</file>
<file>public/index.php</file> <file>public/index.php</file>
<file>src</file> <file>src</file>
<file>tests</file> <file>tests</file>
<exclude-pattern>/config/config.php</exclude-pattern>
<rule ref="PSR12" /> <rule ref="PSR12" />
<rule ref="SlevomatCodingStandard.Namespaces.UnusedUses"> <rule ref="SlevomatCodingStandard.Namespaces.UnusedUses">
@ -21,32 +19,4 @@
<property name="ignoreUnusedValuesWhenOnlyKeysAreUsedInForeach" value="true" /> <property name="ignoreUnusedValuesWhenOnlyKeysAreUsedInForeach" value="true" />
</properties> </properties>
</rule> </rule>
<rule ref="Generic.Files.LineLength.TooLong">
<exclude-pattern>/includes</exclude-pattern>
</rule>
<rule ref="SlevomatCodingStandard.TypeHints.ParameterTypeHint">
<exclude-pattern>/includes</exclude-pattern>
<exclude name="SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingTraversableTypeHintSpecification" />
</rule>
<rule ref="SlevomatCodingStandard.TypeHints.ReturnTypeHint">
<exclude-pattern>/includes</exclude-pattern>
<exclude name="SlevomatCodingStandard.TypeHints.ReturnTypeHint.MissingTraversableTypeHintSpecification" />
</rule>
<rule ref="SlevomatCodingStandard.TypeHints.PropertyTypeHint">
<exclude-pattern>/includes</exclude-pattern>
<exclude name="SlevomatCodingStandard.TypeHints.PropertyTypeHint.MissingTraversableTypeHintSpecification" />
</rule>
<rule ref="SlevomatCodingStandard.Classes.RequireConstructorPropertyPromotion" />
<rule ref="SlevomatCodingStandard.Commenting.EmptyComment" />
<rule ref="SlevomatCodingStandard.Commenting.UselessFunctionDocComment" />
<rule ref="Generic.Formatting.SpaceAfterCast" />
<rule ref="SlevomatCodingStandard.Arrays.TrailingArrayComma"/>
<rule ref="SlevomatCodingStandard.Arrays.SingleLineArrayWhitespace"/>
<rule ref="Squiz.Strings.DoubleQuoteUsage" />
<rule ref="SlevomatCodingStandard.TypeHints.DeclareStrictTypes">
<exclude-pattern>/includes</exclude-pattern>
<properties>
<property name="spacesCountAroundEqualsSign" value="0" />
</properties>
</rule>
</ruleset> </ruleset>

View File

@ -1,5 +0,0 @@
{
"printWidth": 120,
"tabWidth": 2,
"singleQuote": true
}

View File

@ -2,30 +2,12 @@
## Coding guide lines ## Coding guide lines
* Make sure your code follows the [PSR-12](https://www.php-fig.org/psr/psr-12/) code style and is [.editorconfig](.editorconfig) valid. * Make sure your code follows the [PSR-12](https://www.php-fig.org/psr/psr-12/) code style and is [.editorconfig](.editorconfig) valid.
You may use `composer run phpcs` and [Editorconfig-Checker](https://editorconfig-checker.github.io) to verify that. You may use `composer run phpcs` and [Editorconfig-Checker](https://editorconfig-checker.github.io) to verify that.
* You should use an [editorconfig plugin for your editor](https://editorconfig.org/#pre-installed) for automatic basic code formatting.
* Use `use` statements wherever possible instead of writing the fully qualified name. * Use `use` statements wherever possible instead of writing the fully qualified name.
* Code must pass PHPStan checks (`composer phpstan`)
* Order the composer/npm dependencies alphabetically. * Order the composer/npm dependencies alphabetically.
* Do not use code from the [includes](includes) directory anywhere else. * Do not use code from the [includes](./includes) directory anywhere else.
* Don't refactor [includes](includes) code just for the sake of change, it is legacy code that must only be replaced. * Please cover your code by unit tests. Code under `includes` does not require tests.
* Please cover your code by unit tests, our goal is to stay at 100% line coverage.
Code under `includes` does not require tests as it's mostly not testable and needs to be rewritten.
* Do not use vendor prefixes like `-webkit` in styles. * Do not use vendor prefixes like `-webkit` in styles.
This is done by PostCSS + Autoprefixer according to the [`.browserslistrc`](.browserslistrc). This is done by PostCSS + Autoprefixer according to the [`.browserslistrc`](./.browserslistrc).
* Translations must be abbreviated, for example `form.save`.
The `default.po` files contain translations that can be auto-detected using Poedit, `additional.po` contains generated messages like validations.
* JavaScript code must pass the checks `yarn lint`.
Auto-fixing is supported via `yarn lint:fix`.
* Don't put function calls in a template-literal (template-strings).
## Pull requests ## Pull requests
* The PR should contain a short overview of the changes. Please create single pull requests for every feature instead of creating one big monster of pull request containing a complete rewrite.
* Before implementing bigger changes, please open an issue to discuss the feature and possible implementation options.
* Please create single pull requests for every feature instead of creating one big monster of pull request containing a complete rewrite.
* Squash similar commits to make the review easier.
* For visual changes, include both before and after screenshots to easily compare and discuss changes.
## Commits
* The commit message must be meaningful. It should serve as a short overview of the changes.
If needed, an additional description can be provided.
* A commit should be self-contained and result in a working Engelsystem.

View File

@ -8,95 +8,7 @@ Please also read the [CONTRIBUTING.md](CONTRIBUTING.md).
* Yarn (Development/Building only) * Yarn (Development/Building only)
* PHP Composer (Development/Building only) * PHP Composer (Development/Building only)
## Code style ## Local build
Please ensure that your pull requests follow the [PSR-12](https://www.php-fig.org/psr/psr-12/) coding style guide.
You can check that by running
```bash
composer run phpcs
# with docker
docker exec engelsystem_dev-es_workspace-1 composer run phpcs
```
You may auto fix reported issues by running
```bash
composer run phpcbf
# with docker
docker exec engelsystem_dev-es_workspace-1 composer run phpcbf
```
## Pre-commit hooks
You should set up the pre-commit hook to check the code style and run tests on commit:
Docker (recommended):
```sh
echo "docker exec engelsystem_dev-es_workspace-1 bin/pre-commit" > .git/hooks/pre-commit
chmod u+x .git/hooks/pre-commit
```
Host machine:
```sh
ln -s ../../bin/pre-commit .git/hooks/pre-commit
```
## Docker
We suggest using Docker for the Development local build.
If unspecific issues appear try using Docker version >= 20.10.14.
This repo [ships a docker setup](docker/dev) for a quick development start.
If you use another uid/gid than 1000 on your machine you have to adjust it in [docker/dev/.env](docker/dev/.env).
Run this once
```bash
cd docker/dev
docker compose up
```
Run these commands once initially and then as required after changes
```bash
# Install composer dependencies
docker compose exec es_workspace composer i
# Install node packages
docker compose exec es_workspace yarn install
# Run a full front-end build
docker compose exec es_workspace yarn build
# Or run a front-end build for specific themes only, e.g.
docker compose exec -e THEMES=0,1 es_workspace yarn build
# Update the translation files
docker compose exec es_workspace find /var/www/resources/lang -type f -name '*.po' -exec sh -c 'msgfmt "${1%.*}.po" -o"${1%.*}.mo"' shell {} \;
# Run the migrations
docker compose exec es_workspace bin/migrate
```
While developing you may use the watch mode to rebuild the system on changes
```bash
# Run a front-end build and update on change
docker compose exec es_workspace yarn build:watch
# Or run a front-end build and update on change for specific themes only, e.g.
docker compose exec -e THEMES=0,1 es_workspace yarn build:watch
```
It might also be useful to have an interactive database interface for which a phpMyAdmin instance can be startet at [http://localhost:8888](http://localhost:8888).
```bash
docker compose --profile dev up
```
## Localhost
You can find your local Engelsystem on [http://localhost:5080](http://localhost:5080).
## Local build without Docker
The following instructions explain how to get, build and run the latest Engelsystem version directly from the git main branch (may be unstable!). The following instructions explain how to get, build and run the latest Engelsystem version directly from the git main branch (may be unstable!).
* Clone the main branch: `git clone https://github.com/engelsystem/engelsystem.git` * Clone the main branch: `git clone https://github.com/engelsystem/engelsystem.git`
@ -123,11 +35,11 @@ The following instructions explain how to get, build and run the latest Engelsys
``` ```
* Generate translation files * Generate translation files
```bash ```bash
find resources/lang/ -type f -name '*.po' -exec sh -c 'msgfmt "${1%.*}.po" -o"${1%.*}.mo"' shell {} \; find resources/lang/ -type f -name '*.po' -exec sh -c 'file="{}"; msgfmt "${file%.*}.po" -o "${file%.*}.mo"' \;
``` ```
## Testing ## Testing
To run only unit tests (tests that should not change the Engelsystem state) use To run the unit tests use
```bash ```bash
vendor/bin/phpunit --testsuite Unit vendor/bin/phpunit --testsuite Unit
``` ```
@ -136,34 +48,19 @@ If a database is configured and the Engelsystem is allowed to mess around with s
The tests can potentially delete some database entries, so they should never be run on a production system! The tests can potentially delete some database entries, so they should never be run on a production system!
```bash ```bash
vendor/bin/phpunit --testsuite Feature vendor/bin/phpunit --testsuite Feature
``` # or for unit- and feature tests:
When you want to run unit and feature tests at once:
```bash
vendor/bin/phpunit vendor/bin/phpunit
``` ```
To generate code coverage reports it's highly recommended to use [`pcov`](https://github.com/krakjoe/pcov) or To run code coverage reports its highly recommended to use [`pcov`](https://github.com/krakjoe/pcov) or
at least `phpdbg -qrr`(which has problems with switch case statements) as using Xdebug slows down execution. at least `phpdbg -qrr`(which has problems with switch case statements) as using Xdebug slows down execution.
```bash ```bash
php -d pcov.enabled=1 -d pcov.directory=. vendor/bin/phpunit --coverage-text php -d pcov.enabled=1 -d pcov.directory=. vendor/bin/phpunit --testsuite Unit --coverage-text
``` ```
For better debug output, adding `-vvv` might be helpful.
Adding `--coverage-html public/coverage/` exports the coverage reports to the `public/` dir which then can be viewed at [localhost:5080/coverage/index.html](http://localhost:5080/coverage/index.html).
### Docker
If using the Docker-based development environment you can run the following script to retrieve a coverage report.
```sh
docker compose exec es_workspace composer phpunit:coverage
```
A browsable HTML version is available at http://localhost:5080/coverage/index.html .
### Var Dump server ### Var Dump server
Symfony Var Dump server is configured to allow for easier debugging. It is not meant as a replacement for xdebug but can actually be used together with xdebug. Symfony Var Dump server is configured to allow for easier debugging. It is not meant as a replacement for xdebug but can actually be used together with xdebug.
The Var Dump Server is especially useful if you want to debug a request without messing up the output e.g. of API calls or the HTML layout. This Var Dump Server is especially useful for when you want to debug a request without messing up the output e.g API calls ot HTML layout.
To use simply call the method `dump` and pass the arguments in exactly the same way you would when using `var_dump`. To use simply call the method `dump` and pass the arguments in exactly the same way you would when using `var_dump`.
@ -177,7 +74,7 @@ To view the output of `dump` call the following commands:
```bash ```bash
vendor/bin/var-dump-server vendor/bin/var-dump-server
# or for running in docker # or for running in docker
docker compose exec es_server vendor/bin/var-dump-server docker-compose exec es_server vendor/bin/var-dump-server
``` ```
For more information check out the Var Dump Server documentation: [Symfony VarDumper](https://symfony.com/components/VarDumper) For more information check out the Var Dump Server documentation: [Symfony VarDumper](https://symfony.com/components/VarDumper)
@ -186,6 +83,16 @@ For more information check out the Var Dump Server documentation: [Symfony VarDu
We use gettext. You may use POEdit to extract new texts from the sourcecode. We use gettext. You may use POEdit to extract new texts from the sourcecode.
Please config POEdit to extract also the twig template files using the following settings: https://gist.github.com/jlambe/a868d9b63d70902a12254ce47069d0e6 Please config POEdit to extract also the twig template files using the following settings: https://gist.github.com/jlambe/a868d9b63d70902a12254ce47069d0e6
## Code style
Please ensure that your pull requests follow the [PSR-12](https://www.php-fig.org/psr/psr-12/) coding style guide.
You can check that by running
```bash
composer run phpcs
```
You may auto fix reported issues by running
```bash
composer run phpcbf
```
## CI & Build Pipeline ## CI & Build Pipeline
@ -201,12 +108,51 @@ PRODUCTION_REMOTE # Same as STAGING_REMOTE but for the production environm
PRODUCTION_REMOTE_PATH # Same as STAGING_REMOTE_PATH but for the production environment PRODUCTION_REMOTE_PATH # Same as STAGING_REMOTE_PATH but for the production environment
``` ```
## Static code analysis ## Docker
You can run a static code analysis with this command: If unspecific issues appear try using Docker version >= 20.10.14.
This repo [ships a docker setup](docker/dev) for a quick development start.
If you use another uid/gid than 1000 on your machine you have to adjust it in [docker/dev/.env](docker/dev/.env).
Run this once
```bash ```bash
composer phpstan cd docker/dev
docker-compose up
```
Run these commands once initially and then as required after changes
```bash
# Install composer dependencies
docker-compose exec es_workspace composer i
# Install node packages
docker-compose exec es_workspace yarn install
# Run a full front-end build
docker-compose exec es_workspace yarn build
# Or run a front-end build for specific themes only, e.g.
docker-compose exec -e THEMES=0,1 es_workspace yarn build
# Update the translation files
docker-compose exec es_workspace find /var/www/resources/lang -type f -name '*.po' -exec sh -c 'file="{}"; msgfmt "${file%.*}.po" -o "${file%.*}.mo"' \;
# Run the migrations
docker-compose exec es_workspace bin/migrate
```
While developing you may use the watch mode to rebuild the system on changes
```bash
# Run a front-end build and update on change
docker-compose exec es_workspace yarn build:watch
# Or run a front-end build and update on change for specific themes only, e.g.
docker-compose exec -e THEMES=0,1 es_workspace yarn build:watch
``` ```
**Hint for using Xdebug with *PhpStorm*** **Hint for using Xdebug with *PhpStorm***

View File

@ -15,7 +15,7 @@ Please read the [CONTRIBUTING.md](CONTRIBUTING.md) and [DEVELOPMENT.md](DEVELOPM
The Engelsystem may be installed manually or by using the provided [docker setup](#docker). The Engelsystem may be installed manually or by using the provided [docker setup](#docker).
### Requirements ### Requirements
* PHP >= 8.1 * PHP >= 7.4
* Required modules: * Required modules:
* dom * dom
* json * json
@ -28,30 +28,21 @@ The Engelsystem may be installed manually or by using the provided [docker setup
* MySQL-Server >= 5.7.8 or MariaDB-Server >= 10.2.2 * MySQL-Server >= 5.7.8 or MariaDB-Server >= 10.2.2
* Webserver, i.e. lighttpd, nginx, or Apache * Webserver, i.e. lighttpd, nginx, or Apache
From previous experience, 2 cores and 2GB ram are roughly enough for up to 1000 Angels (~700 arrived + 500 arrived but not working) during an event.
### Download ### Download
* Go to the [Releases](https://github.com/engelsystem/engelsystem/releases) page and download the latest stable release file. * Go to the [Releases](https://github.com/engelsystem/engelsystem/releases) page and download the latest stable release file.
* Extract the files to your webroot and continue with the directions for configurations and setup. * Extract the files to your webroot and continue with the directions for configurations and setup.
### Configuration and Setup ### Configuration and Setup
* The webserver must have write access to the `storage` directory and read access for all other directories * The webserver must have write access to the ```storage``` directory and read access for all other directories
* The webserver must point to the `public` directory. * The webserver must point to the ```public``` directory.
* The webserver must read the `.htaccess` file and `mod_rewrite` must be enabled * The webserver must read the ```.htaccess``` file and ```mod_rewrite``` must be enabled
* Recommended: Directory Listing should be disabled. * Recommended: Directory Listing should be disabled.
* There must be a MySQL database set up with a user who has full rights to that database. * There must be a MySQL database set up with a user who has full rights to that database.
* If necessary, create a `config/config.php` to override values from `config/config.default.php`. * If necessary, create a ```config/config.php``` to override values from ```config/config.default.php```.
* To disable/remove values from the following lists, set the value of the entry to `null`: * To edit values from the `footer_items`, `themes`, `locales`, `tshirt_sizes` or `headers` lists, directly modify the ```config/config.default.php``` file or rename it to ```config/config.php```.
* `themes` * To import the database, the ```bin/migrate``` script has to be run. If you can't execute scripts, you can use the `initial-install.sql` file from the release zip.
* `tshirt_sizes` * In the browser, login with credentials ```admin``` : ```asdfasdf``` and change the password.
* `headers`
* `header_items`
* `footer_items`
* `locales`
* `contact_options`
* To import the database, the `bin/migrate` script has to be run. If you can't execute scripts, you can use the `initial-install.sql` file from the release zip.
* In the browser, login with credentials `admin` : `asdfasdf` and change the password.
The Engelsystem can now be used. The Engelsystem can now be used.
@ -64,7 +55,7 @@ The Engelsystem can now be used.
To build the `es_server` container: To build the `es_server` container:
```bash ```bash
cd docker cd docker
docker compose build docker-compose build
``` ```
or to build the container by its own: or to build the container by its own:
@ -76,14 +67,14 @@ docker build -f docker/Dockerfile . -t es_server
Start the Engelsystem Start the Engelsystem
```bash ```bash
cd docker cd docker
docker compose up -d docker-compose up -d
``` ```
#### Set Up / Migrate Database #### Migrate
Create the Database Schema (on a fresh install) or import database changes to migrate it to the newest version Import database changes to migrate it to the newest version
```bash ```bash
cd docker cd docker
docker compose exec es_server bin/migrate docker-compose exec es_server bin/migrate
``` ```
### Scripts ### Scripts

View File

@ -1,16 +0,0 @@
# Security Policy
## Reporting a Vulnerability
If you want to contact us directly regarding a security concern, please write an e-mail to contact@engelsystem.de and explain your findings.
Thank you!
## Use of external reporting / bug bounty services
We kindly ask you to not use any external reporting / bug bounty service. We do not collaborate with any external service and experiences in the past showed that these services usually add a lot of unnecessary overhead.
Please send security critical bug reports to contact@engelsystem.de.
If you feel like we are not reacting fast enough (generally no more than 14 days should go by until an initial response; This is a volunteer project mostly used internally after all), please feel free to go for full disclosure via our github issue tracker, and tag the issue there by creating a title prefixed with [SECURITY].
If you find a critical vulnerability that warrants a CVE, we will also take care of issuing a CVE without any bug bounty platform having to be involved.

View File

@ -4,9 +4,7 @@
use Composer\Autoload\ClassLoader; use Composer\Autoload\ClassLoader;
use Engelsystem\Application; use Engelsystem\Application;
use Engelsystem\Database\Migration\Migrate; use Engelsystem\Database\Migration\Migrate;
use Engelsystem\Database\Migration\Direction;
use Engelsystem\Database\Migration\MigrationServiceProvider; use Engelsystem\Database\Migration\MigrationServiceProvider;
use Engelsystem\Environment;
use Engelsystem\Exceptions\Handler; use Engelsystem\Exceptions\Handler;
use Engelsystem\Exceptions\Handlers\NullHandler; use Engelsystem\Exceptions\Handlers\NullHandler;
@ -21,7 +19,7 @@ $app->register(MigrationServiceProvider::class);
/** @var Handler $errorHandler */ /** @var Handler $errorHandler */
$errorHandler = $app->get(Handler::class); $errorHandler = $app->get(Handler::class);
$errorHandler->setHandler(Environment::PRODUCTION, new NullHandler()); $errorHandler->setHandler(Handler::ENV_PRODUCTION, new NullHandler());
/** @var Migrate $migration */ /** @var Migrate $migration */
$migration = $app->get('db.migration'); $migration = $app->get('db.migration');
@ -34,10 +32,10 @@ if (in_array('help', $argv) || in_array('--help', $argv) || in_array('-h', $argv
exit; exit;
} }
$direction = Direction::UP; $method = Migrate::UP;
if (in_array('down', $argv)) { if (in_array('down', $argv)) {
$argv = array_values($argv); $argv = array_values($argv);
$direction = Direction::DOWN; $method = Migrate::DOWN;
} }
$oneStep = false; $oneStep = false;
@ -50,4 +48,4 @@ if (in_array('force', $argv) || in_array('--force', $argv) || in_array('-f', $ar
$force = true; $force = true;
} }
$migration->run($baseDir, $direction, $oneStep, $force); $migration->run($baseDir, $method, $oneStep, $force);

View File

@ -1,26 +0,0 @@
#!/usr/bin/env sh
# immediate exit after an error
set -e
testing() {
echo
echo "🔎 Checking ${1}"
}
testing 'JS & CSS 🎨'
yarn check
yarn lint
testing 'PHP ⚙️'
composer validate
composer phpcs
composer phpstan
./vendor/bin/phpunit
testing 'translations 🗺️'
find resources/lang -type f -name '*.po' -exec sh -c 'msgfmt "${1%.*}.po" -o"${1%.*}.mo"' shell {} \;
[ "$(find resources/lang -type f -name '*.po' | wc -l)" -eq "$(find resources/lang -type f -name '*.mo' | wc -l)" ]
find resources/lang -type f -name '*.mo' -exec rm {} \;
echo '✅ Done 🎉'

View File

@ -14,61 +14,47 @@
} }
], ],
"scripts": { "scripts": {
"phpcs:setup": "phpcs --config-set php_version 80100", "phpcs": "phpcs -p",
"phpcs": [ "phpcbf": "phpcbf -p"
"composer phpcs:setup",
"phpcs -p --cache"
],
"phpcbf": [
"composer phpcs:setup",
"phpcbf -p"
],
"phpstan": "phpstan",
"phpunit": "phpunit",
"phpunit:coverage": "phpunit --coverage-text --coverage-html ./public/coverage/"
}, },
"require": { "require": {
"php": ">=8.1.0", "php": ">=7.4.0",
"ext-json": "*", "ext-json": "*",
"ext-libxml": "*", "ext-libxml": "*",
"ext-mbstring": "*", "ext-mbstring": "*",
"ext-pdo": "*", "ext-pdo": "*",
"ext-simplexml": "*", "ext-simplexml": "*",
"ext-xml": "*", "ext-xml": "*",
"doctrine/dbal": "^3.7", "doctrine/dbal": "^3.2",
"erusev/parsedown": "^1.7", "erusev/parsedown": "^1.7",
"gettext/gettext": "^5.7", "gettext/gettext": "^5.6",
"gettext/translator": "^1.2", "gettext/translator": "^1.0",
"guzzlehttp/guzzle": "^7.8", "guzzlehttp/guzzle": "^7.4",
"illuminate/container": "^10.38", "illuminate/container": "^8.76",
"illuminate/database": "^10.38", "illuminate/database": "^8.76",
"illuminate/support": "^10.38", "illuminate/support": "^8.76",
"league/oauth2-client": "^2.7", "league/oauth2-client": "^2.6",
"league/openapi-psr7-validator": "^0.21",
"nikic/fast-route": "^1.3", "nikic/fast-route": "^1.3",
"nyholm/psr7": "^1.8", "nyholm/psr7": "^1.4",
"psr/container": "^2.0", "psr/container": "^1.1",
"psr/http-message": "^1.1",
"psr/http-server-middleware": "^1.0", "psr/http-server-middleware": "^1.0",
"psr/log": "^3.0", "psr/log": "^1.1",
"rcrowe/twigbridge": "^0.14.1", "rcrowe/twigbridge": "^0.14.0",
"respect/validation": "^1.1", "respect/validation": "^1.1",
"symfony/http-foundation": "^6.4", "symfony/http-foundation": "^5.4",
"symfony/mailer": "^6.4", "symfony/mailer": "^5.4",
"symfony/psr-http-message-bridge": "^2.3", "symfony/psr-http-message-bridge": "^2.1",
"twig/twig": "^3.8", "twig/twig": "^3.3",
"vlucas/phpdotenv": "^5.6" "vlucas/phpdotenv": "^5.4"
}, },
"require-dev": { "require-dev": {
"dms/phpunit-arraysubset-asserts": "^0.5", "dms/phpunit-arraysubset-asserts": "^0.3.1",
"fakerphp/faker": "^1.23", "fakerphp/faker": "^1.17",
"fig/log-test": "^1.1", "filp/whoops": "^2.14",
"filp/whoops": "^2.15", "phpunit/phpunit": "^9.5",
"phpstan/phpstan": "^1.10", "slevomat/coding-standard": "^7.1",
"phpunit/phpunit": "^9.6", "squizlabs/php_codesniffer": "^3.6",
"slevomat/coding-standard": "^8.14", "symfony/var-dumper": "^5.4"
"squizlabs/php_codesniffer": "^3.8",
"symfony/var-dumper": "^6.4"
}, },
"autoload": { "autoload": {
"psr-4": { "psr-4": {

3580
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,5 @@
<?php <?php
declare(strict_types=1);
// Application config // Application config
return [ return [
@ -28,6 +26,7 @@ return [
\Engelsystem\Renderer\TwigServiceProvider::class, \Engelsystem\Renderer\TwigServiceProvider::class,
\Engelsystem\Middleware\RouteDispatcherServiceProvider::class, \Engelsystem\Middleware\RouteDispatcherServiceProvider::class,
\Engelsystem\Middleware\RequestHandlerServiceProvider::class, \Engelsystem\Middleware\RequestHandlerServiceProvider::class,
\Engelsystem\Middleware\SessionHandlerServiceProvider::class,
\Engelsystem\Http\Validation\ValidationServiceProvider::class, \Engelsystem\Http\Validation\ValidationServiceProvider::class,
\Engelsystem\Http\RedirectServiceProvider::class, \Engelsystem\Http\RedirectServiceProvider::class,
@ -37,7 +36,6 @@ return [
\Engelsystem\Http\HttpClientServiceProvider::class, \Engelsystem\Http\HttpClientServiceProvider::class,
\Engelsystem\Helpers\DumpServerServiceProvider::class, \Engelsystem\Helpers\DumpServerServiceProvider::class,
\Engelsystem\Helpers\UuidServiceProvider::class, \Engelsystem\Helpers\UuidServiceProvider::class,
\Engelsystem\Controllers\Api\UsesAuthServiceProvider::class,
], ],
// Application middleware // Application middleware
@ -48,13 +46,10 @@ return [
// Changes of request/response parameters // Changes of request/response parameters
\Engelsystem\Middleware\SetLocale::class, \Engelsystem\Middleware\SetLocale::class,
\Engelsystem\Middleware\ETagHandler::class,
\Engelsystem\Middleware\AddHeaders::class, \Engelsystem\Middleware\AddHeaders::class,
\Engelsystem\Middleware\TrimInput::class,
// The application code // The application code
\Engelsystem\Middleware\ErrorHandler::class, \Engelsystem\Middleware\ErrorHandler::class,
\Engelsystem\Middleware\ApiRouteHandler::class,
\Engelsystem\Middleware\VerifyCsrfToken::class, \Engelsystem\Middleware\VerifyCsrfToken::class,
\Engelsystem\Middleware\RouteDispatcher::class, \Engelsystem\Middleware\RouteDispatcher::class,
\Engelsystem\Middleware\SessionHandler::class, \Engelsystem\Middleware\SessionHandler::class,
@ -69,22 +64,11 @@ return [
// a list of // a list of
// 'Class@method' or 'Class' (which uses @handle), // 'Class@method' or 'Class' (which uses @handle),
// ['Class', 'method'], // ['Class', 'method'],
// callable like [$instance, 'method'] or 'function' // callable like [$instance, 'method] or 'function'
// or $function // or $function
// ] // ]
'message.created' => \Engelsystem\Events\Listener\Messages::class . '@created',
'news.created' => \Engelsystem\Events\Listener\News::class . '@created', 'news.created' => \Engelsystem\Events\Listener\News::class . '@created',
'news.updated' => \Engelsystem\Events\Listener\News::class . '@updated',
'oauth2.login' => \Engelsystem\Events\Listener\OAuth2::class . '@login', 'oauth2.login' => \Engelsystem\Events\Listener\OAuth2::class . '@login',
'shift.deleting' => [
\Engelsystem\Events\Listener\Shifts::class . '@deletingCreateWorklogs',
\Engelsystem\Events\Listener\Shifts::class . '@deletingSendEmails',
],
'shift.updating' => \Engelsystem\Events\Listener\Shifts::class . '@updatedSendEmail',
], ],
]; ];

View File

@ -1,7 +1,5 @@
<?php <?php
declare(strict_types=1);
// To change settings create a config.php // To change settings create a config.php
return [ return [
@ -13,58 +11,41 @@ return [
'password' => env('MYSQL_PASSWORD', ''), 'password' => env('MYSQL_PASSWORD', ''),
], ],
// For accessing /metrics (and /stats) // For accessing stats
'api_key' => env('API_KEY', ''), 'api_key' => '',
// Enable maintenance mode (show a static page) // Enable maintenance mode (show a static page)
'maintenance' => (bool)env('MAINTENANCE', false), 'maintenance' => (bool)env('MAINTENANCE', false),
// Application name (not the event name) // Application name (not the event name!)
'app_name' => env('APP_NAME', 'Engelsystem'), 'app_name' => env('APP_NAME', 'Engelsystem'),
// Set to development to enable debugging messages // Set to development to enable debugging messages
'environment' => env('ENVIRONMENT', 'production'), 'environment' => env('ENVIRONMENT', 'production'),
// Application URL and base path to use instead of the auto-detected one // Application URL and base path to use instead of the auto detected one
'url' => env('APP_URL'), 'url' => env('APP_URL', null),
// Header links // Header links
// Available link placeholders: %lang% // Available link placeholders: %lang%
// To disable a header_item in the config.php, you can set its value to null
'header_items' => [ 'header_items' => [
// Name can be a translation string, permission is a engelsystem privilege //'Foo' => 'https://foo.bar/batz-%lang%.html',
// 'Name' => 'URL',
// 'Name' => ['URL', 'permission'],
//'Foo' => ['https://foo.bar/batz-%lang%.html', 'logout'], // Permission: for logged-in users
], ],
// Footer links // Footer links
// To disable a footer item in the config.php, you can set its value to null
'footer_items' => [ 'footer_items' => [
// Name can be a translation string, permission is a engelsystem privilege
// 'Name' => 'URL',
// 'Name' => ['URL', 'permission'],
// URL to the angel faq and job description // URL to the angel faq and job description
'faq.faq' => [env('FAQ_URL', '/faq'), 'faq.view'], 'FAQ' => env('FAQ_URL', '/faq'),
// Contact email address, linked on every page // Contact email address, linked on every page
'Contact' => env('CONTACT_EMAIL', 'mailto:ticket@c3heaven.de'), 'Contact' => env('CONTACT_EMAIL', 'mailto:ticket@c3heaven.de'),
], ],
// Other ways to ask the heaven
// Multiple contact options / links are possible, analogue to footer_items
'contact_options' => [
// E-mail address
'general.email' => env('CONTACT_EMAIL', 'mailto:ticket@c3heaven.de'),
],
// Text displayed on the FAQ page, rendered as markdown // Text displayed on the FAQ page, rendered as markdown
'faq_text' => env('FAQ_TEXT'), 'faq_text' => env('FAQ_TEXT', null),
// Link to documentation/help // Link to documentation/help
'documentation_url' => env('DOCUMENTATION_URL', 'https://engelsystem.de/doc/'), 'documentation_url' => 'https://engelsystem.de/doc/',
// Email config // Email config
'email' => [ 'email' => [
@ -79,20 +60,17 @@ return [
'host' => env('MAIL_HOST', 'localhost'), 'host' => env('MAIL_HOST', 'localhost'),
'port' => env('MAIL_PORT', 587), 'port' => env('MAIL_PORT', 587),
// If tls transport encryption should be used // If tls transport encryption should be used
'tls' => env('MAIL_TLS'), 'tls' => env('MAIL_TLS', null),
'username' => env('MAIL_USERNAME'), 'username' => env('MAIL_USERNAME'),
'password' => env('MAIL_PASSWORD'), 'password' => env('MAIL_PASSWORD'),
'sendmail' => env('MAIL_SENDMAIL', '/usr/sbin/sendmail -bs'), 'sendmail' => env('MAIL_SENDMAIL', '/usr/sbin/sendmail -bs'),
], ],
// Your privacy@ contact address # Your privacy@ contact address
'privacy_email' => env('PRIVACY_EMAIL'), 'privacy_email' => '',
// Show opt in to save some personal data after the event on user profile and registration pages
'enable_email_goodie' => (bool) env('ENABLE_EMAIL_GOODIE', true),
// Initial admin password // Initial admin password
'setup_admin_password' => env('SETUP_ADMIN_PASSWORD'), 'setup_admin_password' => env('SETUP_ADMIN_PASSWORD', null),
'oauth' => [ 'oauth' => [
// '[name]' => [config] // '[name]' => [config]
@ -110,8 +88,6 @@ return [
'url_token' => '[generated by provider]', 'url_token' => '[generated by provider]',
// User info URL which provides userdata // User info URL which provides userdata
'url_info' => '[generated by provider]', 'url_info' => '[generated by provider]',
// OAuth Scopes
// 'scope' => ['openid'],
// Info unique user id field // Info unique user id field
'id' => 'uuid', 'id' => 'uuid',
// The following fields are used for registration // The following fields are used for registration
@ -151,19 +127,7 @@ return [
// Default theme, 1=style1.css // Default theme, 1=style1.css
'theme' => env('THEME', 1), 'theme' => env('THEME', 1),
// Supported themes
// To disable a theme in the config.php, you can set its value to null
'themes' => [ 'themes' => [
17 => [
'name' => 'Engelsystem 37c3 (2023)',
'type' => 'dark',
'navbar_classes' => 'navbar-dark',
],
16 => [
'name' => 'Engelsystem cccamp23 (2023)',
'type' => 'dark',
'navbar_classes' => 'navbar-dark',
],
15 => [ 15 => [
'name' => 'Engelsystem rC3 (2021)', 'name' => 'Engelsystem rC3 (2021)',
'type' => 'dark', 'type' => 'dark',
@ -250,34 +214,18 @@ return [
// Must be one of news, meetings, user_shifts, angeltypes, questions // Must be one of news, meetings, user_shifts, angeltypes, questions
'home_site' => env('HOME_SITE', 'news'), 'home_site' => env('HOME_SITE', 'news'),
// Number of News shown on one site and for feed readers (minimum 1) // Number of News shown on one site
'display_news' => env('DISPLAY_NEWS', 10), 'display_news' => env('DISPLAY_NEWS', 10),
// Users are able to sign up // Users are able to sign up
'registration_enabled' => (bool)env('REGISTRATION_ENABLED', true), 'registration_enabled' => (bool)env('REGISTRATION_ENABLED', true),
// URL to external registration page, used on login page
'external_registration_url' => env('EXTERNAL_REGISTRATION_URL'),
// Required user fields
'required_user_fields' => [
'pronoun' => (bool) env('PRONOUN_REQUIRED', false),
'firstname' => (bool) env('FIRSTNAME_REQUIRED', false),
'lastname' => (bool) env('LASTNAME_REQUIRED', false),
'tshirt_size' => (bool) env('TSHIRT_SIZE_REQUIRED', true),
'mobile' => (bool) env('MOBILE_REQUIRED', false),
'dect' => (bool) env('DECT_REQUIRED', false),
],
// Only arrived angels can sign up for shifts // Only arrived angels can sign up for shifts
'signup_requires_arrival' => (bool)env('SIGNUP_REQUIRES_ARRIVAL', false), 'signup_requires_arrival' => (bool)env('SIGNUP_REQUIRES_ARRIVAL', false),
// Whether newly-registered user should automatically be marked as arrived // Whether newly-registered user should automatically be marked as arrived
'autoarrive' => (bool)env('ANGEL_AUTOARRIVE', false), 'autoarrive' => (bool)env('ANGEL_AUTOARRIVE', false),
// Supporters of an angeltype can promote other angels of the angeltype to supporter
'supporters_can_promote' => (bool) env('SUPPORTERS_CAN_PROMOTE', false),
// Only allow shift signup this number of hours in advance // Only allow shift signup this number of hours in advance
// Setting this to 0 disables the feature // Setting this to 0 disables the feature
'signup_advance_hours' => env('SIGNUP_ADVANCE_HOURS', 0), 'signup_advance_hours' => env('SIGNUP_ADVANCE_HOURS', 0),
@ -298,46 +246,33 @@ return [
// Define the algorithm to use for `password_verify()` // Define the algorithm to use for `password_verify()`
// If the user uses an old algorithm the password will be converted to the new format // If the user uses an old algorithm the password will be converted to the new format
// See https://secure.php.net/manual/en/password.constants.php for a complete list // See https://secure.php.net/manual/en/password.constants.php for a complete list
'password_algorithm' => env('PASSWORD_ALGORITHM', PASSWORD_DEFAULT), 'password_algorithm' => PASSWORD_DEFAULT,
// The minimum length for passwords // The minimum length for passwords
'min_password_length' => env('PASSWORD_MINIMUM_LENGTH', 8), 'min_password_length' => env('PASSWORD_MINIMUM_LENGTH', 8),
// Whether the login and registration via password should be enabled (login will be hidden) // Whether the Password field should be enabled on registration.
// This is useful when using oauth, disabling it also disables normal registration without oauth // This is useful when using oauth, disabling it also disables normal
// registration without oauth.
'enable_password' => (bool)env('ENABLE_PASSWORD', true), 'enable_password' => (bool)env('ENABLE_PASSWORD', true),
// Whether the DECT field should be enabled // Whether the DECT field should be enabled
'enable_dect' => (bool)env('ENABLE_DECT', true), 'enable_dect' => (bool)env('ENABLE_DECT', true),
// Whether the mobile number can be shown to other users // Enables prename and lastname
'enable_mobile_show' => (bool) env('ENABLE_MOBILE_SHOW', false),
// Regular expression describing a FALSE username.
// Per default usernames must only contain alphanumeric chars, "-", "_" or ".".
'username_regex' => (string) env('USERNAME_REGEX', '/([^\p{L}\p{N}_.-]+)/ui'),
// Enables first name and last name
'enable_user_name' => (bool)env('ENABLE_USER_NAME', false), 'enable_user_name' => (bool)env('ENABLE_USER_NAME', false),
// Show a users first name and last name instead of username
'display_full_name' => env('DISPLAY_FULL_NAME', false)
&& env('ENABLE_USER_NAME', false),
// Enable displaying the pronoun fields // Enable displaying the pronoun fields
'enable_pronoun' => (bool)env('ENABLE_PRONOUN', true), 'enable_pronoun' => (bool)env('ENABLE_PRONOUN', true),
// Enables the planned arrival/leave date // Enables the planned arrival/leave date
'enable_planned_arrival' => (bool)env('ENABLE_PLANNED_ARRIVAL', true), 'enable_planned_arrival' => (bool)env('ENABLE_PLANNED_ARRIVAL', true),
// Whether force active should be enabled // Enables the T-Shirt configuration on signup and profile
'enable_force_active' => (bool) env('ENABLE_FORCE_ACTIVE', true), 'enable_tshirt_size' => (bool)env('ENABLE_TSHIRT_SIZE', true),
// Resembles the Goodie Type. There are three options: // Enables the goody configuration on signup and profile
// 'none' => no goodie at all 'enable_goody' => (bool)env('ENABLE_GOODY', false),
// 'goodie' => a goodie which has no sizing options
// 'tshirt' => goodie that is called tshirt and has sizing options
'goodie_type' => env('GOODIE_TYPE', 'goodie'),
// Enables the food voucher in the user profile // Enables the food voucher in the user profile
'enable_voucher' => (bool)env('ENABLE_VOUCHER', true), 'enable_voucher' => (bool)env('ENABLE_VOUCHER', true),
@ -345,18 +280,14 @@ return [
// Number of shifts to freeload until angel is locked for shift signup. // Number of shifts to freeload until angel is locked for shift signup.
'max_freeloadable_shifts' => env('MAX_FREELOADABLE_SHIFTS', 2), 'max_freeloadable_shifts' => env('MAX_FREELOADABLE_SHIFTS', 2),
// Hide columns in backend user view. Possible values are any sortable parameters of the table.
'disabled_user_view_columns' => [],
// Local timezone // Local timezone
'timezone' => env('TIMEZONE', 'Europe/Berlin'), 'timezone' => env('TIMEZONE', ini_get('date.timezone') ?: 'Europe/Berlin'),
// Multiply 'night shifts' and freeloaded shifts (start or end between 2 and 8 exclusive) by 2 in goodie score // Multiply 'night shifts' and freeloaded shifts (start or end between 2 and 6 exclusive) by 2
// Goodies must be enabled to use this feature
'night_shifts' => [ 'night_shifts' => [
'enabled' => (bool)env('NIGHT_SHIFTS', true), // Disable to weigh every shift the same 'enabled' => (bool)env('NIGHT_SHIFTS', true), // Disable to weigh every shift the same
'start' => env('NIGHT_SHIFTS_START', 2), // Starting from hour 'start' => env('NIGHT_SHIFTS_START', 2),
'end' => env('NIGHT_SHIFTS_END', 8), // Ends at (without including) hour 'end' => env('NIGHT_SHIFTS_END', 6),
'multiplier' => env('NIGHT_SHIFTS_MULTIPLIER', 2), 'multiplier' => env('NIGHT_SHIFTS_MULTIPLIER', 2),
], ],
@ -366,20 +297,10 @@ return [
'shifts_per_voucher' => env('SHIFTS_PER_VOUCHER', 0), 'shifts_per_voucher' => env('SHIFTS_PER_VOUCHER', 0),
'hours_per_voucher' => env('HOURS_PER_VOUCHER', 2), 'hours_per_voucher' => env('HOURS_PER_VOUCHER', 2),
// 'Y-m-d' formatted // 'Y-m-d' formatted
'voucher_start' => env('VOUCHER_START') ?: null, 'voucher_start' => env('VOUCHER_START', null) ?: null,
], ],
// Enables Driving License
'driving_license_enabled' => (bool) env('DRIVING_LICENSE_ENABLED', true),
# Instruction in accordance with § 43 Para. 1 of the German Infection Protection Act (IfSG)
'ifsg_enabled' => (bool) env('IFSG_ENABLED', false),
# Instruction only onsite in accordance with § 43 Para. 1 of the German Infection Protection Act (IfSG)
'ifsg_light_enabled' => env('IFSG_LIGHT_ENABLED', false) && env('IFSG_ENABLED', false),
// Available locales in /resources/lang/ // Available locales in /resources/lang/
// To disable a locale in the config.php, you can set its value to null
'locales' => [ 'locales' => [
'de_DE' => 'Deutsch', 'de_DE' => 'Deutsch',
'en_US' => 'English', 'en_US' => 'English',
@ -388,31 +309,21 @@ return [
// The default locale to use // The default locale to use
'default_locale' => env('DEFAULT_LOCALE', 'en_US'), 'default_locale' => env('DEFAULT_LOCALE', 'en_US'),
// Available T-Shirt sizes // Available T-Shirt sizes, set value to null if not available
// To disable a t-shirt size in the config.php, you can set its value to null
'tshirt_sizes' => [ 'tshirt_sizes' => [
'S' => 'Small Straight-Cut', 'S' => 'Small Straight-Cut',
'S-F' => 'Small Fitted-Cut', 'S-G' => 'Small Fitted-Cut',
'M' => 'Medium Straight-Cut', 'M' => 'Medium Straight-Cut',
'M-F' => 'Medium Fitted-Cut', 'M-G' => 'Medium Fitted-Cut',
'L' => 'Large Straight-Cut', 'L' => 'Large Straight-Cut',
'L-F' => 'Large Fitted-Cut', 'L-G' => 'Large Fitted-Cut',
'XL' => 'XLarge Straight-Cut', 'XL' => 'XLarge Straight-Cut',
'XL-F' => 'XLarge Fitted-Cut', 'XL-G' => 'XLarge Fitted-Cut',
'2XL' => '2XLarge Straight-Cut', '2XL' => '2XLarge Straight-Cut',
'3XL' => '3XLarge Straight-Cut', '3XL' => '3XLarge Straight-Cut',
'4XL' => '4XLarge Straight-Cut', '4XL' => '4XLarge Straight-Cut',
], ],
// T-shirt Size-Guide link
'tshirt_link' => env('TSHIRT_LINK'),
// Whether to show the current day of the event (-2, -1, 0, 1, 2…) in footer and on the dashboard.
// The event start date has to be set for it to appear.
'enable_show_day_of_event' => (bool) env('ENABLE_SHOW_DAY_OF_EVENT', false),
// If true there will be a day 0 (-1, 0, 1…). If false there won't (-1, 1…)
'event_has_day0' => (bool) env('EVENT_HAS_DAY0', true),
'metrics' => [ 'metrics' => [
// User work buckets in seconds // User work buckets in seconds
'work' => [1 * 60 * 60, 1.5 * 60 * 60, 2 * 60 * 60, 3 * 60 * 60, 5 * 60 * 60, 10 * 60 * 60, 20 * 60 * 60], 'work' => [1 * 60 * 60, 1.5 * 60 * 60, 2 * 60 * 60, 3 * 60 * 60, 5 * 60 * 60, 10 * 60 * 60, 20 * 60 * 60],
@ -431,9 +342,6 @@ return [
// Cookie name // Cookie name
'name' => env('SESSION_NAME', 'session'), 'name' => env('SESSION_NAME', 'session'),
// Lifetime in days
'lifetime' => env('SESSION_LIFETIME', 30),
], ],
// IP addresses of reverse proxies that are trusted, can be an array or a comma separated list // IP addresses of reverse proxies that are trusted, can be an array or a comma separated list
@ -441,16 +349,11 @@ return [
// Add additional headers // Add additional headers
'add_headers' => (bool)env('ADD_HEADERS', true), 'add_headers' => (bool)env('ADD_HEADERS', true),
// Predefined headers
// To disable a header in the config.php, you can set its value to null
'headers' => [ 'headers' => [
'X-Content-Type-Options' => 'nosniff', 'X-Content-Type-Options' => 'nosniff',
'X-Frame-Options' => 'sameorigin', 'X-Frame-Options' => 'sameorigin',
'Referrer-Policy' => 'strict-origin-when-cross-origin', 'Referrer-Policy' => 'strict-origin-when-cross-origin',
'Content-Security-Policy' => 'Content-Security-Policy' => 'default-src \'self\' \'unsafe-inline\' \'unsafe-eval\'; img-src \'self\' data:;',
'default-src \'self\'; '
. ' style-src \'self\' \'unsafe-inline\'; '
. 'img-src \'self\' data:;',
'X-XSS-Protection' => '1; mode=block', 'X-XSS-Protection' => '1; mode=block',
'Feature-Policy' => 'autoplay \'none\'', 'Feature-Policy' => 'autoplay \'none\'',
//'Strict-Transport-Security' => 'max-age=7776000', //'Strict-Transport-Security' => 'max-age=7776000',
@ -461,7 +364,7 @@ return [
'credits' => [ 'credits' => [
'Contribution' => 'Please visit [engelsystem/engelsystem](https://github.com/engelsystem/engelsystem) if ' 'Contribution' => 'Please visit [engelsystem/engelsystem](https://github.com/engelsystem/engelsystem) if '
. 'you want to contribute, have found any [bugs](https://github.com/engelsystem/engelsystem/issues) ' . 'you want to contribute, have found any [bugs](https://github.com/engelsystem/engelsystem/issues) '
. 'or need help.', . 'or need help.'
], ],
// var dump server // var dump server

View File

@ -1,15 +1,11 @@
<?php <?php
declare(strict_types=1);
use FastRoute\RouteCollector; use FastRoute\RouteCollector;
/** @var RouteCollector $route */ /** @var RouteCollector $route */
// Pages // Pages
$route->get('/', 'HomeController@index'); $route->get('/', 'HomeController@index');
$route->get('/register', 'RegistrationController@view');
$route->post('/register', 'RegistrationController@save');
$route->get('/credits', 'CreditsController@index'); $route->get('/credits', 'CreditsController@index');
$route->get('/health', 'HealthController@index'); $route->get('/health', 'HealthController@index');
@ -19,154 +15,54 @@ $route->post('/login', 'AuthController@postLogin');
$route->get('/logout', 'AuthController@logout'); $route->get('/logout', 'AuthController@logout');
// OAuth // OAuth
$route->addGroup( $route->get('/oauth/{provider}', 'OAuthController@index');
'/oauth/{provider}', $route->post('/oauth/{provider}/connect', 'OAuthController@connect');
function (RouteCollector $route): void { $route->post('/oauth/{provider}/disconnect', 'OAuthController@disconnect');
$route->get('', 'OAuthController@index');
$route->post('/connect', 'OAuthController@connect');
$route->post('/disconnect', 'OAuthController@disconnect');
}
);
// User settings // User settings
$route->addGroup( $route->get('/settings/password', 'SettingsController@password');
'/settings', $route->post('/settings/password', 'SettingsController@savePassword');
function (RouteCollector $route): void { $route->get('/settings/theme', 'SettingsController@theme');
$route->get('/profile', 'SettingsController@profile'); $route->post('/settings/theme', 'SettingsController@saveTheme');
$route->post('/profile', 'SettingsController@saveProfile'); $route->get('/settings/language', 'SettingsController@language');
$route->get('/password', 'SettingsController@password'); $route->post('/settings/language', 'SettingsController@saveLanguage');
$route->post('/password', 'SettingsController@savePassword'); $route->get('/settings/oauth', 'SettingsController@oauth');
$route->get('/theme', 'SettingsController@theme');
$route->post('/theme', 'SettingsController@saveTheme');
$route->get('/language', 'SettingsController@language');
$route->post('/language', 'SettingsController@saveLanguage');
$route->get('/certificates', 'SettingsController@certificate');
$route->post('/certificates/ifsg', 'SettingsController@saveIfsgCertificate');
$route->post('/certificates/driving', 'SettingsController@saveDrivingLicense');
$route->get('/api', 'SettingsController@api');
$route->post('/api', 'SettingsController@apiKeyReset');
$route->get('/oauth', 'SettingsController@oauth');
$route->get('/sessions', 'SettingsController@sessions');
$route->post('/sessions', 'SettingsController@sessionsDelete');
}
);
// User admin settings
$route->addGroup(
'/users/{user_id:\d+}',
function (RouteCollector $route): void {
$route->get('/certificates', 'Admin\\UserSettingsController@certificate');
$route->post('/certificates/ifsg', 'Admin\\UserSettingsController@saveIfsgCertificate');
$route->post('/certificates/driving', 'Admin\\UserSettingsController@saveDrivingLicense');
}
);
// Password recovery // Password recovery
$route->addGroup( $route->get('/password/reset', 'PasswordResetController@reset');
'/password/reset', $route->post('/password/reset', 'PasswordResetController@postReset');
function (RouteCollector $route): void { $route->get('/password/reset/{token:.+}', 'PasswordResetController@resetPassword');
$route->get('', 'PasswordResetController@reset'); $route->post('/password/reset/{token:.+}', 'PasswordResetController@postResetPassword');
$route->post('', 'PasswordResetController@postReset');
$route->get('/{token:.+}', 'PasswordResetController@resetPassword');
$route->post('/{token:.+}', 'PasswordResetController@postResetPassword');
}
);
// Stats // Stats
$route->get('/metrics', 'Metrics\\Controller@metrics'); $route->get('/metrics', 'Metrics\\Controller@metrics');
$route->get('/stats', 'Metrics\\Controller@stats'); $route->get('/stats', 'Metrics\\Controller@stats');
// Angeltypes
$route->addGroup('/angeltypes', function (RouteCollector $route): void {
$route->get('/about', 'AngelTypesController@about');
});
// Shifts
$route->addGroup('/shifts', function (RouteCollector $route): void {
$route->get('/random', 'ShiftsController@random');
});
// News // News
$route->get('/news', 'NewsController@index');
$route->get('/meetings', 'NewsController@meetings'); $route->get('/meetings', 'NewsController@meetings');
$route->addGroup( $route->get('/news/{id:\d+}', 'NewsController@show');
'/news', $route->post('/news/{id:\d+}', 'NewsController@comment');
function (RouteCollector $route): void { $route->post('/news/comment/{id:\d+}', 'NewsController@deleteComment');
$route->get('', 'NewsController@index');
$route->get('/{news_id:\d+}', 'NewsController@show');
$route->post('/{news_id:\d+}', 'NewsController@comment');
$route->post('/comment/{comment_id:\d+}', 'NewsController@deleteComment');
}
);
// FAQ // FAQ
$route->get('/faq', 'FaqController@index'); $route->get('/faq', 'FaqController@index');
// Questions // Questions
$route->addGroup( $route->get('/questions', 'QuestionsController@index');
'/questions', $route->post('/questions', 'QuestionsController@delete');
function (RouteCollector $route): void { $route->get('/questions/new', 'QuestionsController@add');
$route->get('', 'QuestionsController@index'); $route->post('/questions/new', 'QuestionsController@save');
$route->post('', 'QuestionsController@delete');
$route->get('/new', 'QuestionsController@add');
$route->post('/new', 'QuestionsController@save');
}
);
// Messages // Messages
$route->addGroup( $route->get('/messages', 'MessagesController@index');
'/messages', $route->post('/messages', 'MessagesController@redirectToConversation');
function (RouteCollector $route): void { $route->get('/messages/{user_id:\d+}', 'MessagesController@messagesOfConversation');
$route->get('', 'MessagesController@index'); $route->post('/messages/{user_id:\d+}', 'MessagesController@send');
$route->post('', 'MessagesController@redirectToConversation'); $route->post('/messages/{user_id:\d+}/{msg_id:\d+}', 'MessagesController@delete');
$route->get('/{user_id:\d+}', 'MessagesController@messagesOfConversation');
$route->post('/{user_id:\d+}', 'MessagesController@send');
$route->post('/{user_id:\d+}/{msg_id:\d+}', 'MessagesController@delete');
}
);
// API // API
$route->addGroup( $route->get('/api[/{resource:.+}]', 'ApiController@index');
'/api',
function (RouteCollector $route): void {
$route->get('', 'Api\IndexController@index');
$route->addGroup(
'/v0-beta',
function (RouteCollector $route): void {
$route->addRoute(['OPTIONS'], '[/{resource:.+}]', 'Api\IndexController@options');
$route->get('', 'Api\IndexController@indexV0');
$route->get('/openapi', 'Api\IndexController@openApiV0');
$route->get('/info', 'Api\IndexController@info');
$route->get('/angeltypes', 'Api\AngelTypeController@index');
$route->get('/angeltypes/{angeltype_id:\d+}/shifts', 'Api\ShiftsController@entriesByAngeltype');
$route->get('/locations', 'Api\LocationsController@index');
$route->get('/locations/{location_id:\d+}/shifts', 'Api\ShiftsController@entriesByLocation');
$route->get('/news', 'Api\NewsController@index');
$route->get('/users/{user_id:(?:\d+|self)}', 'Api\UsersController@user');
$route->get('/users/{user_id:(?:\d+|self)}/angeltypes', 'Api\AngelTypeController@ofUser');
$route->get('/users/{user_id:(?:\d+|self)}/shifts', 'Api\ShiftsController@entriesByUser');
$route->addRoute(
['POST', 'PUT', 'DELETE', 'PATCH'],
'/[{resource:.+}]',
'Api\IndexController@notImplemented'
);
$route->get('/[{resource:.+}]', 'Api\IndexController@notFound');
}
);
$route->get('/[{resource:.+}]', 'Api\IndexController@notFound');
}
);
// Feeds
$route->get('/atom', 'FeedController@atom');
$route->get('/ical', 'FeedController@ical');
$route->get('/rss', 'FeedController@rss');
$route->get('/shifts-json-export', 'FeedController@shifts');
// Design // Design
$route->get('/design', 'DesignController@index'); $route->get('/design', 'DesignController@index');
@ -174,118 +70,59 @@ $route->get('/design', 'DesignController@index');
// Administration // Administration
$route->addGroup( $route->addGroup(
'/admin', '/admin',
function (RouteCollector $route): void { function (RouteCollector $route) {
// FAQ // FAQ
$route->addGroup( $route->addGroup(
'/faq', '/faq',
function (RouteCollector $route): void { function (RouteCollector $route) {
$route->get('[/{faq_id:\d+}]', 'Admin\\FaqController@edit'); $route->get('[/{id:\d+}]', 'Admin\\FaqController@edit');
$route->post('[/{faq_id:\d+}]', 'Admin\\FaqController@save'); $route->post('[/{id:\d+}]', 'Admin\\FaqController@save');
} }
); );
// Log // Log
$route->addGroup( $route->get('/logs', 'Admin\\LogsController@index');
'/logs', $route->post('/logs', 'Admin\\LogsController@index');
function (RouteCollector $route): void {
$route->get('', 'Admin\\LogsController@index');
$route->post('', 'Admin\\LogsController@index');
}
);
// Schedule // Schedule
$route->addGroup( $route->addGroup(
'/schedule', '/schedule',
function (RouteCollector $route): void { function (RouteCollector $route) {
$route->get('', 'Admin\\ScheduleController@index'); $route->get('', 'Admin\\Schedule\\ImportSchedule@index');
$route->get('/edit[/{schedule_id:\d+}]', 'Admin\\ScheduleController@edit'); $route->get('/edit[/{id:\d+}]', 'Admin\\Schedule\\ImportSchedule@edit');
$route->post('/edit[/{schedule_id:\d+}]', 'Admin\\ScheduleController@save'); $route->post('/edit[/{id:\d+}]', 'Admin\\Schedule\\ImportSchedule@save');
$route->get('/load/{schedule_id:\d+}', 'Admin\\ScheduleController@loadSchedule'); $route->get('/load/{id:\d+}', 'Admin\\Schedule\\ImportSchedule@loadSchedule');
$route->post('/import/{schedule_id:\d+}', 'Admin\\ScheduleController@importSchedule'); $route->post('/import/{id:\d+}', 'Admin\\Schedule\\ImportSchedule@importSchedule');
}
);
// Shifts
$route->addGroup(
'/shifts',
function (RouteCollector $route): void {
$route->get('/history', 'Admin\\ShiftsController@history');
$route->post('/history', 'Admin\\ShiftsController@deleteTransaction');
}
);
// Shift types
$route->addGroup(
'/shifttypes',
function (RouteCollector $route): void {
$route->get('', 'Admin\\ShiftTypesController@index');
$route->post('', 'Admin\\ShiftTypesController@delete');
$route->get('/{shift_type_id:\d+}', 'Admin\\ShiftTypesController@view');
$route->get('/edit[/{shift_type_id:\d+}]', 'Admin\\ShiftTypesController@edit');
$route->post('/edit[/{shift_type_id:\d+}]', 'Admin\\ShiftTypesController@save');
} }
); );
// Questions // Questions
$route->addGroup( $route->addGroup(
'/questions', '/questions',
function (RouteCollector $route): void { function (RouteCollector $route) {
$route->get('', 'Admin\\QuestionsController@index'); $route->get('', 'Admin\\QuestionsController@index');
$route->post('', 'Admin\\QuestionsController@delete'); $route->post('', 'Admin\\QuestionsController@delete');
$route->get('/{question_id:\d+}', 'Admin\\QuestionsController@edit'); $route->get('/{id:\d+}', 'Admin\\QuestionsController@edit');
$route->post('/{question_id:\d+}', 'Admin\\QuestionsController@save'); $route->post('/{id:\d+}', 'Admin\\QuestionsController@save');
}
);
// Locations
$route->addGroup(
'/locations',
function (RouteCollector $route): void {
$route->get('', 'Admin\\LocationsController@index');
$route->post('', 'Admin\\LocationsController@delete');
$route->get('/edit[/{location_id:\d+}]', 'Admin\\LocationsController@edit');
$route->post('/edit[/{location_id:\d+}]', 'Admin\\LocationsController@save');
} }
); );
// User // User
$route->addGroup( $route->addGroup(
'/user/{user_id:\d+}', '/user/{id:\d+}',
function (RouteCollector $route): void { // Shirts
// Goodies function (RouteCollector $route) {
$route->addGroup( $route->get('/shirt', 'Admin\\UserShirtController@editShirt');
'/goodie', $route->post('/shirt', 'Admin\\UserShirtController@saveShirt');
function (RouteCollector $route): void {
$route->get('', 'Admin\\UserGoodieController@editGoodie');
$route->post('', 'Admin\\UserGoodieController@saveGoodie');
}
);
// Worklogs
$route->addGroup(
'/worklog',
function (RouteCollector $route): void {
$route->get('[/{worklog_id:\d+}]', 'Admin\\UserWorkLogController@editWorklog');
$route->post('[/{worklog_id:\d+}]', 'Admin\\UserWorkLogController@saveWorklog');
$route->get(
'/{worklog_id:\d+}/delete',
'Admin\\UserWorkLogController@showDeleteWorklog'
);
$route->post(
'/{worklog_id:\d+}/delete',
'Admin\\UserWorkLogController@deleteWorklog'
);
}
);
} }
); );
// News // News
$route->addGroup( $route->addGroup(
'/news', '/news',
function (RouteCollector $route): void { function (RouteCollector $route) {
$route->get('[/{news_id:\d+}]', 'Admin\\NewsController@edit'); $route->get('[/{id:\d+}]', 'Admin\\NewsController@edit');
$route->post('[/{news_id:\d+}]', 'Admin\\NewsController@save'); $route->post('[/{id:\d+}]', 'Admin\\NewsController@save');
} }
); );
} }

View File

@ -1,34 +0,0 @@
<?php
declare(strict_types=1);
namespace Database\Factories\Engelsystem\Models;
use Engelsystem\Models\AngelType;
use Illuminate\Database\Eloquent\Factories\Factory;
class AngelTypeFactory extends Factory
{
/** @var string */
protected $model = AngelType::class; // phpcs:ignore
public function definition(): array
{
return [
'name' => $this->faker->unique()->firstName(),
'description' => $this->faker->text(),
'contact_name' => $this->faker->firstName(),
'contact_dect' => $this->faker->randomNumber(4),
'contact_email' => $this->faker->email(),
'restricted' => $this->faker->boolean(),
'requires_driver_license' => $this->faker->boolean(),
'requires_ifsg_certificate' => $this->faker->boolean(),
'shift_self_signup' => $this->faker->boolean(),
'show_on_dashboard' => $this->faker->boolean(),
'hide_register' => $this->faker->boolean(),
'hide_on_shift_view' => $this->faker->boolean(),
];
}
}

View File

@ -1,7 +1,5 @@
<?php <?php
declare(strict_types=1);
namespace Database\Factories\Engelsystem\Models; namespace Database\Factories\Engelsystem\Models;
use Engelsystem\Models\Faq; use Engelsystem\Models\Faq;
@ -10,9 +8,12 @@ use Illuminate\Database\Eloquent\Factories\Factory;
class FaqFactory extends Factory class FaqFactory extends Factory
{ {
/** @var string */ /** @var string */
protected $model = Faq::class; // phpcs:ignore protected $model = Faq::class;
public function definition(): array /**
* @return array
*/
public function definition()
{ {
return [ return [
'question' => $this->faker->text(100), 'question' => $this->faker->text(100),

View File

@ -1,21 +0,0 @@
<?php
declare(strict_types=1);
namespace Database\Factories\Engelsystem\Models;
use Engelsystem\Models\Group;
use Illuminate\Database\Eloquent\Factories\Factory;
class GroupFactory extends Factory
{
/** @var string */
protected $model = Group::class; // phpcs:ignore
public function definition(): array
{
return [
'name' => $this->faker->unique()->word(),
];
}
}

View File

@ -1,7 +1,5 @@
<?php <?php
declare(strict_types=1);
namespace Database\Factories\Engelsystem\Models; namespace Database\Factories\Engelsystem\Models;
use Engelsystem\Models\Message; use Engelsystem\Models\Message;
@ -11,9 +9,12 @@ use Illuminate\Database\Eloquent\Factories\Factory;
class MessageFactory extends Factory class MessageFactory extends Factory
{ {
/** @var string */ /** @var string */
protected $model = Message::class; // phpcs:ignore protected $model = Message::class;
public function definition(): array /**
* @return array
*/
public function definition()
{ {
return [ return [
'user_id' => User::factory(), 'user_id' => User::factory(),

View File

@ -1,7 +1,5 @@
<?php <?php
declare(strict_types=1);
namespace Database\Factories\Engelsystem\Models; namespace Database\Factories\Engelsystem\Models;
use Engelsystem\Models\News; use Engelsystem\Models\News;
@ -12,9 +10,12 @@ use Illuminate\Database\Eloquent\Factories\Factory;
class NewsCommentFactory extends Factory class NewsCommentFactory extends Factory
{ {
/** @var string */ /** @var string */
protected $model = NewsComment::class; // phpcs:ignore protected $model = NewsComment::class;
public function definition(): array /**
* @return array
*/
public function definition()
{ {
return [ return [
'news_id' => News::factory(), 'news_id' => News::factory(),

View File

@ -1,7 +1,5 @@
<?php <?php
declare(strict_types=1);
namespace Database\Factories\Engelsystem\Models; namespace Database\Factories\Engelsystem\Models;
use Engelsystem\Models\News; use Engelsystem\Models\News;
@ -11,16 +9,18 @@ use Illuminate\Database\Eloquent\Factories\Factory;
class NewsFactory extends Factory class NewsFactory extends Factory
{ {
/** @var string */ /** @var string */
protected $model = News::class; // phpcs:ignore protected $model = News::class;
public function definition(): array /**
* @return array
*/
public function definition()
{ {
return [ return [
'title' => $this->faker->text(50), 'title' => $this->faker->text(50),
'text' => $this->faker->realText(), 'text' => $this->faker->realText(),
'is_meeting' => $this->faker->boolean(), 'is_meeting' => $this->faker->boolean(),
'is_pinned' => $this->faker->boolean(.1), 'is_pinned' => $this->faker->boolean(.1),
'is_highlighted' => $this->faker->boolean(.1),
'user_id' => User::factory(), 'user_id' => User::factory(),
]; ];
} }

View File

@ -1,30 +0,0 @@
<?php
declare(strict_types=1);
namespace Database\Factories\Engelsystem\Models;
use Engelsystem\Models\OAuth;
use Engelsystem\Models\User\User;
use Illuminate\Database\Eloquent\Factories\Factory;
class OAuthFactory extends Factory
{
/** @var class-string */
protected $model = OAuth::class; // phpcs:ignore
/**
* @return array<string, mixed>
*/
public function definition(): array
{
return [
'user_id' => User::factory(),
'provider' => $this->faker->unique()->word(),
'identifier' => $this->faker->unique()->word(),
'access_token' => $this->faker->unique()->word(),
'refresh_token' => $this->faker->unique()->word(),
'expires_at' => $this->faker->dateTimeInInterval('+5 days', '+3 months')->format('Y-m-d'),
];
}
}

View File

@ -1,22 +0,0 @@
<?php
declare(strict_types=1);
namespace Database\Factories\Engelsystem\Models;
use Engelsystem\Models\Privilege;
use Illuminate\Database\Eloquent\Factories\Factory;
class PrivilegeFactory extends Factory
{
/** @var string */
protected $model = Privilege::class; // phpcs:ignore
public function definition(): array
{
return [
'name' => $this->faker->unique()->word(),
'description' => $this->faker->text(),
];
}
}

View File

@ -1,7 +1,5 @@
<?php <?php
declare(strict_types=1);
namespace Database\Factories\Engelsystem\Models; namespace Database\Factories\Engelsystem\Models;
use Carbon\Carbon; use Carbon\Carbon;
@ -12,9 +10,12 @@ use Illuminate\Database\Eloquent\Factories\Factory;
class QuestionFactory extends Factory class QuestionFactory extends Factory
{ {
/** @var string */ /** @var string */
protected $model = Question::class; // phpcs:ignore protected $model = Question::class;
public function definition(): array /**
* @return array
*/
public function definition()
{ {
return [ return [
'user_id' => User::factory(), 'user_id' => User::factory(),

View File

@ -1,24 +1,24 @@
<?php <?php
declare(strict_types=1);
namespace Database\Factories\Engelsystem\Models; namespace Database\Factories\Engelsystem\Models;
use Engelsystem\Models\Location; use Engelsystem\Models\Room;
use Illuminate\Database\Eloquent\Factories\Factory; use Illuminate\Database\Eloquent\Factories\Factory;
class LocationFactory extends Factory class RoomFactory extends Factory
{ {
/** @var string */ /** @var string */
protected $model = Location::class; // phpcs:ignore protected $model = Room::class;
public function definition(): array /**
* @return array
*/
public function definition()
{ {
return [ return [
'name' => $this->faker->unique()->firstName(), 'name' => $this->faker->unique()->firstName(),
'map_url' => $this->faker->url(), 'map_url' => $this->faker->url(),
'description' => $this->faker->text(), 'description' => $this->faker->text(),
'dect' => $this->faker->optional()->numberBetween(1000, 9999),
]; ];
} }
} }

View File

@ -1,24 +0,0 @@
<?php
declare(strict_types=1);
namespace Database\Factories\Engelsystem\Models;
use Engelsystem\Models\Session;
use Engelsystem\Models\User\User;
use Illuminate\Database\Eloquent\Factories\Factory;
class SessionFactory extends Factory
{
/** @var string */
protected $model = Session::class; // phpcs:ignore
public function definition(): array
{
return [
'id' => $this->faker->lexify('????????????????????????????????'),
'payload' => $this->faker->text(100),
'user_id' => $this->faker->optional()->passthrough(User::factory()),
];
}
}

View File

@ -1,30 +0,0 @@
<?php
declare(strict_types=1);
namespace Database\Factories\Engelsystem\Models\Shifts;
use Engelsystem\Models\AngelType;
use Engelsystem\Models\Location;
use Engelsystem\Models\Shifts\NeededAngelType;
use Engelsystem\Models\Shifts\Shift;
use Illuminate\Database\Eloquent\Factories\Factory;
class NeededAngelTypeFactory extends Factory
{
/** @var string */
protected $model = NeededAngelType::class; // phpcs:ignore
public function definition(): array
{
$type = $this->faker->numberBetween(0, 2);
return [
'location_id' => $type == 0 ? Location::factory() : null,
'shift_id' => $type == 1 ? null : Shift::factory(),
'shift_type_id' => $type == 2 ? null : Shift::factory(),
'angel_type_id' => AngelType::factory(),
'count' => $this->faker->numberBetween(1, 5),
];
}
}

View File

@ -1,7 +1,5 @@
<?php <?php
declare(strict_types=1);
namespace Database\Factories\Engelsystem\Models\Shifts; namespace Database\Factories\Engelsystem\Models\Shifts;
use Engelsystem\Models\Shifts\Schedule; use Engelsystem\Models\Shifts\Schedule;
@ -10,15 +8,17 @@ use Illuminate\Database\Eloquent\Factories\Factory;
class ScheduleFactory extends Factory class ScheduleFactory extends Factory
{ {
/** @var string */ /** @var string */
protected $model = Schedule::class; // phpcs:ignore protected $model = Schedule::class;
public function definition(): array /**
* @return array
*/
public function definition()
{ {
return [ return [
'name' => $this->faker->unique()->words(4, true), 'name' => $this->faker->words(4, true),
'url' => $this->faker->parse('https://{{safeEmailDomain}}/{{slug}}.xml'), 'url' => $this->faker->parse('https://{{safeEmailDomain}}/{{slug}}.xml'),
'shift_type' => $this->faker->numberBetween(1, 5), 'shift_type' => $this->faker->numberBetween(1, 5),
'needed_from_shift_type' => $this->faker->boolean(.2),
'minutes_before' => 15, 'minutes_before' => 15,
'minutes_after' => 15, 'minutes_after' => 15,
]; ];

View File

@ -1,31 +0,0 @@
<?php
declare(strict_types=1);
namespace Database\Factories\Engelsystem\Models\Shifts;
use Engelsystem\Models\AngelType;
use Engelsystem\Models\Shifts\Shift;
use Engelsystem\Models\Shifts\ShiftEntry;
use Engelsystem\Models\User\User;
use Illuminate\Database\Eloquent\Factories\Factory;
class ShiftEntryFactory extends Factory
{
/** @var string */
protected $model = ShiftEntry::class; // phpcs:ignore
public function definition(): array
{
$freeloaded = $this->faker->optional(.01, false)->boolean();
return [
'shift_id' => Shift::factory(),
'angel_type_id' => AngelType::factory(),
'user_id' => User::factory(),
'user_comment' => $this->faker->optional(.05, '')->text(),
'freeloaded' => $freeloaded,
'freeloaded_comment' => $freeloaded ? $this->faker->text() : '',
];
}
}

View File

@ -1,34 +0,0 @@
<?php
declare(strict_types=1);
namespace Database\Factories\Engelsystem\Models\Shifts;
use Engelsystem\Models\Location;
use Engelsystem\Models\Shifts\Shift;
use Engelsystem\Models\Shifts\ShiftType;
use Engelsystem\Models\User\User;
use Illuminate\Database\Eloquent\Factories\Factory;
class ShiftFactory extends Factory
{
/** @var string */
protected $model = Shift::class; // phpcs:ignore
public function definition(): array
{
$start = $this->faker->dateTimeThisMonth('2 weeks');
return [
'title' => $this->faker->unique()->text(15),
'description' => $this->faker->text(),
'url' => $this->faker->url(),
'start' => $start,
'end' => $this->faker->dateTimeInInterval($start, '+3 hours'),
'shift_type_id' => ShiftType::factory(),
'location_id' => Location::factory(),
'transaction_id' => $this->faker->optional()->uuid(),
'created_by' => User::factory(),
'updated_by' => $this->faker->optional(.3)->boolean() ? User::factory() : null,
];
}
}

View File

@ -1,22 +0,0 @@
<?php
declare(strict_types=1);
namespace Database\Factories\Engelsystem\Models\Shifts;
use Engelsystem\Models\Shifts\ShiftType;
use Illuminate\Database\Eloquent\Factories\Factory;
class ShiftTypeFactory extends Factory
{
/** @var string */
protected $model = ShiftType::class; // phpcs:ignore
public function definition(): array
{
return [
'name' => $this->faker->unique()->firstName(),
'description' => $this->faker->text(),
];
}
}

View File

@ -1,22 +1,21 @@
<?php <?php
declare(strict_types=1);
namespace Database\Factories\Engelsystem\Models\User; namespace Database\Factories\Engelsystem\Models\User;
use Engelsystem\Models\User\Contact; use Engelsystem\Models\User\Contact;
use Engelsystem\Models\User\User;
use Illuminate\Database\Eloquent\Factories\Factory; use Illuminate\Database\Eloquent\Factories\Factory;
class ContactFactory extends Factory class ContactFactory extends Factory
{ {
/** @var string */ /** @var string */
protected $model = Contact::class; // phpcs:ignore protected $model = Contact::class;
public function definition(): array /**
* @return array
*/
public function definition()
{ {
return [ return [
'user_id' => User::factory(),
'dect' => $this->faker->optional()->numberBetween(1000, 9999), 'dect' => $this->faker->optional()->numberBetween(1000, 9999),
'email' => $this->faker->unique()->optional()->safeEmail(), 'email' => $this->faker->unique()->optional()->safeEmail(),
'mobile' => $this->faker->optional(.2)->phoneNumber(), 'mobile' => $this->faker->optional(.2)->phoneNumber(),

View File

@ -1,19 +1,19 @@
<?php <?php
declare(strict_types=1);
namespace Database\Factories\Engelsystem\Models\User; namespace Database\Factories\Engelsystem\Models\User;
use Engelsystem\Models\User\License; use Engelsystem\Models\User\License;
use Engelsystem\Models\User\User;
use Illuminate\Database\Eloquent\Factories\Factory; use Illuminate\Database\Eloquent\Factories\Factory;
class LicenseFactory extends Factory class LicenseFactory extends Factory
{ {
/** @var string */ /** @var string */
protected $model = License::class; // phpcs:ignore protected $model = License::class;
public function definition(): array /**
* @return array
*/
public function definition()
{ {
$drive_car = $this->faker->boolean(.8); $drive_car = $this->faker->boolean(.8);
$drive_3_5t = $drive_car && $this->faker->boolean(.7); $drive_3_5t = $drive_car && $this->faker->boolean(.7);
@ -21,30 +21,14 @@ class LicenseFactory extends Factory
$drive_12t = $drive_7_5t && $this->faker->boolean(.3); $drive_12t = $drive_7_5t && $this->faker->boolean(.3);
$drive_forklift = ($drive_car && $this->faker->boolean(.1)) $drive_forklift = ($drive_car && $this->faker->boolean(.1))
|| ($drive_12t && $this->faker->boolean(.7)); || ($drive_12t && $this->faker->boolean(.7));
$drive_confirmed = $this->faker->boolean(0.5) && (
$drive_car
|| $drive_3_5t
|| $drive_7_5t
|| $drive_12t
|| $drive_forklift
);
$ifsg_certificate = $this->faker->boolean(0.1);
$ifsg_certificate_light = $this->faker->boolean(0.5) && !$ifsg_certificate;
$ifsg_confirmed = $this->faker->boolean(0.5) && ($ifsg_certificate || $ifsg_certificate_light);
return [ return [
'user_id' => User::factory(),
'has_car' => $drive_car && $this->faker->boolean(.7), 'has_car' => $drive_car && $this->faker->boolean(.7),
'drive_forklift' => $drive_forklift, 'drive_forklift' => $drive_forklift,
'drive_car' => $drive_car, 'drive_car' => $drive_car,
'drive_3_5t' => $drive_3_5t, 'drive_3_5t' => $drive_3_5t,
'drive_7_5t' => $drive_7_5t, 'drive_7_5t' => $drive_7_5t,
'drive_12t' => $drive_12t, 'drive_12t' => $drive_12t,
'drive_confirmed' => $drive_confirmed,
'ifsg_certificate' => $ifsg_certificate,
'ifsg_certificate_light' => $ifsg_certificate_light,
'ifsg_confirmed' => $ifsg_confirmed,
]; ];
} }
} }

View File

@ -1,23 +1,22 @@
<?php <?php
declare(strict_types=1);
namespace Database\Factories\Engelsystem\Models\User; namespace Database\Factories\Engelsystem\Models\User;
use Engelsystem\Models\User\PasswordReset; use Engelsystem\Models\User\PasswordReset;
use Engelsystem\Models\User\User;
use Illuminate\Database\Eloquent\Factories\Factory; use Illuminate\Database\Eloquent\Factories\Factory;
class PasswordResetFactory extends Factory class PasswordResetFactory extends Factory
{ {
/** @var string */ /** @var string */
protected $model = PasswordReset::class; // phpcs:ignore protected $model = PasswordReset::class;
public function definition(): array /**
* @return array
*/
public function definition()
{ {
return [ return [
'user_id' => User::factory(), 'token' => md5($this->faker->unique()->password()),
'token' => bin2hex(random_bytes(16)),
]; ];
} }
} }

View File

@ -1,26 +1,25 @@
<?php <?php
declare(strict_types=1);
namespace Database\Factories\Engelsystem\Models\User; namespace Database\Factories\Engelsystem\Models\User;
use Carbon\Carbon; use Carbon\Carbon;
use Engelsystem\Models\User\PersonalData; use Engelsystem\Models\User\PersonalData;
use Engelsystem\Models\User\User;
use Illuminate\Database\Eloquent\Factories\Factory; use Illuminate\Database\Eloquent\Factories\Factory;
class PersonalDataFactory extends Factory class PersonalDataFactory extends Factory
{ {
/** @var string */ /** @var string */
protected $model = PersonalData::class; // phpcs:ignore protected $model = PersonalData::class;
public function definition(): array /**
* @return array
*/
public function definition()
{ {
$arrival = $this->faker->optional()->dateTimeThisMonth('2 weeks'); $arrival = $this->faker->optional()->dateTimeThisMonth('2 weeks');
$departure = $this->faker->optional()->dateTimeThisMonth('2 weeks'); $departure = $this->faker->optional()->dateTimeThisMonth('2 weeks');
return [ return [
'user_id' => User::factory(),
'first_name' => $this->faker->optional(.7)->firstName(), 'first_name' => $this->faker->optional(.7)->firstName(),
'last_name' => $this->faker->optional()->lastName(), 'last_name' => $this->faker->optional()->lastName(),
'pronoun' => $this->faker->optional(.3)->pronoun(), 'pronoun' => $this->faker->optional(.3)->pronoun(),

View File

@ -1,30 +1,27 @@
<?php <?php
declare(strict_types=1);
namespace Database\Factories\Engelsystem\Models\User; namespace Database\Factories\Engelsystem\Models\User;
use Engelsystem\Models\User\Settings; use Engelsystem\Models\User\Settings;
use Engelsystem\Models\User\User;
use Illuminate\Database\Eloquent\Factories\Factory; use Illuminate\Database\Eloquent\Factories\Factory;
class SettingsFactory extends Factory class SettingsFactory extends Factory
{ {
/** @var string */ /** @var string */
protected $model = Settings::class; // phpcs:ignore protected $model = Settings::class;
public function definition(): array /**
* @return array
*/
public function definition()
{ {
return [ return [
'user_id' => User::factory(),
'language' => $this->faker->locale(), 'language' => $this->faker->locale(),
'theme' => $this->faker->numberBetween(1, 20), 'theme' => $this->faker->numberBetween(1, 20),
'email_human' => $this->faker->boolean(), 'email_human' => $this->faker->boolean(),
'email_messages' => $this->faker->boolean(), 'email_goody' => $this->faker->boolean(),
'email_goodie' => $this->faker->boolean(),
'email_shiftinfo' => $this->faker->boolean(), 'email_shiftinfo' => $this->faker->boolean(),
'email_news' => $this->faker->boolean(), 'email_news' => $this->faker->boolean(),
'mobile_show' => $this->faker->boolean(),
]; ];
} }
} }

View File

@ -1,39 +1,39 @@
<?php <?php
declare(strict_types=1);
namespace Database\Factories\Engelsystem\Models\User; namespace Database\Factories\Engelsystem\Models\User;
use Carbon\Carbon; use Carbon\Carbon;
use Engelsystem\Models\User\State; use Engelsystem\Models\User\State;
use Engelsystem\Models\User\User;
use Illuminate\Database\Eloquent\Factories\Factory; use Illuminate\Database\Eloquent\Factories\Factory;
class StateFactory extends Factory class StateFactory extends Factory
{ {
/** @var string */ /** @var string */
protected $model = State::class; // phpcs:ignore protected $model = State::class;
public function definition(): array /**
* @return array
*/
public function definition()
{ {
$arrival = $this->faker->optional()->dateTimeThisMonth(); $arrival = $this->faker->optional()->dateTimeThisMonth();
return [ return [
'user_id' => User::factory(),
'arrived' => (bool)$arrival, 'arrived' => (bool)$arrival,
'arrival_date' => $arrival ? Carbon::instance($arrival) : null, 'arrival_date' => $arrival ? Carbon::instance($arrival) : null,
'user_info' => $this->faker->optional(.1)->text(),
'active' => $this->faker->boolean(.3), 'active' => $this->faker->boolean(.3),
'force_active' => $this->faker->boolean(.1), 'force_active' => $this->faker->boolean(.1),
'got_goodie' => $this->faker->boolean(), 'got_shirt' => $this->faker->boolean(),
'got_voucher' => $this->faker->numberBetween(0, 10), 'got_voucher' => $this->faker->numberBetween(0, 10),
]; ];
} }
/** /**
* Indicate that the user is arrived * Indicate that the user is arrived
*
* @return self
*/ */
public function arrived(): self public function arrived()
{ {
return $this->state( return $this->state(
function (array $attributes) { function (array $attributes) {

View File

@ -1,7 +1,5 @@
<?php <?php
declare(strict_types=1);
namespace Database\Factories\Engelsystem\Models\User; namespace Database\Factories\Engelsystem\Models\User;
use Engelsystem\Models\User\User; use Engelsystem\Models\User\User;
@ -10,16 +8,18 @@ use Illuminate\Database\Eloquent\Factories\Factory;
class UserFactory extends Factory class UserFactory extends Factory
{ {
/** @var string */ /** @var string */
protected $model = User::class; // phpcs:ignore protected $model = User::class;
public function definition(): array /**
* @return array
*/
public function definition()
{ {
return [ return [
'name' => $this->faker->unique()->userName(), 'name' => $this->faker->unique()->userName(),
'password' => crypt(random_bytes(16), '$1$salt$'), 'password' => password_hash($this->faker->password(), PASSWORD_DEFAULT),
'email' => $this->faker->unique()->safeEmail(), 'email' => $this->faker->unique()->safeEmail(),
'api_key' => bin2hex(random_bytes(32)), 'api_key' => md5($this->faker->unique()->password()),
'updated_at' => $this->faker->dateTimeInInterval('-3 months', 'now'),
]; ];
} }
} }

View File

@ -1,26 +0,0 @@
<?php
declare(strict_types=1);
namespace Database\Factories\Engelsystem\Models;
use Engelsystem\Models\AngelType;
use Engelsystem\Models\User\User;
use Engelsystem\Models\UserAngelType;
use Illuminate\Database\Eloquent\Factories\Factory;
class UserAngelTypeFactory extends Factory
{
/** @var string */
protected $model = UserAngelType::class; // phpcs:ignore
public function definition(): array
{
return [
'user_id' => User::factory(),
'angel_type_id' => AngelType::factory(),
'confirm_user_id' => $this->faker->optional()->passthrough(User::factory()),
'supporter' => $this->faker->boolean(),
];
}
}

View File

@ -1,7 +1,5 @@
<?php <?php
declare(strict_types=1);
namespace Database\Factories\Engelsystem\Models; namespace Database\Factories\Engelsystem\Models;
use Engelsystem\Models\User\User; use Engelsystem\Models\User\User;
@ -11,9 +9,12 @@ use Illuminate\Database\Eloquent\Factories\Factory;
class WorklogFactory extends Factory class WorklogFactory extends Factory
{ {
/** @var string */ /** @var string */
protected $model = Worklog::class; // phpcs:ignore protected $model = Worklog::class;
public function definition(): array /**
* @return array
*/
public function definition()
{ {
return [ return [
'user_id' => User::factory(), 'user_id' => User::factory(),

802
db/install.sql Normal file
View File

@ -0,0 +1,802 @@
-- phpMyAdmin SQL Dump
-- version 4.5.2
-- http://www.phpmyadmin.net
--
-- Host: localhost
-- Erstellungszeit: 27. Sep 2016 um 17:48
-- Server-Version: 10.1.10-MariaDB
-- PHP-Version: 7.0.4
SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
SET time_zone = "+00:00";
--
-- Datenbank: `engelsystem`
--
-- --------------------------------------------------------
--
-- Tabellenstruktur für Tabelle `AngelTypes`
--
DROP TABLE IF EXISTS `AngelTypes`;
CREATE TABLE `AngelTypes` (
`id` int(11) NOT NULL,
`name` varchar(50) NOT NULL DEFAULT '',
`restricted` int(1) NOT NULL,
`description` text NOT NULL,
`requires_driver_license` tinyint(1) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- --------------------------------------------------------
--
-- Tabellenstruktur für Tabelle `EventConfig`
--
DROP TABLE IF EXISTS `EventConfig`;
CREATE TABLE `EventConfig` (
`event_name` varchar(255) DEFAULT NULL,
`buildup_start_date` int(11) DEFAULT NULL,
`event_start_date` int(11) DEFAULT NULL,
`event_end_date` int(11) DEFAULT NULL,
`teardown_end_date` int(11) DEFAULT NULL,
`event_welcome_msg` varchar(255) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- --------------------------------------------------------
--
-- Tabellenstruktur für Tabelle `GroupPrivileges`
--
DROP TABLE IF EXISTS `GroupPrivileges`;
CREATE TABLE `GroupPrivileges` (
`id` int(11) NOT NULL,
`group_id` int(11) NOT NULL,
`privilege_id` int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
--
-- Daten für Tabelle `GroupPrivileges`
--
INSERT INTO `GroupPrivileges` (`id`, `group_id`, `privilege_id`) VALUES
(85, -7, 10),
(87, -7, 18),
(86, -7, 21),
(216, -6, 5),
(212, -6, 6),
(207, -6, 7),
(211, -6, 12),
(208, -6, 13),
(210, -6, 14),
(214, -6, 16),
(209, -6, 21),
(213, -6, 28),
(206, -6, 31),
(215, -6, 33),
(257, -6, 38),
(219, -5, 14),
(221, -5, 25),
(220, -5, 33),
(241, -4, 5),
(238, -4, 14),
(240, -4, 16),
(237, -4, 19),
(242, -4, 25),
(235, -4, 27),
(239, -4, 28),
(236, -4, 32),
(218, -4, 39),
(258, -3, 31),
(247, -2, 3),
(246, -2, 4),
(255, -2, 8),
(252, -2, 9),
(254, -2, 11),
(248, -2, 15),
(251, -2, 17),
(256, -2, 24),
(253, -2, 26),
(245, -2, 30),
(244, -2, 34),
(249, -2, 35),
(243, -2, 36),
(250, -2, 37),
(88, -1, 1),
(23, -1, 2),
(24, -1, 5);
-- --------------------------------------------------------
--
-- Tabellenstruktur für Tabelle `Groups`
--
DROP TABLE IF EXISTS `Groups`;
CREATE TABLE `Groups` (
`Name` varchar(35) NOT NULL,
`UID` int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
--
-- Daten für Tabelle `Groups`
--
INSERT INTO `Groups` (`Name`, `UID`) VALUES
('6-Developer', -7),
('5-Bürokrat', -6),
('4-Team Coordinator', -5),
('3-Shift Coordinator', -4),
('Shirt-Manager', -3),
('2-Engel', -2),
('1-Gast', -1);
-- --------------------------------------------------------
--
-- Tabellenstruktur für Tabelle `LogEntries`
--
DROP TABLE IF EXISTS `LogEntries`;
CREATE TABLE `LogEntries` (
`id` int(11) NOT NULL,
`timestamp` int(11) NOT NULL,
`nick` text NOT NULL,
`message` text NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- --------------------------------------------------------
--
-- Tabellenstruktur für Tabelle `Messages`
--
DROP TABLE IF EXISTS `Messages`;
CREATE TABLE `Messages` (
`id` int(11) NOT NULL,
`Datum` int(11) NOT NULL,
`SUID` int(11) NOT NULL DEFAULT '0',
`RUID` int(11) NOT NULL DEFAULT '0',
`isRead` char(1) NOT NULL DEFAULT 'N',
`Text` text NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Fuers interen Communikationssystem';
-- --------------------------------------------------------
--
-- Tabellenstruktur für Tabelle `NeededAngelTypes`
--
DROP TABLE IF EXISTS `NeededAngelTypes`;
CREATE TABLE `NeededAngelTypes` (
`id` int(11) NOT NULL,
`room_id` int(11) DEFAULT NULL,
`shift_id` int(11) DEFAULT NULL,
`angel_type_id` int(11) NOT NULL,
`count` int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- --------------------------------------------------------
--
-- Tabellenstruktur für Tabelle `News`
--
DROP TABLE IF EXISTS `News`;
CREATE TABLE `News` (
`ID` int(11) NOT NULL,
`Datum` int(11) NOT NULL,
`Betreff` varchar(150) NOT NULL DEFAULT '',
`Text` text NOT NULL,
`UID` int(11) NOT NULL DEFAULT '0',
`Treffen` tinyint(4) NOT NULL DEFAULT '0'
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- --------------------------------------------------------
--
-- Tabellenstruktur für Tabelle `NewsComments`
--
DROP TABLE IF EXISTS `NewsComments`;
CREATE TABLE `NewsComments` (
`ID` bigint(11) NOT NULL,
`Refid` int(11) NOT NULL DEFAULT '0',
`Datum` datetime NOT NULL DEFAULT '0001-01-01 00:00:00',
`Text` text NOT NULL,
`UID` int(11) NOT NULL DEFAULT '0'
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- --------------------------------------------------------
--
-- Tabellenstruktur für Tabelle `Privileges`
--
DROP TABLE IF EXISTS `Privileges`;
CREATE TABLE `Privileges` (
`id` int(11) NOT NULL,
`name` varchar(128) NOT NULL,
`desc` varchar(1024) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
--
-- Daten für Tabelle `Privileges`
--
INSERT INTO `Privileges` (`id`, `name`, `desc`) VALUES
(1, 'start', 'Startseite für Gäste/Nicht eingeloggte User'),
(2, 'login', 'Logindialog'),
(3, 'news', 'Anzeigen der News-Seite'),
(4, 'logout', 'User darf sich ausloggen'),
(5, 'register', 'Einen neuen Engel registerieren'),
(6, 'admin_rooms', 'Räume administrieren'),
(7, 'admin_angel_types', 'Engel Typen administrieren'),
(8, 'user_settings', 'User profile settings'),
(9, 'user_messages', 'Writing and reading messages from user to user'),
(10, 'admin_groups', 'Manage usergroups and their rights'),
(11, 'user_questions', 'Let users ask questions'),
(12, 'admin_questions', 'Answer user''s questions'),
(13, 'admin_faq', 'Edit FAQs'),
(14, 'admin_news', 'Administrate the news section'),
(15, 'news_comments', 'User can comment news'),
(16, 'admin_user', 'Administrate the angels'),
(17, 'user_meetings', 'Lists meetings (news)'),
(18, 'admin_language', 'Translate the system'),
(19, 'admin_log', 'Display recent changes'),
(20, 'user_wakeup', 'User wakeup-service organization'),
(21, 'admin_import', 'Import rooms and shifts from pentabarf'),
(22, 'credits', 'View credits'),
(23, 'faq', 'View FAQ'),
(24, 'user_shifts', 'Signup for shifts'),
(25, 'user_shifts_admin', 'Signup other angels for shifts.'),
(26, 'user_myshifts', 'Allow angels to view their own shifts and cancel them.'),
(27, 'admin_arrive', 'Mark angels when they arrive.'),
(28, 'admin_shifts', 'Create shifts'),
(30, 'ical', 'iCal shift export'),
(31, 'admin_active', 'Mark angels as active and if they got a t-shirt.'),
(32, 'admin_free', 'Show a list of free/unemployed angels.'),
(33, 'admin_user_angeltypes', 'Confirm restricted angel types'),
(34, 'atom', ' Atom news export'),
(35, 'shifts_json_export', 'Export shifts in JSON format'),
(36, 'angeltypes', 'View angeltypes'),
(37, 'user_angeltypes', 'Join angeltypes.'),
(38, 'shifttypes', 'Administrate shift types'),
(39, 'admin_event_config', 'Allow editing event config');
-- --------------------------------------------------------
--
-- Tabellenstruktur für Tabelle `Questions`
--
DROP TABLE IF EXISTS `Questions`;
CREATE TABLE `Questions` (
`QID` bigint(20) NOT NULL,
`UID` int(11) NOT NULL DEFAULT '0',
`Question` text NOT NULL,
`AID` int(11) DEFAULT NULL,
`Answer` text
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Fragen und Antworten';
-- --------------------------------------------------------
--
-- Tabellenstruktur für Tabelle `Room`
--
DROP TABLE IF EXISTS `Room`;
CREATE TABLE `Room` (
`RID` int(11) NOT NULL,
`Name` varchar(35) NOT NULL DEFAULT '',
`Man` text,
`FromPentabarf` char(1) NOT NULL DEFAULT 'N',
`show` char(1) NOT NULL DEFAULT 'Y',
`Number` int(11) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
--
-- Daten für Tabelle `Room`
--
INSERT INTO `Room` (`RID`, `Name`, `Man`, `FromPentabarf`, `show`, `Number`) VALUES
(1, 'Testraum', NULL, '', 'Y', 0);
-- --------------------------------------------------------
--
-- Tabellenstruktur für Tabelle `ShiftEntry`
--
DROP TABLE IF EXISTS `ShiftEntry`;
CREATE TABLE `ShiftEntry` (
`id` int(11) NOT NULL,
`SID` int(11) NOT NULL DEFAULT '0',
`TID` int(11) NOT NULL DEFAULT '0',
`UID` int(11) NOT NULL DEFAULT '0',
`Comment` text,
`freeload_comment` text,
`freeloaded` tinyint(1) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- --------------------------------------------------------
--
-- Tabellenstruktur für Tabelle `Shifts`
--
DROP TABLE IF EXISTS `Shifts`;
CREATE TABLE `Shifts` (
`SID` int(11) NOT NULL,
`title` text,
`shifttype_id` int(11) NOT NULL,
`start` int(11) NOT NULL,
`end` int(11) NOT NULL,
`RID` int(11) NOT NULL DEFAULT '0',
`URL` text,
`PSID` int(11) DEFAULT NULL,
`created_by_user_id` int(11) DEFAULT NULL,
`created_at_timestamp` int(11) NOT NULL,
`edited_by_user_id` int(11) DEFAULT NULL,
`edited_at_timestamp` int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- --------------------------------------------------------
--
-- Tabellenstruktur für Tabelle `ShiftTypes`
--
DROP TABLE IF EXISTS `ShiftTypes`;
CREATE TABLE `ShiftTypes` (
`id` int(11) NOT NULL,
`name` varchar(255) NOT NULL,
`angeltype_id` int(11) DEFAULT NULL,
`description` text NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
--
-- Daten für Tabelle `ShiftTypes`
--
INSERT INTO `ShiftTypes` (`id`, `name`, `angeltype_id`, `description`) VALUES
(4, 'Schichttyp1', NULL, '');
-- --------------------------------------------------------
--
-- Tabellenstruktur für Tabelle `User`
--
DROP TABLE IF EXISTS `User`;
CREATE TABLE `User` (
`UID` int(11) NOT NULL,
`Nick` varchar(23) NOT NULL DEFAULT '',
`Name` varchar(23) DEFAULT NULL,
`Vorname` varchar(23) DEFAULT NULL,
`Alter` int(4) DEFAULT NULL,
`Telefon` varchar(40) DEFAULT NULL,
`DECT` varchar(5) DEFAULT NULL,
`Handy` varchar(40) DEFAULT NULL,
`email` varchar(123) DEFAULT NULL,
`email_shiftinfo` tinyint(1) NOT NULL DEFAULT '0' COMMENT 'User wants to be informed by mail about changes in his shifts',
`jabber` varchar(200) DEFAULT NULL,
`Size` varchar(4) DEFAULT NULL,
`Passwort` varchar(128) DEFAULT NULL,
`password_recovery_token` varchar(32) DEFAULT NULL,
`Gekommen` tinyint(4) NOT NULL DEFAULT '0',
`Aktiv` tinyint(4) NOT NULL DEFAULT '0',
`force_active` tinyint(1) NOT NULL,
`Tshirt` tinyint(4) DEFAULT '0',
`color` tinyint(4) DEFAULT '10',
`Sprache` char(64) NOT NULL,
`Menu` char(1) NOT NULL DEFAULT 'L',
`lastLogIn` int(11) NOT NULL,
`CreateDate` datetime NOT NULL DEFAULT '0001-01-01 00:00:00',
`Art` varchar(30) DEFAULT NULL,
`kommentar` text,
`Hometown` varchar(255) NOT NULL DEFAULT '',
`api_key` varchar(32) NOT NULL,
`got_voucher` int(11) NOT NULL,
`arrival_date` int(11) DEFAULT NULL,
`planned_arrival_date` int(11) NOT NULL,
`planned_departure_date` int(11) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
--
-- Daten für Tabelle `User`
--
INSERT INTO `User` (`UID`, `Nick`, `Name`, `Vorname`, `Alter`, `Telefon`, `DECT`, `Handy`, `email`, `email_shiftinfo`, `jabber`, `Size`, `Passwort`, `password_recovery_token`, `Gekommen`, `Aktiv`, `force_active`, `Tshirt`, `color`, `Sprache`, `Menu`, `lastLogIn`, `CreateDate`, `Art`, `kommentar`, `Hometown`, `api_key`, `got_voucher`, `arrival_date`, `planned_arrival_date`, `planned_departure_date`) VALUES
(1, 'admin', 'Gates', 'Bill', 42, '', '-', '', 'admin@example.com', 1, '', 'XL', '$6$rounds=5000$hjXbIhoRTH3vKiRa$Wl2P2iI5T9iRR.HHu/YFHswBW0WVn0yxCfCiX0Keco9OdIoDK6bIAADswP6KvMCJSwTGdV8PgA8g8Xfw5l8BD1', NULL, 1, 1, 0, 1, 0, 'de_DE.UTF-8', 'L', 1474990948, '0001-01-01 00:00:00', '', '', '', '038850abdd1feb264406be3ffa746235', 0, 1439490478, 1436964455, 1440161255);
-- --------------------------------------------------------
--
-- Tabellenstruktur für Tabelle `UserAngelTypes`
--
DROP TABLE IF EXISTS `UserAngelTypes`;
CREATE TABLE `UserAngelTypes` (
`id` int(11) NOT NULL,
`user_id` int(11) NOT NULL,
`angeltype_id` int(11) NOT NULL,
`confirm_user_id` int(11) DEFAULT NULL,
`coordinator` tinyint(1) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- --------------------------------------------------------
--
-- Tabellenstruktur für Tabelle `UserDriverLicenses`
--
DROP TABLE IF EXISTS `UserDriverLicenses`;
CREATE TABLE `UserDriverLicenses` (
`user_id` int(11) NOT NULL,
`has_car` tinyint(1) NOT NULL,
`has_license_car` tinyint(1) NOT NULL,
`has_license_3_5t_transporter` tinyint(1) NOT NULL,
`has_license_7_5t_truck` tinyint(1) NOT NULL,
`has_license_12_5t_truck` tinyint(1) NOT NULL,
`has_license_forklift` tinyint(1) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
--
-- Daten für Tabelle `UserDriverLicenses`
--
INSERT INTO `UserDriverLicenses` (`user_id`, `has_car`, `has_license_car`, `has_license_3_5t_transporter`, `has_license_7_5t_truck`, `has_license_12_5t_truck`, `has_license_forklift`) VALUES
(1, 1, 1, 1, 1, 1, 1);
-- --------------------------------------------------------
--
-- Tabellenstruktur für Tabelle `UserGroups`
--
DROP TABLE IF EXISTS `UserGroups`;
CREATE TABLE `UserGroups` (
`id` int(11) NOT NULL,
`uid` int(11) NOT NULL,
`group_id` int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
--
-- Daten für Tabelle `UserGroups`
--
INSERT INTO `UserGroups` (`id`, `uid`, `group_id`) VALUES
(3, 1, -7),
(4, 1, -6),
(12, 1, -5),
(2, 1, -4),
(1, 1, -2);
--
-- Indizes der exportierten Tabellen
--
--
-- Indizes für die Tabelle `AngelTypes`
--
ALTER TABLE `AngelTypes`
ADD PRIMARY KEY (`id`),
ADD UNIQUE KEY `Name` (`name`);
--
-- Indizes für die Tabelle `GroupPrivileges`
--
ALTER TABLE `GroupPrivileges`
ADD PRIMARY KEY (`id`),
ADD KEY `group_id` (`group_id`,`privilege_id`),
ADD KEY `privilege_id` (`privilege_id`);
--
-- Indizes für die Tabelle `Groups`
--
ALTER TABLE `Groups`
ADD PRIMARY KEY (`UID`);
--
-- Indizes für die Tabelle `LogEntries`
--
ALTER TABLE `LogEntries`
ADD PRIMARY KEY (`id`),
ADD KEY `timestamp` (`timestamp`);
--
-- Indizes für die Tabelle `Messages`
--
ALTER TABLE `Messages`
ADD PRIMARY KEY (`id`),
ADD KEY `Datum` (`Datum`),
ADD KEY `SUID` (`SUID`),
ADD KEY `RUID` (`RUID`);
--
-- Indizes für die Tabelle `NeededAngelTypes`
--
ALTER TABLE `NeededAngelTypes`
ADD PRIMARY KEY (`id`),
ADD KEY `room_id` (`room_id`,`angel_type_id`),
ADD KEY `shift_id` (`shift_id`),
ADD KEY `angel_type_id` (`angel_type_id`);
--
-- Indizes für die Tabelle `News`
--
ALTER TABLE `News`
ADD PRIMARY KEY (`ID`),
ADD KEY `UID` (`UID`);
--
-- Indizes für die Tabelle `NewsComments`
--
ALTER TABLE `NewsComments`
ADD PRIMARY KEY (`ID`),
ADD KEY `Refid` (`Refid`),
ADD KEY `UID` (`UID`);
--
-- Indizes für die Tabelle `Privileges`
--
ALTER TABLE `Privileges`
ADD PRIMARY KEY (`id`),
ADD UNIQUE KEY `name` (`name`);
--
-- Indizes für die Tabelle `Questions`
--
ALTER TABLE `Questions`
ADD PRIMARY KEY (`QID`),
ADD KEY `UID` (`UID`),
ADD KEY `AID` (`AID`);
--
-- Indizes für die Tabelle `Room`
--
ALTER TABLE `Room`
ADD PRIMARY KEY (`RID`),
ADD UNIQUE KEY `Name` (`Name`);
--
-- Indizes für die Tabelle `ShiftEntry`
--
ALTER TABLE `ShiftEntry`
ADD PRIMARY KEY (`id`),
ADD KEY `TID` (`TID`),
ADD KEY `UID` (`UID`),
ADD KEY `SID` (`SID`,`TID`),
ADD KEY `freeloaded` (`freeloaded`);
--
-- Indizes für die Tabelle `Shifts`
--
ALTER TABLE `Shifts`
ADD PRIMARY KEY (`SID`),
ADD UNIQUE KEY `PSID` (`PSID`),
ADD KEY `RID` (`RID`),
ADD KEY `shifttype_id` (`shifttype_id`),
ADD KEY `created_by_user_id` (`created_by_user_id`),
ADD KEY `edited_by_user_id` (`edited_by_user_id`);
--
-- Indizes für die Tabelle `ShiftTypes`
--
ALTER TABLE `ShiftTypes`
ADD PRIMARY KEY (`id`),
ADD KEY `angeltype_id` (`angeltype_id`);
--
-- Indizes für die Tabelle `User`
--
ALTER TABLE `User`
ADD PRIMARY KEY (`UID`),
ADD UNIQUE KEY `Nick` (`Nick`),
ADD KEY `api_key` (`api_key`),
ADD KEY `password_recovery_token` (`password_recovery_token`),
ADD KEY `force_active` (`force_active`),
ADD KEY `arrival_date` (`arrival_date`,`planned_arrival_date`),
ADD KEY `planned_departure_date` (`planned_departure_date`);
--
-- Indizes für die Tabelle `UserAngelTypes`
--
ALTER TABLE `UserAngelTypes`
ADD PRIMARY KEY (`id`),
ADD KEY `user_id` (`user_id`,`angeltype_id`,`confirm_user_id`),
ADD KEY `angeltype_id` (`angeltype_id`),
ADD KEY `confirm_user_id` (`confirm_user_id`),
ADD KEY `coordinator` (`coordinator`);
--
-- Indizes für die Tabelle `UserDriverLicenses`
--
ALTER TABLE `UserDriverLicenses`
ADD PRIMARY KEY (`user_id`);
--
-- Indizes für die Tabelle `UserGroups`
--
ALTER TABLE `UserGroups`
ADD PRIMARY KEY (`id`),
ADD KEY `uid` (`uid`,`group_id`),
ADD KEY `group_id` (`group_id`);
--
-- AUTO_INCREMENT für exportierte Tabellen
--
--
-- AUTO_INCREMENT für Tabelle `AngelTypes`
--
ALTER TABLE `AngelTypes`
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=4;
--
-- AUTO_INCREMENT für Tabelle `GroupPrivileges`
--
ALTER TABLE `GroupPrivileges`
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=259;
--
-- AUTO_INCREMENT für Tabelle `LogEntries`
--
ALTER TABLE `LogEntries`
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;
--
-- AUTO_INCREMENT für Tabelle `Messages`
--
ALTER TABLE `Messages`
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;
--
-- AUTO_INCREMENT für Tabelle `NeededAngelTypes`
--
ALTER TABLE `NeededAngelTypes`
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;
--
-- AUTO_INCREMENT für Tabelle `News`
--
ALTER TABLE `News`
MODIFY `ID` int(11) NOT NULL AUTO_INCREMENT;
--
-- AUTO_INCREMENT für Tabelle `NewsComments`
--
ALTER TABLE `NewsComments`
MODIFY `ID` bigint(11) NOT NULL AUTO_INCREMENT;
--
-- AUTO_INCREMENT für Tabelle `Privileges`
--
ALTER TABLE `Privileges`
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=40;
--
-- AUTO_INCREMENT für Tabelle `Questions`
--
ALTER TABLE `Questions`
MODIFY `QID` bigint(20) NOT NULL AUTO_INCREMENT;
--
-- AUTO_INCREMENT für Tabelle `Room`
--
ALTER TABLE `Room`
MODIFY `RID` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=2;
--
-- AUTO_INCREMENT für Tabelle `ShiftEntry`
--
ALTER TABLE `ShiftEntry`
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=2;
--
-- AUTO_INCREMENT für Tabelle `Shifts`
--
ALTER TABLE `Shifts`
MODIFY `SID` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=13;
--
-- AUTO_INCREMENT für Tabelle `ShiftTypes`
--
ALTER TABLE `ShiftTypes`
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=5;
--
-- AUTO_INCREMENT für Tabelle `User`
--
ALTER TABLE `User`
MODIFY `UID` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=2;
--
-- AUTO_INCREMENT für Tabelle `UserAngelTypes`
--
ALTER TABLE `UserAngelTypes`
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=2;
--
-- AUTO_INCREMENT für Tabelle `UserGroups`
--
ALTER TABLE `UserGroups`
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=13;
--
-- Constraints der exportierten Tabellen
--
--
-- Constraints der Tabelle `GroupPrivileges`
--
ALTER TABLE `GroupPrivileges`
ADD CONSTRAINT `groupprivileges_ibfk_1` FOREIGN KEY (`group_id`) REFERENCES `Groups` (`UID`) ON DELETE CASCADE ON UPDATE CASCADE,
ADD CONSTRAINT `groupprivileges_ibfk_2` FOREIGN KEY (`privilege_id`) REFERENCES `Privileges` (`id`) ON DELETE CASCADE ON UPDATE CASCADE;
--
-- Constraints der Tabelle `Messages`
--
ALTER TABLE `Messages`
ADD CONSTRAINT `messages_ibfk_1` FOREIGN KEY (`SUID`) REFERENCES `User` (`UID`) ON DELETE CASCADE ON UPDATE CASCADE,
ADD CONSTRAINT `messages_ibfk_2` FOREIGN KEY (`RUID`) REFERENCES `User` (`UID`) ON DELETE CASCADE ON UPDATE CASCADE;
--
-- Constraints der Tabelle `NeededAngelTypes`
--
ALTER TABLE `NeededAngelTypes`
ADD CONSTRAINT `neededangeltypes_ibfk_1` FOREIGN KEY (`room_id`) REFERENCES `Room` (`RID`) ON DELETE CASCADE ON UPDATE CASCADE,
ADD CONSTRAINT `neededangeltypes_ibfk_2` FOREIGN KEY (`shift_id`) REFERENCES `Shifts` (`SID`) ON DELETE CASCADE ON UPDATE CASCADE,
ADD CONSTRAINT `neededangeltypes_ibfk_3` FOREIGN KEY (`angel_type_id`) REFERENCES `AngelTypes` (`id`) ON DELETE CASCADE ON UPDATE CASCADE;
--
-- Constraints der Tabelle `News`
--
ALTER TABLE `News`
ADD CONSTRAINT `news_ibfk_1` FOREIGN KEY (`UID`) REFERENCES `User` (`UID`) ON DELETE CASCADE ON UPDATE CASCADE;
--
-- Constraints der Tabelle `NewsComments`
--
ALTER TABLE `NewsComments`
ADD CONSTRAINT `newscomments_ibfk_1` FOREIGN KEY (`Refid`) REFERENCES `News` (`ID`) ON DELETE CASCADE ON UPDATE CASCADE,
ADD CONSTRAINT `newscomments_ibfk_2` FOREIGN KEY (`UID`) REFERENCES `User` (`UID`) ON DELETE CASCADE ON UPDATE CASCADE;
--
-- Constraints der Tabelle `Questions`
--
ALTER TABLE `Questions`
ADD CONSTRAINT `questions_ibfk_1` FOREIGN KEY (`UID`) REFERENCES `User` (`UID`) ON DELETE CASCADE ON UPDATE CASCADE,
ADD CONSTRAINT `questions_ibfk_2` FOREIGN KEY (`AID`) REFERENCES `User` (`UID`) ON DELETE CASCADE ON UPDATE CASCADE;
--
-- Constraints der Tabelle `ShiftEntry`
--
ALTER TABLE `ShiftEntry`
ADD CONSTRAINT `shiftentry_ibfk_1` FOREIGN KEY (`SID`) REFERENCES `Shifts` (`SID`) ON DELETE CASCADE ON UPDATE CASCADE,
ADD CONSTRAINT `shiftentry_ibfk_2` FOREIGN KEY (`UID`) REFERENCES `User` (`UID`) ON DELETE CASCADE ON UPDATE CASCADE,
ADD CONSTRAINT `shiftentry_ibfk_3` FOREIGN KEY (`TID`) REFERENCES `AngelTypes` (`id`) ON DELETE CASCADE ON UPDATE CASCADE;
--
-- Constraints der Tabelle `Shifts`
--
ALTER TABLE `Shifts`
ADD CONSTRAINT `shifts_ibfk_1` FOREIGN KEY (`RID`) REFERENCES `Room` (`RID`) ON DELETE CASCADE ON UPDATE CASCADE,
ADD CONSTRAINT `shifts_ibfk_2` FOREIGN KEY (`shifttype_id`) REFERENCES `ShiftTypes` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
ADD CONSTRAINT `shifts_ibfk_3` FOREIGN KEY (`created_by_user_id`) REFERENCES `User` (`UID`) ON DELETE SET NULL ON UPDATE CASCADE,
ADD CONSTRAINT `shifts_ibfk_4` FOREIGN KEY (`edited_by_user_id`) REFERENCES `User` (`UID`) ON DELETE SET NULL ON UPDATE CASCADE;
--
-- Constraints der Tabelle `ShiftTypes`
--
ALTER TABLE `ShiftTypes`
ADD CONSTRAINT `shifttypes_ibfk_1` FOREIGN KEY (`angeltype_id`) REFERENCES `AngelTypes` (`id`) ON DELETE CASCADE ON UPDATE CASCADE;
--
-- Constraints der Tabelle `UserAngelTypes`
--
ALTER TABLE `UserAngelTypes`
ADD CONSTRAINT `userangeltypes_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `User` (`UID`) ON DELETE CASCADE ON UPDATE CASCADE,
ADD CONSTRAINT `userangeltypes_ibfk_2` FOREIGN KEY (`angeltype_id`) REFERENCES `AngelTypes` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
ADD CONSTRAINT `userangeltypes_ibfk_3` FOREIGN KEY (`confirm_user_id`) REFERENCES `User` (`UID`) ON DELETE SET NULL ON UPDATE CASCADE;
--
-- Constraints der Tabelle `UserDriverLicenses`
--
ALTER TABLE `UserDriverLicenses`
ADD CONSTRAINT `userdriverlicenses_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `User` (`UID`) ON DELETE CASCADE ON UPDATE CASCADE;
--
-- Constraints der Tabelle `UserGroups`
--
ALTER TABLE `UserGroups`
ADD CONSTRAINT `usergroups_ibfk_1` FOREIGN KEY (`group_id`) REFERENCES `Groups` (`UID`) ON DELETE CASCADE ON UPDATE CASCADE,
ADD CONSTRAINT `usergroups_ibfk_2` FOREIGN KEY (`uid`) REFERENCES `User` (`UID`) ON DELETE CASCADE ON UPDATE CASCADE;

View File

@ -1,15 +1,12 @@
<?php <?php
declare(strict_types=1);
namespace Engelsystem\Migrations; namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration; use Engelsystem\Database\Migration\Migration;
class ImportInstallSql extends Migration class ImportInstallSql extends Migration
{ {
/** @var array<string> */ protected $oldTables = [
protected array $oldTables = [
'AngelTypes', 'AngelTypes',
'EventConfig', 'EventConfig',
'GroupPrivileges', 'GroupPrivileges',
@ -29,17 +26,31 @@ class ImportInstallSql extends Migration
'UserAngelTypes', 'UserAngelTypes',
'UserDriverLicenses', 'UserDriverLicenses',
'UserGroups', 'UserGroups',
'UserWorkLog',
]; ];
/**
* Run the migration
*/
public function up()
{
foreach ($this->oldTables as $table) {
if ($this->schema->hasTable($table)) {
return;
}
}
$sql = file_get_contents(__DIR__ . '/../install.sql');
$this->schema->getConnection()->unprepared($sql);
}
/** /**
* Reverse the migration * Reverse the migration
*/ */
public function down(): void public function down()
{ {
$this->schema->getConnection()->statement('SET FOREIGN_KEY_CHECKS=0;'); $this->schema->getConnection()->statement('SET FOREIGN_KEY_CHECKS=0;');
// Delete all remaining tables
foreach ($this->oldTables as $table) { foreach ($this->oldTables as $table) {
if ($this->schema->hasTable($table)) { if ($this->schema->hasTable($table)) {
$this->schema->dropIfExists($table); $this->schema->dropIfExists($table);

View File

@ -1,12 +1,29 @@
<?php <?php
declare(strict_types=1);
namespace Engelsystem\Migrations; namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration; use Engelsystem\Database\Migration\Migration;
class ImportUpdateSql extends Migration class ImportUpdateSql extends Migration
{ {
// Do nothing as the tables will be created by later migrations and deleted by ImportInstall /**
* Run the migration
*/
public function up()
{
if ($this->schema->hasTable('UserWorkLog')) {
return;
}
$sql = file_get_contents(__DIR__ . '/../update.sql');
$this->schema->getConnection()->unprepared($sql);
}
/**
* Reverse the migration
*/
public function down()
{
$this->schema->dropIfExists('UserWorkLog');
}
} }

View File

@ -1,7 +1,5 @@
<?php <?php
declare(strict_types=1);
namespace Engelsystem\Migrations; namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration; use Engelsystem\Database\Migration\Migration;
@ -12,7 +10,7 @@ class FixOldTables extends Migration
/** /**
* Run the migration * Run the migration
*/ */
public function up(): void public function up()
{ {
$connection = $this->schema->getConnection(); $connection = $this->schema->getConnection();
@ -31,9 +29,16 @@ class FixOldTables extends Migration
->where($column, '<', '0001-01-01 00:00:00') ->where($column, '<', '0001-01-01 00:00:00')
->update([$column => '0001-01-01 00:00:00']); ->update([$column => '0001-01-01 00:00:00']);
$this->schema->table($table, function (Blueprint $table) use ($column): void { $this->schema->table($table, function (Blueprint $table) use ($column) {
$table->dateTime($column)->default('0001-01-01 00:00:00')->change(); $table->dateTime($column)->default('0001-01-01 00:00:00')->change();
}); });
} }
} }
/**
* Reverse the migration
*/
public function down()
{
}
} }

View File

@ -1,7 +1,5 @@
<?php <?php
declare(strict_types=1);
namespace Engelsystem\Migrations; namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration; use Engelsystem\Database\Migration\Migration;
@ -11,7 +9,7 @@ class CleanupGroupPrivileges extends Migration
/** /**
* Run the migration * Run the migration
*/ */
public function up(): void public function up()
{ {
if (!$this->schema->hasTable('GroupPrivileges')) { if (!$this->schema->hasTable('GroupPrivileges')) {
return; return;
@ -45,7 +43,7 @@ class CleanupGroupPrivileges extends Migration
/** /**
* Reverse the migration * Reverse the migration
*/ */
public function down(): void public function down()
{ {
if (!$this->schema->hasTable('GroupPrivileges')) { if (!$this->schema->hasTable('GroupPrivileges')) {
return; return;

View File

@ -1,7 +1,5 @@
<?php <?php
declare(strict_types=1);
namespace Engelsystem\Migrations; namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration; use Engelsystem\Database\Migration\Migration;
@ -9,7 +7,7 @@ use Engelsystem\Database\Migration\Migration;
class AddAngelSupporterPermissions extends Migration class AddAngelSupporterPermissions extends Migration
{ {
/** @var string[] */ /** @var string[] */
protected array $data = [ protected $data = [
'2-Engel', '2-Engel',
'shiftentry_edit_angeltype_supporter', 'shiftentry_edit_angeltype_supporter',
]; ];
@ -17,7 +15,7 @@ class AddAngelSupporterPermissions extends Migration
/** /**
* Run the migration * Run the migration
*/ */
public function up(): void public function up()
{ {
if (!$this->schema->hasTable('GroupPrivileges')) { if (!$this->schema->hasTable('GroupPrivileges')) {
return; return;
@ -41,7 +39,7 @@ class AddAngelSupporterPermissions extends Migration
/** /**
* Reverse the migration * Reverse the migration
*/ */
public function down(): void public function down()
{ {
if (!$this->schema->hasTable('GroupPrivileges')) { if (!$this->schema->hasTable('GroupPrivileges')) {
return; return;
@ -54,7 +52,11 @@ class AddAngelSupporterPermissions extends Migration
); );
} }
private function getQuery(string $type): string /**
* @param string $type
* @return string
*/
protected function getQuery($type)
{ {
return sprintf(' return sprintf('
%s FROM GroupPrivileges %s FROM GroupPrivileges

View File

@ -1,7 +1,5 @@
<?php <?php
declare(strict_types=1);
namespace Engelsystem\Migrations; namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration; use Engelsystem\Database\Migration\Migration;
@ -12,9 +10,9 @@ class CreateLogEntriesTable extends Migration
/** /**
* Run the migration * Run the migration
*/ */
public function up(): void public function up()
{ {
$this->schema->create('log_entries', function (Blueprint $table): void { $this->schema->create('log_entries', function (Blueprint $table) {
$table->increments('id'); $table->increments('id');
$table->string('level', 20); $table->string('level', 20);
$table->text('message'); $table->text('message');
@ -34,9 +32,9 @@ class CreateLogEntriesTable extends Migration
/** /**
* Reverse the migration * Reverse the migration
*/ */
public function down(): void public function down()
{ {
$this->schema->create('LogEntries', function (Blueprint $table): void { $this->schema->create('LogEntries', function (Blueprint $table) {
$table->increments('id'); $table->increments('id');
$table->string('level', 20); $table->string('level', 20);
$table->text('message'); $table->text('message');

View File

@ -1,7 +1,5 @@
<?php <?php
declare(strict_types=1);
namespace Engelsystem\Migrations; namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration; use Engelsystem\Database\Migration\Migration;
@ -12,9 +10,9 @@ class CreateSessionsTable extends Migration
/** /**
* Run the migration * Run the migration
*/ */
public function up(): void public function up()
{ {
$this->schema->create('sessions', function (Blueprint $table): void { $this->schema->create('sessions', function (Blueprint $table) {
$table->string('id')->unique(); $table->string('id')->unique();
$table->text('payload'); $table->text('payload');
$table->dateTime('last_activity')->useCurrent(); $table->dateTime('last_activity')->useCurrent();
@ -24,7 +22,7 @@ class CreateSessionsTable extends Migration
/** /**
* Reverse the migration * Reverse the migration
*/ */
public function down(): void public function down()
{ {
$this->schema->dropIfExists('sessions'); $this->schema->dropIfExists('sessions');
} }

View File

@ -1,18 +1,16 @@
<?php <?php
declare(strict_types=1);
namespace Engelsystem\Migrations; namespace Engelsystem\Migrations;
use Carbon\Carbon; use Carbon\Carbon;
use Engelsystem\Database\Migration\Migration; use Engelsystem\Database\Migration\Migration;
use Engelsystem\Models\EventConfig;
use Illuminate\Database\QueryException; use Illuminate\Database\QueryException;
use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Collection;
class CreateEventConfigTable extends Migration class CreateEventConfigTable extends Migration
{ {
protected array $mapping = [ protected $mapping = [
'buildup_start_date' => 'buildup_start', 'buildup_start_date' => 'buildup_start',
'event_start_date' => 'event_start', 'event_start_date' => 'event_start',
'event_end_date' => 'event_end', 'event_end_date' => 'event_end',
@ -22,11 +20,11 @@ class CreateEventConfigTable extends Migration
/** /**
* Run the migration * Run the migration
*/ */
public function up(): void public function up()
{ {
foreach (['json', 'text'] as $type) { foreach (['json', 'text'] as $type) {
try { try {
$this->schema->create('event_config', function (Blueprint $table) use ($type): void { $this->schema->create('event_config', function (Blueprint $table) use ($type) {
$table->string('name')->index()->unique(); $table->string('name')->index()->unique();
$table->{$type}('value'); $table->{$type}('value');
$table->timestamps(); $table->timestamps();
@ -43,24 +41,26 @@ class CreateEventConfigTable extends Migration
} }
if ($this->schema->hasTable('EventConfig')) { if ($this->schema->hasTable('EventConfig')) {
$connection = $this->schema->getConnection(); $config = $this->schema->getConnection()
$config = $connection
->table('EventConfig') ->table('EventConfig')
->first(); ->first();
if (!empty($config)) { if (!empty($config)) {
$connection->table('event_config') (new EventConfig([
->insert([ 'name' => 'name',
['name' => 'name', 'value' => $config->event_name], 'value' => $config->event_name,
['name' => 'welcome_msg', 'value' => $config->event_welcome_msg], ]))->save();
]);
(new EventConfig([
'name' => 'welcome_msg',
'value' => $config->event_welcome_msg,
]))->save();
foreach ($this->mapping as $old => $new) { foreach ($this->mapping as $old => $new) {
$connection->table('event_config') (new EventConfig([
->insert([
'name' => $new, 'name' => $new,
'value' => (new Carbon())->setTimestamp($config->{$old}), 'value' => (new Carbon())->setTimestamp($config->{$old}),
]); ]))->save();
} }
} }
@ -71,11 +71,9 @@ class CreateEventConfigTable extends Migration
/** /**
* Reverse the migration * Reverse the migration
*/ */
public function down(): void public function down()
{ {
$connection = $this->schema->getConnection(); $this->schema->create('EventConfig', function (Blueprint $table) {
$this->schema->create('EventConfig', function (Blueprint $table): void {
$table->string('event_name')->nullable(); $table->string('event_name')->nullable();
$table->integer('buildup_start_date')->nullable(); $table->integer('buildup_start_date')->nullable();
$table->integer('event_start_date')->nullable(); $table->integer('event_start_date')->nullable();
@ -84,19 +82,19 @@ class CreateEventConfigTable extends Migration
$table->string('event_welcome_msg')->nullable(); $table->string('event_welcome_msg')->nullable();
}); });
$config = $connection->table('event_config')->get(); $config = new EventConfig();
$data = [ $data = [
'event_name' => $this->getConfigValue($config, 'name'), 'event_name' => $config->findOrNew('name')->value,
'event_welcome_msg' => $this->getConfigValue($config, 'welcome_msg'), 'event_welcome_msg' => $config->findOrNew('welcome_msg')->value,
]; ];
foreach ($this->mapping as $new => $old) { foreach ($this->mapping as $new => $old) {
$value = $this->getConfigValue($config, $old); /** @var Carbon $value */
$value = $config->findOrNew($old)->value;
if (!$value) { if (!$value) {
continue; continue;
} }
$value = Carbon::make($value);
$data[$new] = $value->getTimestamp(); $data[$new] = $value->getTimestamp();
} }
@ -113,11 +111,4 @@ class CreateEventConfigTable extends Migration
$this->schema->dropIfExists('event_config'); $this->schema->dropIfExists('event_config');
} }
private function getConfigValue(Collection $config, string $name): mixed
{
$value = $config->where('name', $name)->first('value', (object) ['value' => null])->value;
return $value ? json_decode($value, true) : null;
}
} }

View File

@ -1,11 +1,15 @@
<?php <?php
declare(strict_types=1);
namespace Engelsystem\Migrations; namespace Engelsystem\Migrations;
use Carbon\Carbon; use Carbon\Carbon;
use Engelsystem\Database\Migration\Migration; use Engelsystem\Database\Migration\Migration;
use Engelsystem\Models\User\Contact;
use Engelsystem\Models\User\PasswordReset;
use Engelsystem\Models\User\PersonalData;
use Engelsystem\Models\User\Settings;
use Engelsystem\Models\User\State;
use Engelsystem\Models\User\User;
use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Schema\Blueprint;
use stdClass; use stdClass;
@ -17,9 +21,9 @@ class CreateUsersTables extends Migration
/** /**
* Run the migration * Run the migration
*/ */
public function up(): void public function up()
{ {
$this->schema->create('users', function (Blueprint $table): void { $this->schema->create('users', function (Blueprint $table) {
$table->increments('id'); $table->increments('id');
$table->string('name', 24)->unique(); $table->string('name', 24)->unique();
@ -31,7 +35,7 @@ class CreateUsersTables extends Migration
$table->timestamps(); $table->timestamps();
}); });
$this->schema->create('users_personal_data', function (Blueprint $table): void { $this->schema->create('users_personal_data', function (Blueprint $table) {
$this->referencesUser($table, true); $this->referencesUser($table, true);
$table->string('first_name', 64)->nullable(); $table->string('first_name', 64)->nullable();
@ -42,7 +46,7 @@ class CreateUsersTables extends Migration
$table->date('planned_departure_date')->nullable(); $table->date('planned_departure_date')->nullable();
}); });
$this->schema->create('users_contact', function (Blueprint $table): void { $this->schema->create('users_contact', function (Blueprint $table) {
$this->referencesUser($table, true); $this->referencesUser($table, true);
$table->string('dect', 5)->nullable(); $table->string('dect', 5)->nullable();
@ -50,7 +54,7 @@ class CreateUsersTables extends Migration
$table->string('email', 254)->nullable(); $table->string('email', 254)->nullable();
}); });
$this->schema->create('users_settings', function (Blueprint $table): void { $this->schema->create('users_settings', function (Blueprint $table) {
$this->referencesUser($table, true); $this->referencesUser($table, true);
$table->string('language', 64); $table->string('language', 64);
@ -59,7 +63,7 @@ class CreateUsersTables extends Migration
$table->boolean('email_shiftinfo')->default(false); $table->boolean('email_shiftinfo')->default(false);
}); });
$this->schema->create('users_state', function (Blueprint $table): void { $this->schema->create('users_state', function (Blueprint $table) {
$this->referencesUser($table, true); $this->referencesUser($table, true);
$table->boolean('arrived')->default(false); $table->boolean('arrived')->default(false);
@ -70,7 +74,7 @@ class CreateUsersTables extends Migration
$table->integer('got_voucher')->default(0); $table->integer('got_voucher')->default(0);
}); });
$this->schema->create('password_resets', function (Blueprint $table): void { $this->schema->create('password_resets', function (Blueprint $table) {
$this->referencesUser($table, true); $this->referencesUser($table, true);
$table->text('token'); $table->text('token');
@ -79,33 +83,33 @@ class CreateUsersTables extends Migration
}); });
if ($this->schema->hasTable('User')) { if ($this->schema->hasTable('User')) {
$connection = $this->schema->getConnection();
$emptyDates = ['0000-00-00 00:00:00', '0001-01-01 00:00:00', '1000-01-01 00:00:00']; $emptyDates = ['0000-00-00 00:00:00', '0001-01-01 00:00:00', '1000-01-01 00:00:00'];
/** @var stdClass[] $users */ /** @var stdClass[] $users */
$users = $connection->table('User')->get(); $users = $this->schema->getConnection()->table('User')->get();
foreach ($users as $data) { foreach ($users as $data) {
$user = [ $user = new User([
'id' => $data->UID,
'name' => $data->Nick, 'name' => $data->Nick,
'password' => $data->Passwort, 'password' => $data->Passwort,
'email' => $data->email, 'email' => $data->email,
'api_key' => $data->api_key, 'api_key' => $data->api_key,
'last_login_at' => $data->lastLogIn ? Carbon::createFromTimestamp($data->lastLogIn) : null, 'last_login_at' => $data->lastLogIn ? Carbon::createFromTimestamp($data->lastLogIn) : null,
]; ]);
$user->setAttribute('id', $data->UID);
if (!in_array($data->CreateDate, $emptyDates)) { if (!in_array($data->CreateDate, $emptyDates)) {
$user['created_at'] = new Carbon($data->CreateDate); $user->setAttribute('created_at', new Carbon($data->CreateDate));
} }
$connection->table('users')->insert($user); $user->save();
$connection->table('users_contact')->insert([ $contact = new Contact([
'user_id' => $data->UID, 'dect' => $data->DECT ? $data->DECT : null,
'dect' => $data->DECT ?: null,
'mobile' => $data->Handy ?: ($data->Telefon ?: null), 'mobile' => $data->Handy ?: ($data->Telefon ?: null),
]); ]);
$contact->user()
->associate($user)
->save();
$connection->table('users_personal_data')->insert([ $personalData = new PersonalData([
'user_id' => $data->UID,
'first_name' => $data->Vorname ?: null, 'first_name' => $data->Vorname ?: null,
'last_name' => $data->Name ?: null, 'last_name' => $data->Name ?: null,
'shirt_size' => $data->Size ?: null, 'shirt_size' => $data->Size ?: null,
@ -116,17 +120,24 @@ class CreateUsersTables extends Migration
? Carbon::createFromTimestamp($data->planned_departure_date) ? Carbon::createFromTimestamp($data->planned_departure_date)
: null, : null,
]); ]);
$personalData->user()
->associate($user)
->save();
$connection->table('users_settings')->insert([ $settings = new Settings([
'user_id' => $data->UID,
'language' => $data->Sprache, 'language' => $data->Sprache,
'theme' => $data->color, 'theme' => $data->color,
'email_human' => $data->email_by_human_allowed, 'email_human' => $data->email_by_human_allowed,
'email_shiftinfo' => $data->email_shiftinfo, 'email_shiftinfo' => $data->email_shiftinfo,
]); ]);
unset($settings->email_news);
unset($settings->email_goody);
$connection->table('users_state')->insert([ $settings->user()
'user_id' => $data->UID, ->associate($user)
->save();
$state = new State([
'arrived' => $data->Gekommen, 'arrived' => $data->Gekommen,
'arrival_date' => $data->arrival_date ? Carbon::createFromTimestamp($data->arrival_date) : null, 'arrival_date' => $data->arrival_date ? Carbon::createFromTimestamp($data->arrival_date) : null,
'active' => $data->Aktiv, 'active' => $data->Aktiv,
@ -134,12 +145,17 @@ class CreateUsersTables extends Migration
'got_shirt' => $data->Tshirt, 'got_shirt' => $data->Tshirt,
'got_voucher' => $data->got_voucher, 'got_voucher' => $data->got_voucher,
]); ]);
$state->user()
->associate($user)
->save();
if ($data->password_recovery_token) { if ($data->password_recovery_token) {
$connection->table('password_resets')->insert([ $passwordReset = new PasswordReset([
'user_id' => $data->UID,
'token' => $data->password_recovery_token, 'token' => $data->password_recovery_token,
]); ]);
$passwordReset->user()
->associate($user)
->save();
} }
} }
@ -157,12 +173,10 @@ class CreateUsersTables extends Migration
/** /**
* Reverse the migration * Reverse the migration
*/ */
public function down(): void public function down()
{ {
$connection = $this->schema->getConnection(); $this->schema->create('User', function (Blueprint $table) {
$table->integer('UID', true, false);
$this->schema->create('User', function (Blueprint $table): void {
$table->integer('UID', true);
$table->string('Nick', 23)->unique()->default(''); $table->string('Nick', 23)->unique()->default('');
$table->string('Name', 23)->nullable(); $table->string('Name', 23)->nullable();
@ -203,16 +217,12 @@ class CreateUsersTables extends Migration
$table->index('planned_departure_date', 'planned_departure_date'); $table->index('planned_departure_date', 'planned_departure_date');
}); });
foreach ($connection->table('users')->get() as $user) { foreach (User::all() as $user) {
/** @var stdClass $user */ /** @var User $user */
/** @var stdClass $contact */ $contact = $user->contact;
$contact = $connection->table('users_contact')->where('user_id', $user->id)->first(); $personal = $user->personalData;
/** @var stdClass $personal */ $settings = $user->settings;
$personal = $connection->table('users_personal_data')->where('user_id', $user->id)->first(); $state = $user->state;
/** @var stdClass $settings */
$settings = $connection->table('users_settings')->where('user_id', $user->id)->first();
/** @var stdClass $state */
$state = $connection->table('users_state')->where('user_id', $user->id)->first();
$this->schema $this->schema
->getConnection() ->getConnection()
@ -234,28 +244,23 @@ class CreateUsersTables extends Migration
'Tshirt' => $state->got_shirt, 'Tshirt' => $state->got_shirt,
'color' => $settings->theme, 'color' => $settings->theme,
'Sprache' => $settings->language, 'Sprache' => $settings->language,
'lastLogIn' => $user->last_login_at 'lastLogIn' => $user->last_login_at ? $user->last_login_at->getTimestamp() : null,
? Carbon::make($user->last_login_at)->getTimestamp() 'CreateDate' => $user->created_at ? $user->created_at->toDateTimeString() : null,
: null,
'CreateDate' => $user->created_at
? Carbon::make($user->created_at)->toDateTimeString()
: '0001-01-01 00:00:00',
'api_key' => $user->api_key, 'api_key' => $user->api_key,
'got_voucher' => $state->got_voucher, 'got_voucher' => $state->got_voucher,
'arrival_date' => $state->arrival_date 'arrival_date' => $state->arrival_date ? $state->arrival_date->getTimestamp() : null,
? Carbon::make($state->arrival_date)->getTimestamp()
: null,
'planned_arrival_date' => $personal->planned_arrival_date 'planned_arrival_date' => $personal->planned_arrival_date
? Carbon::make($personal->planned_arrival_date)->getTimestamp() ? $personal->planned_arrival_date->getTimestamp()
: 0, : null,
'planned_departure_date' => $personal->planned_departure_date 'planned_departure_date' => $personal->planned_departure_date
? Carbon::make($personal->planned_departure_date)->getTimestamp() ? $personal->planned_departure_date->getTimestamp()
: null, : null,
'email_by_human_allowed' => $settings->email_human, 'email_by_human_allowed' => $settings->email_human,
]); ]);
} }
foreach ($connection->table('password_resets')->get() as $passwordReset) { foreach (PasswordReset::all() as $passwordReset) {
/** @var PasswordReset $passwordReset */
$this->schema->getConnection() $this->schema->getConnection()
->table('User') ->table('User')
->where('UID', '=', $passwordReset->user_id) ->where('UID', '=', $passwordReset->user_id)

View File

@ -1,7 +1,5 @@
<?php <?php
declare(strict_types=1);
namespace Engelsystem\Migrations; namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration; use Engelsystem\Database\Migration\Migration;
@ -9,7 +7,8 @@ use Illuminate\Database\Schema\Blueprint;
class ChangeUsersContactDectFieldSize extends Migration class ChangeUsersContactDectFieldSize extends Migration
{ {
protected array $tables = [ /** @var array */
protected $tables = [
'AngelTypes' => 'contact_dect', 'AngelTypes' => 'contact_dect',
'users_contact' => 'dect', 'users_contact' => 'dect',
]; ];
@ -17,7 +16,7 @@ class ChangeUsersContactDectFieldSize extends Migration
/** /**
* Run the migration * Run the migration
*/ */
public function up(): void public function up()
{ {
$this->changeDectTo(40); $this->changeDectTo(40);
} }
@ -25,19 +24,22 @@ class ChangeUsersContactDectFieldSize extends Migration
/** /**
* Reverse the migration * Reverse the migration
*/ */
public function down(): void public function down()
{ {
$this->changeDectTo(5); $this->changeDectTo(5);
} }
private function changeDectTo(int $length): void /**
* @param int $length
*/
protected function changeDectTo(int $length)
{ {
foreach ($this->tables as $table => $column) { foreach ($this->tables as $table => $column) {
if (!$this->schema->hasTable($table)) { if (!$this->schema->hasTable($table)) {
continue; continue;
} }
$this->schema->table($table, function (Blueprint $table) use ($column, $length): void { $this->schema->table($table, function (Blueprint $table) use ($column, $length) {
$table->string($column, $length)->change(); $table->string($column, $length)->change();
}); });
} }

View File

@ -1,37 +1,28 @@
<?php <?php
declare(strict_types=1);
namespace Engelsystem\Migrations; namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration; use Engelsystem\Database\Migration\Migration;
use stdClass; use Engelsystem\Models\User\State;
class FixMissingArrivalDates extends Migration class FixMissingArrivalDates extends Migration
{ {
/** /**
* Run the migration * Run the migration
*/ */
public function up(): void public function up()
{ {
$connection = $this->schema->getConnection(); $states = State::whereArrived(true)->whereArrivalDate(null)->get();
/** @var stdClass[] $states */
$states = $connection
->table('users_state')
->where('arrived', true)
->where('arrival_date', null)
->get();
foreach ($states as $state) { foreach ($states as $state) {
/** @var stdClass $personalData */ $state->arrival_date = $state->user->personalData->planned_arrival_date;
$personalData = $connection $state->save();
->table('users_personal_data')
->where('user_id', $state->user_id)
->first();
$state->arrival_date = $personalData->planned_arrival_date;
$connection->table('users_state')
->update((array) $state);
} }
} }
/**
* Down is not possible and not needed since this is a bugfix.
*/
public function down()
{
}
} }

View File

@ -1,7 +1,5 @@
<?php <?php
declare(strict_types=1);
namespace Engelsystem\Migrations; namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration; use Engelsystem\Database\Migration\Migration;
@ -11,26 +9,26 @@ class FixUserLanguages extends Migration
/** /**
* Run the migration * Run the migration
*/ */
public function up(): void public function up()
{ {
$connection = $this->schema->getConnection(); $connection = $this->schema->getConnection();
$connection $connection
->table('users_settings') ->table('users_settings')
->update([ ->update([
'language' => $connection->raw('REPLACE(language, ".UTF-8", "")'), 'language' => $connection->raw('REPLACE(language, ".UTF-8", "")')
]); ]);
} }
/** /**
* Reverse the migration * Reverse the migration
*/ */
public function down(): void public function down()
{ {
$connection = $this->schema->getConnection(); $connection = $this->schema->getConnection();
$connection $connection
->table('users_settings') ->table('users_settings')
->update([ ->update([
'language' => $connection->raw('CONCAT(language, ".UTF-8")'), 'language' => $connection->raw('CONCAT(language, ".UTF-8")')
]); ]);
} }
} }

View File

@ -1,7 +1,5 @@
<?php <?php
declare(strict_types=1);
namespace Engelsystem\Migrations; namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration; use Engelsystem\Database\Migration\Migration;
@ -11,7 +9,7 @@ class MigrateAdminSchedulePermissions extends Migration
/** /**
* Run the migration * Run the migration
*/ */
public function up(): void public function up()
{ {
if (!$this->schema->hasTable('Privileges')) { if (!$this->schema->hasTable('Privileges')) {
return; return;
@ -31,7 +29,7 @@ class MigrateAdminSchedulePermissions extends Migration
/** /**
* Reverse the migration * Reverse the migration
*/ */
public function down(): void public function down()
{ {
if (!$this->schema->hasTable('Privileges')) { if (!$this->schema->hasTable('Privileges')) {
return; return;

View File

@ -1,7 +1,5 @@
<?php <?php
declare(strict_types=1);
namespace Engelsystem\Migrations; namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration; use Engelsystem\Database\Migration\Migration;
@ -14,14 +12,19 @@ class CreateScheduleShiftTable extends Migration
/** /**
* Run the migration * Run the migration
*/ */
public function up(): void public function up()
{ {
$this->schema->create('schedules', function (Blueprint $table): void { $this->schema->create(
'schedules',
function (Blueprint $table) {
$table->increments('id'); $table->increments('id');
$table->string('url'); $table->string('url');
}); }
);
$this->schema->create('schedule_shift', function (Blueprint $table): void { $this->schema->create(
'schedule_shift',
function (Blueprint $table) {
$table->integer('shift_id')->index()->unique(); $table->integer('shift_id')->index()->unique();
if ($this->schema->hasTable('Shifts')) { if ($this->schema->hasTable('Shifts')) {
// Legacy table access // Legacy table access
@ -33,36 +36,52 @@ class CreateScheduleShiftTable extends Migration
$this->references($table, 'schedules'); $this->references($table, 'schedules');
$table->uuid('guid'); $table->uuid('guid');
}); }
);
if ($this->schema->hasTable('Shifts')) { if ($this->schema->hasTable('Shifts')) {
$this->schema->table('Shifts', function (Blueprint $table): void { $this->schema->table(
'Shifts',
function (Blueprint $table) {
$table->dropColumn('PSID'); $table->dropColumn('PSID');
}); }
);
} }
if ($this->schema->hasTable('Room')) { if ($this->schema->hasTable('Room')) {
$this->schema->table('Room', function (Blueprint $table): void { $this->schema->table(
'Room',
function (Blueprint $table) {
$table->dropColumn('from_frab'); $table->dropColumn('from_frab');
}); }
);
} }
} }
/** /**
* Reverse the migration * Reverse the migration
*/ */
public function down(): void public function down()
{ {
if ($this->schema->hasTable('Room')) { if ($this->schema->hasTable('Room')) {
$this->schema->table('Room', function (Blueprint $table): void { $this->schema->table(
$table->boolean('from_frab')->default(false); 'Room',
}); function (Blueprint $table) {
$table->boolean('from_frab')
->default(false);
}
);
} }
if ($this->schema->hasTable('Shifts')) { if ($this->schema->hasTable('Shifts')) {
$this->schema->table('Shifts', function (Blueprint $table): void { $this->schema->table(
$table->integer('PSID')->nullable()->default(null)->unique(); 'Shifts',
}); function (Blueprint $table) {
$table->integer('PSID')
->nullable()->default(null)
->unique();
}
);
} }
$this->schema->drop('schedule_shift'); $this->schema->drop('schedule_shift');

View File

@ -64,9 +64,12 @@ class CreateNewsTable extends Migration
$this->schema->drop('new_news'); $this->schema->drop('new_news');
} }
/**
* @return void
*/
private function createNewNewsTable(): void private function createNewNewsTable(): void
{ {
$this->schema->create('news', function (Blueprint $table): void { $this->schema->create('news', function (Blueprint $table) {
$table->increments('id'); $table->increments('id');
$table->string('title', 150); $table->string('title', 150);
$table->text('text'); $table->text('text');
@ -76,6 +79,9 @@ class CreateNewsTable extends Migration
}); });
} }
/**
* @return void
*/
private function copyPreviousToNewNewsTable(): void private function copyPreviousToNewNewsTable(): void
{ {
$connection = $this->schema->getConnection(); $connection = $this->schema->getConnection();
@ -98,18 +104,25 @@ class CreateNewsTable extends Migration
} }
} }
/**
* @return void
*/
private function createPreviousNewsTable(): void private function createPreviousNewsTable(): void
{ {
$this->schema->create('News', function (Blueprint $table): void { $this->schema->create('News', function (Blueprint $table) {
$table->increments('ID'); $table->increments('ID');
$table->integer('Datum'); $table->integer('Datum');
$table->string('Betreff', 150)->default(''); $table->string('Betreff', 150)
->default('');
$table->text('Text'); $table->text('Text');
$this->references($table, 'users', 'UID'); $this->references($table, 'users', 'UID');
$table->boolean('Treffen')->default(false); $table->boolean('Treffen')->default(false);
}); });
} }
/**
* @return void
*/
private function copyNewToPreviousNewsTable(): void private function copyNewToPreviousNewsTable(): void
{ {
$connection = $this->schema->getConnection(); $connection = $this->schema->getConnection();

View File

@ -53,9 +53,12 @@ class CreateNewsCommentsTable extends Migration
$this->schema->drop('news_comments'); $this->schema->drop('news_comments');
} }
/**
* @return void
*/
private function createNewNewsCommentsTable(): void private function createNewNewsCommentsTable(): void
{ {
$this->schema->create('news_comments', function (Blueprint $table): void { $this->schema->create('news_comments', function (Blueprint $table) {
$table->increments('id'); $table->increments('id');
$this->references($table, 'news', 'news_id'); $this->references($table, 'news', 'news_id');
$table->text('text'); $table->text('text');
@ -64,6 +67,9 @@ class CreateNewsCommentsTable extends Migration
}); });
} }
/**
* @return void
*/
private function copyPreviousToNewNewsCommentsTable(): void private function copyPreviousToNewNewsCommentsTable(): void
{ {
$connection = $this->schema->getConnection(); $connection = $this->schema->getConnection();
@ -84,9 +90,12 @@ class CreateNewsCommentsTable extends Migration
} }
} }
/**
* @return void
*/
private function createPreviousNewsCommentsTable(): void private function createPreviousNewsCommentsTable(): void
{ {
$this->schema->create('NewsComments', function (Blueprint $table): void { $this->schema->create('NewsComments', function (Blueprint $table) {
$table->increments('ID'); $table->increments('ID');
$this->references($table, 'news', 'Refid'); $this->references($table, 'news', 'Refid');
$table->dateTime('Datum'); $table->dateTime('Datum');
@ -95,6 +104,9 @@ class CreateNewsCommentsTable extends Migration
}); });
} }
/**
* @return void
*/
private function copyNewToPreviousNewsCommentsTable(): void private function copyNewToPreviousNewsCommentsTable(): void
{ {
$connection = $this->schema->getConnection(); $connection = $this->schema->getConnection();

View File

@ -64,18 +64,27 @@ class CreateMessagesTable extends Migration
$this->schema->drop('new_messages'); $this->schema->drop('new_messages');
} }
/**
* @return void
*/
private function createNewMessagesTable(): void private function createNewMessagesTable(): void
{ {
$this->schema->create('messages', function (Blueprint $table): void { $this->schema->create(
'messages',
function (Blueprint $table) {
$table->increments('id'); $table->increments('id');
$this->referencesUser($table); $this->referencesUser($table);
$this->references($table, 'users', 'receiver_id'); $this->references($table, 'users', 'receiver_id');
$table->boolean('read')->default(0); $table->boolean('read')->default(0);
$table->text('text'); $table->text('text');
$table->timestamps(); $table->timestamps();
}); }
);
} }
/**
* @return void
*/
private function copyPreviousToNewMessagesTable(): void private function copyPreviousToNewMessagesTable(): void
{ {
$connection = $this->schema->getConnection(); $connection = $this->schema->getConnection();
@ -100,18 +109,28 @@ class CreateMessagesTable extends Migration
} }
} }
/**
* @return void
*/
private function createPreviousMessagesTable(): void private function createPreviousMessagesTable(): void
{ {
$this->schema->create('Messages', function (Blueprint $table): void { $this->schema->create(
'Messages',
function (Blueprint $table) {
$table->increments('id'); $table->increments('id');
$table->integer('Datum'); $table->integer('Datum');
$this->references($table, 'users', 'SUID'); $this->references($table, 'users', 'SUID');
$this->references($table, 'users', 'RUID'); $this->references($table, 'users', 'RUID');
$table->char('isRead')->default('N'); $table->char('isRead')
->default('N');
$table->text('Text'); $table->text('Text');
}); }
);
} }
/**
* @return void
*/
private function copyNewToPreviousMessagesTable(): void private function copyNewToPreviousMessagesTable(): void
{ {
$connection = $this->schema->getConnection(); $connection = $this->schema->getConnection();

View File

@ -17,6 +17,9 @@ class CreateQuestionsTable extends Migration
use ChangesReferences; use ChangesReferences;
use Reference; use Reference;
/**
* @return void
*/
public function up(): void public function up(): void
{ {
$hasPreviousQuestionsTable = $this->schema->hasTable('Questions'); $hasPreviousQuestionsTable = $this->schema->hasTable('Questions');
@ -40,6 +43,9 @@ class CreateQuestionsTable extends Migration
} }
} }
/**
* @return void
*/
public function down(): void public function down(): void
{ {
// Rename as some SQL DBMS handle identifiers case insensitive // Rename as some SQL DBMS handle identifiers case insensitive
@ -57,17 +63,28 @@ class CreateQuestionsTable extends Migration
$this->schema->drop('new_questions'); $this->schema->drop('new_questions');
} }
/**
* @return void
*/
private function createNewQuestionsTable(): void private function createNewQuestionsTable(): void
{ {
$this->schema->create('questions', function (Blueprint $table): void { $this->schema->create(
'questions',
function (Blueprint $table) {
$table->increments('id'); $table->increments('id');
$this->referencesUser($table); $this->referencesUser($table);
$table->text('text'); $table->text('text');
$table->text('answer')->nullable(); $table->text('answer')
$this->references($table, 'users', 'answerer_id')->nullable(); ->nullable();
}); $this->references($table, 'users', 'answerer_id')
->nullable();
}
);
} }
/**
* @return void
*/
private function copyPreviousToNewQuestionsTable(): void private function copyPreviousToNewQuestionsTable(): void
{ {
$connection = $this->schema->getConnection(); $connection = $this->schema->getConnection();
@ -87,17 +104,28 @@ class CreateQuestionsTable extends Migration
} }
} }
/**
* @return void
*/
private function createPreviousQuestionsTable(): void private function createPreviousQuestionsTable(): void
{ {
$this->schema->create('Questions', function (Blueprint $table): void { $this->schema->create(
'Questions',
function (Blueprint $table) {
$table->increments('QID'); $table->increments('QID');
$this->references($table, 'users', 'UID'); $this->references($table, 'users', 'UID');
$table->text('Question'); $table->text('Question');
$this->references($table, 'users', 'AID')->nullable(); $this->references($table, 'users', 'AID')
$table->text('Answer')->nullable(); ->nullable();
}); $table->text('Answer')
->nullable();
}
);
} }
/**
* @return void
*/
private function copyNewToPreviousQuestionsTable(): void private function copyNewToPreviousQuestionsTable(): void
{ {
$connection = $this->schema->getConnection(); $connection = $this->schema->getConnection();

View File

@ -14,8 +14,11 @@ class UserPersonalDataAddPronounField extends Migration
*/ */
public function up(): void public function up(): void
{ {
$this->schema->table('users_personal_data', function (Blueprint $table): void { $this->schema->table('users_personal_data', function (Blueprint $table) {
$table->string('pronoun', 15)->nullable()->default(null)->after('last_name'); $table->string('pronoun', 15)
->nullable()
->default(null)
->after('last_name');
}); });
} }
@ -24,7 +27,7 @@ class UserPersonalDataAddPronounField extends Migration
*/ */
public function down(): void public function down(): void
{ {
$this->schema->table('users_personal_data', function (Blueprint $table): void { $this->schema->table('users_personal_data', function (Blueprint $table) {
$table->dropColumn('pronoun'); $table->dropColumn('pronoun');
}); });
} }

View File

@ -28,5 +28,11 @@ class ChangeMysqlDatabaseEncodingToUtf8mb4 extends Migration
} }
} }
// As utf8mb4 is a superset of utf8, there is nothing to do in the downgrade /**
* Reverse the migration
*/
public function down(): void
{
// As utf8mb4 is a superset of utf8, there is nothing to do here
}
} }

View File

@ -5,19 +5,21 @@ declare(strict_types=1);
namespace Engelsystem\Migrations; namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration; use Engelsystem\Database\Migration\Migration;
use Engelsystem\Models\Room;
use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Schema\Blueprint;
use stdClass; use stdClass;
class CreateRoomsTable extends Migration class CreateRoomsTable extends Migration
{ {
use ChangesReferences; use ChangesReferences;
use Reference;
/** /**
* Run the migration * Run the migration
*/ */
public function up(): void public function up(): void
{ {
$this->schema->create('rooms', function (Blueprint $table): void { $this->schema->create('rooms', function (Blueprint $table) {
$table->increments('id'); $table->increments('id');
$table->string('name', 35)->unique(); $table->string('name', 35)->unique();
$table->string('map_url', 300)->nullable(); $table->string('map_url', 300)->nullable();
@ -33,13 +35,13 @@ class CreateRoomsTable extends Migration
->get(); ->get();
foreach ($previousRecords as $previousRecord) { foreach ($previousRecords as $previousRecord) {
$connection->table('rooms') $room = new Room([
->insert([
'id' => $previousRecord->RID,
'name' => $previousRecord->Name, 'name' => $previousRecord->Name,
'map_url' => $previousRecord->map_url ?: null, 'map_url' => $previousRecord->map_url ?: null,
'description' => $previousRecord->description ?: null, 'description' => $previousRecord->description ?: null,
]); ]);
$room->setAttribute('id', $previousRecord->RID);
$room->save();
} }
$this->changeReferences( $this->changeReferences(
@ -58,18 +60,16 @@ class CreateRoomsTable extends Migration
*/ */
public function down(): void public function down(): void
{ {
$connection = $this->schema->getConnection(); $this->schema->create('Room', function (Blueprint $table) {
$this->schema->create('Room', function (Blueprint $table): void {
$table->increments('RID'); $table->increments('RID');
$table->string('Name', 35)->unique(); $table->string('Name', 35)->unique();
$table->string('map_url', 300)->nullable(); $table->string('map_url', 300)->nullable();
$table->mediumText('description')->nullable(); $table->mediumText('description')->nullable();
}); });
foreach ($connection->table('rooms')->get() as $room) { foreach (Room::all() as $room) {
/** @var stdClass $room */ $this->schema
$connection ->getConnection()
->table('Room') ->table('Room')
->insert([ ->insert([
'RID' => $room->id, 'RID' => $room->id,

View File

@ -6,6 +6,7 @@ namespace Engelsystem\Migrations;
use Carbon\Carbon; use Carbon\Carbon;
use Engelsystem\Database\Migration\Migration; use Engelsystem\Database\Migration\Migration;
use Engelsystem\Models\Worklog;
use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Schema\Blueprint;
use stdClass; use stdClass;
@ -19,7 +20,7 @@ class CreateWorklogsTable extends Migration
*/ */
public function up(): void public function up(): void
{ {
$this->schema->create('worklogs', function (Blueprint $table): void { $this->schema->create('worklogs', function (Blueprint $table) {
$table->increments('id'); $table->increments('id');
$this->referencesUser($table); $this->referencesUser($table);
$this->references($table, 'users', 'creator_id'); $this->references($table, 'users', 'creator_id');
@ -37,20 +38,18 @@ class CreateWorklogsTable extends Migration
->get(); ->get();
foreach ($previousRecords as $previousRecord) { foreach ($previousRecords as $previousRecord) {
$worked_at = Carbon::createFromTimestamp($previousRecord->work_timestamp); $room = new Worklog([
$created_at = Carbon::createFromTimestamp($previousRecord->created_timestamp);
$this->schema->getConnection()
->table('worklogs')
->insert([
'id' => $previousRecord->id,
'user_id' => $previousRecord->user_id, 'user_id' => $previousRecord->user_id,
'creator_id' => $previousRecord->created_user_id, 'creator_id' => $previousRecord->created_user_id,
'worked_at' => $worked_at, 'worked_at' => $previousRecord->work_timestamp,
'hours' => $previousRecord->work_hours, 'hours' => $previousRecord->work_hours,
'comment' => $previousRecord->comment, 'comment' => $previousRecord->comment,
'created_at' => $created_at,
'updated_at' => $created_at,
]); ]);
$created_at = Carbon::createFromTimestamp($previousRecord->created_timestamp);
$room->setAttribute('id', $previousRecord->id);
$room->setAttribute('created_at', $created_at);
$room->setAttribute('updated_at', $created_at);
$room->save();
} }
$this->changeReferences( $this->changeReferences(
@ -69,9 +68,7 @@ class CreateWorklogsTable extends Migration
*/ */
public function down(): void public function down(): void
{ {
$connection = $this->schema->getConnection(); $this->schema->create('UserWorkLog', function (Blueprint $table) {
$this->schema->create('UserWorkLog', function (Blueprint $table): void {
$table->increments('id'); $table->increments('id');
$this->referencesUser($table); $this->referencesUser($table);
$table->integer('work_timestamp'); $table->integer('work_timestamp');
@ -81,18 +78,19 @@ class CreateWorklogsTable extends Migration
$table->integer('created_timestamp')->index(); $table->integer('created_timestamp')->index();
}); });
foreach ($connection->table('worklogs')->get() as $record) { foreach (Worklog::all() as $record) {
/** @var stdClass $record */ /** @var Worklog $record */
$connection $this->schema
->getConnection()
->table('UserWorkLog') ->table('UserWorkLog')
->insert([ ->insert([
'id' => $record->id, 'id' => $record->id,
'user_id' => $record->user_id, 'user_id' => $record->user_id,
'work_timestamp' => Carbon::createFromFormat('Y-m-d', $record->worked_at)->timestamp, 'work_timestamp' => $record->worked_at->timestamp,
'work_hours' => $record->hours, 'work_hours' => $record->hours,
'comment' => $record->comment, 'comment' => $record->comment,
'created_user_id' => $record->creator_id, 'created_user_id' => $record->creator_id,
'created_timestamp' => Carbon::createFromFormat('Y-m-d H:i:s', $record->created_at)->timestamp, 'created_timestamp' => $record->created_at->timestamp,
]); ]);
} }

View File

@ -1,7 +1,5 @@
<?php <?php
declare(strict_types=1);
namespace Engelsystem\Migrations; namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration; use Engelsystem\Database\Migration\Migration;
@ -11,7 +9,7 @@ class CreateWelcomeAngelPermissionsGroup extends Migration
/** /**
* Run the migration * Run the migration
*/ */
public function up(): void public function up()
{ {
if (!$this->schema->hasTable('Groups')) { if (!$this->schema->hasTable('Groups')) {
return; return;
@ -40,7 +38,7 @@ class CreateWelcomeAngelPermissionsGroup extends Migration
/** /**
* Reverse the migration * Reverse the migration
*/ */
public function down(): void public function down()
{ {
if (!$this->schema->hasTable('Groups')) { if (!$this->schema->hasTable('Groups')) {
return; return;

View File

@ -1,34 +1,32 @@
<?php <?php
declare(strict_types=1);
namespace Engelsystem\Migrations; namespace Engelsystem\Migrations;
use Carbon\Carbon; use Carbon\Carbon;
use Engelsystem\Database\Migration\Migration; use Engelsystem\Database\Migration\Migration;
use Engelsystem\Models\Question;
use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Schema\Blueprint;
class AddTimestampsToQuestions extends Migration class AddTimestampsToQuestions extends Migration
{ {
use ChangesReferences;
/** /**
* Run the migration * Run the migration
*/ */
public function up(): void public function up(): void
{ {
$connection = $this->schema->getConnection(); $this->schema->table('questions', function (Blueprint $table) {
$now = Carbon::now();
$this->schema->table('questions', function (Blueprint $table): void {
$table->timestamp('answered_at')->after('answerer_id')->nullable(); $table->timestamp('answered_at')->after('answerer_id')->nullable();
$table->timestamps(); $table->timestamps();
}); });
$connection->table('questions') $now = Carbon::now();
->update([ Question::query()->update([
'created_at' => $now, 'created_at' => $now,
'updated_at' => $now, 'updated_at' => $now,
]); ]);
$connection->table('questions') Question::query()
->whereNotNull('answerer_id') ->whereNotNull('answerer_id')
->update([ ->update([
'answered_at' => $now, 'answered_at' => $now,
@ -40,7 +38,7 @@ class AddTimestampsToQuestions extends Migration
*/ */
public function down(): void public function down(): void
{ {
$this->schema->table('questions', function (Blueprint $table): void { $this->schema->table('questions', function (Blueprint $table) {
$table->dropColumn('answered_at'); $table->dropColumn('answered_at');
$table->dropTimestamps(); $table->dropTimestamps();
}); });

View File

@ -1,7 +1,5 @@
<?php <?php
declare(strict_types=1);
namespace Engelsystem\Migrations; namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration; use Engelsystem\Database\Migration\Migration;
@ -12,9 +10,9 @@ class CreateFaqTableAndPermissions extends Migration
/** /**
* Run the migration * Run the migration
*/ */
public function up(): void public function up()
{ {
$this->schema->create('faq', function (Blueprint $table): void { $this->schema->create('faq', function (Blueprint $table) {
$table->increments('id'); $table->increments('id');
$table->string('question'); $table->string('question');
$table->text('text'); $table->text('text');
@ -48,7 +46,7 @@ class CreateFaqTableAndPermissions extends Migration
/** /**
* Reverse the migration * Reverse the migration
*/ */
public function down(): void public function down()
{ {
$this->schema->drop('faq'); $this->schema->drop('faq');

View File

@ -1,7 +1,5 @@
<?php <?php
declare(strict_types=1);
namespace Engelsystem\Migrations; namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration; use Engelsystem\Database\Migration\Migration;
@ -11,7 +9,7 @@ class CreateQuestionsPermissions extends Migration
/** /**
* Run the migration * Run the migration
*/ */
public function up(): void public function up()
{ {
if ($this->schema->hasTable('Privileges')) { if ($this->schema->hasTable('Privileges')) {
$db = $this->schema->getConnection(); $db = $this->schema->getConnection();
@ -38,7 +36,7 @@ class CreateQuestionsPermissions extends Migration
/** /**
* Reverse the migration * Reverse the migration
*/ */
public function down(): void public function down()
{ {
if (!$this->schema->hasTable('Privileges')) { if (!$this->schema->hasTable('Privileges')) {
return; return;

View File

@ -16,7 +16,7 @@ class CreateOauthTable extends Migration
*/ */
public function up(): void public function up(): void
{ {
$this->schema->create('oauth', function (Blueprint $table): void { $this->schema->create('oauth', function (Blueprint $table) {
$table->increments('id'); $table->increments('id');
$this->referencesUser($table); $this->referencesUser($table);
$table->string('provider'); $table->string('provider');

View File

@ -1,11 +1,10 @@
<?php <?php
declare(strict_types=1);
namespace Engelsystem\Migrations; namespace Engelsystem\Migrations;
use Carbon\Carbon; use Carbon\Carbon;
use Engelsystem\Database\Migration\Migration; use Engelsystem\Database\Migration\Migration;
use Engelsystem\Models\Shifts\Schedule;
use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Schema\Blueprint;
class AddNameMinutesAndTimestampsToSchedules extends Migration class AddNameMinutesAndTimestampsToSchedules extends Migration
@ -15,34 +14,39 @@ class AddNameMinutesAndTimestampsToSchedules extends Migration
/** /**
* Run the migration * Run the migration
*/ */
public function up(): void public function up()
{ {
$connection = $this->schema->getConnection(); $this->schema->table(
'schedules',
$this->schema->table('schedules', function (Blueprint $table): void { function (Blueprint $table) {
$table->string('name')->default('')->after('id'); $table->string('name')->default('')->after('id');
$table->unsignedInteger('shift_type')->default(0)->after('name'); $table->integer('shift_type')->default(0)->after('name');
$table->integer('minutes_before')->default(0)->after('shift_type'); $table->integer('minutes_before')->default(0)->after('shift_type');
$table->integer('minutes_after')->default(0)->after('minutes_before'); $table->integer('minutes_after')->default(0)->after('minutes_before');
$table->timestamps(); $table->timestamps();
}); }
);
$connection->table('schedules') Schedule::query()
->update([ ->update([
'created_at' => Carbon::now(), 'created_at' => Carbon::now(),
'minutes_before' => 15, 'minutes_before' => 15,
'minutes_after' => 15, 'minutes_after' => 15,
]); ]);
$this->schema->table('schedules', function (Blueprint $table): void { $this->schema->table(
'schedules',
function (Blueprint $table) {
$table->string('name')->default(null)->change(); $table->string('name')->default(null)->change();
$table->unsignedInteger('shift_type')->default(null)->change(); $table->integer('shift_type')->default(null)->change();
$table->integer('minutes_before')->default(null)->change(); $table->integer('minutes_before')->default(null)->change();
$table->integer('minutes_after')->default(null)->change(); $table->integer('minutes_after')->default(null)->change();
}); }
);
// Add legacy reference // Add legacy reference
if ($this->schema->hasTable('ShiftTypes')) { if ($this->schema->hasTable('ShiftTypes')) {
$connection = $this->schema->getConnection();
$query = $connection $query = $connection
->table('Shifts') ->table('Shifts')
->select('Shifts.shifttype_id') ->select('Shifts.shifttype_id')
@ -50,29 +54,33 @@ class AddNameMinutesAndTimestampsToSchedules extends Migration
->where('schedule_shift.schedule_id', $connection->raw('schedules.id')) ->where('schedule_shift.schedule_id', $connection->raw('schedules.id'))
->limit(1); ->limit(1);
$connection->table('schedules') Schedule::query()
->update([ ->update(['shift_type' => $connection->raw('(' . $query->toSql() . ')')]);
'shift_type' => $connection->raw('(' . $query->toSql() . ')'),
]);
$this->schema->table('schedules', function (Blueprint $table): void { $this->schema->table(
'schedules',
function (Blueprint $table) {
$this->addReference($table, 'shift_type', 'ShiftTypes'); $this->addReference($table, 'shift_type', 'ShiftTypes');
}); }
);
} }
} }
/** /**
* Reverse the migration * Reverse the migration
*/ */
public function down(): void public function down()
{ {
$this->schema->table('schedules', function (Blueprint $table): void { $this->schema->table(
'schedules',
function (Blueprint $table) {
$table->dropForeign('schedules_shift_type_foreign'); $table->dropForeign('schedules_shift_type_foreign');
$table->dropColumn('name'); $table->dropColumn('name');
$table->dropColumn('shift_type'); $table->dropColumn('shift_type');
$table->dropColumn('minutes_before'); $table->dropColumn('minutes_before');
$table->dropColumn('minutes_after'); $table->dropColumn('minutes_after');
$table->dropTimestamps(); $table->dropTimestamps();
}); }
);
} }
} }

View File

@ -1,7 +1,5 @@
<?php <?php
declare(strict_types=1);
namespace Engelsystem\Migrations; namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration; use Engelsystem\Database\Migration\Migration;
@ -9,23 +7,31 @@ use Illuminate\Database\Schema\Blueprint;
class AddEmailNewsToUsersSettings extends Migration class AddEmailNewsToUsersSettings extends Migration
{ {
use Reference;
/** /**
* Run the migration * Run the migration
*/ */
public function up(): void public function up()
{ {
$this->schema->table('users_settings', function (Blueprint $table): void { $this->schema->table(
'users_settings',
function (Blueprint $table) {
$table->boolean('email_news')->default(false)->after('email_shiftinfo'); $table->boolean('email_news')->default(false)->after('email_shiftinfo');
}); }
);
} }
/** /**
* Reverse the migration * Reverse the migration
*/ */
public function down(): void public function down()
{ {
$this->schema->table('users_settings', function (Blueprint $table): void { $this->schema->table(
'users_settings',
function (Blueprint $table) {
$table->dropColumn('email_news'); $table->dropColumn('email_news');
}); }
);
} }
} }

View File

@ -1,7 +1,5 @@
<?php <?php
declare(strict_types=1);
namespace Engelsystem\Migrations; namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration; use Engelsystem\Database\Migration\Migration;
@ -9,27 +7,35 @@ use Illuminate\Database\Schema\Blueprint;
class OauthAddTokens extends Migration class OauthAddTokens extends Migration
{ {
use Reference;
/** /**
* Run the migration * Run the migration
*/ */
public function up(): void public function up()
{ {
$this->schema->table('oauth', function (Blueprint $table): void { $this->schema->table(
'oauth',
function (Blueprint $table) {
$table->string('access_token')->nullable()->default(null)->after('identifier'); $table->string('access_token')->nullable()->default(null)->after('identifier');
$table->string('refresh_token')->nullable()->default(null)->after('access_token'); $table->string('refresh_token')->nullable()->default(null)->after('access_token');
$table->dateTime('expires_at')->nullable()->default(null)->after('refresh_token'); $table->dateTime('expires_at')->nullable()->default(null)->after('refresh_token');
}); }
);
} }
/** /**
* Reverse the migration * Reverse the migration
*/ */
public function down(): void public function down()
{ {
$this->schema->table('oauth', function (Blueprint $table): void { $this->schema->table(
'oauth',
function (Blueprint $table) {
$table->dropColumn('access_token'); $table->dropColumn('access_token');
$table->dropColumn('refresh_token'); $table->dropColumn('refresh_token');
$table->dropColumn('expires_at'); $table->dropColumn('expires_at');
}); }
);
} }
} }

View File

@ -1,7 +1,5 @@
<?php <?php
declare(strict_types=1);
namespace Engelsystem\Migrations; namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration; use Engelsystem\Database\Migration\Migration;
@ -9,23 +7,31 @@ use Illuminate\Database\Schema\Blueprint;
class NewsAddIsPinned extends Migration class NewsAddIsPinned extends Migration
{ {
use Reference;
/** /**
* Run the migration * Run the migration
*/ */
public function up(): void public function up()
{ {
$this->schema->table('news', function (Blueprint $table): void { $this->schema->table(
'news',
function (Blueprint $table) {
$table->boolean('is_pinned')->default(false)->after('is_meeting'); $table->boolean('is_pinned')->default(false)->after('is_meeting');
}); }
);
} }
/** /**
* Reverse the migration * Reverse the migration
*/ */
public function down(): void public function down()
{ {
$this->schema->table('news', function (Blueprint $table): void { $this->schema->table(
'news',
function (Blueprint $table) {
$table->dropColumn('is_pinned'); $table->dropColumn('is_pinned');
}); }
);
} }
} }

View File

@ -1,7 +1,5 @@
<?php <?php
declare(strict_types=1);
namespace Engelsystem\Migrations; namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration; use Engelsystem\Database\Migration\Migration;
@ -9,25 +7,33 @@ use Illuminate\Database\Schema\Blueprint;
class OauthChangeTokensToText extends Migration class OauthChangeTokensToText extends Migration
{ {
use Reference;
/** /**
* Run the migration * Run the migration
*/ */
public function up(): void public function up()
{ {
$this->schema->table('oauth', function (Blueprint $table): void { $this->schema->table(
'oauth',
function (Blueprint $table) {
$table->text('access_token')->change(); $table->text('access_token')->change();
$table->text('refresh_token')->change(); $table->text('refresh_token')->change();
}); }
);
} }
/** /**
* Reverse the migration * Reverse the migration
*/ */
public function down(): void public function down()
{ {
$this->schema->table('oauth', function (Blueprint $table): void { $this->schema->table(
'oauth',
function (Blueprint $table) {
$table->string('access_token')->change(); $table->string('access_token')->change();
$table->string('refresh_token')->change(); $table->string('refresh_token')->change();
}); }
);
} }
} }

View File

@ -1,45 +0,0 @@
<?php
declare(strict_types=1);
namespace Engelsystem\Migrations;
use Engelsystem\Config\Config;
use Engelsystem\Database\Migration\Migration;
use Engelsystem\Helpers\Carbon;
use Illuminate\Database\Schema\Builder as SchemaBuilder;
use stdClass;
class CreateFirstUser extends Migration
{
public function __construct(SchemaBuilder $schemaBuilder, protected Config $config)
{
parent::__construct($schemaBuilder);
}
/**
* Run the migration
*/
public function up(): void
{
$db = $this->schema->getConnection();
if ($db->table('users')->count() > 0) {
return;
}
$db->table('users')->insert([
'name' => 'admin',
'email' => 'admin@localhost',
'password' => password_hash('asdfasdf', PASSWORD_DEFAULT),
'api_key' => bin2hex(random_bytes(16)),
'created_at' => Carbon::now(),
]);
/** @var stdClass $admin */
$admin = $db->table('users')->where('name', 'admin')->first();
foreach (['users_contact', 'users_personal_data', 'users_state'] as $table) {
$db->table($table)->insert(['user_id' => $admin->id]);
}
$db->table('users_settings')->insert(['user_id' => $admin->id, 'language' => 'en_US', 'theme' => 0]);
}
}

View File

@ -1,41 +1,48 @@
<?php <?php
declare(strict_types=1);
namespace Engelsystem\Migrations; namespace Engelsystem\Migrations;
use Engelsystem\Config\Config; use Engelsystem\Config\Config;
use Engelsystem\Database\Migration\Migration; use Engelsystem\Database\Migration\Migration;
use Engelsystem\Helpers\Authenticator;
use Engelsystem\Models\User\User;
use Illuminate\Database\Schema\Builder as SchemaBuilder; use Illuminate\Database\Schema\Builder as SchemaBuilder;
use stdClass;
class SetAdminPassword extends Migration class SetAdminPassword extends Migration
{ {
public function __construct(SchemaBuilder $schemaBuilder, protected Config $config) use Reference;
/** @var Authenticator */
protected $auth;
/** @var Config */
protected $config;
/**
* @param SchemaBuilder $schemaBuilder
* @param Authenticator $auth
* @param Config $config
*/
public function __construct(SchemaBuilder $schemaBuilder, Authenticator $auth, Config $config)
{ {
parent::__construct($schemaBuilder); parent::__construct($schemaBuilder);
$this->auth = $auth;
$this->config = $config;
} }
/** /**
* Run the migration * Run the migration
*/ */
public function up(): void public function up()
{ {
$db = $this->schema->getConnection(); /** @var User $admin */
/** @var stdClass $admin */ $admin = $this->auth->authenticate('admin', 'asdfasdf');
$admin = $db->table('users')->where('name', 'admin')->first();
$setupPassword = $this->config->get('setup_admin_password'); $setupPassword = $this->config->get('setup_admin_password');
if (!$admin || !$setupPassword) {
if (
!$admin
|| !password_verify('asdfasdf', $admin->password)
|| !$setupPassword
) {
return; return;
} }
$db->table('users') $this->auth->setPassword($admin, $setupPassword);
->where('id', $admin->id)
->update(['password' => password_hash($setupPassword, PASSWORD_DEFAULT)]);
} }
} }

View File

@ -1,7 +1,5 @@
<?php <?php
declare(strict_types=1);
namespace Engelsystem\Migrations; namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration; use Engelsystem\Database\Migration\Migration;
@ -11,7 +9,7 @@ class AddShirtEditPermissions extends Migration
/** /**
* Run the migration * Run the migration
*/ */
public function up(): void public function up()
{ {
if (!$this->schema->hasTable('GroupPrivileges')) { if (!$this->schema->hasTable('GroupPrivileges')) {
return; return;
@ -42,7 +40,7 @@ class AddShirtEditPermissions extends Migration
/** /**
* Reverse the migration * Reverse the migration
*/ */
public function down(): void public function down()
{ {
if (!$this->schema->hasTable('GroupPrivileges')) { if (!$this->schema->hasTable('GroupPrivileges')) {
return; return;

View File

@ -1,7 +1,5 @@
<?php <?php
declare(strict_types=1);
namespace Engelsystem\Migrations; namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration; use Engelsystem\Database\Migration\Migration;
@ -9,31 +7,39 @@ use Illuminate\Database\Schema\Blueprint;
class AddShiftsDescription extends Migration class AddShiftsDescription extends Migration
{ {
use Reference;
/** /**
* Run the migration * Run the migration
*/ */
public function up(): void public function up()
{ {
if (!$this->schema->hasTable('Shifts')) { if (!$this->schema->hasTable('Shifts')) {
return; return;
} }
$this->schema->table('Shifts', function (Blueprint $table): void { $this->schema->table(
'Shifts',
function (Blueprint $table) {
$table->text('description')->nullable()->after('shifttype_id'); $table->text('description')->nullable()->after('shifttype_id');
}); }
);
} }
/** /**
* Reverse the migration * Reverse the migration
*/ */
public function down(): void public function down()
{ {
if (!$this->schema->hasTable('Shifts')) { if (!$this->schema->hasTable('Shifts')) {
return; return;
} }
$this->schema->table('Shifts', function (Blueprint $table): void { $this->schema->table(
'Shifts',
function (Blueprint $table) {
$table->dropColumn('description'); $table->dropColumn('description');
}); }
);
} }
} }

View File

@ -16,7 +16,7 @@ class CreateUserLicensesTable extends Migration
*/ */
public function up(): void public function up(): void
{ {
$this->schema->create('users_licenses', function (Blueprint $table): void { $this->schema->create('users_licenses', function (Blueprint $table) {
$this->referencesUser($table, true); $this->referencesUser($table, true);
$table->boolean('has_car')->default(false); $table->boolean('has_car')->default(false);
$table->boolean('drive_forklift')->default(false); $table->boolean('drive_forklift')->default(false);
@ -54,7 +54,7 @@ class CreateUserLicensesTable extends Migration
*/ */
public function down(): void public function down(): void
{ {
$this->schema->create('UserDriverLicenses', function (Blueprint $table): void { $this->schema->create('UserDriverLicenses', function (Blueprint $table) {
$this->referencesUser($table, true); $this->referencesUser($table, true);
$table->boolean('has_car'); $table->boolean('has_car');
$table->boolean('has_license_car'); $table->boolean('has_license_car');

View File

@ -1,7 +1,5 @@
<?php <?php
declare(strict_types=1);
namespace Engelsystem\Migrations; namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration; use Engelsystem\Database\Migration\Migration;
@ -12,9 +10,9 @@ class IncreaseSessionsTablePayloadSize extends Migration
/** /**
* Run the migration * Run the migration
*/ */
public function up(): void public function up()
{ {
$this->schema->table('sessions', function (Blueprint $table): void { $this->schema->table('sessions', function (Blueprint $table) {
$table->mediumText('payload')->change(); $table->mediumText('payload')->change();
}); });
} }
@ -22,9 +20,9 @@ class IncreaseSessionsTablePayloadSize extends Migration
/** /**
* Reverse the migration * Reverse the migration
*/ */
public function down(): void public function down()
{ {
$this->schema->table('sessions', function (Blueprint $table): void { $this->schema->table('sessions', function (Blueprint $table) {
$table->text('payload')->change(); $table->text('payload')->change();
}); });
} }

View File

@ -1,7 +1,5 @@
<?php <?php
declare(strict_types=1);
namespace Engelsystem\Migrations; namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration; use Engelsystem\Database\Migration\Migration;
@ -9,17 +7,21 @@ use Illuminate\Database\Schema\Blueprint;
class UsersSettingsAddEmailGoody extends Migration class UsersSettingsAddEmailGoody extends Migration
{ {
use Reference;
/** /**
* Run the migration * Run the migration
*/ */
public function up(): void public function up()
{ {
$connection = $this->schema->getConnection(); $this->schema->table(
'users_settings',
$this->schema->table('users_settings', function (Blueprint $table): void { function (Blueprint $table) {
$table->boolean('email_goody')->default(false)->after('email_human'); $table->boolean('email_goody')->default(false)->after('email_human');
}); }
);
$connection = $this->schema->getConnection();
$connection $connection
->table('users_settings') ->table('users_settings')
->update(['email_goody' => $connection->raw('email_human')]); ->update(['email_goody' => $connection->raw('email_human')]);
@ -28,10 +30,13 @@ class UsersSettingsAddEmailGoody extends Migration
/** /**
* Reverse the migration * Reverse the migration
*/ */
public function down(): void public function down()
{ {
$this->schema->table('users_settings', function (Blueprint $table): void { $this->schema->table(
'users_settings',
function (Blueprint $table) {
$table->dropColumn('email_goody'); $table->dropColumn('email_goody');
}); }
);
} }
} }

View File

@ -1,7 +1,5 @@
<?php <?php
declare(strict_types=1);
namespace Engelsystem\Migrations; namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration; use Engelsystem\Database\Migration\Migration;
@ -11,7 +9,7 @@ class RemoveAdminNewsHtmlPrivilege extends Migration
/** /**
* Run the migration * Run the migration
*/ */
public function up(): void public function up()
{ {
if (!$this->schema->hasTable('GroupPrivileges')) { if (!$this->schema->hasTable('GroupPrivileges')) {
return; return;
@ -29,7 +27,7 @@ class RemoveAdminNewsHtmlPrivilege extends Migration
/** /**
* Reverse the migration * Reverse the migration
*/ */
public function down(): void public function down()
{ {
if (!$this->schema->hasTable('GroupPrivileges')) { if (!$this->schema->hasTable('GroupPrivileges')) {
return; return;

View File

@ -1,7 +1,5 @@
<?php <?php
declare(strict_types=1);
namespace Engelsystem\Migrations; namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration; use Engelsystem\Database\Migration\Migration;
@ -15,9 +13,9 @@ class IncreaseTshirtFieldWidth extends Migration
/** /**
* Run the migration * Run the migration
*/ */
public function up(): void public function up()
{ {
$this->schema->table('users_personal_data', function (Blueprint $table): void { $this->schema->table('users_personal_data', function (Blueprint $table) {
$table->string('shirt_size', 10)->change(); $table->string('shirt_size', 10)->change();
}); });
} }
@ -25,9 +23,9 @@ class IncreaseTshirtFieldWidth extends Migration
/** /**
* Reverse the migration * Reverse the migration
*/ */
public function down(): void public function down()
{ {
$this->schema->table('users_personal_data', function (Blueprint $table): void { $this->schema->table('users_personal_data', function (Blueprint $table) {
$table->string('shirt_size', 4)->change(); $table->string('shirt_size', 4)->change();
}); });
} }

View File

@ -1,7 +1,5 @@
<?php <?php
declare(strict_types=1);
namespace Engelsystem\Migrations; namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration; use Engelsystem\Database\Migration\Migration;
@ -11,7 +9,7 @@ class CreateVoucherEditPermission extends Migration
/** /**
* Run the migration * Run the migration
*/ */
public function up(): void public function up()
{ {
if (!$this->schema->hasTable('Privileges')) { if (!$this->schema->hasTable('Privileges')) {
return; return;
@ -38,7 +36,7 @@ class CreateVoucherEditPermission extends Migration
/** /**
* Reverse the migration * Reverse the migration
*/ */
public function down(): void public function down()
{ {
if (!$this->schema->hasTable('Privileges')) { if (!$this->schema->hasTable('Privileges')) {
return; return;

View File

@ -18,7 +18,7 @@ class ShiftsAddTransactionId extends Migration
return; return;
} }
$this->schema->table('Shifts', function (Blueprint $table): void { $this->schema->table('Shifts', function (Blueprint $table) {
$table->uuid('transaction_id')->index()->nullable()->default(null); $table->uuid('transaction_id')->index()->nullable()->default(null);
}); });
} }
@ -32,7 +32,7 @@ class ShiftsAddTransactionId extends Migration
return; return;
} }
$this->schema->table('Shifts', function (Blueprint $table): void { $this->schema->table('Shifts', function (Blueprint $table) {
$table->dropColumn('transaction_id'); $table->dropColumn('transaction_id');
}); });
} }

View File

@ -1,82 +0,0 @@
<?php
declare(strict_types=1);
namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration;
class FixOldGroupsTableIdAndName extends Migration
{
/** @var string[] */
protected array $naming = [
'1-Gast' => 'Guest',
'2-Engel' => 'Angel',
'Shirt-Manager' => 'Shirt Manager',
'3-Shift Coordinator' => 'Shift Coordinator',
'4-Team Coordinator' => 'Team Coordinator',
'5-Bürokrat' => 'Bureaucrat',
'6-Developer' => 'Developer',
];
/** @var int[] */
protected array $ids = [
-25 => -30,
-26 => -35,
-30 => -50,
-40 => -60,
-50 => -65,
-60 => -80,
-65 => -85,
-70 => -90,
];
/**
* Run the migration
*/
public function up(): void
{
$this->migrate($this->naming, $this->ids);
}
/**
* Reverse the migration
*/
public function down(): void
{
$this->migrate(array_flip($this->naming), array_flip($this->ids));
}
/**
* @param string[] $naming
* @param int[] $ids
*/
private function migrate(array $naming, array $ids): void
{
if (!$this->schema->hasTable('Groups')) {
return;
}
$connection = $this->schema->getConnection();
foreach ($connection->table('Groups')->orderByDesc('UID')->get() as $data) {
if (isset($naming[$data->Name])) {
$data->Name = $naming[$data->Name];
}
$data->oldId = $data->UID;
if (isset($ids[$data->oldId])) {
$data->UID = $ids[$data->oldId];
} elseif (isset($ids[$data->oldId * -1])) {
$data->UID = $ids[$data->oldId * -1] * -1;
}
$connection
->table('Groups')
->where('UID', $data->oldId)
->update([
'UID' => $data->UID * -1,
'Name' => $data->Name,
]);
}
}
}

View File

@ -1,31 +0,0 @@
<?php
declare(strict_types=1);
namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration;
use Illuminate\Database\Schema\Blueprint;
class AddMobileShowToUsersSettings extends Migration
{
/**
* Run the migration
*/
public function up(): void
{
$this->schema->table('users_settings', function (Blueprint $table): void {
$table->boolean('mobile_show')->default(false)->after('email_news');
});
}
/**
* Reverse the migration
*/
public function down(): void
{
$this->schema->table('users_settings', function (Blueprint $table): void {
$table->dropColumn('mobile_show');
});
}
}

View File

@ -1,31 +0,0 @@
<?php
declare(strict_types=1);
namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration;
use Illuminate\Database\Schema\Blueprint;
class AddDectToRooms extends Migration
{
/**
* Run the migration
*/
public function up(): void
{
$this->schema->table('rooms', function (Blueprint $table): void {
$table->text('dect')->nullable()->after('description');
});
}
/**
* Reverse the migration
*/
public function down(): void
{
$this->schema->table('rooms', function (Blueprint $table): void {
$table->dropColumn('dect');
});
}
}

View File

@ -1,39 +0,0 @@
<?php
declare(strict_types=1);
namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration;
use Illuminate\Database\Schema\Blueprint;
class AddHideRegisterToAngeltypes extends Migration
{
/**
* Run the migration
*/
public function up(): void
{
if (!$this->schema->hasTable('AngelTypes')) {
return;
}
$this->schema->table('AngelTypes', function (Blueprint $table): void {
$table->boolean('hide_register')->default(false)->after('show_on_dashboard');
});
}
/**
* Reverse the migration
*/
public function down(): void
{
if (!$this->schema->hasTable('AngelTypes')) {
return;
}
$this->schema->table('AngelTypes', function (Blueprint $table): void {
$table->dropColumn('hide_register');
});
}
}

View File

@ -1,262 +0,0 @@
<?php
declare(strict_types=1);
namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Schema\Blueprint;
use stdClass;
class CreatePrivilegesAndGroupsRelatedTables extends Migration
{
use ChangesReferences;
use Reference;
/**
* Creates the new table, copies the data and drops the old one.
*/
public function up(): void
{
$hasPrevious = $this->schema->hasTable('Privileges');
if ($hasPrevious) {
// Rename because some DBMS handle identifiers case-insensitive
$this->schema->rename('Groups', 'groups_old');
$this->schema->rename('Privileges', 'privileges_old');
}
$this->createNew();
if ($hasPrevious) {
$this->copyOldToNew();
$this->changeReferences(
'groups_old',
'UID',
'groups',
'id'
);
$this->changeReferences(
'privileges_old',
'id',
'privileges',
'id'
);
$this->changeReferences(
'UserGroups',
'id',
'users_groups',
'id'
);
$this->changeReferences(
'GroupPrivileges',
'id',
'group_privileges',
'id'
);
$this->schema->drop('UserGroups');
$this->schema->drop('GroupPrivileges');
$this->schema->drop('groups_old');
$this->schema->drop('privileges_old');
}
}
/**
* Recreates the previous table, copies the data and drops the new one.
*/
public function down(): void
{
// Rename because some DBMS handle identifiers case-insensitive
$this->schema->rename('groups', 'groups_new');
$this->schema->rename('privileges', 'privileges_new');
$this->createOldTable();
$this->copyNewToOld();
$this->changeReferences(
'groups_new',
'id',
'Groups',
'UID',
'integer'
);
$this->changeReferences(
'privileges_new',
'id',
'Privileges',
'id'
);
$this->changeReferences(
'users_groups',
'id',
'UserGroups',
'id'
);
$this->changeReferences(
'group_privileges',
'id',
'GroupPrivileges',
'id'
);
$this->schema->drop('users_groups');
$this->schema->drop('group_privileges');
$this->schema->drop('groups_new');
$this->schema->drop('privileges_new');
}
private function createNew(): void
{
$this->schema->create('groups', function (Blueprint $table): void {
$table->increments('id');
$table->string('name', 35)->unique();
});
$this->schema->create('privileges', function (Blueprint $table): void {
$table->increments('id');
$table->string('name', 128)->unique();
$table->string('description', 1024);
});
$this->schema->create('users_groups', function (Blueprint $table): void {
$table->increments('id');
$this->referencesUser($table)->index();
$this->references($table, 'groups')->index();
});
$this->schema->create('group_privileges', function (Blueprint $table): void {
$table->increments('id');
$this->references($table, 'groups')->index();
$this->references($table, 'privileges')->index();
});
}
private function createOldTable(): void
{
$this->schema->create('Groups', function (Blueprint $table): void {
$table->string('Name', 35);
$table->integer('UID')->primary();
});
$this->schema->create('Privileges', function (Blueprint $table): void {
$table->increments('id');
$table->string('name', 128)->unique();
$table->string('desc', 1024);
});
$this->schema->create('UserGroups', function (Blueprint $table): void {
$table->increments('id');
$this->references($table, 'users', 'uid');
$this->references($table, 'Groups', 'group_id', 'UID', false, 'integer')->index();
$table->index(['uid', 'group_id']);
});
$this->schema->create('GroupPrivileges', function (Blueprint $table): void {
$table->increments('id');
$this->references($table, 'Groups', 'group_id', 'UID', false, 'integer');
$this->references($table, 'Privileges', 'privilege_id')->index();
$table->index(['group_id', 'privilege_id']);
});
}
private function copyOldToNew(): void
{
$connection = $this->schema->getConnection();
/** @var stdClass[] $records */
$records = $connection
->table('groups_old')
->get();
foreach ($records as $record) {
$connection->table('groups')->insert([
'id' => $record->UID,
'name' => $record->Name,
]);
}
$records = $connection
->table('privileges_old')
->get();
foreach ($records as $record) {
$connection->table('privileges')->insert([
'id' => $record->id,
'name' => $record->name,
'description' => $record->desc,
]);
}
$records = $connection
->table('UserGroups')
->get();
foreach ($records as $record) {
$connection->table('users_groups')->insert([
'id' => $record->id,
'user_id' => $record->uid,
'group_id' => $record->group_id,
]);
}
$records = $connection
->table('GroupPrivileges')
->get();
foreach ($records as $record) {
$connection->table('group_privileges')->insert([
'id' => $record->id,
'group_id' => $record->group_id,
'privilege_id' => $record->privilege_id,
]);
}
}
private function copyNewToOld(): void
{
$connection = $this->schema->getConnection();
/** @var Collection|stdClass[] $records */
$records = $connection
->table('groups_new')
->get();
foreach ($records as $record) {
$connection->table('Groups')->insert([
'Name' => $record->name,
'UID' => $record->id,
]);
}
$records = $connection
->table('privileges_new')
->get();
foreach ($records as $record) {
$connection->table('Privileges')->insert([
'id' => $record->id,
'name' => $record->name,
'desc' => $record->description,
]);
}
$records = $connection
->table('users_groups')
->get();
foreach ($records as $record) {
$connection->table('UserGroups')->insert([
'id' => $record->id,
'uid' => $record->user_id,
'group_id' => $record->group_id,
]);
}
$records = $connection
->table('group_privileges')
->get();
foreach ($records as $record) {
$connection->table('GroupPrivileges')->insert([
'id' => $record->id,
'group_id' => $record->group_id,
'privilege_id' => $record->privilege_id,
]);
}
}
}

View File

@ -1,158 +0,0 @@
<?php
declare(strict_types=1);
namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration;
use stdClass;
class FillPrivilegesAndGroupsRelatedTables extends Migration
{
/**
* Inserts missing data into permissions & groups related tables
*/
public function up(): void
{
$db = $this->schema->getConnection();
if ($db->table('privileges')->count() > 0) {
return;
}
$db->table('groups')
->insert([
['id' => 10, 'name' => 'Guest'],
['id' => 20, 'name' => 'Angel'],
['id' => 30, 'name' => 'Welcome Angel'],
['id' => 35, 'name' => 'Voucher Angel'],
['id' => 50, 'name' => 'Shirt Manager'],
['id' => 60, 'name' => 'Shift Coordinator'],
['id' => 65, 'name' => 'Team Coordinator'],
['id' => 80, 'name' => 'Bureaucrat'],
['id' => 85, 'name' => 'News Admin'],
['id' => 90, 'name' => 'Developer'],
]);
$db->table('privileges')
->insert([
['id' => 1, 'name' => 'start', 'description' => 'Startseite für Gäste/Nicht eingeloggte User'],
['id' => 2, 'name' => 'login', 'description' => 'Logindialog'],
['id' => 3, 'name' => 'news', 'description' => 'Anzeigen der News-Seite'],
['id' => 4, 'name' => 'logout', 'description' => 'User darf sich ausloggen'],
['id' => 5, 'name' => 'register', 'description' => 'Einen neuen Engel registerieren'],
['id' => 6, 'name' => 'admin_rooms', 'description' => 'Räume administrieren'],
['id' => 7, 'name' => 'admin_angel_types', 'description' => 'Engel Typen administrieren'],
['id' => 8, 'name' => 'user_settings', 'description' => 'User profile settings'],
['id' => 9, 'name' => 'user_messages',
'description' => 'Writing and reading messages from user to user'],
['id' => 10, 'name' => 'admin_groups', 'description' => 'Manage usergroups and their rights'],
['id' => 14, 'name' => 'admin_news', 'description' => 'Administrate the news section'],
['id' => 15, 'name' => 'news_comments', 'description' => 'User can comment news'],
['id' => 16, 'name' => 'admin_user', 'description' => 'Administrate the angels'],
['id' => 17, 'name' => 'user_meetings', 'description' => 'Lists meetings (news)'],
['id' => 18, 'name' => 'admin_language', 'description' => 'Translate the system'],
['id' => 19, 'name' => 'admin_log', 'description' => 'Display recent changes'],
['id' => 21, 'name' => 'schedule.import', 'description' => 'Import rooms and shifts from schedule.xml'],
['id' => 24, 'name' => 'user_shifts', 'description' => 'Signup for shifts'],
['id' => 25, 'name' => 'user_shifts_admin', 'description' => 'Signup other angels for shifts.'],
['id' => 26, 'name' => 'user_myshifts',
'description' => 'Allow angels to view their own shifts and cancel them.'],
['id' => 27, 'name' => 'admin_arrive', 'description' => 'Mark angels when they arrive.'],
['id' => 28, 'name' => 'admin_shifts', 'description' => 'Create shifts'],
['id' => 30, 'name' => 'ical', 'description' => 'iCal shift export'],
['id' => 31, 'name' => 'admin_active',
'description' => 'Mark angels as active and if they got a t-shirt.'],
['id' => 32, 'name' => 'admin_free', 'description' => 'Show a list of free/unemployed angels.'],
['id' => 33, 'name' => 'admin_user_angeltypes', 'description' => 'Confirm restricted angel types'],
['id' => 34, 'name' => 'atom', 'description' => ' Atom news export'],
['id' => 35, 'name' => 'shifts_json_export', 'description' => 'Export shifts in JSON format'],
['id' => 36, 'name' => 'angeltypes', 'description' => 'View angeltypes'],
['id' => 37, 'name' => 'user_angeltypes', 'description' => 'Join angeltypes.'],
['id' => 38, 'name' => 'shifttypes', 'description' => 'Administrate shift types'],
['id' => 39, 'name' => 'admin_event_config', 'description' => 'Allow editing event config'],
['id' => 40, 'name' => 'view_rooms', 'description' => 'User can view rooms'],
['id' => 41, 'name' => 'shiftentry_edit_angeltype_supporter',
'description' => 'If user with this privilege is angeltype supporter, '
. 'he can put users in shifts for their angeltype'],
['id' => 43, 'name' => 'admin_user_worklog', 'description' => 'Manage user work log entries.'],
['id' => 44, 'name' => 'faq.view', 'description' => 'View FAQ entries'],
['id' => 45, 'name' => 'faq.edit', 'description' => 'Edit FAQ entries'],
['id' => 46, 'name' => 'question.add', 'description' => 'Ask questions'],
['id' => 47, 'name' => 'question.edit', 'description' => 'Answer questions'],
['id' => 48, 'name' => 'user.edit.shirt', 'description' => 'Edit user shirts'],
['id' => 49, 'name' => 'voucher.edit', 'description' => 'Edit vouchers'],
]);
$db->table('group_privileges')->insert([
['id' => 23, 'group_id' => 10, 'privilege_id' => 2],
['id' => 24, 'group_id' => 10, 'privilege_id' => 5],
['id' => 85, 'group_id' => 90, 'privilege_id' => 10],
['id' => 86, 'group_id' => 90, 'privilege_id' => 21],
['id' => 87, 'group_id' => 90, 'privilege_id' => 18],
['id' => 88, 'group_id' => 10, 'privilege_id' => 1],
['id' => 206, 'group_id' => 80, 'privilege_id' => 31],
['id' => 207, 'group_id' => 80, 'privilege_id' => 7],
['id' => 209, 'group_id' => 80, 'privilege_id' => 21],
['id' => 210, 'group_id' => 80, 'privilege_id' => 14],
['id' => 212, 'group_id' => 80, 'privilege_id' => 6],
['id' => 213, 'group_id' => 80, 'privilege_id' => 28],
['id' => 214, 'group_id' => 80, 'privilege_id' => 16],
['id' => 215, 'group_id' => 80, 'privilege_id' => 33],
['id' => 216, 'group_id' => 80, 'privilege_id' => 5],
['id' => 218, 'group_id' => 60, 'privilege_id' => 39],
['id' => 219, 'group_id' => 65, 'privilege_id' => 14],
['id' => 220, 'group_id' => 65, 'privilege_id' => 33],
['id' => 221, 'group_id' => 65, 'privilege_id' => 25],
['id' => 235, 'group_id' => 60, 'privilege_id' => 27],
['id' => 236, 'group_id' => 60, 'privilege_id' => 32],
['id' => 237, 'group_id' => 60, 'privilege_id' => 19],
['id' => 238, 'group_id' => 60, 'privilege_id' => 14],
['id' => 239, 'group_id' => 60, 'privilege_id' => 28],
['id' => 240, 'group_id' => 60, 'privilege_id' => 16],
['id' => 241, 'group_id' => 60, 'privilege_id' => 5],
['id' => 242, 'group_id' => 60, 'privilege_id' => 25],
['id' => 243, 'group_id' => 20, 'privilege_id' => 36],
['id' => 244, 'group_id' => 20, 'privilege_id' => 34],
['id' => 245, 'group_id' => 20, 'privilege_id' => 30],
['id' => 246, 'group_id' => 20, 'privilege_id' => 4],
['id' => 247, 'group_id' => 20, 'privilege_id' => 3],
['id' => 248, 'group_id' => 20, 'privilege_id' => 15],
['id' => 249, 'group_id' => 20, 'privilege_id' => 35],
['id' => 250, 'group_id' => 20, 'privilege_id' => 37],
['id' => 251, 'group_id' => 20, 'privilege_id' => 17],
['id' => 252, 'group_id' => 20, 'privilege_id' => 9],
['id' => 253, 'group_id' => 20, 'privilege_id' => 26],
['id' => 255, 'group_id' => 20, 'privilege_id' => 8],
['id' => 256, 'group_id' => 20, 'privilege_id' => 24],
['id' => 257, 'group_id' => 80, 'privilege_id' => 38],
['id' => 258, 'group_id' => 50, 'privilege_id' => 31],
['id' => 259, 'group_id' => 20, 'privilege_id' => 40],
['id' => 260, 'group_id' => 85, 'privilege_id' => 14],
['id' => 262, 'group_id' => 60, 'privilege_id' => 43],
['id' => 263, 'group_id' => 20, 'privilege_id' => 41],
['id' => 264, 'group_id' => 30, 'privilege_id' => 27],
['id' => 265, 'group_id' => 10, 'privilege_id' => 44],
['id' => 266, 'group_id' => 20, 'privilege_id' => 44],
['id' => 267, 'group_id' => 60, 'privilege_id' => 45],
['id' => 268, 'group_id' => 20, 'privilege_id' => 46],
['id' => 269, 'group_id' => 60, 'privilege_id' => 47],
['id' => 270, 'group_id' => 60, 'privilege_id' => 48],
['id' => 271, 'group_id' => 50, 'privilege_id' => 48],
['id' => 272, 'group_id' => 50, 'privilege_id' => 27],
['id' => 273, 'group_id' => 60, 'privilege_id' => 49],
['id' => 274, 'group_id' => 35, 'privilege_id' => 49],
['id' => 275, 'group_id' => 35, 'privilege_id' => 27],
]);
/** @var stdClass $admin */
$admin = $db->table('users')->where('name', 'admin')->first();
if (!$admin) {
return;
}
// Angel, ShiCo, Team coordinator, Bureaucrat, Dev
foreach ([20, 60, 65, 80, 90] as $group) {
$db->table('users_groups')->insert(['user_id' => $admin->id, 'group_id' => $group]);
}
}
}

View File

@ -1,43 +0,0 @@
<?php
declare(strict_types=1);
namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration;
use Illuminate\Database\Schema\Blueprint;
class ShifttypeRemoveAngeltype extends Migration
{
use Reference;
/**
* Run the migration
*/
public function up(): void
{
if (!$this->schema->hasTable('ShiftTypes')) {
return;
}
$this->schema->table('ShiftTypes', function (Blueprint $table): void {
$table->dropForeign('shifttypes_ibfk_1');
$table->dropColumn('angeltype_id');
});
}
/**
* Reverse the migration
*/
public function down(): void
{
if (!$this->schema->hasTable('ShiftTypes')) {
return;
}
$this->schema->table('ShiftTypes', function (Blueprint $table): void {
$table->integer('angeltype_id')->after('name')->index()->nullable();
$this->addReference($table, 'angeltype_id', 'AngelTypes', null, 'shifttypes_ibfk_1');
});
}
}

View File

@ -1,86 +0,0 @@
<?php
declare(strict_types=1);
namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration;
use Illuminate\Database\Schema\Blueprint;
use stdClass;
class CreateShiftTypesTable extends Migration
{
use ChangesReferences;
/**
* Creates the new table, copies the data and drops the old one
*/
public function up(): void
{
$connection = $this->schema->getConnection();
$this->schema->create('shift_types', function (Blueprint $table): void {
$table->increments('id');
$table->string('name')->unique();
$table->text('description');
});
if (!$this->schema->hasTable('ShiftTypes')) {
return;
}
/** @var stdClass[] $records */
$records = $connection
->table('ShiftTypes')
->get();
foreach ($records as $record) {
$connection->table('shift_types')->insert([
'id' => $record->id,
'name' => $record->name,
'description' => $record->description,
]);
}
$this->changeReferences(
'ShiftTypes',
'id',
'shift_types',
'id'
);
$this->schema->drop('ShiftTypes');
}
/**
* Recreates the previous table, copies the data and drops the new one
*/
public function down(): void
{
$connection = $this->schema->getConnection();
$this->schema->create('ShiftTypes', function (Blueprint $table): void {
$table->increments('id');
$table->string('name', 255);
$table->mediumText('description');
});
/** @var stdClass[] $records */
$records = $connection
->table('shift_types')
->get();
foreach ($records as $record) {
$connection->table('ShiftTypes')->insert([
'id' => $record->id,
'name' => $record->name,
'description' => $record->description,
]);
}
$this->changeReferences(
'shift_types',
'id',
'ShiftTypes',
'id'
);
$this->schema->drop('shift_types');
}
}

View File

@ -1,126 +0,0 @@
<?php
declare(strict_types=1);
namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration;
use Illuminate\Support\Collection;
use Illuminate\Database\Schema\Blueprint;
use stdClass;
class CreateAngelTypesTable extends Migration
{
use ChangesReferences;
/**
* Creates the new table, copies the data and drops the old one
*/
public function up(): void
{
$connection = $this->schema->getConnection();
$this->schema->create('angel_types', function (Blueprint $table): void {
$table->increments('id');
$table->string('name')->unique();
$table->text('description')->default('');
$table->string('contact_name')->default('');
$table->string('contact_dect')->default('');
$table->string('contact_email')->default('');
$table->boolean('restricted')->default(false);
$table->boolean('requires_driver_license')->default(false);
$table->boolean('no_self_signup')->default(false);
$table->boolean('show_on_dashboard')->default(true);
$table->boolean('hide_register')->default(false);
});
if (!$this->schema->hasTable('AngelTypes')) {
return;
}
/** @var Collection|stdClass[] $records */
$records = $connection
->table('AngelTypes')
->get();
foreach ($records as $record) {
$connection->table('angel_types')->insert([
'id' => $record->id,
'name' => $record->name,
'description' => $record->description,
'contact_name' => (string) $record->contact_name,
'contact_dect' => (string) $record->contact_dect,
'contact_email' => (string) $record->contact_email,
'restricted' => $record->restricted,
'requires_driver_license' => $record->requires_driver_license,
'no_self_signup' => $record->no_self_signup,
'show_on_dashboard' => $record->show_on_dashboard,
'hide_register' => $record->hide_register,
]);
}
$this->changeReferences(
'AngelTypes',
'id',
'angel_types',
'id'
);
$this->schema->drop('AngelTypes');
}
/**
* Recreates the previous table, copies the data and drops the new one
*/
public function down(): void
{
$connection = $this->schema->getConnection();
$this->schema->create('AngelTypes', function (Blueprint $table): void {
$table->integer('id', true);
$table->string('name', 50)->default('')->unique();
$table->boolean('restricted');
$table->mediumText('description');
$table->boolean('requires_driver_license');
$table->boolean('no_self_signup');
$table->string('contact_name', 250)->nullable();
$table->string('contact_dect', 40)->nullable();
$table->string('contact_email', 250)->nullable();
$table->boolean('show_on_dashboard');
$table->boolean('hide_register')->default(false);
});
/** @var Collection|stdClass[] $records */
$records = $connection
->table('angel_types')
->get();
foreach ($records as $record) {
$connection->table('AngelTypes')->insert([
'id' => $record->id,
'name' => $record->name,
'description' => $record->description,
'contact_name' => $record->contact_name ?: null,
'contact_dect' => $record->contact_dect ?: null,
'contact_email' => $record->contact_email ?: null,
'restricted' => $record->restricted,
'requires_driver_license' => $record->requires_driver_license,
'no_self_signup' => $record->no_self_signup,
'show_on_dashboard' => $record->show_on_dashboard,
'hide_register' => $record->hide_register,
]);
}
$this->changeReferences(
'angel_types',
'id',
'AngelTypes',
'id',
'integer'
);
$this->schema->drop('angel_types');
}
}

View File

@ -1,101 +0,0 @@
<?php
declare(strict_types=1);
namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration;
use Illuminate\Database\Schema\Blueprint;
use stdClass;
class CreateUserAngelTypesTable extends Migration
{
use ChangesReferences;
use Reference;
/**
* Creates the new table, copies the data and drops the old one
*/
public function up(): void
{
$connection = $this->schema->getConnection();
$this->schema->create('user_angel_type', function (Blueprint $table): void {
$table->increments('id');
$this->referencesUser($table);
$this->references($table, 'angel_types')->index();
$this->references($table, 'users', 'confirm_user_id')->nullable()->default(null)->index();
$table->boolean('supporter')->default(false)->index();
$table->index(['user_id', 'angel_type_id', 'confirm_user_id']);
$table->unique(['user_id', 'angel_type_id']);
});
if (!$this->schema->hasTable('UserAngelTypes')) {
return;
}
/** @var stdClass[] $records */
$records = $connection
->table('UserAngelTypes')
->get();
foreach ($records as $record) {
$connection->table('user_angel_type')->insert([
'id' => $record->id,
'user_id' => $record->user_id,
'angel_type_id' => $record->angeltype_id,
'confirm_user_id' => $record->confirm_user_id ?: null,
'supporter' => (bool) $record->supporter,
]);
}
$this->changeReferences(
'UserAngelTypes',
'id',
'user_angel_type',
'id'
);
$this->schema->drop('UserAngelTypes');
}
/**
* Recreates the previous table, copies the data and drops the new one
*/
public function down(): void
{
$connection = $this->schema->getConnection();
$this->schema->create('UserAngelTypes', function (Blueprint $table): void {
$table->increments('id');
$this->referencesUser($table);
$this->references($table, 'angel_types', 'angeltype_id')->index('angeltype_id');
$this->references($table, 'users', 'confirm_user_id')->nullable()->index('confirm_user_id');
$table->boolean('supporter')->nullable()->index('coordinator');
$table->index(['user_id', 'angeltype_id', 'confirm_user_id'], 'user_id');
});
/** @var stdClass[] $records */
$records = $connection
->table('user_angel_type')
->get();
foreach ($records as $record) {
$connection->table('UserAngelTypes')->insert([
'id' => $record->id,
'user_id' => $record->user_id,
'angeltype_id' => $record->angel_type_id,
'confirm_user_id' => $record->confirm_user_id ?: null,
'supporter' => (bool) $record->supporter,
]);
}
$this->changeReferences(
'user_angel_type',
'id',
'UserAngelTypes',
'id',
'integer'
);
$this->schema->drop('user_angel_type');
}
}

View File

@ -1,45 +0,0 @@
<?php
declare(strict_types=1);
namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Str;
class ChangeApiKeyLength extends Migration
{
/**
* Run the migration
*/
public function up(): void
{
$this->schema->table('users', function (Blueprint $table): void {
$table->string('api_key', 64)->change();
});
}
/**
* Reverse the migration
*/
public function down(): void
{
$connection = $this->schema->getConnection();
$data = $connection->table('users')->get(['id', 'api_key']);
foreach ($data as $user) {
if (Str::length($user->api_key) <= 32) {
continue;
}
$key = Str::substr($user->api_key, 0, 32);
$connection->table('users')
->where('id', $user->id)
->update(['api_key' => $key]);
}
$this->schema->table('users', function (Blueprint $table): void {
$table->string('api_key', 32)->change();
});
}
}

View File

@ -1,149 +0,0 @@
<?php
declare(strict_types=1);
namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration;
use Engelsystem\Helpers\Carbon;
use Illuminate\Database\Schema\Blueprint;
use stdClass;
class CreateShiftsTable extends Migration
{
use ChangesReferences;
use Reference;
/**
* Creates the new table, copies the data and drops the old one
*/
public function up(): void
{
$connection = $this->schema->getConnection();
$previous = $this->schema->hasTable('Shifts');
if ($previous) {
$this->schema->rename('Shifts', 'shifts_old');
}
$this->schema->create('shifts', function (Blueprint $table): void {
$table->increments('id');
$table->string('title');
$table->text('description')->default('');
$table->string('url')->default('');
$table->dateTime('start')->index();
$table->dateTime('end');
$this->references($table, 'shift_types');
$this->references($table, 'rooms');
$table->uuid('transaction_id')->nullable()->default(null)->index();
$this->references($table, 'users', 'created_by');
$this->references($table, 'users', 'updated_by')->nullable()->default(null);
$table->timestamps();
});
if (!$previous) {
return;
}
/** @var stdClass[] $records */
$records = $connection
->table('shifts_old')
->get();
foreach ($records as $record) {
$isUpdated = !empty($record->edited_at_timestamp)
&& $record->edited_at_timestamp != $record->created_at_timestamp;
$connection->table('shifts')->insert([
'id' => $record->SID,
'title' => (string) $record->title,
'description' => (string) $record->description,
'url' => (string) $record->URL,
'start' => Carbon::createFromTimestamp($record->start),
'end' => Carbon::createFromTimestamp($record->end),
'shift_type_id' => $record->shifttype_id,
'room_id' => $record->RID,
'transaction_id' => $record->transaction_id,
'created_by' => $record->created_by_user_id,
'updated_by' => $isUpdated ? $record->edited_by_user_id : null,
'created_at' => Carbon::createFromTimestamp($record->created_at_timestamp),
'updated_at' => $isUpdated ? Carbon::createFromTimestamp($record->edited_at_timestamp) : null,
]);
}
$this->changeReferences(
'shifts_old',
'SID',
'shifts',
'id'
);
$this->schema->drop('shifts_old');
}
/**
* Recreates the previous table, copies the data and drops the new one
*/
public function down(): void
{
$connection = $this->schema->getConnection();
$this->schema->rename('shifts', 'shifts_old');
$this->schema->create('Shifts', function (Blueprint $table): void {
$table->increments('SID');
$table->mediumText('title')->nullable()->default(null);
$this->references($table, 'shift_types', 'shifttype_id');
$table->text('description')->nullable()->default(null);
$table->integer('start')->index();
$table->integer('end');
$this->references($table, 'rooms', 'RID')->default(0);
$table->mediumText('URL')->nullable()->default(null);
$this->references($table, 'users', 'created_by_user_id')->nullable()->default(null);
$table->integer('created_at_timestamp');
$this->references($table, 'users', 'edited_by_user_id')->nullable()->default(null);
$table->integer('edited_at_timestamp');
$table->uuid('transaction_id')->nullable()->default(null)->index();
});
/** @var stdClass[] $records */
$records = $connection
->table('shifts_old')
->get();
$now = Carbon::now()->getTimestamp();
foreach ($records as $record) {
$createdAt = $record->created_at ? Carbon::make($record->created_at)->getTimestamp() : $now;
$updatedAt = $record->updated_at ? Carbon::make($record->updated_at)->getTimestamp() : $createdAt;
$connection->table('Shifts')->insert([
'SID' => $record->id,
'title' => $record->title,
'shifttype_id' => $record->shift_type_id,
'description' => $record->description ?: null,
'start' => Carbon::make($record->start)->getTimestamp(),
'end' => Carbon::make($record->end)->getTimestamp(),
'RID' => $record->room_id,
'URL' => $record->url ?: null,
'created_by_user_id' => $record->created_by,
'created_at_timestamp' => $createdAt,
'edited_by_user_id' => $record->updated_by,
'edited_at_timestamp' => $updatedAt,
'transaction_id' => $record->transaction_id,
]);
}
$this->changeReferences(
'shifts_old',
'id',
'Shifts',
'SID'
);
$this->schema->drop('shifts_old');
}
}

View File

@ -1,114 +0,0 @@
<?php
declare(strict_types=1);
namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration;
use Illuminate\Database\Schema\Blueprint;
use stdClass;
class CreateShiftEntriesTable extends Migration
{
use ChangesReferences;
use Reference;
/**
* Creates the new table, copies the data and drops the old one
*/
public function up(): void
{
$connection = $this->schema->getConnection();
$previous = $this->schema->hasTable('ShiftEntry');
$this->schema->create('shift_entries', function (Blueprint $table): void {
$table->increments('id');
$this->references($table, 'shifts');
$this->references($table, 'angel_types');
$this->referencesUser($table);
$table->mediumText('user_comment')->default('');
$table->boolean('freeloaded')->default(false)->index();
$table->mediumText('freeloaded_comment')->default('');
$table->index(['angel_type_id', 'shift_id']);
});
if (!$previous) {
return;
}
/** @var stdClass[] $records */
$records = $connection
->table('ShiftEntry')
->get();
foreach ($records as $record) {
$connection->table('shift_entries')->insert([
'id' => $record->id,
'shift_id' => $record->SID,
'angel_type_id' => $record->TID,
'user_id' => $record->UID,
'user_comment' => $record->Comment,
'freeloaded' => (bool) $record->freeloaded,
'freeloaded_comment' => $record->freeload_comment,
]);
}
$this->changeReferences(
'ShiftEntry',
'id',
'shift_entries',
'id'
);
$this->schema->drop('ShiftEntry');
}
/**
* Recreates the previous table, copies the data and drops the new one
*/
public function down(): void
{
$connection = $this->schema->getConnection();
$this->schema->create('ShiftEntry', function (Blueprint $table): void {
$table->increments('id');
$this->references($table, 'shifts', 'SID')->default(0);
$this->references($table, 'angel_types', 'TID')->default(0);
$this->references($table, 'users', 'UID')->default(0);
$table->mediumText('Comment')->nullable();
$table->mediumText('freeload_comment')->nullable()->default(null);
$table->boolean('freeloaded')->index();
$table->index(['SID', 'TID']);
});
/** @var stdClass[] $records */
$records = $connection
->table('shift_entries')
->get();
foreach ($records as $record) {
$connection->table('ShiftEntry')->insert([
'id' => $record->id,
'SID' => $record->shift_id,
'TID' => $record->angel_type_id,
'UID' => $record->user_id,
'Comment' => $record->user_comment,
'freeloaded' => (bool) $record->freeloaded,
'freeload_comment' => $record->freeloaded_comment,
]);
}
$this->changeReferences(
'shift_entries',
'id',
'ShiftEntry',
'id'
);
$this->schema->drop('shift_entries');
}
}

Some files were not shown because too many files have changed in this diff Show More