Compare commits

..

539 Commits

Author SHA1 Message Date
Xu 3fb5120142 phpstan ignore config.php 2024-05-26 17:34:04 +02:00
Xu 833af4c62e add edit and back macros to twig 2024-05-26 17:34:04 +02:00
Xu b380d7e68e m.button with opt 2024-05-26 17:34:04 +02:00
Xu 6f8dad070c load day config from env, fixed multiple texts 2024-05-26 17:34:04 +02:00
Xu 40bd61fd32 Angeltype view: Add requires info for not members 2024-05-26 13:07:39 +02:00
Xu 300786e5d0 shift colors when signup_requires_arrival and not arrived 2024-05-26 12:55:10 +02:00
Xu 13ded8de49 supporters can view users_myshifts 2024-05-26 12:27:04 +02:00
Xu c82e3183d6 fix shifttypes permission 2024-05-21 19:22:00 +02:00
Xu f1f5cd7c01 Add users.arrive.list permission & refactored LegacyMiddleware test 2024-05-07 00:25:59 +02:00
Xu b2951b7337 refactor permissions and groups 2024-05-07 00:25:59 +02:00
Xu 4e2e929c7e fix schedule logs 2024-05-04 17:51:48 +02:00
Xu 4a0f5c2e78 throw error on goodie page if no goodie 2024-05-04 17:51:48 +02:00
Xu 0fb09280b3 angeltype view member dect to link 2024-05-04 17:51:48 +02:00
Xu 3972998ba0 rename has_permission_to(_any) to can(Any) 2024-05-04 13:43:27 +02:00
Igor Scheller e514685444 Use settings page for API key resets 2024-05-04 13:43:27 +02:00
Igor Scheller 87f7a74f27 Implement canAny handling for controllers 2024-05-04 13:43:27 +02:00
Igor Scheller a214e0ff8f Auth: Added canAny 2024-05-04 13:43:27 +02:00
Xu d18e203560 docker dev setup on localhost 2024-04-27 00:15:07 +02:00
Xu 0f2c7c5394 refactor shirt to goodie 2024-04-27 00:12:23 +02:00
Xu 3fd8267f12 rename goody into goodie 2024-04-23 00:21:08 +02:00
Xu d0388e8344 fix colors of shifts for admins 2024-04-17 23:09:14 +02:00
Igor Scheller 8f6bd547d3 Move shifts event handler to right location 2024-04-14 21:13:40 +02:00
Igor Scheller f397d809de Extract controller delete blocks to methods 2024-04-14 21:13:40 +02:00
Igor Scheller dd096b0f46 Move Shifts helper methods to Shift model 2024-04-14 21:13:40 +02:00
Igor Scheller cb82ad9c74 Updated config parser to use consistent formatting 2024-04-14 21:13:40 +02:00
Daniel Poelzleithner 0155a33beb Add external_register_url to link to external registration site, hide password form if enable_password is false
Our users have problems with the disabled register button and
keep creating tickets. Add option to link to external site instead
of a disabled button.

People get confused by the login form if they should only
use the oauth login.
Now the login form is hidden if enable_password is false.
It can be shown by clicking the welcome text, in case an
admin needs access
2024-04-10 21:49:55 +02:00
Igor Scheller ab967c6f9c docker dev: Add config for phpMyAdmin, cleanup 2024-04-10 21:24:50 +02:00
Igor Scheller 87b50507f3 Fixed linter warnings 2024-04-10 21:24:50 +02:00
Igor Scheller 905d91d6ed Added/updated comments 2024-04-10 21:24:50 +02:00
Xu 9bf9bd2823 add 'enable_email_goody' config and fix wording 2024-04-07 22:05:33 +02:00
Xu d7d99900f8 Use icons in user edit view 2024-04-07 21:52:14 +02:00
Xu 7e06923ed0 Add user.fa.edit permission 2024-04-07 21:52:14 +02:00
Xu e6251256b3 fix certificates button on AngelTypes_view, add id to location change log 2024-04-07 21:27:03 +02:00
Xu 6e76843db4 add ifsg and drive confirmed stats to metrics 2024-04-07 21:27:03 +02:00
Igor Scheller fcf23d3824 Active angels page: Fix fa angels sorting 2024-03-29 14:31:59 +01:00
Igor Scheller c82e902360 CI: Remove base path from unittest results 2024-03-24 18:01:12 +01:00
Igor Scheller fc9b4d6da4 Fix worklog edit user & rename user on profile page 2024-03-24 18:01:12 +01:00
Igor Scheller 63c70c0ec2 Fixed notification translations & show larger map in locations 2024-03-24 18:01:12 +01:00
Igor Scheller 087d1cf31e Show password reset count and fix query 2024-03-24 18:01:12 +01:00
Igor Scheller f9059161ec Fix oauth name autofill for registration 2024-03-24 18:01:12 +01:00
Xu 541789ae27 add shifts column to Location index view 2024-03-24 16:06:21 +01:00
Xu 865ffe5e5a rename "Shifts" translation 2024-03-24 16:06:21 +01:00
Xu 49cc935ceb driving license: can be confirmed and edited by admins and config options 2024-03-24 14:34:54 +01:00
Igor Scheller 9639a0fe3f Fix coverage warning 2024-03-19 20:33:14 +01:00
Igor Scheller 8c24b78333 Shift deletion: Simplify notification workflow 2024-03-19 20:28:02 +01:00
Igor Scheller 1217de096a Fix disabled choices select color on dark theme 2024-03-16 17:36:34 +01:00
Igor Scheller ba908bf849 Fix translations when removing users from angeltype 2024-03-16 17:36:34 +01:00
Igor Scheller 0642bff804 Fix group rights edit buttons 2024-03-16 17:36:34 +01:00
Igor Scheller aea88b3579 Move footer to page bottom 2024-03-16 17:36:34 +01:00
Igor Scheller 460b416ff1 Shifts view: Highlight current time 2024-03-16 17:36:34 +01:00
Igor Scheller 8dda9a0dc3 Fix night shift calculation & update times 2024-03-16 17:36:34 +01:00
Igor Scheller 4ad8385386 isNightShift: Sync with sql query 2024-03-16 17:36:34 +01:00
Igor Scheller f56e9c534c Add title to "Enough" goodie score 2024-03-16 17:36:34 +01:00
Xu c0088d6601 add hints to myshifts table 2024-03-16 16:31:27 +01:00
Xu f3a12ebda8 explain freeloads for users and shicos 2024-03-16 16:31:27 +01:00
Xu 100d62134f fix table on admin_active length and score 2024-03-10 19:29:58 +01:00
Xu 873803eb2d ifsg: can be confirmed and edited by admins 2024-03-10 19:08:05 +01:00
Jens Brandt 400edd9a19 Fix typo in english language file 2024-03-09 09:59:53 +01:00
Xu a94aa36fa4 Password reset in User state 2024-02-27 16:00:58 +01:00
Xu 9a07a7afb3 add other contact options to questions page 2024-02-27 16:00:58 +01:00
Xu ef3f58e999 differentiate Answer questions page 2024-02-27 16:00:58 +01:00
Xu e18cddae86 success join angeltype button 2024-02-27 16:00:58 +01:00
Xu 5b8b59008a number of mails send when news saved 2024-02-19 20:25:25 +01:00
Xu ec7fb0615c add target="_blank" to links 2024-02-19 20:25:25 +01:00
Xu 759a4f9a14 add night shift multiplier to translations
more night shift hints
2024-02-18 14:14:34 +01:00
Igor Scheller d8f8a4f67d Schedule: Update to parse newer specification 2024-02-17 19:34:03 +01:00
Igor Scheller b63eb44b39 Schedule: Simplify & cleanup data classes 2024-02-17 19:34:03 +01:00
Igor Scheller e3e0fb33a2 Added tests for schedule import 2024-02-17 19:34:03 +01:00
Igor Scheller 790a04dc14 Schedule Import: Moved file, initial cleanup, updated schedules 2024-02-17 19:34:03 +01:00
Igor Scheller aef53a306b Fix formatting 2024-02-17 17:20:43 +01:00
Igor Scheller 4fa5db8a42 Use confirmation dialog and redirect back when deleting shifts 2024-02-17 17:02:09 +01:00
Igor Scheller b10264d6ef Fix random shifts test 2024-02-17 16:45:30 +01:00
Igor Scheller ff1edaad10 Added rough system requirements to readme 2024-02-17 16:45:30 +01:00
Lotte Steenbrink 5e505cb8d2
note that shift length is in minutes 2024-02-17 16:32:18 +01:00
Xu cf570502f4 make force active a config option 2024-01-29 19:54:15 +01:00
Xu e7ff3b657a supporters can freeload 2024-01-29 19:54:15 +01:00
Xu 7e26e20608 User view pronoun after name 2024-01-29 19:54:15 +01:00
Xu 67b24032a0 add shift no signout hint and disable buttons 2024-01-29 19:54:15 +01:00
Xu 76c37a5f18 config options supporters can promote 2024-01-29 19:54:15 +01:00
weeman 496d75b9ef Autofocus confirm modal submit button
So that it can be confirmed with enter
2024-01-29 14:39:09 +01:00
weeman c03ccf94c7 Add console log to design submit modal 2024-01-29 14:39:09 +01:00
weeman e47da9b8dd
Fix linter setup 2024-01-29 11:20:39 +01:00
Xu 0476083e77 add needed angels from to shift view 2024-01-28 21:11:55 +01:00
xuwhite 89d8a070d9
add hint admin_shifts no location, shift type or angeltype (#1337) 2024-01-28 20:57:59 +01:00
Lotte Steenbrink f387bc655d active_angels.php, default.po: fix typo 2024-01-27 17:01:35 +01:00
Xu 276b1aa976 add shirt sizes information hint and optional link 2024-01-27 16:37:13 +01:00
Lotte Steenbrink 50b1abe0d1 README: make it clearer that you have to run `migrate` on fresh installs too 2024-01-16 14:33:33 +01:00
Xu b20124e57e error admin_user.php nick or email already exits 2024-01-13 17:20:58 +01:00
Igor Scheller 4d1502d092 CI: Remove api key on db dump 2024-01-10 15:04:49 +01:00
Igor Scheller 00f039dbaa CI: Use tag as release version, fix delete 2024-01-10 12:58:06 +01:00
Igor Scheller dbbf30e233 Replace empty or too short api keys instead of resetting them 2024-01-08 10:57:09 +01:00
Igor Scheller 3f03d6b1d8 API: Set access-control-allow-origin header on api responses, trim bearer api key 2024-01-08 10:57:09 +01:00
Igor Scheller 8c64447273 API: Show from schedule via shift type, added comments 2024-01-08 10:57:09 +01:00
Igor Scheller 3432829c91 API: Document x-api-key header auth 2024-01-08 10:57:09 +01:00
Igor Scheller 6e4c9b2405 API: Added event time 2024-01-08 10:57:09 +01:00
Xu 7637e0c66e refactor user info icon 2024-01-03 19:43:58 +01:00
Xu 8cff7aa205 add user_info to admin_active 2024-01-03 19:43:58 +01:00
Xu 0239bf1988 goodie score visible with admin_user permission 2023-12-29 23:31:21 +01:00
Xu 1798ccda83 add shifttypes and angeltypes count to metrics 2023-12-29 17:50:54 +01:00
Xu 7d5837c5f1 fix needed angeltypes in shifttypes and locations, search for more user related data in log 2023-12-29 17:44:36 +01:00
msquare 8603d47fe0 fix random shift button, again, again 2023-12-29 16:05:39 +01:00
Xu 4a0c0994f0 fix errors when tshirt-size required 2023-12-29 16:02:19 +01:00
Xu ffa531f311 disable shirt size edit for user in settings if got shirt 2023-12-29 13:52:00 +01:00
xuwhite 89d68a56e7
Add needed angel types to location & shift type and permission to edit shift types (#1316) 2023-12-29 13:40:01 +01:00
Xu 9dac2a53db set arrive in user edit view 2023-12-29 13:08:19 +01:00
Igor Scheller 33209ea70b Remove unused functions and methods 2023-12-29 13:06:53 +01:00
Igor Scheller 05725cd58c Eager load relations and optimize queries 2023-12-29 13:06:53 +01:00
Igor Scheller 5fccc7e421 Remove inline js 2023-12-29 13:06:53 +01:00
Igor Scheller b76144b23d Remove unused reference references 2023-12-29 13:06:53 +01:00
Xu 2883a66f49 add user info to metrics 2023-12-28 18:15:52 +01:00
weeman d6412605f2 Add 37c3 theme 2023-12-28 17:56:50 +01:00
Xu 57373c846a Metrics: Added not arrived users 2023-12-28 17:17:26 +01:00
Igor Scheller 1d3509ba3c Fix error messages 2023-12-28 12:48:00 +01:00
Igor Scheller 57862ba722 random shift: check for schedule load flag 2023-12-28 01:08:57 +01:00
Igor Scheller b229d697a3 Only send notifications on new news by default 2023-12-27 18:16:32 +01:00
Igor Scheller 3c0cbe55b6 Cleanup the Fix 2023-12-27 18:16:32 +01:00
Igor Scheller 8140ebd1cc Added edit link on shift type page 2023-12-27 18:16:32 +01:00
Igor Scheller b62d4b4dce Improve history by showing more information, fix users list 2023-12-27 18:16:32 +01:00
Igor Scheller d803591a91 Shifts creation: Simplify log message, fix "room angels" validation 2023-12-27 18:16:32 +01:00
Igor Scheller 6d4f059b3a Fix join angeltype message 2023-12-27 18:16:32 +01:00
Igor Scheller f3e1192695 Worklog: log deletion, User page: fix voucher calculation 2023-12-27 18:16:32 +01:00
Igor Scheller 8833506e04 Cleanup template styles 2023-12-27 18:16:32 +01:00
Igor Scheller cc160e3e20 Error page: Add translation 2023-12-27 18:16:32 +01:00
Igor Scheller bcfcb95786 Use type_bg_class() macro in templates 2023-12-27 18:16:32 +01:00
Igor Scheller f7b0ee9ebb Fix random test 2023-12-27 17:46:13 +01:00
Igor Scheller 0f794be25e Update composer packages 2023-12-27 16:57:58 +01:00
Igor Scheller c5ae5d4aa0 Formatting 2023-12-27 16:43:55 +01:00
Leandra Eberle 64fef42087
Merge pull request #1306 from xuwhite/fixes
small bug fixes
2023-12-27 13:26:10 +01:00
msquare ea9aa9ef40 fixes 2023-12-27 12:50:03 +01:00
Igor Scheller caa699ff05 Added room selection for schedules 2023-12-27 12:50:03 +01:00
Xu 99dd081651 small bug fixes 2023-12-27 12:42:47 +01:00
Igor Scheller 197d0d724a Shifts creation: Add reset to previous input 2023-12-26 20:47:05 +01:00
Igor Scheller 7888dfad78 Send notifications on news updates, make notifications optional 2023-12-26 20:36:02 +01:00
Igor Scheller 4429516a22 Added shift update event to send templated emails 2023-12-26 16:32:02 +01:00
Igor Scheller 4bbeb93d64 Implemented loading angels by shift type on schedule import 2023-12-26 16:32:02 +01:00
Igor Scheller 909f7bba5a Fix formatting... 2023-12-26 16:32:02 +01:00
Igor Scheller 2baa101a8f Random shit: Fix selection to exclude parallel shifts 2023-12-26 12:54:21 +01:00
Igor Scheller a3a36de985 Fixed formatting 2023-12-25 13:38:44 +01:00
Igor Scheller 4244acfb4d Header/Footer items config: Add configurable permissions 2023-12-25 13:32:49 +01:00
Xu 4fa99b8a04 Show "not marked as arrived" Notification only from set arrival date 2023-12-24 18:15:31 +01:00
Igor Scheller 14dbe7f5d9 Added random shift button to shifts view 2023-12-23 11:17:50 +01:00
Igor Scheller dc7c62ffe5 API: Added event / api info endpoint, simplified spec 2023-12-22 15:14:01 +01:00
Igor Scheller da8178b0bc API: Allow usage of self in user routes 2023-12-22 15:14:01 +01:00
Igor Scheller 02f998fc38 API: Added user info and shifts by user and angeltype, simplified neededAngelTypes 2023-12-22 15:14:01 +01:00
Igor Scheller 4de882ef85 API: Add API settings page 2023-12-22 15:14:01 +01:00
Igor Scheller fe836e281e API: Add openapi endpoint to view specification 2023-12-22 15:14:01 +01:00
Igor Scheller 8894f183f2 API: Use resource classes to serialize models 2023-12-22 15:14:01 +01:00
Igor Scheller 5b237febf8 API: Add /users/{id}/angeltypes, updated openapi formatting 2023-12-22 15:14:01 +01:00
Igor Scheller 497c1772f7 API: Rename rooms to locations and start/end to starts_at/ends_at 2023-12-22 15:14:01 +01:00
Igor Scheller 2e38b55167 API: Added API value tests 2023-12-22 15:14:01 +01:00
Igor Scheller 1a250dc250 API: Update index response codes and api descriptions 2023-12-22 15:14:01 +01:00
Igor Scheller ef3bd7c319 API: Show needed/added users by angeltype in shifts 2023-12-22 15:14:01 +01:00
Igor Scheller ea93e27a9d API: Add urls to response, configure required fields 2023-12-22 15:14:01 +01:00
Igor Scheller a5cebc8535 API: Add /angeltypes, /rooms, /rooms/{id}/shifts 2023-12-22 15:14:01 +01:00
Igor Scheller 72649c9522 API: Load api info from yaml 2023-12-22 15:14:01 +01:00
Igor Scheller b5d94971bc API: Split to multiple controllers, removed / from routes 2023-12-22 15:14:01 +01:00
Igor Scheller ca0a69b17d API: Wrapped lists in data objects, specified datetime format 2023-12-22 15:14:01 +01:00
Igor Scheller 1505d0229d API: Documented additional endpoints in OpenAPI 2023-12-22 15:14:01 +01:00
Igor Scheller e2e18db460 API: Moved json handling and route-api tagging to ApiRouteHandler 2023-12-22 15:14:01 +01:00
Igor Scheller 8adad075bf API: Init with news endpoint (ro) 2023-12-22 15:14:01 +01:00
Igor Scheller f826cee63c Move api key reset to authenticator, set api_key on registration 2023-12-22 15:14:01 +01:00
Igor Scheller 0dbf88ad1c Cleanup short api keys 2023-12-22 15:14:01 +01:00
Igor Scheller 8185a74edc Added user id to logs, implemented filter by user 2023-12-22 11:17:07 +01:00
Xu 162116998c edit user nick needs buerocrat 2023-12-21 14:01:40 +01:00
xuwhite ac73489aed
Icons (#1279)
* add icons to design page
* make icons more consistent
2023-12-21 13:08:29 +01:00
Xu f4c3f7a39e highlight freeloaded shifts in user myshifts view 2023-12-21 11:35:40 +01:00
Igor Scheller 23de3579af Set cookie secure attribute matching request 2023-12-15 11:13:30 +01:00
Igor Scheller ba4ba8f2f8 Lint & fix translations 2023-12-15 11:13:30 +01:00
Igor Scheller 8b1cd8130e Fix & cleanup page titles 2023-12-15 11:13:30 +01:00
xuwhite 48ea35562e
show user-info icon with admin_arrive permission 2023-12-14 22:15:17 +01:00
Xu a35a3580e0 highlight actual time in users shifts list 2023-12-14 22:09:28 +01:00
Igor Scheller 15a6ba1c52 Implemented schedule deletion 2023-12-13 22:18:20 +01:00
Xu d89fe01ddd shirt edit in edit user requires bureaucrat 2023-12-07 20:26:33 +01:00
Xu f292ce5331 Edit Shirt requires bureaucrat permission 2023-12-07 20:26:33 +01:00
Xu 269541293c password minimal length hint 2023-12-07 13:15:29 +01:00
Xu 545d2a7ccf fix email formatting 2023-12-07 12:59:56 +01:00
Xu dfd72d2d69 fix footer translations 2023-12-07 12:59:56 +01:00
Igor Scheller f2edb1a45c Merge tag 'v3.4.1' 2023-12-06 19:08:38 +01:00
Igor Scheller efda1ffc1c Escape text outputs in includes 2023-12-06 18:18:05 +01:00
dependabot[bot] b8095492ec Updated build dependencies 2023-12-06 14:51:20 +01:00
Igor Scheller 4e6ba3d684 Fix password reset e-mail wording in de translation 2023-12-01 12:03:10 +01:00
Igor Scheller 1b91d84b5f Added error page translations 2023-11-24 17:10:10 +01:00
Xu 47ad0a6133 fix translation keys in twig templates 2023-11-24 17:10:10 +01:00
Xu fec2f17bea fix date translations 2023-11-24 17:10:10 +01:00
xuwhite fd56966435
add user angeltype info in shift entries (#1262) 2023-11-24 15:11:36 +01:00
Xu d8310ed6e7 minor improvements on angeltypes 2023-11-24 14:44:55 +01:00
Xu 3ffb0a38e8 add user-info hint 2023-11-19 20:51:04 +01:00
Xu e9b8977728 add user info to user view 2023-11-19 20:51:04 +01:00
Igor Scheller 9acd06cb04 Feed export: Convert to string/int, updated docs 2023-11-19 19:04:13 +01:00
Igor Scheller b17dbf46e0 Route resolving: Show better error message when method is not callable 2023-11-19 19:04:13 +01:00
Igor Scheller 7f2f5ab7ed Templates: Update spacing handling 2023-11-19 19:04:13 +01:00
Igor Scheller 58c457be86 Fix choices dropdown search order and z-index to show on top of shifts table 2023-11-19 19:04:13 +01:00
Igor Scheller 36c7db40a7 Test all factories 2023-11-19 19:04:13 +01:00
Igor Scheller 0b165bc24c Recreated shift type admin backend 2023-11-19 18:55:06 +01:00
Igor Scheller bf83e6a300 Recreated shifts history page 2023-11-19 18:32:47 +01:00
Igor Scheller ac74ab489d Migration: Fix worklog times and schedule shift type 2023-11-19 18:18:26 +01:00
Igor Scheller f3347ba140 Migration: Trim api key length before down migration 2023-11-19 18:18:26 +01:00
Igor Scheller 39dbfabea7 Enabled foreign keys in sqlite tests, added missing fields to factories 2023-11-19 18:18:26 +01:00
Igor Scheller 0a0cf5265c Cleanup migrations: removed old install files 2023-11-19 18:18:26 +01:00
Igor Scheller 176a0b65c5 Decouple setting admin password from auth provider 2023-11-19 18:18:26 +01:00
Xu 7fda1fc14b unify T-shirt wording 2023-11-19 13:09:49 +01:00
Xu 66738298a9 clarify hint for nightshifts, simplify username regex, add missing translation
fix untranslated string
2023-11-19 13:09:49 +01:00
Xu 5d14109dbd unify e-mail wording 2023-11-19 13:09:49 +01:00
Xu 44efd910c6 Add day of event to date dropdowns, move task notice 2023-11-18 21:04:50 +01:00
Igor Scheller ecc3976c27 Show specific error message titles 2023-11-13 18:28:27 +01:00
Xu 93270a10fd Added more confirmation dialogs to delete forms 2023-11-13 18:28:27 +01:00
Igor Scheller ff179360cc Added confirmation dialog to delete forms 2023-11-13 18:28:27 +01:00
Igor Scheller 1b21bcf769 Added bootstrap modals 2023-11-13 18:28:27 +01:00
Xu b6bd3eba56 Replace page_link_to() with url() 2023-11-13 17:37:52 +01:00
Xu 6477e5dabd refactor driving license into the user certificate settings 2023-11-13 16:36:07 +01:00
Xu 24f91ce9b5 disable needed angels input if shift is imported 2023-11-13 01:09:31 +01:00
Xu 6022d792dc add hints for required profile settings 2023-11-12 18:46:19 +01:00
Igor Scheller 9e3adf6179 Rename user sign up to registration 2023-11-12 18:35:50 +01:00
Xu 6564056f16 Sign-up page wording fixed 2023-11-12 18:35:50 +01:00
Xu 343ce8241c wording on user page 2023-11-12 18:35:50 +01:00
Igor Scheller 7f6e1ff18e Rename rooms to locations 2023-11-06 20:39:01 +01:00
Igor Scheller a31534d9b7 Shifts feed: Added URL to shift and shifttype name & description 2023-11-03 18:45:30 +01:00
Xu 24204b1f3c add more buttons 2023-11-03 16:23:39 +01:00
xuwhite 27323bfba5
make required fields configurable 2023-11-03 15:15:44 +01:00
Xu 1397fe90ce creation of new entity's from overview pages (+ sign) 2023-11-03 13:32:39 +01:00
Xu 89321306bc back buttons on edit and deletion pages 2023-11-03 12:29:17 +01:00
Xu 185b7e3fb6 rename shirt size keys G to F 2023-11-03 12:09:17 +01:00
Igor Scheller 9ffe739b24 Fixed erroneous translation replacements 2023-10-20 23:31:14 +02:00
Xu 9fb6bd4d10 clear way more translations 2023-10-20 21:38:34 +02:00
Xu fe37258b35 clear even more translations 2023-10-20 21:38:34 +02:00
Xu 6195692d3d cleaning more translations 2023-10-20 21:38:34 +02:00
dependabot[bot] fc58d55274 Bump @babel/traverse from 7.20.13 to 7.23.2
Bumps [@babel/traverse](https://github.com/babel/babel/tree/HEAD/packages/babel-traverse) from 7.20.13 to 7.23.2.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.23.2/packages/babel-traverse)

---
updated-dependencies:
- dependency-name: "@babel/traverse"
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-19 17:44:51 +02:00
Igor Scheller 9fcee133eb Updated email_goody opt in text 2023-10-15 23:14:22 +02:00
Xu fed27210eb removing pt translation 2023-10-15 23:04:01 +02:00
Xu aeea3067b0 cleaning translations 2023-10-15 21:30:26 +02:00
Igor Scheller 38838352e2 Handle email send errors in Mailer class 2023-10-15 18:45:37 +02:00
Igor Scheller d251b4c7f7 Shifts: Fix sign up text when self sign up is disallowed 2023-10-15 18:44:11 +02:00
Igor Scheller 7dbc0481b9 Fix form buttons in btn-group 2023-10-15 18:37:27 +02:00
Igor Scheller 0aa4cdd2b0 Tests: Fix flaky NewsController tests 2023-10-15 18:21:41 +02:00
Igor Scheller 1d5f16a59e Tests: Fix flaky freeloader test 2023-10-15 18:21:41 +02:00
Igor Scheller fddae62669 Tests: Fix string length validation tests 2023-10-15 18:21:41 +02:00
Igor Scheller 599fff26d4 Tests: Fix --repeat in EventDispatcherTest 2023-10-15 18:21:41 +02:00
Igor Scheller cd8c01c080 Speedup password tests 2023-10-15 18:21:41 +02:00
Igor Scheller a70bc6ded8 Upgrade composer packages 2023-10-15 18:13:43 +02:00
Igor Scheller 7ce2cca052 Update composer packages 2023-10-15 18:13:43 +02:00
Igor Scheller cf4dc63495 Profile settings page: Add "back to my shifts" menu item and icons 2023-10-15 18:10:12 +02:00
Igor Scheller dc9441d925 SettingsControllerTest: Fix assertion order 2023-10-15 18:10:12 +02:00
Igor Scheller 8438b8dc51 Legacy logger: be less noisy on cli (no double logging and oneliners) 2023-10-15 18:10:12 +02:00
xuwhite 00f4afa2ab
rename rooms to locations (#1226) 2023-10-13 11:53:13 +02:00
Tobias Fiebig 9f113958ca
Update SECURITY.md
Included statement on the use of external reporting services / bug bounty services.
2023-10-13 10:16:17 +02:00
dependabot[bot] b3dd2b1d47 Bump postcss from 8.4.21 to 8.4.31
Bumps [postcss](https://github.com/postcss/postcss) from 8.4.21 to 8.4.31.
- [Release notes](https://github.com/postcss/postcss/releases)
- [Changelog](https://github.com/postcss/postcss/blob/main/CHANGELOG.md)
- [Commits](https://github.com/postcss/postcss/compare/8.4.21...8.4.31)

---
updated-dependencies:
- dependency-name: postcss
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-08 12:48:02 +02:00
xuwhite adf00b2739
add hide angeltype in shift view option for angeltypes (#1195) 2023-09-27 20:25:10 +02:00
xuwhite 8ebaffd71a
rename is_important to is_highlighted (#1215) 2023-09-27 18:15:12 +02:00
Xu 383f8ebde5 refactor no self signup to shift self signup 2023-09-26 18:02:23 +02:00
Igor Scheller 4cd7103121 Fix users page link 2023-09-24 22:50:44 +02:00
weeman 4267a76adb Redirect to sign-up if already logged in 2023-09-24 22:50:44 +02:00
msquare a2a57ec852 prefill fields from oauth 2023-09-24 22:50:44 +02:00
Igor Scheller 29a4b244dc Fixed some smaller error messages due to null values 2023-09-24 22:50:44 +02:00
Michael Weimann 4329ee4af9 Implement new sign up page 2023-09-24 22:50:44 +02:00
Tim Neumann c2dd25fc7c
Allow admins to remove entries from some config arrays (#1155)
This is done by setting the respective value to null
2023-09-24 21:42:44 +02:00
xuwhite 3b241529b7
Add event name and day of event to mail footer (#1214) 2023-09-24 15:10:10 +02:00
Igor Scheller 40b93e3d8b Sessions: Only show part of the session ID 2023-09-18 19:00:51 +02:00
Igor Scheller c06cb767da Delete all other sessions after setting a new password 2023-09-18 18:10:40 +02:00
Igor Scheller dbb089315f Delete all sessions on password reset 2023-09-18 18:10:40 +02:00
Igor Scheller 5c59fec1cf Add page to view and delete user sessions 2023-09-18 18:10:40 +02:00
Igor Scheller 102c8428c8 Save user id in Session model 2023-09-18 18:10:40 +02:00
Igor Scheller 67d5950926 Add Session model 2023-09-18 18:10:40 +02:00
Igor Scheller ee7d30b339 Schedule import: Show error message on schedule parsing errors 2023-09-18 17:27:15 +02:00
msquare 87bd4f4fa1
Create SECURITY.md 2023-09-12 12:39:38 +02:00
Igor Scheller 9a9ffcfdaf Hide arrival hint if signup does not require arrival 2023-09-02 18:26:14 +02:00
Xu f3ec62e121 update models with defaults 2023-08-30 20:25:13 +02:00
Xu 1ca9b99612 added tests for config ifsg_light_enabled 2023-08-30 20:04:32 +02:00
Xu 6b273288bd add config option for ifsg_light 2023-08-30 20:04:32 +02:00
Igor Scheller d1d0acf622 Fixed styling 2023-08-30 17:32:00 +02:00
Igor Scheller 68dd73e333 Shifts creation: Fix start/end date value after going back 2023-08-30 17:21:03 +02:00
Igor Scheller 94ba51bc46 Shifts creation: Fix start hours before 10:00 2023-08-30 17:21:03 +02:00
Igor Scheller 24ecea0d65 Shifts: Fix day marker on start of day 2023-08-29 20:11:37 +02:00
Igor Scheller 5e702cd177 News creation: Show error on duplicates 2023-08-29 20:11:37 +02:00
Igor Scheller f966b1521f Arrive search: Ignore datetime 2023-08-29 20:11:37 +02:00
Igor Scheller 2252819800 Shifts preview: added end year on hover and hours 2023-08-29 20:11:37 +02:00
Igor Scheller 931f3ba10d Sort shift types by name 2023-08-29 20:11:37 +02:00
Igor Scheller a60c5987ab Worklog: create log entry on successfull creation 2023-08-29 20:11:37 +02:00
Igor Scheller 80bec733bd Add table for ifsg to angeltype 2023-08-29 20:11:37 +02:00
msquare c63a671dc4 goodie manager needs to see shifts and worklogs from users 2023-08-18 16:42:16 +02:00
Igor Scheller 009b0f3f27 Fixed tests 2023-08-18 15:18:45 +02:00
Michael Weimann f4030b86af Add day of event in footer and on dashboard 2023-08-18 14:46:19 +02:00
Igor Scheller e0b552d18b Show angel name in tshirt view
resolves #1186
2023-08-17 20:13:46 +02:00
Jan-Philipp Litza 74989df119 Fix msgfmt error: keyword "settings" unknown 2023-08-17 15:22:00 +02:00
Xu b5803caf44 fix work log suggestion during the event 2023-08-16 20:54:35 +02:00
Michael Weimann e03f2936e7 Make news footer responsive 2023-08-15 22:06:34 +02:00
msquare 6c3bb7521f fixes #1181: fix misleading back link in admin edit worklog 2023-08-14 16:49:17 +02:00
Michael Weimann 85bc95fea9
Fix code style 2023-08-14 16:38:44 +02:00
msquare 0a3a3c3b56 make tests happy again 2023-08-14 16:30:14 +02:00
msquare df4f744f6d fixes #1180: meeting/news pagination 2023-08-14 16:02:11 +02:00
msquare e11b0db526 fixes #1157: secure cookies???ßßß 2023-08-14 11:11:27 +02:00
msquare 7f41d5eb1e fixes #1179: stop choices.js from escaping choices 2023-08-14 10:52:02 +02:00
hexchen 4a907600b7 Improve translation on admin_user page 2023-08-14 00:02:44 +02:00
msquare 47f0587cd9 fixes #1169: improve shift change hour sanitation 2023-08-13 16:52:41 +02:00
msquare cffc9854f8 fixes #1173: removes double escapes form input twig macro 2023-08-13 15:56:35 +02:00
msquare af2ac1bc3e fixes #1175: time lane scrolling out of screen 2023-08-13 15:31:51 +02:00
Igor Scheller 49300900d6 News: Catch all throwable exceptions 2023-08-13 13:47:37 +02:00
Michael Weimann 86da8758a4 Fix camp23 input group 2023-08-12 20:06:42 +02:00
msquare 3ae8424aea so much space... 2023-08-12 13:09:09 +02:00
msquare 98d2316b08 further improvements on hint link colors 2023-08-12 12:57:07 +02:00
msquare 6622680baf add ifsg tests 2023-08-12 12:19:24 +02:00
Xu 21423ef305 renaming ifsg 2023-08-12 12:19:24 +02:00
msquare c93c241dc9 make info+danger hint links readable again 2023-08-12 12:19:24 +02:00
Xu 4378fa2d7d fix tests after ifsg implementation 2023-08-12 12:19:24 +02:00
Xu 8dd4af1bb6 add requires ifsg certificate 2023-08-12 12:19:24 +02:00
Xu f345942e46 add ifsg certificates 2023-08-12 12:19:24 +02:00
Michael Weimann da2baa75bb Fix pre-code blocks 2023-08-03 19:37:36 +02:00
Michael Weimann 2c702fc67d Increase camp23 contrast 2023-08-03 19:37:36 +02:00
Igor Scheller d9b93e4236 News: Show updated date besides "updated" state 2023-07-30 18:57:49 +02:00
Igor Scheller 1c4c164c39 Fix shift sign up angel button not always displayed 2023-07-30 18:57:49 +02:00
Igor Scheller e407a3b780 OAuth: Fix error when user id is numeric 2023-07-30 18:57:49 +02:00
Igor Scheller 24f958b00d Fix 500 error on angeltypes edit page when logged out 2023-07-30 18:57:49 +02:00
msquare db4c5eec1c improme cccamp23 theme contrast 2023-07-26 20:25:28 +02:00
msquare 0a1c85d6bd cccamp23 theme improvements on badges 2023-07-24 18:49:32 +02:00
msquare c2e6dc5223 cccamp23 theme much prettier 2023-07-18 21:21:25 +02:00
msquare 19a5673231 cccamp23 theme 2023-07-18 21:02:31 +02:00
Michael Weimann 9feed46d4e Add TrimMiddleware to trim all request values 2023-07-10 12:59:02 +02:00
Michael Weimann 8a3c2eaec5 Update NPM dependencies 2023-07-02 23:28:05 +02:00
Igor Scheller fc8d335ea2 Fix ics escaping and IDs 2023-06-05 08:28:07 +02:00
Igor Scheller ab5f6a270c Replace `Please select...` with translation key 2023-06-05 08:28:07 +02:00
Igor Scheller b07f879d64 macros: arguments are mostly defined, cleanup 2023-06-05 08:28:07 +02:00
Igor Scheller 2e26f41964 Profile settings: Fix shiftinfo email text 2023-06-05 08:28:07 +02:00
Igor Scheller fa95bca673 Fixed code spacing 2023-05-19 16:16:46 +02:00
xuwhite 9bd3978257
Fix user sorting on angeltype page (#1144) 2023-05-19 16:09:25 +02:00
Xu 063e9a8ec2 delete all comments in translation files 2023-05-13 18:16:37 +02:00
Michael Weimann c4f65bfbdb Fix spinner button 2023-05-11 18:54:55 +02:00
Michael Weimann c5317e2536 Add ShirtSize validation 2023-05-11 18:48:28 +02:00
Igor Scheller 8bb8837e38 Shifts filter: Only show rooms with shifts 2023-05-03 16:04:39 +02:00
Igor Scheller 983fb988b4 Make profile page layout and shifts renderer less worse for normal users 2023-05-03 16:04:39 +02:00
Igor Scheller 72d48de3ae Add ETag to FeedController 2023-05-03 16:04:39 +02:00
Michael Weimann dc216a0464 Move optional twig form macro attributes to opt 2023-05-01 16:59:26 +02:00
dependabot[bot] c0957955fd Bump nyholm/psr7 from 1.5.1 to 1.6.1
Bumps [nyholm/psr7](https://github.com/Nyholm/psr7) from 1.5.1 to 1.6.1.
- [Release notes](https://github.com/Nyholm/psr7/releases)
- [Changelog](https://github.com/Nyholm/psr7/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Nyholm/psr7/compare/1.5.1...1.6.1)

---
updated-dependencies:
- dependency-name: nyholm/psr7
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-04-26 11:31:37 +02:00
dependabot[bot] 93d3d46be7 Bump guzzlehttp/psr7 from 2.4.3 to 2.5.0
Bumps [guzzlehttp/psr7](https://github.com/guzzle/psr7) from 2.4.3 to 2.5.0.
- [Release notes](https://github.com/guzzle/psr7/releases)
- [Changelog](https://github.com/guzzle/psr7/blob/2.5/CHANGELOG.md)
- [Commits](https://github.com/guzzle/psr7/compare/2.4.3...2.5.0)

---
updated-dependencies:
- dependency-name: guzzlehttp/psr7
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-04-21 15:23:12 +02:00
Thomas Rupprecht 79519aaa07
Update node to v20 (#1075)
* uppercase keywords
* update node to v20
2023-04-21 15:10:26 +02:00
Michael Weimann 3901cdbf2a
Tweak navbar collapse as guest and fix language dropdown position (#1128)
* Fix language switcher position
* Tweak navbar collapse as guest
2023-04-19 21:19:22 +02:00
Igor Scheller 16632706e0 menu: Don't scroll to top when clicking info 2023-04-19 20:11:38 +02:00
Igor Scheller a0c879948d shifts: Add additional filter button on mobile devices 2023-04-19 20:11:38 +02:00
Igor Scheller 683d4a0e62 Config: Load more values from env variables 2023-04-19 20:11:38 +02:00
Igor Scheller e359d93db6 CI: Added build cache 2023-04-19 20:11:38 +02:00
Igor Scheller 24765902a2 Profile edit: Add rows to fix layout 2023-04-19 20:11:38 +02:00
Igor Scheller ca6e0813ba RouteDispatcher: Fixed string conversion 2023-04-19 20:11:38 +02:00
Igor Scheller c85eb2f3d2 Migrations: Fix migration name 2023-04-19 20:11:38 +02:00
Michael Weimann 1292722ac3 Add Username validation 2023-04-17 23:09:08 +02:00
Thomas Rupprecht 57940cf570 fix mailto link of angeltypes in about page 2023-04-16 18:57:36 +02:00
Thomas Rupprecht aafc01b01e fix radius of card on questions page 2023-04-13 15:47:15 +02:00
Igor Scheller 6e8dc642de Catch Exception when sending emails to users 2023-04-08 19:55:54 +02:00
Igor Scheller bf4a818e01 Make session cleanup more robust and tests explicit 2023-04-08 14:14:57 +02:00
Igor Scheller 9f35ebc482 Use app configured session lifetime for garbage collection 2023-04-08 00:34:43 +02:00
Igor Scheller 6da0c8a835 Fixed public dashboard stats and sorting 2023-04-07 23:48:07 +02:00
Thomas Rupprecht 460a449a8b
use angle macro (#1121) 2023-04-03 19:05:35 +02:00
Thomas Rupprecht 84c1cc36e5
Improve javascript (#1077) 2023-04-01 15:14:32 +02:00
Thomas Rupprecht d4104850be
phpstan fixes (partial level 3) (#1091) 2023-04-01 14:39:25 +02:00
Igor Scheller 131c6af6a2 Updated contributing guidelines: Clarified includes 2023-03-31 14:30:51 +02:00
Thomas Rupprecht 3f0a5a5b73 hide language/theme menu if not more than 1 selection is available 2023-03-30 21:55:28 +02:00
Thomas Rupprecht 21d8c27c92 improve profile layout 2023-03-30 17:25:19 +02:00
Thomas Rupprecht 14ff157a12
uppercase DISPLAY_FULL_NAME env var
improve default config #1118
2023-03-30 13:30:41 +02:00
bk-debug ebed5acd5a
Add Room import to shifts controller 2023-03-25 20:54:06 +01:00
dependabot[bot] ad775cc37c
Bump webpack from 5.75.0 to 5.76.0
Bumps [webpack](https://github.com/webpack/webpack) from 5.75.0 to 5.76.0.
- [Release notes](https://github.com/webpack/webpack/releases)
- [Commits](https://github.com/webpack/webpack/compare/v5.75.0...v5.76.0)

---
updated-dependencies:
- dependency-name: webpack
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-15 08:28:00 +00:00
Johannes Rudolph c67fbbad73 Add option to show user first and last name instead of nickname 2023-03-13 17:33:17 +01:00
Igor Scheller 031e1a08fe
Fix button types and remove unused classes
Co-authored-by: Thomas Rupprecht <rupprecht.thomas@gmail.com>
2023-03-10 15:53:54 +01:00
xuwhite 668a9e86f5
refactor goodie config option as enum (#1100)
* goodie config as enum
* Unified goodie check, updated test
* Changed tshirt to goodie in url

---------

Co-authored-by: Igor Scheller <igor.scheller@igorshp.de>
2023-03-05 03:00:38 +01:00
Igor Scheller 523e984122 Added git HEAD to version parsing 2023-02-28 16:12:01 +01:00
Igor Scheller fb8c05edad Added email notification on new private messages 2023-02-26 16:59:48 +01:00
Igor Scheller a464682b47 Reimplemented admin room pages 2023-02-26 16:55:04 +01:00
Igor Scheller baca49c53b Fixed quotest 2023-02-26 16:32:02 +01:00
Igor Scheller 34e9d01c18 Translate more date / time outputs 2023-02-26 14:10:02 +01:00
Igor Scheller 6b15e6b86e Fixed news test 2023-02-26 13:49:13 +01:00
Igor Scheller 09e6e9d239 Basic maintenance page styling 2023-02-26 13:49:13 +01:00
Igor Scheller cf18f058b5 Moved logging tests from feature to unit 2023-02-26 13:49:13 +01:00
Igor Scheller b35a5af515 Added code coverage hint to development doc 2023-02-26 13:49:13 +01:00
Igor Scheller 642a49aefe Show dropdowns above sticky shifts headers 2023-02-26 13:49:13 +01:00
Igor Scheller e2f387d111 Remove type="text/javascript" from <script> tags 2023-02-26 13:49:13 +01:00
Igor Scheller e0a702ec3b Fixed stats test 2023-02-26 13:49:13 +01:00
Michael Weimann 920fa7feb9 Add composer phpunit:coverage script 2023-02-17 22:12:41 +01:00
Igor Scheller 98a0937b82 Reimplemented angeltypes about page 2023-02-15 18:05:30 +01:00
Thomas Rupprecht 0e033256f0
improve webpack.config.js 2023-02-15 17:51:15 +01:00
xuwhite 6fcb656299
Added important news (#1096) 2023-02-13 21:19:45 +01:00
Igor Scheller 713f8222e4 Unified user notifications 2023-02-13 19:38:29 +01:00
Thomas Rupprecht 1fe30fc82f update libs 2023-02-09 18:37:35 +01:00
Bot ad360a70fb Require comma at last array element and no single line space 2023-02-09 18:19:38 +01:00
Igor Scheller 216185b65c Don't use double-quoted strings if not needed 2023-02-09 18:19:38 +01:00
Thomas Rupprecht a1a1cf6f93
Unify migration style and cleanup (#1037)
* unify helper methods access type to private
* unify codestyle
* remove unused down methods
2023-02-08 21:53:58 +01:00
Thomas Rupprecht 2ff953ef89 fix php docs types 2023-02-07 15:37:20 +01:00
Thomas Rupprecht c147f06b91 rename `docker-compose` to `docker compose` 2023-02-04 01:35:10 +01:00
Thomas Rupprecht cbdee7a9f3 language fixes 2023-02-03 21:06:40 +01:00
Bot f9d22f9bda Set strict types everywhere (except includes) 2023-02-03 20:55:58 +01:00
Michael Weimann 3c6a5bb385 Fix strict types errors 2023-02-03 20:55:58 +01:00
Thomas Rupprecht 4dde4cd9fa update libs and move bootstrap-icons to dependencies 2023-02-03 14:36:18 +01:00
Igor Scheller 7eccf2c535 Reimplemented shifts json export 2023-02-02 20:01:31 +01:00
Igor Scheller b0b4cb54ec Reimplemented shifts ical export 2023-02-02 20:01:31 +01:00
Igor Scheller 3d0d5067fd Reimplemented news Atom feed, added RSS feed 2023-02-02 20:01:31 +01:00
Igor Scheller 8223193330 Added uuid/uuidBy twig functions 2023-02-02 20:01:31 +01:00
Igor Scheller a9cd00c37a Authenticator: Improve auth methods handling, esp. for api endpoints 2023-02-02 20:01:31 +01:00
Igor Scheller ac97413f3f Add public/fahrplan.xml to .gitignore 2023-01-31 15:20:09 +01:00
Michael Weimann 321fbc82fc Add git to dev container 2023-01-31 14:57:21 +01:00
Xu 21eafb7d26 restructure of DEVELOPMENT.md and adding the new port 5080 localhost to it 2023-01-31 02:06:44 +01:00
Xu ccdf1aa8d5 add config option for other goodies 2023-01-31 01:51:31 +01:00
Igor Scheller 3ca39dc8e1 Fixed shifts bulk deletion 2023-01-25 01:00:42 +01:00
Igor Scheller 0188ed5562 Fixed StringInputLength validation 2023-01-24 23:28:15 +01:00
Xu b99e6ed8c1 add hint on how many shifts to be created 2023-01-24 21:33:13 +01:00
Igor Scheller 99ab7853da Added time input to /design 2023-01-24 20:49:31 +01:00
Igor Scheller bfa0d91704 Fix empty checks 2023-01-24 20:49:31 +01:00
Igor Scheller 37a26c123e Validation: Fixed worklog comment: ... 2023-01-24 20:49:31 +01:00
Igor Scheller f5a7598a45 tests: Removed exception handler registration because it has side effects 2023-01-24 20:49:31 +01:00
Thomas Rupprecht 733586dfd5 replace sticky-headers javascript impl with css 2023-01-24 20:13:13 +01:00
Thomas Rupprecht 3412ed2924
invert input time icon color for chrome based browsers in dark themes (#1060) 2023-01-24 19:45:48 +01:00
Thomas Rupprecht e844c98871
Convert class const's to enum's (#1050)
* convert `Migrate::(UP|DOWN)` class const to `MigrateDirection` enum
* convert `Handler::(ENV_PRODUCTION|ENV_DEVELOPMENT)` class const to `Environment` enum
* convert `ShiftSignupState::(FREE|...|NOT_ARRIVED)` class const to `ShiftSignupStatus::(FREE|...|NOT_ARRIVED)` enum
2023-01-24 19:23:57 +01:00
Michael Weimann 2db70c96ed
Add pre-commit hook (#1071) 2023-01-24 14:26:10 +01:00
Thomas Rupprecht 5a2b8f7ff9
Improve navbar 2023-01-22 19:16:33 +01:00
Igor Scheller 96f703bf22
Migrate NeededAngelType model 2023-01-22 18:43:09 +01:00
Igor Scheller 89dc85c3d5
Add ShiftEntry model 2023-01-18 13:02:11 +01:00
xuwhite 89f9b423b1
room view & angeltype view: show all shifts (#1067) 2023-01-17 20:01:29 +01:00
Johannes Rudolph 64be48c646 Add Possibility for Custom Translations: config/[locale]/custom.po 2023-01-17 19:22:59 +01:00
Thomas Rupprecht d18185f49e
Improve alerts and conversation (#1062)
* add role="alert"
* improve conversation styling
* replace alert with card for conversation
2023-01-17 15:05:47 +01:00
Michael Weimann 01373cb192 Replace select 2 with choices.js and kill jQuery 2023-01-17 14:27:38 +01:00
Igor Scheller 2be8e565bf Refactored UUID generation: use pseudo unique named UUID for schedules 2023-01-06 14:16:41 +01:00
Igor Scheller 23424830e7 Removed unused reference 2023-01-03 22:42:50 +01:00
Igor Scheller 3115870ec4
Added Shift model 2023-01-03 22:19:03 +01:00
Michael Weimann 1d1618836b
Fix frontend formatting 2023-01-03 20:20:46 +01:00
Thomas Rupprecht 30f50dab6d
Extract shifts filter JavaScript and improve HTML structure 2023-01-02 18:54:32 +01:00
Michael Weimann c2e3902c53
Update frontend deps 2023-01-02 17:59:06 +01:00
Igor Scheller 26b5a6e1f0 Fix shifts edit page 2022-12-28 12:31:31 +01:00
Igor Scheller 9409b320f0 CI: Improve GitLab k8s deployment for agents support 2022-12-28 11:54:47 +01:00
Michael Weimann 59cfce0c76
Enable space after cast sniff and remove .git-blame-ignore-revs 2022-12-25 11:59:45 +01:00
Michael Weimann 86cc0a238d
Remove function-paren-newline from ESLint, covered by prettier 2022-12-23 19:21:02 +01:00
Michael Weimann 43993aaba5
Fix JS code style 2022-12-23 19:15:03 +01:00
Thomas Rupprecht 2bab370221
enable/disable all html-tags corresponding to a radio button checked state (#1046) 2022-12-23 18:31:26 +01:00
Johannes Rudolph b1b08afd23
Make user view columns dynamic by config 2022-12-23 04:46:32 +01:00
Johannes Rudolph 92e0b8be65
Hide dect, voucher and t-shirt options shown to users when disabled via config 2022-12-23 04:22:39 +01:00
Johannes Rudolph 737066414e
Fix i18n on User Edit Page 2022-12-23 03:20:10 +01:00
Michael Weimann 0ae10471d1 Add prettier 2022-12-23 02:20:43 +01:00
Igor Scheller b024650eaf Fix formatting 2022-12-22 00:35:07 +01:00
Thomas Rupprecht 3d88ae7916
convert `switch` to `match` 2022-12-22 00:08:54 +01:00
Thomas Rupprecht fdddd63aae
fix input radio id and default to multi on shift creation 2022-12-21 23:53:47 +01:00
Igor Scheller 559517e017 Ignore the timezone configured in php.ini, better cleanup after feature tests 2022-12-21 17:22:45 +01:00
Igor Scheller d1b7b6886e Fix tests coverage 2022-12-21 15:11:37 +01:00
Thomas Rupprecht f24d31b928
Improve countdown logic
use `Intl.RelativeTimeFormat` to support different l10n add week as possible duration
2022-12-21 14:18:21 +01:00
Igor Scheller 98a3187899
Use native types where possible + ctor prop promotion 💣 2022-12-21 12:46:40 +01:00
Igor Scheller d92733f658 Schedule: Make URLs klickable on overview and handle connection errors 2022-12-21 12:08:48 +01:00
Igor Scheller 700d841a87 Fix atom, ical and json exports 2022-12-21 11:42:55 +01:00
Michael Weimann 6dac44d67f
Rename class props to match ctor param 2022-12-20 22:19:52 +01:00
Michael Weimann 202eae5136
Specify PHP version for PHPCS
Signed-off-by: Michael Weimann <mail@michael-weimann.eu>
2022-12-20 22:19:52 +01:00
Michael Weimann 2532e87029
Add git-blame-ignore-revs 2022-12-20 22:19:51 +01:00
Michael Weimann 2ad4203dd3
Add useless comment phpcs sniff 2022-12-20 22:19:49 +01:00
Michael Weimann 61139e03c3
Use constructor property promotion
Signed-off-by: Michael Weimann <mail@michael-weimann.eu>
2022-12-20 22:18:34 +01:00
Michael Weimann b004f865b4
Set native property types
Signed-off-by: Michael Weimann <mail@michael-weimann.eu>
2022-12-15 20:13:50 +01:00
Michael Weimann aff8826c99
Set native return types
Signed-off-by: Michael Weimann <mail@michael-weimann.eu>
2022-12-15 20:13:31 +01:00
Michael Weimann 2b88322c0c
Set native parameter types
Signed-off-by: Michael Weimann <mail@michael-weimann.eu>
2022-12-15 20:13:30 +01:00
Igor Scheller f835a7538c Tests: Improved execution time, test more factories 2022-12-13 22:59:56 +01:00
Igor Scheller 93b30dcbdf OAuth2 event: refactoring 2022-12-13 22:46:16 +01:00
Igor Scheller 5b8805f884 Moved OAuth2 event helper and added tests 2022-12-13 22:46:16 +01:00
Igor Scheller 7f78f59840 Added UserAngelType model 2022-12-13 22:46:16 +01:00
Igor Scheller 99e7a088b0 Use PHP 8.2 for builds and fixed warning in email validation rule 2022-12-13 22:03:08 +01:00
Igor Scheller b4402a5b59 Update PHP dependencies (major version bumps) 2022-12-13 22:03:08 +01:00
Igor Scheller 6c4e92baf2 Bump minimum PHP version to 8.1 and update packages 2022-12-13 22:03:08 +01:00
Thomas Rupprecht 2d454ca8ae move js code for spinner into js file
now the code is needed only once for all spinners
2022-12-11 18:44:58 +01:00
Thomas Rupprecht f12f8a1b3b set autocomplete attribute for password inputs 2022-12-11 18:17:42 +01:00
Thomas Rupprecht ce0ac6f823
Use specific ID parameter names in routes (#1023) 2022-12-11 18:01:34 +01:00
Thomas Rupprecht 61cff64d96 cast timestamp to number 2022-12-11 10:21:47 +01:00
Thomas Rupprecht 5da586bc2c add JsDoc for `formatFromNow` 2022-12-11 10:21:47 +01:00
Thomas Rupprecht f446f0da7d fix wrong param name in JSDoc 2022-12-11 10:21:47 +01:00
Thomas Rupprecht fef5d77443 add JSDoc for `ready` function 2022-12-11 10:21:47 +01:00
Thomas Rupprecht 5bd922d109 code improvements
unify lowercase variant of form method post
remove duplicate class selector
improve comments
2022-12-11 10:21:47 +01:00
Michael Weimann 4c3dc1e081 Fix shift creation
Regression introduced by changing the angeltype count field IDs
2022-12-11 10:20:44 +01:00
Thomas Rupprecht 5604176675 fix mailto link 2022-12-11 10:14:07 +01:00
Michael Weimann 0633f8f335 Enable PHPCS cache 2022-12-11 10:12:05 +01:00
Igor Scheller 147a40e581 Docker: Dev: Install linux-headers for xdebug 2022-12-11 10:10:06 +01:00
Thomas Rupprecht cafbddabbf change form submit button text to "save" 2022-12-10 17:28:50 +01:00
Thomas Rupprecht c906af1010 use int instead of float for spinner value 2022-12-10 17:25:04 +01:00
Thomas Rupprecht ece4d261c4 add comment about css rules to hide the arrows in the input field 2022-12-10 17:25:04 +01:00
Thomas Rupprecht 59e623c938 add function parameter types for form_spinner 2022-12-10 17:25:04 +01:00
Thomas Rupprecht fbe52117ed improve spinner control
use input type `number` with `min` and `step`
use `.stepDown()` and `.stepUp()` to change value
hide browser controls
2022-12-10 17:25:04 +01:00
Thomas Rupprecht 3bcbca97ab improve spinner ids 2022-12-10 17:25:04 +01:00
Thomas Rupprecht 7a376399b8 use better and more icons 2022-12-10 17:22:11 +01:00
Igor Scheller 3e22315caa CI: Fixed php version 2022-12-10 00:44:16 +01:00
Igor Scheller 31afc07d22 Ignore code coverage (parent::boot is not registered) 2022-12-08 19:23:44 +01:00
Igor Scheller 6686d58c06 Implemented AngelTypes model 2022-12-08 18:35:22 +01:00
frischler bdc62eaac3
Worklog Refactoring 2022-12-08 17:40:24 +01:00
Michael Weimann 9396a49412 Add phpstan 2022-12-08 16:32:04 +01:00
Thomas Rupprecht 0e3d47f2e1
replace md5 with random_bytes and use 64 chars for api_key 2022-12-08 15:57:13 +01:00
Thomas Rupprecht 1d158da441 remove self closing tag 2022-12-08 15:43:34 +01:00
Thomas Rupprecht 3b8a275e1c remove unused `form_multi_checkboxes` function 2022-12-08 15:43:34 +01:00
Thomas Rupprecht e8ccbd7c5e style checkboxes with bootstrap classes 2022-12-08 15:43:34 +01:00
Thomas Rupprecht 0a1014496a fix tag nesting 2022-12-08 15:36:44 +01:00
Thomas Rupprecht 2b5ffca1b0
Use template literals instead of string concatenation (#1003)
* use template literals instead of string concatenation
* extract function call out of template literals
* add contributing hint to don't put function calls in template-literals
2022-12-04 12:00:18 +01:00
Thomas Rupprecht d4a9861751
Add function-paren-newline ESLint rule; align config code style (#1000)
* unify indentation in config.default.php

* add eslint rule `function-paren-newline`

* fix `function-param-newline` lint rule
2022-12-04 11:33:25 +01:00
Michael Weimann 282f4b45ac
Replace jQuery with VanillaJS 2022-12-02 17:07:12 +01:00
Michael Weimann 7bbdb95885
Replace jQuery ready 2022-12-02 17:07:11 +01:00
Joshua Bachmeier 6917f7805b Add support for oauth scopes
As defined in RFC6749:
* https://www.rfc-editor.org/rfc/rfc6749#section-4.1.1
* https://www.rfc-editor.org/rfc/rfc6749#section-3.3

Scopes can be configured per-provider in engelsystem config.
2022-12-02 15:35:10 +01:00
Joshua Bachmeier 44821019b6 Add error handling to oauth provider response processing 2022-12-02 15:35:10 +01:00
Igor Scheller 7a92ea077f ShiftType test: Fix test 2022-12-02 15:07:29 +01:00
Thomas Rupprecht 65dca1cebd improve admin-shifts ui
on larger screens put start & end next to each other
size of the "needed angles" fit on more screen sizes
2022-12-02 14:49:14 +01:00
Thomas Rupprecht 6d5748f9f8
fix label to input link for `form_spinner`, `form_date` and `form_datetime` 2022-12-02 14:45:23 +01:00
Thomas Rupprecht 9c3c2cc2ac select2 width should be 100% to scale if the browser width changes 2022-12-02 14:25:57 +01:00
Thomas Rupprecht 4ccceb271c style input radios with bootstrap classes 2022-12-02 14:19:45 +01:00
Thomas Rupprecht 0002585de4 fix border radius on time input in shift filter 2022-12-02 13:58:30 +01:00
Thomas Rupprecht 37c7b876f3 fix select_array. needed for a correct format for select2
if `$data` is a `Collection` than the return format is `[{"key":["value"]}]` and not `[{"key":"value"}]`
2022-12-02 13:53:29 +01:00
Thomas Rupprecht 47b80b504c documentation improvements
remove trailing whitspaces
use single backticks
2022-12-02 13:27:10 +01:00
Thomas Rupprecht d952dfe262 update libs 2022-11-28 22:13:09 +01:00
Michael Weimann 1b83d0bb77
Add yarn check CI 2022-11-27 17:04:06 +01:00
Michael Weimann 9d9211c054 Format JS code 2022-11-27 16:31:32 +01:00
Michael Weimann 4752c9306c Add eslint 2022-11-27 16:31:32 +01:00
Igor Scheller 992e708276 Replaced ShiftTypes with shift_types / ShiftType model 2022-11-27 14:17:02 +01:00
Igor Scheller ac162f4411 Removed referenced angeltype from shift type 2022-11-27 14:17:02 +01:00
Igor Scheller 354ec084eb Show driver's license button on user page when angeltype requires it 2022-11-27 12:14:14 +01:00
Igor Scheller cdc218e116 db factories: More unique constrains 2022-11-26 13:36:47 +01:00
Thomas Rupprecht 23d7e8632b javascript improvements
use `const` instead of `var`/`let`
use `$(function () { ... })` instead of `$(document).ready(function () { ... })`
unify codestyle
2022-11-25 13:44:39 +01:00
Thomas Rupprecht 887add83f6 `<head>` optimizations
lowercase charset utf-8
move `<title>` after `<meta charset="utf-8"/>`
charset should be in the first 1024 bytes and the title after the charset definition
unify self closing tags
2022-11-25 12:41:43 +01:00
Michael Weimann 4f504e98f1 Update frontend deps 2022-11-25 12:32:06 +01:00
Igor Scheller 99afe3f651
Permissions refactoring
* Migration: Added groups, privileges, user_groups, group_privileges, improved references
* Models: Added Group, Privilege and integrated it into User
* Replaced old permission handling with new models
2022-11-06 12:41:52 +01:00
frischler 35815b0838 Settings Modernization: Applied suggested changed from #972 2022-11-01 16:55:23 +01:00
frischler dba7bc29f9 Settings Modernization: Added mobile_show setting to /settings/profile page. 2022-11-01 16:55:23 +01:00
frischler 63f1c12429 Settings Modernization: Refactoring
Settings Modernization: Fixing Date issue

Settings Modernization: Reroute

Settings Modernization: Reroute settings to /settings/profile, Cleanup and Refactoring
2022-11-01 16:55:23 +01:00
frischler d6899d37d9 Settings Modernization: Applying buildup and teardown time, add localization 2022-11-01 16:55:23 +01:00
frischler 203531629f Settings Modernization: Creating /settings/profile page with Controller methods and tests 2022-11-01 16:55:23 +01:00
Igor Scheller 96f4e1b3a8 Fix typo in config, default group on registration and edit comparison 2022-10-24 00:07:05 +02:00
Igor Scheller 74be132f47 Improve `/design`: Add section links and disable in-text-links 2022-10-22 20:31:41 +02:00
Igor Scheller 4d9f4694ae Groups: Fix naming and update IDs 2022-10-22 17:49:20 +02:00
Michael Weimann 968f0141cb
Remove moment 2022-10-22 17:22:59 +02:00
Michael Weimann 00eb800f96
Replace moment date format with vanilla JS 2022-10-22 17:22:59 +02:00
Michael Weimann 7049a08bcd
Replace moment-countdown with countdown function 2022-10-22 17:22:53 +02:00
Michael Weimann a81992ca04
Add countdowns to /design 2022-10-22 17:11:55 +02:00
Xu b860b37ba9 add option to hide angeltype at registration 2022-10-21 22:30:17 +02:00
Igor Scheller ff1dfd5a18 Use config for session tests 2022-10-21 19:49:18 +02:00
Xu 2391415969 make session lifetime configurable 2022-10-21 19:42:10 +02:00
Igor Scheller c0a39cb2a1 Migrations: Removed references to models to prevent further migration issues 2022-10-21 16:11:27 +02:00
Igor Scheller 3964982db0 Fixed migrations 2022-10-18 22:22:54 +02:00
Igor Scheller 855d3535db Fixed formatting 2022-10-18 22:08:49 +02:00
Xu f9da096308 add option to show mobile number of user in users view 2022-10-18 22:06:08 +02:00
Xu 4d6da1894a added dect option for rooms 2022-10-18 21:22:37 +02:00
Michael Weimann 88c727bf8e
Manually migrate /includes code to be phpcs compliant 2022-10-18 19:30:43 +02:00
Michael Weimann f7d499b362
Include phpcs for /includes 2022-10-18 19:15:22 +02:00
Igor Scheller 1af185c7ac Updated contributing guidelines 2022-10-14 16:46:03 +02:00
Igor Scheller 7cd4befdfa Refactored shift entry deletion: Use event for notification and worklog creation 2022-10-14 16:27:51 +02:00
Igor Scheller 870a92efd5 Move NightShiftMultiplier calculation to Shifts helper 2022-10-14 16:27:51 +02:00
Igor Scheller 20e389fccd k8s: Use traefik as default ingress, added improved app url handling to support subpath deployments 2022-10-14 13:36:11 +02:00
Igor Scheller f2c9e4a3d6 Change "delete" to "sign off" when removing user from shift 2022-10-01 19:53:44 +02:00
Igor Scheller 2ec61a6db2 Fixed composer.lock hash 2022-10-01 19:41:43 +02:00
dependabot[bot] cb65bcb79c Bump moment-timezone from 0.5.34 to 0.5.35
Bumps [moment-timezone](https://github.com/moment/moment-timezone) from 0.5.34 to 0.5.35.
- [Release notes](https://github.com/moment/moment-timezone/releases)
- [Changelog](https://github.com/moment/moment-timezone/blob/develop/changelog.md)
- [Commits](https://github.com/moment/moment-timezone/compare/0.5.34...0.5.35)

---
updated-dependencies:
- dependency-name: moment-timezone
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-10-01 19:39:34 +02:00
Igor Scheller 7450fe87d0 Update twig 2022-10-01 19:30:14 +02:00
819 changed files with 40139 additions and 25627 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}] [{.babelrc,package.json,.eslintrc.json,.prettierrc.json}]
indent_size = 2 indent_size = 2
[docker/**.conf] [docker/**.conf]
@ -27,6 +27,8 @@ 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}]

3
.eslintignore Normal file
View File

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

10
.eslintrc.json Normal file
View File

@ -0,0 +1,10 @@
{
"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,8 +26,10 @@ _vimrc_local.vim
# Project files # Project files
/config/config.php /config/config.php
/test/coverage /config/lang/
/public/*.xml
/public/coverage /public/coverage
/test/coverage
/coverage /coverage
/unittests.xml /unittests.xml
/resources/lang/*/*.mo /resources/lang/*/*.mo
@ -40,3 +42,4 @@ _vimrc_local.vim
/public/assets /public/assets
/package-lock.json /package-lock.json
/yarn-error.log /yarn-error.log
/.yarn-cache

View File

@ -12,6 +12,7 @@ variables:
DOCROOT: /var/www/ DOCROOT: /var/www/
stages: stages:
- prepare
- validate - validate
- build - build
- test - test
@ -20,44 +21,90 @@ stages:
- deploy-production - deploy-production
- stop - stop
# .use_cache: &use_cache
# Validation cache:
# key: "$CI_JOB_NAME-$CI_COMMIT_REF_SLUG"
paths:
- .yarn-cache/
- vendor/
check-style: # for jobs that depend on composer
image: composer:latest .use_composer: &use_composer
stage: validate <<: *use_cache
needs:
- composer install
before_script: before_script:
- composer --no-ansi global config --no-plugins allow-plugins.dealerdirect/phpcodesniffer-composer-installer true - composer install --no-ansi --no-progress
- 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: # for jobs that depend on yarn
image: mstruebing/editorconfig-checker .use_yarn: &use_yarn
stage: validate <<: *use_cache
script: needs:
- ec -v - yarn install
before_script:
- yarn install --check-frontend --cache-folder .yarn-cache
validate-composer: #
# Preparation
#
composer validate:
image: composer:latest image: composer:latest
stage: validate stage: prepare
script: script:
- composer --no-ansi validate --strict - composer --no-ansi validate --strict
validate-yarn: composer install:
<<: *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: validate stage: prepare
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: validate stage: prepare
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
@ -66,10 +113,64 @@ 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
# #
@ -87,39 +188,25 @@ build-image:
<<: *container_definition <<: *container_definition
stage: build stage: build
needs: needs:
- check-editorconfig - phpcs
- check-style - phpstan
- 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}
@ -148,10 +235,11 @@ test:
- ./bin/migrate - ./bin/migrate
script: script:
- >- - >-
php -d pcov.enabled=1 -d pcov.directory=. vendor/bin/phpunit -vvv --colors=never php -d memory_limit=1024M -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:
@ -172,6 +260,9 @@ 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"
@ -201,7 +292,11 @@ release-image:
- test - test
dependencies: [ ] dependencies: [ ]
script: script:
- echo -e "FROM ${TEST_IMAGE}" | /kaniko/executor --dockerfile /dev/stdin --destination "${RELEASE_IMAGE}" - echo -e "FROM ${TEST_IMAGE}"
| /kaniko/executor
--dockerfile /dev/stdin
--destination "${RELEASE_IMAGE}"
--cache=true
only: only:
- main - main
@ -218,8 +313,8 @@ build-release-file:
stage: release stage: release
needs: needs:
- build-image - build-image
- audit-yarn - yarn audit
- audit-composer - composer audit
- test - test
- dump-database - dump-database
- generate-assets - generate-assets
@ -274,6 +369,7 @@ deploy:
dependencies: *deploy_needs dependencies: *deploy_needs
environment: environment:
name: rsync-staging name: rsync-staging
deployment_tier: development
only: only:
- main - main
script: script:
@ -296,7 +392,10 @@ deploy:
- test - test
- build-image - build-image
before_script: before_script:
- &kubectl_deployment_script if [[ -z "${KUBE_INGRESS_BASE_DOMAIN}" ]]; then echo "Skipping deployment"; exit; fi - &kubectl_deployment_script |-
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
@ -311,8 +410,12 @@ 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}"}
@ -321,19 +424,24 @@ 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 apply -f deployment.yaml - kubectl -n "${CI_KUBE_NAMESPACE}" diff -f deployment.yaml || true
- 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
@ -344,7 +452,8 @@ deploy:
GIT_STRATEGY: none GIT_STRATEGY: none
when: manual when: manual
script: script:
- kubectl delete all,ingress,pvc -l app=$CI_PROJECT_PATH_SLUG -l environment=$CI_ENVIRONMENT_SLUG - TARGETS=all,ingress,pvc,certificate
- 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
@ -353,6 +462,7 @@ 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}
@ -366,6 +476,7 @@ 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
@ -376,8 +487,8 @@ deploy-production:
stage: deploy-production stage: deploy-production
needs: needs:
- test - test
- audit-yarn - yarn audit
- audit-composer - composer audit
- build-image - build-image
- generate-assets - generate-assets
dependencies: dependencies:
@ -385,6 +496,7 @@ 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
@ -404,8 +516,8 @@ deploy-k8s-production:
stage: deploy-production stage: deploy-production
needs: needs:
- release-image - release-image
- audit-yarn - yarn audit
- audit-composer - composer audit
environment: environment:
name: production name: production
on_stop: stop-k8s-production on_stop: stop-k8s-production

View File

@ -4,9 +4,11 @@
<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">
@ -19,4 +21,32 @@
<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>

5
.prettierrc.json Normal file
View File

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

View File

@ -2,12 +2,30 @@
## 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.
* Please cover your code by unit tests. Code under `includes` does not require tests. * 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, 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
Please create single pull requests for every feature instead of creating one big monster of pull request containing a complete rewrite. * The PR should contain a short overview of the changes.
* 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,7 +8,95 @@ 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)
## Local build ## 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
# 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`
@ -35,36 +123,51 @@ 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 'file="{}"; msgfmt "${file%.*}.po" -o "${file%.*}.mo"' \; find resources/lang/ -type f -name '*.po' -exec sh -c 'msgfmt "${1%.*}.po" -o"${1%.*}.mo"' shell {} \;
``` ```
## Testing ## Testing
To run the unit tests use To run only unit tests (tests that should not change the Engelsystem state) use
```bash ```bash
vendor/bin/phpunit --testsuite Unit vendor/bin/phpunit --testsuite Unit
``` ```
If a database is configured and the Engelsystem is allowed to mess around with some files, you can run feature tests. If a database is configured and the Engelsystem is allowed to mess around with some files, you can run feature tests.
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: ```
vendor/bin/phpunit
```
To run code coverage reports its highly recommended to use [`pcov`](https://github.com/krakjoe/pcov) or When you want to run unit and feature tests at once:
```bash
vendor/bin/phpunit
```
To generate code coverage reports it's 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 --testsuite Unit --coverage-text php -d pcov.enabled=1 -d pcov.directory=. vendor/bin/phpunit --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.
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. 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.
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`.
This will send the output to the Var Dump server which can be viewed in the terminal. This will send the output to the Var Dump server which can be viewed in the terminal.
This does however require that you start the var-dump-server otherwise the output will be printed in your browser This does however require that you start the var-dump-server otherwise the output will be printed in your browser
You can also `dump` and `die` if you wish to not let your code continue any further by calling the `dd` method You can also `dump` and `die` if you wish to not let your code continue any further by calling the `dd` method
@ -74,7 +177,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)
@ -83,16 +186,6 @@ 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
@ -108,51 +201,12 @@ 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
``` ```
## Docker ## Static code analysis
If unspecific issues appear try using Docker version >= 20.10.14. You can run a static code analysis with this command:
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
cd docker/dev composer phpstan
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 >= 7.4 * PHP >= 8.1
* Required modules: * Required modules:
* dom * dom
* json * json
@ -28,21 +28,30 @@ 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 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```. * To disable/remove values from the following lists, set the value of the entry to `null`:
* 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. * `themes`
* In the browser, login with credentials ```admin``` : ```asdfasdf``` and change the password. * `tshirt_sizes`
* `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.
@ -55,7 +64,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:
@ -67,14 +76,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
``` ```
#### Migrate #### Set Up / Migrate Database
Import database changes to migrate it to the newest version Create the Database Schema (on a fresh install) or 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

16
SECURITY.md Normal file
View File

@ -0,0 +1,16 @@
# 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,7 +4,9 @@
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;
@ -19,7 +21,7 @@ $app->register(MigrationServiceProvider::class);
/** @var Handler $errorHandler */ /** @var Handler $errorHandler */
$errorHandler = $app->get(Handler::class); $errorHandler = $app->get(Handler::class);
$errorHandler->setHandler(Handler::ENV_PRODUCTION, new NullHandler()); $errorHandler->setHandler(Environment::PRODUCTION, new NullHandler());
/** @var Migrate $migration */ /** @var Migrate $migration */
$migration = $app->get('db.migration'); $migration = $app->get('db.migration');
@ -32,10 +34,10 @@ if (in_array('help', $argv) || in_array('--help', $argv) || in_array('-h', $argv
exit; exit;
} }
$method = Migrate::UP; $direction = Direction::UP;
if (in_array('down', $argv)) { if (in_array('down', $argv)) {
$argv = array_values($argv); $argv = array_values($argv);
$method = Migrate::DOWN; $direction = Direction::DOWN;
} }
$oneStep = false; $oneStep = false;
@ -48,4 +50,4 @@ if (in_array('force', $argv) || in_array('--force', $argv) || in_array('-f', $ar
$force = true; $force = true;
} }
$migration->run($baseDir, $method, $oneStep, $force); $migration->run($baseDir, $direction, $oneStep, $force);

26
bin/pre-commit Executable file
View File

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

3598
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,7 @@
<?php <?php
declare(strict_types=1);
// Application config // Application config
return [ return [
@ -26,7 +28,6 @@ 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,
@ -36,6 +37,7 @@ 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
@ -46,10 +48,13 @@ 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,
@ -64,11 +69,22 @@ 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,5 +1,7 @@
<?php <?php
declare(strict_types=1);
// To change settings create a config.php // To change settings create a config.php
return [ return [
@ -11,41 +13,58 @@ return [
'password' => env('MYSQL_PASSWORD', ''), 'password' => env('MYSQL_PASSWORD', ''),
], ],
// For accessing stats // For accessing /metrics (and /stats)
'api_key' => '', 'api_key' => env('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', null), 'url' => env('APP_URL'),
// 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' => [
//'Foo' => 'https://foo.bar/batz-%lang%.html', // Name can be a translation string, permission is a engelsystem privilege
// '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' => env('FAQ_URL', '/faq'), 'faq.faq' => [env('FAQ_URL', '/faq'), 'faq.view'],
// 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', null), 'faq_text' => env('FAQ_TEXT'),
// Link to documentation/help // Link to documentation/help
'documentation_url' => 'https://engelsystem.de/doc/', 'documentation_url' => env('DOCUMENTATION_URL', 'https://engelsystem.de/doc/'),
// Email config // Email config
'email' => [ 'email' => [
@ -60,17 +79,20 @@ 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', null), 'tls' => env('MAIL_TLS'),
'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' => '', 'privacy_email' => env('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', null), 'setup_admin_password' => env('SETUP_ADMIN_PASSWORD'),
'oauth' => [ 'oauth' => [
// '[name]' => [config] // '[name]' => [config]
@ -88,6 +110,8 @@ 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
@ -127,7 +151,19 @@ 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',
@ -214,17 +250,33 @@ 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 // Number of News shown on one site and for feed readers (minimum 1)
'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
@ -246,48 +298,65 @@ 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' => PASSWORD_DEFAULT, 'password_algorithm' => env('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 Password field should be enabled on registration. // Whether the login and registration via password should be enabled (login will be hidden)
// This is useful when using oauth, disabling it also disables normal // This is useful when using oauth, disabling it also disables normal registration without oauth
// 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),
// Enables prename and lastname // Whether the mobile number can be shown to other users
'enable_user_name' => (bool)env('ENABLE_USER_NAME', false), '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),
// 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),
// Enables the T-Shirt configuration on signup and profile // Whether force active should be enabled
'enable_tshirt_size' => (bool)env('ENABLE_TSHIRT_SIZE', true), 'enable_force_active' => (bool) env('ENABLE_FORCE_ACTIVE', true),
// Enables the goody configuration on signup and profile // Resembles the Goodie Type. There are three options:
'enable_goody' => (bool)env('ENABLE_GOODY', false), // 'none' => no goodie at all
// '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),
// 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),
// Local timezone // Hide columns in backend user view. Possible values are any sortable parameters of the table.
'timezone' => env('TIMEZONE', ini_get('date.timezone') ?: 'Europe/Berlin'), 'disabled_user_view_columns' => [],
// Multiply 'night shifts' and freeloaded shifts (start or end between 2 and 6 exclusive) by 2 // Local timezone
'timezone' => env('TIMEZONE', 'Europe/Berlin'),
// Multiply 'night shifts' and freeloaded shifts (start or end between 2 and 8 exclusive) by 2 in goodie score
// 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), 'start' => env('NIGHT_SHIFTS_START', 2), // Starting from hour
'end' => env('NIGHT_SHIFTS_END', 6), 'end' => env('NIGHT_SHIFTS_END', 8), // Ends at (without including) hour
'multiplier' => env('NIGHT_SHIFTS_MULTIPLIER', 2), 'multiplier' => env('NIGHT_SHIFTS_MULTIPLIER', 2),
], ],
@ -297,10 +366,20 @@ 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) ?: null, 'voucher_start' => env('VOUCHER_START') ?: 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',
@ -309,21 +388,31 @@ 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, set value to null if not available // Available T-Shirt sizes
// 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-G' => 'Small Fitted-Cut', 'S-F' => 'Small Fitted-Cut',
'M' => 'Medium Straight-Cut', 'M' => 'Medium Straight-Cut',
'M-G' => 'Medium Fitted-Cut', 'M-F' => 'Medium Fitted-Cut',
'L' => 'Large Straight-Cut', 'L' => 'Large Straight-Cut',
'L-G' => 'Large Fitted-Cut', 'L-F' => 'Large Fitted-Cut',
'XL' => 'XLarge Straight-Cut', 'XL' => 'XLarge Straight-Cut',
'XL-G' => 'XLarge Fitted-Cut', 'XL-F' => '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],
@ -342,18 +431,26 @@ 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
'trusted_proxies' => env('TRUSTED_PROXIES', ['127.0.0.0/8', '::ffff:127.0.0.0/8', '::1/128']), 'trusted_proxies' => env('TRUSTED_PROXIES', ['127.0.0.0/8', '::ffff:127.0.0.0/8', '::1/128']),
// 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' => 'default-src \'self\' \'unsafe-inline\' \'unsafe-eval\'; img-src \'self\' data:;', 'Content-Security-Policy' =>
'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',
@ -364,7 +461,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,11 +1,15 @@
<?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');
@ -15,54 +19,154 @@ $route->post('/login', 'AuthController@postLogin');
$route->get('/logout', 'AuthController@logout'); $route->get('/logout', 'AuthController@logout');
// OAuth // OAuth
$route->get('/oauth/{provider}', 'OAuthController@index'); $route->addGroup(
$route->post('/oauth/{provider}/connect', 'OAuthController@connect'); '/oauth/{provider}',
$route->post('/oauth/{provider}/disconnect', 'OAuthController@disconnect'); function (RouteCollector $route): void {
$route->get('', 'OAuthController@index');
$route->post('/connect', 'OAuthController@connect');
$route->post('/disconnect', 'OAuthController@disconnect');
}
);
// User settings // User settings
$route->get('/settings/password', 'SettingsController@password'); $route->addGroup(
$route->post('/settings/password', 'SettingsController@savePassword'); '/settings',
$route->get('/settings/theme', 'SettingsController@theme'); function (RouteCollector $route): void {
$route->post('/settings/theme', 'SettingsController@saveTheme'); $route->get('/profile', 'SettingsController@profile');
$route->get('/settings/language', 'SettingsController@language'); $route->post('/profile', 'SettingsController@saveProfile');
$route->post('/settings/language', 'SettingsController@saveLanguage'); $route->get('/password', 'SettingsController@password');
$route->get('/settings/oauth', 'SettingsController@oauth'); $route->post('/password', 'SettingsController@savePassword');
$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->get('/password/reset', 'PasswordResetController@reset'); $route->addGroup(
$route->post('/password/reset', 'PasswordResetController@postReset'); '/password/reset',
$route->get('/password/reset/{token:.+}', 'PasswordResetController@resetPassword'); function (RouteCollector $route): void {
$route->post('/password/reset/{token:.+}', 'PasswordResetController@postResetPassword'); $route->get('', 'PasswordResetController@reset');
$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->get('/news/{id:\d+}', 'NewsController@show'); $route->addGroup(
$route->post('/news/{id:\d+}', 'NewsController@comment'); '/news',
$route->post('/news/comment/{id:\d+}', 'NewsController@deleteComment'); function (RouteCollector $route): void {
$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->get('/questions', 'QuestionsController@index'); $route->addGroup(
$route->post('/questions', 'QuestionsController@delete'); '/questions',
$route->get('/questions/new', 'QuestionsController@add'); function (RouteCollector $route): void {
$route->post('/questions/new', 'QuestionsController@save'); $route->get('', 'QuestionsController@index');
$route->post('', 'QuestionsController@delete');
$route->get('/new', 'QuestionsController@add');
$route->post('/new', 'QuestionsController@save');
}
);
// Messages // Messages
$route->get('/messages', 'MessagesController@index'); $route->addGroup(
$route->post('/messages', 'MessagesController@redirectToConversation'); '/messages',
$route->get('/messages/{user_id:\d+}', 'MessagesController@messagesOfConversation'); function (RouteCollector $route): void {
$route->post('/messages/{user_id:\d+}', 'MessagesController@send'); $route->get('', 'MessagesController@index');
$route->post('/messages/{user_id:\d+}/{msg_id:\d+}', 'MessagesController@delete'); $route->post('', 'MessagesController@redirectToConversation');
$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->get('/api[/{resource:.+}]', 'ApiController@index'); $route->addGroup(
'/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');
@ -70,59 +174,118 @@ $route->get('/design', 'DesignController@index');
// Administration // Administration
$route->addGroup( $route->addGroup(
'/admin', '/admin',
function (RouteCollector $route) { function (RouteCollector $route): void {
// FAQ // FAQ
$route->addGroup( $route->addGroup(
'/faq', '/faq',
function (RouteCollector $route) { function (RouteCollector $route): void {
$route->get('[/{id:\d+}]', 'Admin\\FaqController@edit'); $route->get('[/{faq_id:\d+}]', 'Admin\\FaqController@edit');
$route->post('[/{id:\d+}]', 'Admin\\FaqController@save'); $route->post('[/{faq_id:\d+}]', 'Admin\\FaqController@save');
} }
); );
// Log // Log
$route->get('/logs', 'Admin\\LogsController@index'); $route->addGroup(
$route->post('/logs', 'Admin\\LogsController@index'); '/logs',
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) { function (RouteCollector $route): void {
$route->get('', 'Admin\\Schedule\\ImportSchedule@index'); $route->get('', 'Admin\\ScheduleController@index');
$route->get('/edit[/{id:\d+}]', 'Admin\\Schedule\\ImportSchedule@edit'); $route->get('/edit[/{schedule_id:\d+}]', 'Admin\\ScheduleController@edit');
$route->post('/edit[/{id:\d+}]', 'Admin\\Schedule\\ImportSchedule@save'); $route->post('/edit[/{schedule_id:\d+}]', 'Admin\\ScheduleController@save');
$route->get('/load/{id:\d+}', 'Admin\\Schedule\\ImportSchedule@loadSchedule'); $route->get('/load/{schedule_id:\d+}', 'Admin\\ScheduleController@loadSchedule');
$route->post('/import/{id:\d+}', 'Admin\\Schedule\\ImportSchedule@importSchedule'); $route->post('/import/{schedule_id:\d+}', 'Admin\\ScheduleController@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) { function (RouteCollector $route): void {
$route->get('', 'Admin\\QuestionsController@index'); $route->get('', 'Admin\\QuestionsController@index');
$route->post('', 'Admin\\QuestionsController@delete'); $route->post('', 'Admin\\QuestionsController@delete');
$route->get('/{id:\d+}', 'Admin\\QuestionsController@edit'); $route->get('/{question_id:\d+}', 'Admin\\QuestionsController@edit');
$route->post('/{id:\d+}', 'Admin\\QuestionsController@save'); $route->post('/{question_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/{id:\d+}', '/user/{user_id:\d+}',
// Shirts function (RouteCollector $route): void {
function (RouteCollector $route) { // Goodies
$route->get('/shirt', 'Admin\\UserShirtController@editShirt'); $route->addGroup(
$route->post('/shirt', 'Admin\\UserShirtController@saveShirt'); '/goodie',
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) { function (RouteCollector $route): void {
$route->get('[/{id:\d+}]', 'Admin\\NewsController@edit'); $route->get('[/{news_id:\d+}]', 'Admin\\NewsController@edit');
$route->post('[/{id:\d+}]', 'Admin\\NewsController@save'); $route->post('[/{news_id:\d+}]', 'Admin\\NewsController@save');
} }
); );
} }

View File

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

View File

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

View File

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

View File

@ -1,5 +1,7 @@
<?php <?php
declare(strict_types=1);
namespace Database\Factories\Engelsystem\Models; namespace Database\Factories\Engelsystem\Models;
use Engelsystem\Models\News; use Engelsystem\Models\News;
@ -9,19 +11,17 @@ use Illuminate\Database\Eloquent\Factories\Factory;
class NewsFactory extends Factory class NewsFactory extends Factory
{ {
/** @var string */ /** @var string */
protected $model = News::class; protected $model = News::class; // phpcs:ignore
/** 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),
'user_id' => User::factory(), 'is_highlighted' => $this->faker->boolean(.1),
'user_id' => User::factory(),
]; ];
} }
} }

View File

@ -0,0 +1,30 @@
<?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

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

View File

@ -0,0 +1,24 @@
<?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

@ -0,0 +1,30 @@
<?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,5 +1,7 @@
<?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;
@ -8,17 +10,15 @@ use Illuminate\Database\Eloquent\Factories\Factory;
class ScheduleFactory extends Factory class ScheduleFactory extends Factory
{ {
/** @var string */ /** @var string */
protected $model = Schedule::class; protected $model = Schedule::class; // phpcs:ignore
/** public function definition(): array
* @return array
*/
public function definition()
{ {
return [ return [
'name' => $this->faker->words(4, true), 'name' => $this->faker->unique()->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

@ -0,0 +1,31 @@
<?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

@ -0,0 +1,34 @@
<?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

@ -0,0 +1,22 @@
<?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,21 +1,22 @@
<?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; protected $model = Contact::class; // phpcs:ignore
/** 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; protected $model = License::class; // phpcs:ignore
/** 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,14 +21,30 @@ 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 [
'has_car' => $drive_car && $this->faker->boolean(.7), 'user_id' => User::factory(),
'drive_forklift' => $drive_forklift, 'has_car' => $drive_car && $this->faker->boolean(.7),
'drive_car' => $drive_car, 'drive_forklift' => $drive_forklift,
'drive_3_5t' => $drive_3_5t, 'drive_car' => $drive_car,
'drive_7_5t' => $drive_7_5t, 'drive_3_5t' => $drive_3_5t,
'drive_12t' => $drive_12t, 'drive_7_5t' => $drive_7_5t,
'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,22 +1,23 @@
<?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; protected $model = PasswordReset::class; // phpcs:ignore
/** public function definition(): array
* @return array
*/
public function definition()
{ {
return [ return [
'token' => md5($this->faker->unique()->password()), 'user_id' => User::factory(),
'token' => bin2hex(random_bytes(16)),
]; ];
} }
} }

View File

@ -1,25 +1,26 @@
<?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; protected $model = PersonalData::class; // phpcs:ignore
/** 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,27 +1,30 @@
<?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; protected $model = Settings::class; // phpcs:ignore
/** 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_goody' => $this->faker->boolean(), 'email_messages' => $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; protected $model = State::class; // phpcs:ignore
/** public function definition(): array
* @return array
*/
public function definition()
{ {
$arrival = $this->faker->optional()->dateTimeThisMonth(); $arrival = $this->faker->optional()->dateTimeThisMonth();
return [ return [
'arrived' => (bool)$arrival, 'user_id' => User::factory(),
'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_shirt' => $this->faker->boolean(), 'got_goodie' => $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() public function arrived(): self
{ {
return $this->state( return $this->state(
function (array $attributes) { function (array $attributes) {

View File

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

View File

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

View File

@ -1,802 +0,0 @@
-- 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,12 +1,15 @@
<?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
{ {
protected $oldTables = [ /** @var array<string> */
protected array $oldTables = [
'AngelTypes', 'AngelTypes',
'EventConfig', 'EventConfig',
'GroupPrivileges', 'GroupPrivileges',
@ -26,31 +29,17 @@ 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() public function down(): void
{ {
$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,29 +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 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,5 +1,7 @@
<?php <?php
declare(strict_types=1);
namespace Engelsystem\Migrations; namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration; use Engelsystem\Database\Migration\Migration;
@ -10,7 +12,7 @@ class FixOldTables extends Migration
/** /**
* Run the migration * Run the migration
*/ */
public function up() public function up(): void
{ {
$connection = $this->schema->getConnection(); $connection = $this->schema->getConnection();
@ -29,16 +31,9 @@ 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) { $this->schema->table($table, function (Blueprint $table) use ($column): void {
$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,5 +1,7 @@
<?php <?php
declare(strict_types=1);
namespace Engelsystem\Migrations; namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration; use Engelsystem\Database\Migration\Migration;
@ -9,7 +11,7 @@ class CleanupGroupPrivileges extends Migration
/** /**
* Run the migration * Run the migration
*/ */
public function up() public function up(): void
{ {
if (!$this->schema->hasTable('GroupPrivileges')) { if (!$this->schema->hasTable('GroupPrivileges')) {
return; return;
@ -43,7 +45,7 @@ class CleanupGroupPrivileges extends Migration
/** /**
* Reverse the migration * Reverse the migration
*/ */
public function down() public function down(): void
{ {
if (!$this->schema->hasTable('GroupPrivileges')) { if (!$this->schema->hasTable('GroupPrivileges')) {
return; return;

View File

@ -1,5 +1,7 @@
<?php <?php
declare(strict_types=1);
namespace Engelsystem\Migrations; namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration; use Engelsystem\Database\Migration\Migration;
@ -7,7 +9,7 @@ use Engelsystem\Database\Migration\Migration;
class AddAngelSupporterPermissions extends Migration class AddAngelSupporterPermissions extends Migration
{ {
/** @var string[] */ /** @var string[] */
protected $data = [ protected array $data = [
'2-Engel', '2-Engel',
'shiftentry_edit_angeltype_supporter', 'shiftentry_edit_angeltype_supporter',
]; ];
@ -15,7 +17,7 @@ class AddAngelSupporterPermissions extends Migration
/** /**
* Run the migration * Run the migration
*/ */
public function up() public function up(): void
{ {
if (!$this->schema->hasTable('GroupPrivileges')) { if (!$this->schema->hasTable('GroupPrivileges')) {
return; return;
@ -39,7 +41,7 @@ class AddAngelSupporterPermissions extends Migration
/** /**
* Reverse the migration * Reverse the migration
*/ */
public function down() public function down(): void
{ {
if (!$this->schema->hasTable('GroupPrivileges')) { if (!$this->schema->hasTable('GroupPrivileges')) {
return; return;
@ -52,11 +54,7 @@ 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,5 +1,7 @@
<?php <?php
declare(strict_types=1);
namespace Engelsystem\Migrations; namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration; use Engelsystem\Database\Migration\Migration;
@ -10,9 +12,9 @@ class CreateLogEntriesTable extends Migration
/** /**
* Run the migration * Run the migration
*/ */
public function up() public function up(): void
{ {
$this->schema->create('log_entries', function (Blueprint $table) { $this->schema->create('log_entries', function (Blueprint $table): void {
$table->increments('id'); $table->increments('id');
$table->string('level', 20); $table->string('level', 20);
$table->text('message'); $table->text('message');
@ -32,9 +34,9 @@ class CreateLogEntriesTable extends Migration
/** /**
* Reverse the migration * Reverse the migration
*/ */
public function down() public function down(): void
{ {
$this->schema->create('LogEntries', function (Blueprint $table) { $this->schema->create('LogEntries', function (Blueprint $table): void {
$table->increments('id'); $table->increments('id');
$table->string('level', 20); $table->string('level', 20);
$table->text('message'); $table->text('message');

View File

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

View File

@ -1,16 +1,18 @@
<?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 $mapping = [ protected array $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',
@ -20,11 +22,11 @@ class CreateEventConfigTable extends Migration
/** /**
* Run the migration * Run the migration
*/ */
public function up() public function up(): void
{ {
foreach (['json', 'text'] as $type) { foreach (['json', 'text'] as $type) {
try { try {
$this->schema->create('event_config', function (Blueprint $table) use ($type) { $this->schema->create('event_config', function (Blueprint $table) use ($type): void {
$table->string('name')->index()->unique(); $table->string('name')->index()->unique();
$table->{$type}('value'); $table->{$type}('value');
$table->timestamps(); $table->timestamps();
@ -41,26 +43,24 @@ class CreateEventConfigTable extends Migration
} }
if ($this->schema->hasTable('EventConfig')) { if ($this->schema->hasTable('EventConfig')) {
$config = $this->schema->getConnection() $connection = $this->schema->getConnection();
$config = $connection
->table('EventConfig') ->table('EventConfig')
->first(); ->first();
if (!empty($config)) { if (!empty($config)) {
(new EventConfig([ $connection->table('event_config')
'name' => 'name', ->insert([
'value' => $config->event_name, ['name' => 'name', 'value' => $config->event_name],
]))->save(); ['name' => 'welcome_msg', 'value' => $config->event_welcome_msg],
]);
(new EventConfig([
'name' => 'welcome_msg',
'value' => $config->event_welcome_msg,
]))->save();
foreach ($this->mapping as $old => $new) { foreach ($this->mapping as $old => $new) {
(new EventConfig([ $connection->table('event_config')
'name' => $new, ->insert([
'value' => (new Carbon())->setTimestamp($config->{$old}), 'name' => $new,
]))->save(); 'value' => (new Carbon())->setTimestamp($config->{$old}),
]);
} }
} }
@ -71,9 +71,11 @@ class CreateEventConfigTable extends Migration
/** /**
* Reverse the migration * Reverse the migration
*/ */
public function down() public function down(): void
{ {
$this->schema->create('EventConfig', function (Blueprint $table) { $connection = $this->schema->getConnection();
$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();
@ -82,19 +84,19 @@ class CreateEventConfigTable extends Migration
$table->string('event_welcome_msg')->nullable(); $table->string('event_welcome_msg')->nullable();
}); });
$config = new EventConfig(); $config = $connection->table('event_config')->get();
$data = [ $data = [
'event_name' => $config->findOrNew('name')->value, 'event_name' => $this->getConfigValue($config, 'name'),
'event_welcome_msg' => $config->findOrNew('welcome_msg')->value, 'event_welcome_msg' => $this->getConfigValue($config, 'welcome_msg'),
]; ];
foreach ($this->mapping as $new => $old) { foreach ($this->mapping as $new => $old) {
/** @var Carbon $value */ $value = $this->getConfigValue($config, $old);
$value = $config->findOrNew($old)->value;
if (!$value) { if (!$value) {
continue; continue;
} }
$value = Carbon::make($value);
$data[$new] = $value->getTimestamp(); $data[$new] = $value->getTimestamp();
} }
@ -111,4 +113,11 @@ 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,15 +1,11 @@
<?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;
@ -21,9 +17,9 @@ class CreateUsersTables extends Migration
/** /**
* Run the migration * Run the migration
*/ */
public function up() public function up(): void
{ {
$this->schema->create('users', function (Blueprint $table) { $this->schema->create('users', function (Blueprint $table): void {
$table->increments('id'); $table->increments('id');
$table->string('name', 24)->unique(); $table->string('name', 24)->unique();
@ -35,7 +31,7 @@ class CreateUsersTables extends Migration
$table->timestamps(); $table->timestamps();
}); });
$this->schema->create('users_personal_data', function (Blueprint $table) { $this->schema->create('users_personal_data', function (Blueprint $table): void {
$this->referencesUser($table, true); $this->referencesUser($table, true);
$table->string('first_name', 64)->nullable(); $table->string('first_name', 64)->nullable();
@ -46,7 +42,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) { $this->schema->create('users_contact', function (Blueprint $table): void {
$this->referencesUser($table, true); $this->referencesUser($table, true);
$table->string('dect', 5)->nullable(); $table->string('dect', 5)->nullable();
@ -54,7 +50,7 @@ class CreateUsersTables extends Migration
$table->string('email', 254)->nullable(); $table->string('email', 254)->nullable();
}); });
$this->schema->create('users_settings', function (Blueprint $table) { $this->schema->create('users_settings', function (Blueprint $table): void {
$this->referencesUser($table, true); $this->referencesUser($table, true);
$table->string('language', 64); $table->string('language', 64);
@ -63,7 +59,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) { $this->schema->create('users_state', function (Blueprint $table): void {
$this->referencesUser($table, true); $this->referencesUser($table, true);
$table->boolean('arrived')->default(false); $table->boolean('arrived')->default(false);
@ -74,7 +70,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) { $this->schema->create('password_resets', function (Blueprint $table): void {
$this->referencesUser($table, true); $this->referencesUser($table, true);
$table->text('token'); $table->text('token');
@ -83,33 +79,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 = $this->schema->getConnection()->table('User')->get(); $users = $connection->table('User')->get();
foreach ($users as $data) { foreach ($users as $data) {
$user = new User([ $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->setAttribute('created_at', new Carbon($data->CreateDate)); $user['created_at'] = new Carbon($data->CreateDate);
} }
$user->save(); $connection->table('users')->insert($user);
$contact = new Contact([ $connection->table('users_contact')->insert([
'dect' => $data->DECT ? $data->DECT : null, 'user_id' => $data->UID,
'mobile' => $data->Handy ?: ($data->Telefon ?: null), 'dect' => $data->DECT ?: null,
'mobile' => $data->Handy ?: ($data->Telefon ?: null),
]); ]);
$contact->user()
->associate($user)
->save();
$personalData = new PersonalData([ $connection->table('users_personal_data')->insert([
'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,
@ -120,24 +116,17 @@ class CreateUsersTables extends Migration
? Carbon::createFromTimestamp($data->planned_departure_date) ? Carbon::createFromTimestamp($data->planned_departure_date)
: null, : null,
]); ]);
$personalData->user()
->associate($user)
->save();
$settings = new Settings([ $connection->table('users_settings')->insert([
'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);
$settings->user() $connection->table('users_state')->insert([
->associate($user) 'user_id' => $data->UID,
->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,
@ -145,17 +134,12 @@ 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) {
$passwordReset = new PasswordReset([ $connection->table('password_resets')->insert([
'token' => $data->password_recovery_token, 'user_id' => $data->UID,
'token' => $data->password_recovery_token,
]); ]);
$passwordReset->user()
->associate($user)
->save();
} }
} }
@ -173,10 +157,12 @@ class CreateUsersTables extends Migration
/** /**
* Reverse the migration * Reverse the migration
*/ */
public function down() public function down(): void
{ {
$this->schema->create('User', function (Blueprint $table) { $connection = $this->schema->getConnection();
$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();
@ -217,12 +203,16 @@ class CreateUsersTables extends Migration
$table->index('planned_departure_date', 'planned_departure_date'); $table->index('planned_departure_date', 'planned_departure_date');
}); });
foreach (User::all() as $user) { foreach ($connection->table('users')->get() as $user) {
/** @var User $user */ /** @var stdClass $user */
$contact = $user->contact; /** @var stdClass $contact */
$personal = $user->personalData; $contact = $connection->table('users_contact')->where('user_id', $user->id)->first();
$settings = $user->settings; /** @var stdClass $personal */
$state = $user->state; $personal = $connection->table('users_personal_data')->where('user_id', $user->id)->first();
/** @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()
@ -244,23 +234,28 @@ 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 ? $user->last_login_at->getTimestamp() : null, 'lastLogIn' => $user->last_login_at
'CreateDate' => $user->created_at ? $user->created_at->toDateTimeString() : null, ? Carbon::make($user->last_login_at)->getTimestamp()
: 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 ? $state->arrival_date->getTimestamp() : null, 'arrival_date' => $state->arrival_date
'planned_arrival_date' => $personal->planned_arrival_date ? Carbon::make($state->arrival_date)->getTimestamp()
? $personal->planned_arrival_date->getTimestamp()
: null, : null,
'planned_arrival_date' => $personal->planned_arrival_date
? Carbon::make($personal->planned_arrival_date)->getTimestamp()
: 0,
'planned_departure_date' => $personal->planned_departure_date 'planned_departure_date' => $personal->planned_departure_date
? $personal->planned_departure_date->getTimestamp() ? Carbon::make($personal->planned_departure_date)->getTimestamp()
: null, : null,
'email_by_human_allowed' => $settings->email_human, 'email_by_human_allowed' => $settings->email_human,
]); ]);
} }
foreach (PasswordReset::all() as $passwordReset) { foreach ($connection->table('password_resets')->get() 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,5 +1,7 @@
<?php <?php
declare(strict_types=1);
namespace Engelsystem\Migrations; namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration; use Engelsystem\Database\Migration\Migration;
@ -7,8 +9,7 @@ use Illuminate\Database\Schema\Blueprint;
class ChangeUsersContactDectFieldSize extends Migration class ChangeUsersContactDectFieldSize extends Migration
{ {
/** @var array */ protected array $tables = [
protected $tables = [
'AngelTypes' => 'contact_dect', 'AngelTypes' => 'contact_dect',
'users_contact' => 'dect', 'users_contact' => 'dect',
]; ];
@ -16,7 +17,7 @@ class ChangeUsersContactDectFieldSize extends Migration
/** /**
* Run the migration * Run the migration
*/ */
public function up() public function up(): void
{ {
$this->changeDectTo(40); $this->changeDectTo(40);
} }
@ -24,22 +25,19 @@ class ChangeUsersContactDectFieldSize extends Migration
/** /**
* Reverse the migration * Reverse the migration
*/ */
public function down() public function down(): void
{ {
$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) { $this->schema->table($table, function (Blueprint $table) use ($column, $length): void {
$table->string($column, $length)->change(); $table->string($column, $length)->change();
}); });
} }

View File

@ -1,28 +1,37 @@
<?php <?php
declare(strict_types=1);
namespace Engelsystem\Migrations; namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration; use Engelsystem\Database\Migration\Migration;
use Engelsystem\Models\User\State; use stdClass;
class FixMissingArrivalDates extends Migration class FixMissingArrivalDates extends Migration
{ {
/** /**
* Run the migration * Run the migration
*/ */
public function up() public function up(): void
{ {
$states = State::whereArrived(true)->whereArrivalDate(null)->get(); $connection = $this->schema->getConnection();
/** @var stdClass[] $states */
$states = $connection
->table('users_state')
->where('arrived', true)
->where('arrival_date', null)
->get();
foreach ($states as $state) { foreach ($states as $state) {
$state->arrival_date = $state->user->personalData->planned_arrival_date; /** @var stdClass $personalData */
$state->save(); $personalData = $connection
->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,5 +1,7 @@
<?php <?php
declare(strict_types=1);
namespace Engelsystem\Migrations; namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration; use Engelsystem\Database\Migration\Migration;
@ -9,26 +11,26 @@ class FixUserLanguages extends Migration
/** /**
* Run the migration * Run the migration
*/ */
public function up() public function up(): void
{ {
$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() public function down(): void
{ {
$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,5 +1,7 @@
<?php <?php
declare(strict_types=1);
namespace Engelsystem\Migrations; namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration; use Engelsystem\Database\Migration\Migration;
@ -9,7 +11,7 @@ class MigrateAdminSchedulePermissions extends Migration
/** /**
* Run the migration * Run the migration
*/ */
public function up() public function up(): void
{ {
if (!$this->schema->hasTable('Privileges')) { if (!$this->schema->hasTable('Privileges')) {
return; return;
@ -29,7 +31,7 @@ class MigrateAdminSchedulePermissions extends Migration
/** /**
* Reverse the migration * Reverse the migration
*/ */
public function down() public function down(): void
{ {
if (!$this->schema->hasTable('Privileges')) { if (!$this->schema->hasTable('Privileges')) {
return; return;

View File

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

View File

@ -64,12 +64,9 @@ 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) { $this->schema->create('news', function (Blueprint $table): void {
$table->increments('id'); $table->increments('id');
$table->string('title', 150); $table->string('title', 150);
$table->text('text'); $table->text('text');
@ -79,9 +76,6 @@ class CreateNewsTable extends Migration
}); });
} }
/**
* @return void
*/
private function copyPreviousToNewNewsTable(): void private function copyPreviousToNewNewsTable(): void
{ {
$connection = $this->schema->getConnection(); $connection = $this->schema->getConnection();
@ -104,25 +98,18 @@ class CreateNewsTable extends Migration
} }
} }
/**
* @return void
*/
private function createPreviousNewsTable(): void private function createPreviousNewsTable(): void
{ {
$this->schema->create('News', function (Blueprint $table) { $this->schema->create('News', function (Blueprint $table): void {
$table->increments('ID'); $table->increments('ID');
$table->integer('Datum'); $table->integer('Datum');
$table->string('Betreff', 150) $table->string('Betreff', 150)->default('');
->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,12 +53,9 @@ 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) { $this->schema->create('news_comments', function (Blueprint $table): void {
$table->increments('id'); $table->increments('id');
$this->references($table, 'news', 'news_id'); $this->references($table, 'news', 'news_id');
$table->text('text'); $table->text('text');
@ -67,9 +64,6 @@ class CreateNewsCommentsTable extends Migration
}); });
} }
/**
* @return void
*/
private function copyPreviousToNewNewsCommentsTable(): void private function copyPreviousToNewNewsCommentsTable(): void
{ {
$connection = $this->schema->getConnection(); $connection = $this->schema->getConnection();
@ -90,12 +84,9 @@ class CreateNewsCommentsTable extends Migration
} }
} }
/**
* @return void
*/
private function createPreviousNewsCommentsTable(): void private function createPreviousNewsCommentsTable(): void
{ {
$this->schema->create('NewsComments', function (Blueprint $table) { $this->schema->create('NewsComments', function (Blueprint $table): void {
$table->increments('ID'); $table->increments('ID');
$this->references($table, 'news', 'Refid'); $this->references($table, 'news', 'Refid');
$table->dateTime('Datum'); $table->dateTime('Datum');
@ -104,9 +95,6 @@ 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,27 +64,18 @@ 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( $this->schema->create('messages', function (Blueprint $table): void {
'messages', $table->increments('id');
function (Blueprint $table) { $this->referencesUser($table);
$table->increments('id'); $this->references($table, 'users', 'receiver_id');
$this->referencesUser($table); $table->boolean('read')->default(0);
$this->references($table, 'users', 'receiver_id'); $table->text('text');
$table->boolean('read')->default(0); $table->timestamps();
$table->text('text'); });
$table->timestamps();
}
);
} }
/**
* @return void
*/
private function copyPreviousToNewMessagesTable(): void private function copyPreviousToNewMessagesTable(): void
{ {
$connection = $this->schema->getConnection(); $connection = $this->schema->getConnection();
@ -109,28 +100,18 @@ class CreateMessagesTable extends Migration
} }
} }
/**
* @return void
*/
private function createPreviousMessagesTable(): void private function createPreviousMessagesTable(): void
{ {
$this->schema->create( $this->schema->create('Messages', function (Blueprint $table): void {
'Messages', $table->increments('id');
function (Blueprint $table) { $table->integer('Datum');
$table->increments('id'); $this->references($table, 'users', 'SUID');
$table->integer('Datum'); $this->references($table, 'users', 'RUID');
$this->references($table, 'users', 'SUID'); $table->char('isRead')->default('N');
$this->references($table, 'users', 'RUID'); $table->text('Text');
$table->char('isRead') });
->default('N');
$table->text('Text');
}
);
} }
/**
* @return void
*/
private function copyNewToPreviousMessagesTable(): void private function copyNewToPreviousMessagesTable(): void
{ {
$connection = $this->schema->getConnection(); $connection = $this->schema->getConnection();

View File

@ -17,9 +17,6 @@ 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');
@ -43,9 +40,6 @@ 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
@ -63,28 +57,17 @@ 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( $this->schema->create('questions', function (Blueprint $table): void {
'questions', $table->increments('id');
function (Blueprint $table) { $this->referencesUser($table);
$table->increments('id'); $table->text('text');
$this->referencesUser($table); $table->text('answer')->nullable();
$table->text('text'); $this->references($table, 'users', 'answerer_id')->nullable();
$table->text('answer') });
->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();
@ -104,28 +87,17 @@ class CreateQuestionsTable extends Migration
} }
} }
/**
* @return void
*/
private function createPreviousQuestionsTable(): void private function createPreviousQuestionsTable(): void
{ {
$this->schema->create( $this->schema->create('Questions', function (Blueprint $table): void {
'Questions', $table->increments('QID');
function (Blueprint $table) { $this->references($table, 'users', 'UID');
$table->increments('QID'); $table->text('Question');
$this->references($table, 'users', 'UID'); $this->references($table, 'users', 'AID')->nullable();
$table->text('Question'); $table->text('Answer')->nullable();
$this->references($table, 'users', 'AID') });
->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,11 +14,8 @@ class UserPersonalDataAddPronounField extends Migration
*/ */
public function up(): void public function up(): void
{ {
$this->schema->table('users_personal_data', function (Blueprint $table) { $this->schema->table('users_personal_data', function (Blueprint $table): void {
$table->string('pronoun', 15) $table->string('pronoun', 15)->nullable()->default(null)->after('last_name');
->nullable()
->default(null)
->after('last_name');
}); });
} }
@ -27,7 +24,7 @@ class UserPersonalDataAddPronounField extends Migration
*/ */
public function down(): void public function down(): void
{ {
$this->schema->table('users_personal_data', function (Blueprint $table) { $this->schema->table('users_personal_data', function (Blueprint $table): void {
$table->dropColumn('pronoun'); $table->dropColumn('pronoun');
}); });
} }

View File

@ -28,11 +28,5 @@ 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,21 +5,19 @@ 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) { $this->schema->create('rooms', function (Blueprint $table): void {
$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();
@ -35,13 +33,13 @@ class CreateRoomsTable extends Migration
->get(); ->get();
foreach ($previousRecords as $previousRecord) { foreach ($previousRecords as $previousRecord) {
$room = new Room([ $connection->table('rooms')
'name' => $previousRecord->Name, ->insert([
'map_url' => $previousRecord->map_url ?: null, 'id' => $previousRecord->RID,
'description' => $previousRecord->description ?: null, 'name' => $previousRecord->Name,
]); 'map_url' => $previousRecord->map_url ?: null,
$room->setAttribute('id', $previousRecord->RID); 'description' => $previousRecord->description ?: null,
$room->save(); ]);
} }
$this->changeReferences( $this->changeReferences(
@ -60,16 +58,18 @@ class CreateRoomsTable extends Migration
*/ */
public function down(): void public function down(): void
{ {
$this->schema->create('Room', function (Blueprint $table) { $connection = $this->schema->getConnection();
$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 (Room::all() as $room) { foreach ($connection->table('rooms')->get() as $room) {
$this->schema /** @var stdClass $room */
->getConnection() $connection
->table('Room') ->table('Room')
->insert([ ->insert([
'RID' => $room->id, 'RID' => $room->id,

View File

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

View File

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

View File

@ -1,32 +1,34 @@
<?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
{ {
$this->schema->table('questions', function (Blueprint $table) { $connection = $this->schema->getConnection();
$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();
}); });
$now = Carbon::now(); $connection->table('questions')
Question::query()->update([ ->update([
'created_at' => $now, 'created_at' => $now,
'updated_at' => $now, 'updated_at' => $now,
]); ]);
Question::query() $connection->table('questions')
->whereNotNull('answerer_id') ->whereNotNull('answerer_id')
->update([ ->update([
'answered_at' => $now, 'answered_at' => $now,
@ -38,7 +40,7 @@ class AddTimestampsToQuestions extends Migration
*/ */
public function down(): void public function down(): void
{ {
$this->schema->table('questions', function (Blueprint $table) { $this->schema->table('questions', function (Blueprint $table): void {
$table->dropColumn('answered_at'); $table->dropColumn('answered_at');
$table->dropTimestamps(); $table->dropTimestamps();
}); });

View File

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

View File

@ -1,5 +1,7 @@
<?php <?php
declare(strict_types=1);
namespace Engelsystem\Migrations; namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration; use Engelsystem\Database\Migration\Migration;
@ -9,7 +11,7 @@ class CreateQuestionsPermissions extends Migration
/** /**
* Run the migration * Run the migration
*/ */
public function up() public function up(): void
{ {
if ($this->schema->hasTable('Privileges')) { if ($this->schema->hasTable('Privileges')) {
$db = $this->schema->getConnection(); $db = $this->schema->getConnection();
@ -36,7 +38,7 @@ class CreateQuestionsPermissions extends Migration
/** /**
* Reverse the migration * Reverse the migration
*/ */
public function down() public function down(): void
{ {
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) { $this->schema->create('oauth', function (Blueprint $table): void {
$table->increments('id'); $table->increments('id');
$this->referencesUser($table); $this->referencesUser($table);
$table->string('provider'); $table->string('provider');

View File

@ -1,10 +1,11 @@
<?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
@ -14,39 +15,34 @@ class AddNameMinutesAndTimestampsToSchedules extends Migration
/** /**
* Run the migration * Run the migration
*/ */
public function up() public function up(): void
{ {
$this->schema->table( $connection = $this->schema->getConnection();
'schedules',
function (Blueprint $table) {
$table->string('name')->default('')->after('id');
$table->integer('shift_type')->default(0)->after('name');
$table->integer('minutes_before')->default(0)->after('shift_type');
$table->integer('minutes_after')->default(0)->after('minutes_before');
$table->timestamps();
}
);
Schedule::query() $this->schema->table('schedules', function (Blueprint $table): void {
$table->string('name')->default('')->after('id');
$table->unsignedInteger('shift_type')->default(0)->after('name');
$table->integer('minutes_before')->default(0)->after('shift_type');
$table->integer('minutes_after')->default(0)->after('minutes_before');
$table->timestamps();
});
$connection->table('schedules')
->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( $this->schema->table('schedules', function (Blueprint $table): void {
'schedules', $table->string('name')->default(null)->change();
function (Blueprint $table) { $table->unsignedInteger('shift_type')->default(null)->change();
$table->string('name')->default(null)->change(); $table->integer('minutes_before')->default(null)->change();
$table->integer('shift_type')->default(null)->change(); $table->integer('minutes_after')->default(null)->change();
$table->integer('minutes_before')->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')
@ -54,33 +50,29 @@ 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);
Schedule::query() $connection->table('schedules')
->update(['shift_type' => $connection->raw('(' . $query->toSql() . ')')]); ->update([
'shift_type' => $connection->raw('(' . $query->toSql() . ')'),
]);
$this->schema->table( $this->schema->table('schedules', function (Blueprint $table): void {
'schedules', $this->addReference($table, 'shift_type', 'ShiftTypes');
function (Blueprint $table) { });
$this->addReference($table, 'shift_type', 'ShiftTypes');
}
);
} }
} }
/** /**
* Reverse the migration * Reverse the migration
*/ */
public function down() public function down(): void
{ {
$this->schema->table( $this->schema->table('schedules', function (Blueprint $table): void {
'schedules', $table->dropForeign('schedules_shift_type_foreign');
function (Blueprint $table) { $table->dropColumn('name');
$table->dropForeign('schedules_shift_type_foreign'); $table->dropColumn('shift_type');
$table->dropColumn('name'); $table->dropColumn('minutes_before');
$table->dropColumn('shift_type'); $table->dropColumn('minutes_after');
$table->dropColumn('minutes_before'); $table->dropTimestamps();
$table->dropColumn('minutes_after'); });
$table->dropTimestamps();
}
);
} }
} }

View File

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

View File

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

View File

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

View File

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

View File

@ -0,0 +1,45 @@
<?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,48 +1,41 @@
<?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
{ {
use Reference; public function __construct(SchemaBuilder $schemaBuilder, protected Config $config)
/** @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() public function up(): void
{ {
/** @var User $admin */ $db = $this->schema->getConnection();
$admin = $this->auth->authenticate('admin', 'asdfasdf'); /** @var stdClass $admin */
$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;
} }
$this->auth->setPassword($admin, $setupPassword); $db->table('users')
->where('id', $admin->id)
->update(['password' => password_hash($setupPassword, PASSWORD_DEFAULT)]);
} }
} }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -0,0 +1,82 @@
<?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

@ -0,0 +1,31 @@
<?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

@ -0,0 +1,31 @@
<?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

@ -0,0 +1,39 @@
<?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

@ -0,0 +1,262 @@
<?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

@ -0,0 +1,158 @@
<?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

@ -0,0 +1,43 @@
<?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

@ -0,0 +1,86 @@
<?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

@ -0,0 +1,126 @@
<?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

@ -0,0 +1,101 @@
<?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

@ -0,0 +1,45 @@
<?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

@ -0,0 +1,149 @@
<?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

@ -0,0 +1,114 @@
<?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