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
max_line_length = 120
[{.babelrc,package.json}]
[{.babelrc,package.json,.eslintrc.json,.prettierrc.json}]
indent_size = 2
[docker/**.conf]
@ -27,6 +27,8 @@ max_line_length = unset
indent_size = 2
[*.js]
indent_size = 2
max_line_length = unset
quote_type = single
[{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
/config/config.php
/test/coverage
/config/lang/
/public/*.xml
/public/coverage
/test/coverage
/coverage
/unittests.xml
/resources/lang/*/*.mo
@ -40,3 +42,4 @@ _vimrc_local.vim
/public/assets
/package-lock.json
/yarn-error.log
/.yarn-cache

View File

@ -12,6 +12,7 @@ variables:
DOCROOT: /var/www/
stages:
- prepare
- validate
- build
- test
@ -20,44 +21,90 @@ stages:
- deploy-production
- stop
#
# Validation
#
.use_cache: &use_cache
cache:
key: "$CI_JOB_NAME-$CI_COMMIT_REF_SLUG"
paths:
- .yarn-cache/
- vendor/
check-style:
image: composer:latest
stage: validate
# for jobs that depend on composer
.use_composer: &use_composer
<<: *use_cache
needs:
- composer install
before_script:
- composer --no-ansi global config --no-plugins allow-plugins.dealerdirect/phpcodesniffer-composer-installer true
- composer --no-ansi global require slevomat/coding-standard squizlabs/php_codesniffer
- export PATH=$PATH:$COMPOSER_HOME/vendor/bin
script:
- phpcs -p --no-colors --basepath="$PWD"
- composer install --no-ansi --no-progress
check-editorconfig:
image: mstruebing/editorconfig-checker
stage: validate
script:
- ec -v
# for jobs that depend on yarn
.use_yarn: &use_yarn
<<: *use_cache
needs:
- yarn install
before_script:
- yarn install --check-frontend --cache-folder .yarn-cache
validate-composer:
#
# Preparation
#
composer validate:
image: composer:latest
stage: validate
stage: prepare
script:
- 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
stage: validate
stage: prepare
before_script:
- yarn global add package-json-validator
- export PATH=$PATH:~/.yarn/bin
script:
- 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:
image: alpine
stage: validate
stage: prepare
artifacts:
name: "${CI_JOB_NAME}_${CI_JOB_ID}_version"
expire_in: 1 day
@ -66,10 +113,64 @@ generate-version:
before_script:
- apk add -q git
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 -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
#
@ -87,39 +188,25 @@ build-image:
<<: *container_definition
stage: build
needs:
- check-editorconfig
- check-style
- phpcs
- phpstan
- composer validate
- yarn check
- yarn lint
- translations lint
- generate-version
- validate-composer
- validate-yarn
dependencies:
- generate-version
script:
- /kaniko/executor --context ${CI_PROJECT_DIR}
--dockerfile ${CI_PROJECT_DIR}/docker/Dockerfile
--destination "${TEST_IMAGE}"
--cache=true
#
# 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:
image:
name: ${TEST_IMAGE}
@ -148,10 +235,11 @@ test:
- ./bin/migrate
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/"
--log-junit "${HOMEDIR}/unittests.xml"
after_script:
- sed -i 's~/var/www/~~' unittests.xml
- '"${DOCROOT}/bin/migrate" down'
dump-database:
@ -172,6 +260,9 @@ dump-database:
- cd "${DOCROOT}"
- ./bin/migrate
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}"
> "${HOMEDIR}/initial-install.sql"
@ -201,7 +292,11 @@ release-image:
- test
dependencies: [ ]
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:
- main
@ -218,8 +313,8 @@ build-release-file:
stage: release
needs:
- build-image
- audit-yarn
- audit-composer
- yarn audit
- composer audit
- test
- dump-database
- generate-assets
@ -274,6 +369,7 @@ deploy:
dependencies: *deploy_needs
environment:
name: rsync-staging
deployment_tier: development
only:
- main
script:
@ -296,7 +392,10 @@ deploy:
- test
- build-image
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
<<: *kubectl_deployment
@ -311,8 +410,12 @@ deploy:
# 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_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_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
# 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}"}
@ -321,19 +424,24 @@ deploy:
- export CI_CLUSTER_ISSUER=${CI_CLUSTER_ISSUER:-letsencrypt}
- export CI_SETUP_ADMIN_PASSWORD=${CI_SETUP_ADMIN_PASSWORD}
- echo "Generating config"
- cp deployment.tpl.yaml deployment.yaml
- >-
for env in ${!CI_*}; do
sed -i "s#<${env}>#$( echo "${!env}" | head -n1 | sed -e 's~\\~\\\\~' -e 's~#~\\#~' )#g" deployment.yaml;
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}"
- 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
- >-
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
.deploy_k8s_stop: &deploy_k8s_stop
@ -344,7 +452,8 @@ deploy:
GIT_STRATEGY: none
when: manual
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
@ -353,6 +462,7 @@ deploy-k8s-review:
on_stop: stop-k8s-review
auto_stop_in: 1 week
url: https://${CI_PROJECT_PATH_SLUG}-review.${KUBE_INGRESS_BASE_DOMAIN}/${CI_COMMIT_REF_SLUG}
deployment_tier: development
variables:
CI_REPLICAS_REVIEW: 1
CI_APP_NAME: review/${CI_COMMIT_REF_NAME}
@ -366,6 +476,7 @@ stop-k8s-review:
environment:
name: review/${CI_COMMIT_REF_NAME}
action: stop
deployment_tier: development
#
# Deploy production
@ -376,8 +487,8 @@ deploy-production:
stage: deploy-production
needs:
- test
- audit-yarn
- audit-composer
- yarn audit
- composer audit
- build-image
- generate-assets
dependencies:
@ -385,6 +496,7 @@ deploy-production:
- generate-assets
environment:
name: rsync-production
deployment_tier: production
when: manual
only:
- main
@ -404,8 +516,8 @@ deploy-k8s-production:
stage: deploy-production
needs:
- release-image
- audit-yarn
- audit-composer
- yarn audit
- composer audit
environment:
name: production
on_stop: stop-k8s-production

View File

@ -4,9 +4,11 @@
<file>config</file>
<file>db</file>
<file>includes</file>
<file>public/index.php</file>
<file>src</file>
<file>tests</file>
<exclude-pattern>/config/config.php</exclude-pattern>
<rule ref="PSR12" />
<rule ref="SlevomatCodingStandard.Namespaces.UnusedUses">
@ -19,4 +21,32 @@
<property name="ignoreUnusedValuesWhenOnlyKeysAreUsedInForeach" value="true" />
</properties>
</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>

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
* 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 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.
* Code must pass PHPStan checks (`composer phpstan`)
* Order the composer/npm dependencies alphabetically.
* 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.
* Do not use code from the [includes](includes) directory anywhere else.
* Don't refactor [includes](includes) code just for the sake of change, it is legacy code that must only be replaced.
* Please cover your code by unit tests, 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.
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
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)
* 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!).
* Clone the main branch: `git clone https://github.com/engelsystem/engelsystem.git`
@ -35,11 +123,11 @@ The following instructions explain how to get, build and run the latest Engelsys
```
* Generate translation files
```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
To run the unit tests use
To run only unit tests (tests that should not change the Engelsystem state) use
```bash
vendor/bin/phpunit --testsuite Unit
```
@ -48,19 +136,34 @@ If a database is configured and the Engelsystem is allowed to mess around with s
The tests can potentially delete some database entries, so they should never be run on a production system!
```bash
vendor/bin/phpunit --testsuite Feature
# or for unit- and feature tests:
```
When you want to run unit and feature tests at once:
```bash
vendor/bin/phpunit
```
To run code coverage reports its highly recommended to use [`pcov`](https://github.com/krakjoe/pcov) or
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.
```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
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`.
@ -74,7 +177,7 @@ To view the output of `dump` call the following commands:
```bash
vendor/bin/var-dump-server
# 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)
@ -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.
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
@ -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
```
## Docker
## Static code analysis
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
You can run a static code analysis with this command:
```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 '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
composer phpstan
```
**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).
### Requirements
* PHP >= 7.4
* PHP >= 8.1
* Required modules:
* dom
* 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
* 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
* 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.
### Configuration and Setup
* 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 read the ```.htaccess``` file and ```mod_rewrite``` must be enabled
* 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 read the `.htaccess` file and `mod_rewrite` must be enabled
* Recommended: Directory Listing should be disabled.
* 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```.
* 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 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.
* If necessary, create a `config/config.php` to override values from `config/config.default.php`.
* To disable/remove values from the following lists, set the value of the entry to `null`:
* `themes`
* `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.
@ -55,7 +64,7 @@ The Engelsystem can now be used.
To build the `es_server` container:
```bash
cd docker
docker-compose build
docker compose build
```
or to build the container by its own:
@ -67,14 +76,14 @@ docker build -f docker/Dockerfile . -t es_server
Start the Engelsystem
```bash
cd docker
docker-compose up -d
docker compose up -d
```
#### Migrate
Import database changes to migrate it to the newest version
#### Set Up / Migrate Database
Create the Database Schema (on a fresh install) or import database changes to migrate it to the newest version
```bash
cd docker
docker-compose exec es_server bin/migrate
docker compose exec es_server bin/migrate
```
### 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 Engelsystem\Application;
use Engelsystem\Database\Migration\Migrate;
use Engelsystem\Database\Migration\Direction;
use Engelsystem\Database\Migration\MigrationServiceProvider;
use Engelsystem\Environment;
use Engelsystem\Exceptions\Handler;
use Engelsystem\Exceptions\Handlers\NullHandler;
@ -19,7 +21,7 @@ $app->register(MigrationServiceProvider::class);
/** @var Handler $errorHandler */
$errorHandler = $app->get(Handler::class);
$errorHandler->setHandler(Handler::ENV_PRODUCTION, new NullHandler());
$errorHandler->setHandler(Environment::PRODUCTION, new NullHandler());
/** @var Migrate $migration */
$migration = $app->get('db.migration');
@ -32,10 +34,10 @@ if (in_array('help', $argv) || in_array('--help', $argv) || in_array('-h', $argv
exit;
}
$method = Migrate::UP;
$direction = Direction::UP;
if (in_array('down', $argv)) {
$argv = array_values($argv);
$method = Migrate::DOWN;
$direction = Direction::DOWN;
}
$oneStep = false;
@ -48,4 +50,4 @@ if (in_array('force', $argv) || in_array('--force', $argv) || in_array('-f', $ar
$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": {
"phpcs": "phpcs -p",
"phpcbf": "phpcbf -p"
"phpcs:setup": "phpcs --config-set php_version 80100",
"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": {
"php": ">=7.4.0",
"php": ">=8.1.0",
"ext-json": "*",
"ext-libxml": "*",
"ext-mbstring": "*",
"ext-pdo": "*",
"ext-simplexml": "*",
"ext-xml": "*",
"doctrine/dbal": "^3.2",
"doctrine/dbal": "^3.7",
"erusev/parsedown": "^1.7",
"gettext/gettext": "^5.6",
"gettext/translator": "^1.0",
"guzzlehttp/guzzle": "^7.4",
"illuminate/container": "^8.76",
"illuminate/database": "^8.76",
"illuminate/support": "^8.76",
"league/oauth2-client": "^2.6",
"gettext/gettext": "^5.7",
"gettext/translator": "^1.2",
"guzzlehttp/guzzle": "^7.8",
"illuminate/container": "^10.38",
"illuminate/database": "^10.38",
"illuminate/support": "^10.38",
"league/oauth2-client": "^2.7",
"league/openapi-psr7-validator": "^0.21",
"nikic/fast-route": "^1.3",
"nyholm/psr7": "^1.4",
"psr/container": "^1.1",
"nyholm/psr7": "^1.8",
"psr/container": "^2.0",
"psr/http-message": "^1.1",
"psr/http-server-middleware": "^1.0",
"psr/log": "^1.1",
"rcrowe/twigbridge": "^0.14.0",
"psr/log": "^3.0",
"rcrowe/twigbridge": "^0.14.1",
"respect/validation": "^1.1",
"symfony/http-foundation": "^5.4",
"symfony/mailer": "^5.4",
"symfony/psr-http-message-bridge": "^2.1",
"twig/twig": "^3.3",
"vlucas/phpdotenv": "^5.4"
"symfony/http-foundation": "^6.4",
"symfony/mailer": "^6.4",
"symfony/psr-http-message-bridge": "^2.3",
"twig/twig": "^3.8",
"vlucas/phpdotenv": "^5.6"
},
"require-dev": {
"dms/phpunit-arraysubset-asserts": "^0.3.1",
"fakerphp/faker": "^1.17",
"filp/whoops": "^2.14",
"phpunit/phpunit": "^9.5",
"slevomat/coding-standard": "^7.1",
"squizlabs/php_codesniffer": "^3.6",
"symfony/var-dumper": "^5.4"
"dms/phpunit-arraysubset-asserts": "^0.5",
"fakerphp/faker": "^1.23",
"fig/log-test": "^1.1",
"filp/whoops": "^2.15",
"phpstan/phpstan": "^1.10",
"phpunit/phpunit": "^9.6",
"slevomat/coding-standard": "^8.14",
"squizlabs/php_codesniffer": "^3.8",
"symfony/var-dumper": "^6.4"
},
"autoload": {
"psr-4": {

3598
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
// Application config
return [
@ -26,7 +28,6 @@ return [
\Engelsystem\Renderer\TwigServiceProvider::class,
\Engelsystem\Middleware\RouteDispatcherServiceProvider::class,
\Engelsystem\Middleware\RequestHandlerServiceProvider::class,
\Engelsystem\Middleware\SessionHandlerServiceProvider::class,
\Engelsystem\Http\Validation\ValidationServiceProvider::class,
\Engelsystem\Http\RedirectServiceProvider::class,
@ -36,6 +37,7 @@ return [
\Engelsystem\Http\HttpClientServiceProvider::class,
\Engelsystem\Helpers\DumpServerServiceProvider::class,
\Engelsystem\Helpers\UuidServiceProvider::class,
\Engelsystem\Controllers\Api\UsesAuthServiceProvider::class,
],
// Application middleware
@ -46,10 +48,13 @@ return [
// Changes of request/response parameters
\Engelsystem\Middleware\SetLocale::class,
\Engelsystem\Middleware\ETagHandler::class,
\Engelsystem\Middleware\AddHeaders::class,
\Engelsystem\Middleware\TrimInput::class,
// The application code
\Engelsystem\Middleware\ErrorHandler::class,
\Engelsystem\Middleware\ApiRouteHandler::class,
\Engelsystem\Middleware\VerifyCsrfToken::class,
\Engelsystem\Middleware\RouteDispatcher::class,
\Engelsystem\Middleware\SessionHandler::class,
@ -64,11 +69,22 @@ return [
// a list of
// 'Class@method' or 'Class' (which uses @handle),
// ['Class', 'method'],
// callable like [$instance, 'method] or 'function'
// callable like [$instance, 'method'] or 'function'
// or $function
// ]
'message.created' => \Engelsystem\Events\Listener\Messages::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',
'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
declare(strict_types=1);
// To change settings create a config.php
return [
@ -11,41 +13,58 @@ return [
'password' => env('MYSQL_PASSWORD', ''),
],
// For accessing stats
'api_key' => '',
// For accessing /metrics (and /stats)
'api_key' => env('API_KEY', ''),
// 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'),
// Set to development to enable debugging messages
'environment' => env('ENVIRONMENT', 'production'),
// Application URL and base path to use instead of the auto detected one
'url' => env('APP_URL', null),
// Application URL and base path to use instead of the auto-detected one
'url' => env('APP_URL'),
// Header links
// Available link placeholders: %lang%
// To disable a header_item in the config.php, you can set its value to null
'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
// To disable a footer item in the config.php, you can set its value to null
'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
'FAQ' => env('FAQ_URL', '/faq'),
'faq.faq' => [env('FAQ_URL', '/faq'), 'faq.view'],
// Contact email address, linked on every page
'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
'faq_text' => env('FAQ_TEXT', null),
'faq_text' => env('FAQ_TEXT'),
// Link to documentation/help
'documentation_url' => 'https://engelsystem.de/doc/',
'documentation_url' => env('DOCUMENTATION_URL', 'https://engelsystem.de/doc/'),
// Email config
'email' => [
@ -60,17 +79,20 @@ return [
'host' => env('MAIL_HOST', 'localhost'),
'port' => env('MAIL_PORT', 587),
// If tls transport encryption should be used
'tls' => env('MAIL_TLS', null),
'tls' => env('MAIL_TLS'),
'username' => env('MAIL_USERNAME'),
'password' => env('MAIL_PASSWORD'),
'sendmail' => env('MAIL_SENDMAIL', '/usr/sbin/sendmail -bs'),
],
# Your privacy@ contact address
'privacy_email' => '',
// Your privacy@ contact address
'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
'setup_admin_password' => env('SETUP_ADMIN_PASSWORD', null),
'setup_admin_password' => env('SETUP_ADMIN_PASSWORD'),
'oauth' => [
// '[name]' => [config]
@ -88,6 +110,8 @@ return [
'url_token' => '[generated by provider]',
// User info URL which provides userdata
'url_info' => '[generated by provider]',
// OAuth Scopes
// 'scope' => ['openid'],
// Info unique user id field
'id' => 'uuid',
// The following fields are used for registration
@ -127,7 +151,19 @@ return [
// Default theme, 1=style1.css
'theme' => env('THEME', 1),
// Supported themes
// To disable a theme in the config.php, you can set its value to null
'themes' => [
17 => [
'name' => 'Engelsystem 37c3 (2023)',
'type' => 'dark',
'navbar_classes' => 'navbar-dark',
],
16 => [
'name' => 'Engelsystem cccamp23 (2023)',
'type' => 'dark',
'navbar_classes' => 'navbar-dark',
],
15 => [
'name' => 'Engelsystem rC3 (2021)',
'type' => 'dark',
@ -214,17 +250,33 @@ return [
// Must be one of news, meetings, user_shifts, angeltypes, questions
'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),
// 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
'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
'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
// Setting this to 0 disables the feature
@ -246,48 +298,65 @@ return [
// Define the algorithm to use for `password_verify()`
// 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
'password_algorithm' => PASSWORD_DEFAULT,
'password_algorithm' => env('PASSWORD_ALGORITHM', PASSWORD_DEFAULT),
// The minimum length for passwords
'min_password_length' => env('PASSWORD_MINIMUM_LENGTH', 8),
// Whether the Password field should be enabled on registration.
// This is useful when using oauth, disabling it also disables normal
// registration without oauth.
'enable_password' => (bool)env('ENABLE_PASSWORD', true),
// 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 registration without oauth
'enable_password' => (bool) env('ENABLE_PASSWORD', true),
// 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
'enable_user_name' => (bool)env('ENABLE_USER_NAME', false),
// Whether the mobile number can be shown to other users
'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_pronoun' => (bool)env('ENABLE_PRONOUN', true),
'enable_pronoun' => (bool) env('ENABLE_PRONOUN', true),
// 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
'enable_tshirt_size' => (bool)env('ENABLE_TSHIRT_SIZE', true),
// Whether force active should be enabled
'enable_force_active' => (bool) env('ENABLE_FORCE_ACTIVE', true),
// Enables the goody configuration on signup and profile
'enable_goody' => (bool)env('ENABLE_GOODY', false),
// Resembles the Goodie Type. There are three options:
// '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
'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.
'max_freeloadable_shifts' => env('MAX_FREELOADABLE_SHIFTS', 2),
// Local timezone
'timezone' => env('TIMEZONE', ini_get('date.timezone') ?: 'Europe/Berlin'),
// Hide columns in backend user view. Possible values are any sortable parameters of the table.
'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' => [
'enabled' => (bool)env('NIGHT_SHIFTS', true), // Disable to weigh every shift the same
'start' => env('NIGHT_SHIFTS_START', 2),
'end' => env('NIGHT_SHIFTS_END', 6),
'enabled' => (bool) env('NIGHT_SHIFTS', true), // Disable to weigh every shift the same
'start' => env('NIGHT_SHIFTS_START', 2), // Starting from hour
'end' => env('NIGHT_SHIFTS_END', 8), // Ends at (without including) hour
'multiplier' => env('NIGHT_SHIFTS_MULTIPLIER', 2),
],
@ -297,10 +366,20 @@ return [
'shifts_per_voucher' => env('SHIFTS_PER_VOUCHER', 0),
'hours_per_voucher' => env('HOURS_PER_VOUCHER', 2),
// '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/
// To disable a locale in the config.php, you can set its value to null
'locales' => [
'de_DE' => 'Deutsch',
'en_US' => 'English',
@ -309,21 +388,31 @@ return [
// The default locale to use
'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' => [
'S' => 'Small Straight-Cut',
'S-G' => 'Small Fitted-Cut',
'S-F' => 'Small Fitted-Cut',
'M' => 'Medium Straight-Cut',
'M-G' => 'Medium Fitted-Cut',
'M-F' => 'Medium Fitted-Cut',
'L' => 'Large Straight-Cut',
'L-G' => 'Large Fitted-Cut',
'L-F' => 'Large Fitted-Cut',
'XL' => 'XLarge Straight-Cut',
'XL-G' => 'XLarge Fitted-Cut',
'XL-F' => 'XLarge Fitted-Cut',
'2XL' => '2XLarge Straight-Cut',
'3XL' => '3XLarge 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' => [
// 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],
@ -342,18 +431,26 @@ return [
// Cookie name
'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
'trusted_proxies' => env('TRUSTED_PROXIES', ['127.0.0.0/8', '::ffff:127.0.0.0/8', '::1/128']),
// 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' => [
'X-Content-Type-Options' => 'nosniff',
'X-Frame-Options' => 'sameorigin',
'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',
'Feature-Policy' => 'autoplay \'none\'',
//'Strict-Transport-Security' => 'max-age=7776000',
@ -364,7 +461,7 @@ return [
'credits' => [
'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) '
. 'or need help.'
. 'or need help.',
],
// var dump server

View File

@ -1,11 +1,15 @@
<?php
declare(strict_types=1);
use FastRoute\RouteCollector;
/** @var RouteCollector $route */
// Pages
$route->get('/', 'HomeController@index');
$route->get('/register', 'RegistrationController@view');
$route->post('/register', 'RegistrationController@save');
$route->get('/credits', 'CreditsController@index');
$route->get('/health', 'HealthController@index');
@ -15,54 +19,154 @@ $route->post('/login', 'AuthController@postLogin');
$route->get('/logout', 'AuthController@logout');
// OAuth
$route->get('/oauth/{provider}', 'OAuthController@index');
$route->post('/oauth/{provider}/connect', 'OAuthController@connect');
$route->post('/oauth/{provider}/disconnect', 'OAuthController@disconnect');
$route->addGroup(
'/oauth/{provider}',
function (RouteCollector $route): void {
$route->get('', 'OAuthController@index');
$route->post('/connect', 'OAuthController@connect');
$route->post('/disconnect', 'OAuthController@disconnect');
}
);
// User settings
$route->get('/settings/password', 'SettingsController@password');
$route->post('/settings/password', 'SettingsController@savePassword');
$route->get('/settings/theme', 'SettingsController@theme');
$route->post('/settings/theme', 'SettingsController@saveTheme');
$route->get('/settings/language', 'SettingsController@language');
$route->post('/settings/language', 'SettingsController@saveLanguage');
$route->get('/settings/oauth', 'SettingsController@oauth');
$route->addGroup(
'/settings',
function (RouteCollector $route): void {
$route->get('/profile', 'SettingsController@profile');
$route->post('/profile', 'SettingsController@saveProfile');
$route->get('/password', 'SettingsController@password');
$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
$route->get('/password/reset', 'PasswordResetController@reset');
$route->post('/password/reset', 'PasswordResetController@postReset');
$route->get('/password/reset/{token:.+}', 'PasswordResetController@resetPassword');
$route->post('/password/reset/{token:.+}', 'PasswordResetController@postResetPassword');
$route->addGroup(
'/password/reset',
function (RouteCollector $route): void {
$route->get('', 'PasswordResetController@reset');
$route->post('', 'PasswordResetController@postReset');
$route->get('/{token:.+}', 'PasswordResetController@resetPassword');
$route->post('/{token:.+}', 'PasswordResetController@postResetPassword');
}
);
// Stats
$route->get('/metrics', 'Metrics\\Controller@metrics');
$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
$route->get('/news', 'NewsController@index');
$route->get('/meetings', 'NewsController@meetings');
$route->get('/news/{id:\d+}', 'NewsController@show');
$route->post('/news/{id:\d+}', 'NewsController@comment');
$route->post('/news/comment/{id:\d+}', 'NewsController@deleteComment');
$route->addGroup(
'/news',
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
$route->get('/faq', 'FaqController@index');
// Questions
$route->get('/questions', 'QuestionsController@index');
$route->post('/questions', 'QuestionsController@delete');
$route->get('/questions/new', 'QuestionsController@add');
$route->post('/questions/new', 'QuestionsController@save');
$route->addGroup(
'/questions',
function (RouteCollector $route): void {
$route->get('', 'QuestionsController@index');
$route->post('', 'QuestionsController@delete');
$route->get('/new', 'QuestionsController@add');
$route->post('/new', 'QuestionsController@save');
}
);
// Messages
$route->get('/messages', 'MessagesController@index');
$route->post('/messages', 'MessagesController@redirectToConversation');
$route->get('/messages/{user_id:\d+}', 'MessagesController@messagesOfConversation');
$route->post('/messages/{user_id:\d+}', 'MessagesController@send');
$route->post('/messages/{user_id:\d+}/{msg_id:\d+}', 'MessagesController@delete');
$route->addGroup(
'/messages',
function (RouteCollector $route): void {
$route->get('', 'MessagesController@index');
$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
$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
$route->get('/design', 'DesignController@index');
@ -70,59 +174,118 @@ $route->get('/design', 'DesignController@index');
// Administration
$route->addGroup(
'/admin',
function (RouteCollector $route) {
function (RouteCollector $route): void {
// FAQ
$route->addGroup(
'/faq',
function (RouteCollector $route) {
$route->get('[/{id:\d+}]', 'Admin\\FaqController@edit');
$route->post('[/{id:\d+}]', 'Admin\\FaqController@save');
function (RouteCollector $route): void {
$route->get('[/{faq_id:\d+}]', 'Admin\\FaqController@edit');
$route->post('[/{faq_id:\d+}]', 'Admin\\FaqController@save');
}
);
// Log
$route->get('/logs', 'Admin\\LogsController@index');
$route->post('/logs', 'Admin\\LogsController@index');
$route->addGroup(
'/logs',
function (RouteCollector $route): void {
$route->get('', 'Admin\\LogsController@index');
$route->post('', 'Admin\\LogsController@index');
}
);
// Schedule
$route->addGroup(
'/schedule',
function (RouteCollector $route) {
$route->get('', 'Admin\\Schedule\\ImportSchedule@index');
$route->get('/edit[/{id:\d+}]', 'Admin\\Schedule\\ImportSchedule@edit');
$route->post('/edit[/{id:\d+}]', 'Admin\\Schedule\\ImportSchedule@save');
$route->get('/load/{id:\d+}', 'Admin\\Schedule\\ImportSchedule@loadSchedule');
$route->post('/import/{id:\d+}', 'Admin\\Schedule\\ImportSchedule@importSchedule');
function (RouteCollector $route): void {
$route->get('', 'Admin\\ScheduleController@index');
$route->get('/edit[/{schedule_id:\d+}]', 'Admin\\ScheduleController@edit');
$route->post('/edit[/{schedule_id:\d+}]', 'Admin\\ScheduleController@save');
$route->get('/load/{schedule_id:\d+}', 'Admin\\ScheduleController@loadSchedule');
$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
$route->addGroup(
'/questions',
function (RouteCollector $route) {
function (RouteCollector $route): void {
$route->get('', 'Admin\\QuestionsController@index');
$route->post('', 'Admin\\QuestionsController@delete');
$route->get('/{id:\d+}', 'Admin\\QuestionsController@edit');
$route->post('/{id:\d+}', 'Admin\\QuestionsController@save');
$route->get('/{question_id:\d+}', 'Admin\\QuestionsController@edit');
$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
$route->addGroup(
'/user/{id:\d+}',
// Shirts
function (RouteCollector $route) {
$route->get('/shirt', 'Admin\\UserShirtController@editShirt');
$route->post('/shirt', 'Admin\\UserShirtController@saveShirt');
'/user/{user_id:\d+}',
function (RouteCollector $route): void {
// Goodies
$route->addGroup(
'/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
$route->addGroup(
'/news',
function (RouteCollector $route) {
$route->get('[/{id:\d+}]', 'Admin\\NewsController@edit');
$route->post('[/{id:\d+}]', 'Admin\\NewsController@save');
function (RouteCollector $route): void {
$route->get('[/{news_id:\d+}]', 'Admin\\NewsController@edit');
$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
declare(strict_types=1);
namespace Database\Factories\Engelsystem\Models;
use Engelsystem\Models\Faq;
@ -8,12 +10,9 @@ use Illuminate\Database\Eloquent\Factories\Factory;
class FaqFactory extends Factory
{
/** @var string */
protected $model = Faq::class;
protected $model = Faq::class; // phpcs:ignore
/**
* @return array
*/
public function definition()
public function definition(): array
{
return [
'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
declare(strict_types=1);
namespace Database\Factories\Engelsystem\Models;
use Engelsystem\Models\Room;
use Engelsystem\Models\Location;
use Illuminate\Database\Eloquent\Factories\Factory;
class RoomFactory extends Factory
class LocationFactory extends Factory
{
/** @var string */
protected $model = Room::class;
protected $model = Location::class; // phpcs:ignore
/**
* @return array
*/
public function definition()
public function definition(): array
{
return [
'name' => $this->faker->unique()->firstName(),
'map_url' => $this->faker->url(),
'description' => $this->faker->text(),
'dect' => $this->faker->optional()->numberBetween(1000, 9999),
];
}
}

View File

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

View File

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

View File

@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
namespace Database\Factories\Engelsystem\Models;
use Engelsystem\Models\News;
@ -9,18 +11,16 @@ use Illuminate\Database\Eloquent\Factories\Factory;
class NewsFactory extends Factory
{
/** @var string */
protected $model = News::class;
protected $model = News::class; // phpcs:ignore
/**
* @return array
*/
public function definition()
public function definition(): array
{
return [
'title' => $this->faker->text(50),
'text' => $this->faker->realText(),
'is_meeting' => $this->faker->boolean(),
'is_pinned' => $this->faker->boolean(.1),
'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
declare(strict_types=1);
namespace Database\Factories\Engelsystem\Models;
use Carbon\Carbon;
@ -10,12 +12,9 @@ use Illuminate\Database\Eloquent\Factories\Factory;
class QuestionFactory extends Factory
{
/** @var string */
protected $model = Question::class;
protected $model = Question::class; // phpcs:ignore
/**
* @return array
*/
public function definition()
public function definition(): array
{
return [
'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
declare(strict_types=1);
namespace Database\Factories\Engelsystem\Models\Shifts;
use Engelsystem\Models\Shifts\Schedule;
@ -8,17 +10,15 @@ use Illuminate\Database\Eloquent\Factories\Factory;
class ScheduleFactory extends Factory
{
/** @var string */
protected $model = Schedule::class;
protected $model = Schedule::class; // phpcs:ignore
/**
* @return array
*/
public function definition()
public function definition(): array
{
return [
'name' => $this->faker->words(4, true),
'name' => $this->faker->unique()->words(4, true),
'url' => $this->faker->parse('https://{{safeEmailDomain}}/{{slug}}.xml'),
'shift_type' => $this->faker->numberBetween(1, 5),
'needed_from_shift_type' => $this->faker->boolean(.2),
'minutes_before' => 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
declare(strict_types=1);
namespace Database\Factories\Engelsystem\Models\User;
use Engelsystem\Models\User\Contact;
use Engelsystem\Models\User\User;
use Illuminate\Database\Eloquent\Factories\Factory;
class ContactFactory extends Factory
{
/** @var string */
protected $model = Contact::class;
protected $model = Contact::class; // phpcs:ignore
/**
* @return array
*/
public function definition()
public function definition(): array
{
return [
'user_id' => User::factory(),
'dect' => $this->faker->optional()->numberBetween(1000, 9999),
'email' => $this->faker->unique()->optional()->safeEmail(),
'mobile' => $this->faker->optional(.2)->phoneNumber(),

View File

@ -1,19 +1,19 @@
<?php
declare(strict_types=1);
namespace Database\Factories\Engelsystem\Models\User;
use Engelsystem\Models\User\License;
use Engelsystem\Models\User\User;
use Illuminate\Database\Eloquent\Factories\Factory;
class LicenseFactory extends Factory
{
/** @var string */
protected $model = License::class;
protected $model = License::class; // phpcs:ignore
/**
* @return array
*/
public function definition()
public function definition(): array
{
$drive_car = $this->faker->boolean(.8);
$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_forklift = ($drive_car && $this->faker->boolean(.1))
|| ($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 [
'user_id' => User::factory(),
'has_car' => $drive_car && $this->faker->boolean(.7),
'drive_forklift' => $drive_forklift,
'drive_car' => $drive_car,
'drive_3_5t' => $drive_3_5t,
'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
declare(strict_types=1);
namespace Database\Factories\Engelsystem\Models\User;
use Engelsystem\Models\User\PasswordReset;
use Engelsystem\Models\User\User;
use Illuminate\Database\Eloquent\Factories\Factory;
class PasswordResetFactory extends Factory
{
/** @var string */
protected $model = PasswordReset::class;
protected $model = PasswordReset::class; // phpcs:ignore
/**
* @return array
*/
public function definition()
public function definition(): array
{
return [
'token' => md5($this->faker->unique()->password()),
'user_id' => User::factory(),
'token' => bin2hex(random_bytes(16)),
];
}
}

View File

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

View File

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

View File

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

View File

@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
namespace Database\Factories\Engelsystem\Models\User;
use Engelsystem\Models\User\User;
@ -8,18 +10,16 @@ use Illuminate\Database\Eloquent\Factories\Factory;
class UserFactory extends Factory
{
/** @var string */
protected $model = User::class;
protected $model = User::class; // phpcs:ignore
/**
* @return array
*/
public function definition()
public function definition(): array
{
return [
'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(),
'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
declare(strict_types=1);
namespace Database\Factories\Engelsystem\Models;
use Engelsystem\Models\User\User;
@ -9,12 +11,9 @@ use Illuminate\Database\Eloquent\Factories\Factory;
class WorklogFactory extends Factory
{
/** @var string */
protected $model = Worklog::class;
protected $model = Worklog::class; // phpcs:ignore
/**
* @return array
*/
public function definition()
public function definition(): array
{
return [
'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
declare(strict_types=1);
namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration;
class ImportInstallSql extends Migration
{
protected $oldTables = [
/** @var array<string> */
protected array $oldTables = [
'AngelTypes',
'EventConfig',
'GroupPrivileges',
@ -26,31 +29,17 @@ class ImportInstallSql extends Migration
'UserAngelTypes',
'UserDriverLicenses',
'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
*/
public function down()
public function down(): void
{
$this->schema->getConnection()->statement('SET FOREIGN_KEY_CHECKS=0;');
// Delete all remaining tables
foreach ($this->oldTables as $table) {
if ($this->schema->hasTable($table)) {
$this->schema->dropIfExists($table);

View File

@ -1,29 +1,12 @@
<?php
declare(strict_types=1);
namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration;
class ImportUpdateSql extends Migration
{
/**
* 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');
}
// Do nothing as the tables will be created by later migrations and deleted by ImportInstall
}

View File

@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration;
@ -10,7 +12,7 @@ class FixOldTables extends Migration
/**
* Run the migration
*/
public function up()
public function up(): void
{
$connection = $this->schema->getConnection();
@ -29,16 +31,9 @@ class FixOldTables extends Migration
->where($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();
});
}
}
/**
* Reverse the migration
*/
public function down()
{
}
}

View File

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

View File

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

View File

@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration;
@ -10,9 +12,9 @@ class CreateLogEntriesTable extends 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->string('level', 20);
$table->text('message');
@ -32,9 +34,9 @@ class CreateLogEntriesTable extends 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->string('level', 20);
$table->text('message');

View File

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

View File

@ -1,16 +1,18 @@
<?php
declare(strict_types=1);
namespace Engelsystem\Migrations;
use Carbon\Carbon;
use Engelsystem\Database\Migration\Migration;
use Engelsystem\Models\EventConfig;
use Illuminate\Database\QueryException;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Collection;
class CreateEventConfigTable extends Migration
{
protected $mapping = [
protected array $mapping = [
'buildup_start_date' => 'buildup_start',
'event_start_date' => 'event_start',
'event_end_date' => 'event_end',
@ -20,11 +22,11 @@ class CreateEventConfigTable extends Migration
/**
* Run the migration
*/
public function up()
public function up(): void
{
foreach (['json', 'text'] as $type) {
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->{$type}('value');
$table->timestamps();
@ -41,26 +43,24 @@ class CreateEventConfigTable extends Migration
}
if ($this->schema->hasTable('EventConfig')) {
$config = $this->schema->getConnection()
$connection = $this->schema->getConnection();
$config = $connection
->table('EventConfig')
->first();
if (!empty($config)) {
(new EventConfig([
'name' => 'name',
'value' => $config->event_name,
]))->save();
(new EventConfig([
'name' => 'welcome_msg',
'value' => $config->event_welcome_msg,
]))->save();
$connection->table('event_config')
->insert([
['name' => 'name', 'value' => $config->event_name],
['name' => 'welcome_msg', 'value' => $config->event_welcome_msg],
]);
foreach ($this->mapping as $old => $new) {
(new EventConfig([
$connection->table('event_config')
->insert([
'name' => $new,
'value' => (new Carbon())->setTimestamp($config->{$old}),
]))->save();
]);
}
}
@ -71,9 +71,11 @@ class CreateEventConfigTable extends 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->integer('buildup_start_date')->nullable();
$table->integer('event_start_date')->nullable();
@ -82,19 +84,19 @@ class CreateEventConfigTable extends Migration
$table->string('event_welcome_msg')->nullable();
});
$config = new EventConfig();
$config = $connection->table('event_config')->get();
$data = [
'event_name' => $config->findOrNew('name')->value,
'event_welcome_msg' => $config->findOrNew('welcome_msg')->value,
'event_name' => $this->getConfigValue($config, 'name'),
'event_welcome_msg' => $this->getConfigValue($config, 'welcome_msg'),
];
foreach ($this->mapping as $new => $old) {
/** @var Carbon $value */
$value = $config->findOrNew($old)->value;
$value = $this->getConfigValue($config, $old);
if (!$value) {
continue;
}
$value = Carbon::make($value);
$data[$new] = $value->getTimestamp();
}
@ -111,4 +113,11 @@ class CreateEventConfigTable extends Migration
$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
declare(strict_types=1);
namespace Engelsystem\Migrations;
use Carbon\Carbon;
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 stdClass;
@ -21,9 +17,9 @@ class CreateUsersTables extends 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->string('name', 24)->unique();
@ -35,7 +31,7 @@ class CreateUsersTables extends Migration
$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);
$table->string('first_name', 64)->nullable();
@ -46,7 +42,7 @@ class CreateUsersTables extends Migration
$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);
$table->string('dect', 5)->nullable();
@ -54,7 +50,7 @@ class CreateUsersTables extends Migration
$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);
$table->string('language', 64);
@ -63,7 +59,7 @@ class CreateUsersTables extends Migration
$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);
$table->boolean('arrived')->default(false);
@ -74,7 +70,7 @@ class CreateUsersTables extends Migration
$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);
$table->text('token');
@ -83,33 +79,33 @@ class CreateUsersTables extends Migration
});
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'];
/** @var stdClass[] $users */
$users = $this->schema->getConnection()->table('User')->get();
$users = $connection->table('User')->get();
foreach ($users as $data) {
$user = new User([
$user = [
'id' => $data->UID,
'name' => $data->Nick,
'password' => $data->Passwort,
'email' => $data->email,
'api_key' => $data->api_key,
'last_login_at' => $data->lastLogIn ? Carbon::createFromTimestamp($data->lastLogIn) : null,
]);
$user->setAttribute('id', $data->UID);
];
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([
'dect' => $data->DECT ? $data->DECT : null,
$connection->table('users_contact')->insert([
'user_id' => $data->UID,
'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,
'last_name' => $data->Name ?: null,
'shirt_size' => $data->Size ?: null,
@ -120,24 +116,17 @@ class CreateUsersTables extends Migration
? Carbon::createFromTimestamp($data->planned_departure_date)
: null,
]);
$personalData->user()
->associate($user)
->save();
$settings = new Settings([
$connection->table('users_settings')->insert([
'user_id' => $data->UID,
'language' => $data->Sprache,
'theme' => $data->color,
'email_human' => $data->email_by_human_allowed,
'email_shiftinfo' => $data->email_shiftinfo,
]);
unset($settings->email_news);
unset($settings->email_goody);
$settings->user()
->associate($user)
->save();
$state = new State([
$connection->table('users_state')->insert([
'user_id' => $data->UID,
'arrived' => $data->Gekommen,
'arrival_date' => $data->arrival_date ? Carbon::createFromTimestamp($data->arrival_date) : null,
'active' => $data->Aktiv,
@ -145,17 +134,12 @@ class CreateUsersTables extends Migration
'got_shirt' => $data->Tshirt,
'got_voucher' => $data->got_voucher,
]);
$state->user()
->associate($user)
->save();
if ($data->password_recovery_token) {
$passwordReset = new PasswordReset([
$connection->table('password_resets')->insert([
'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
*/
public function down()
public function down(): void
{
$this->schema->create('User', function (Blueprint $table) {
$table->integer('UID', true, false);
$connection = $this->schema->getConnection();
$this->schema->create('User', function (Blueprint $table): void {
$table->integer('UID', true);
$table->string('Nick', 23)->unique()->default('');
$table->string('Name', 23)->nullable();
@ -217,12 +203,16 @@ class CreateUsersTables extends Migration
$table->index('planned_departure_date', 'planned_departure_date');
});
foreach (User::all() as $user) {
/** @var User $user */
$contact = $user->contact;
$personal = $user->personalData;
$settings = $user->settings;
$state = $user->state;
foreach ($connection->table('users')->get() as $user) {
/** @var stdClass $user */
/** @var stdClass $contact */
$contact = $connection->table('users_contact')->where('user_id', $user->id)->first();
/** @var stdClass $personal */
$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
->getConnection()
@ -244,23 +234,28 @@ class CreateUsersTables extends Migration
'Tshirt' => $state->got_shirt,
'color' => $settings->theme,
'Sprache' => $settings->language,
'lastLogIn' => $user->last_login_at ? $user->last_login_at->getTimestamp() : null,
'CreateDate' => $user->created_at ? $user->created_at->toDateTimeString() : null,
'lastLogIn' => $user->last_login_at
? 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,
'got_voucher' => $state->got_voucher,
'arrival_date' => $state->arrival_date ? $state->arrival_date->getTimestamp() : null,
'planned_arrival_date' => $personal->planned_arrival_date
? $personal->planned_arrival_date->getTimestamp()
'arrival_date' => $state->arrival_date
? Carbon::make($state->arrival_date)->getTimestamp()
: null,
'planned_arrival_date' => $personal->planned_arrival_date
? Carbon::make($personal->planned_arrival_date)->getTimestamp()
: 0,
'planned_departure_date' => $personal->planned_departure_date
? $personal->planned_departure_date->getTimestamp()
? Carbon::make($personal->planned_departure_date)->getTimestamp()
: null,
'email_by_human_allowed' => $settings->email_human,
]);
}
foreach (PasswordReset::all() as $passwordReset) {
/** @var PasswordReset $passwordReset */
foreach ($connection->table('password_resets')->get() as $passwordReset) {
$this->schema->getConnection()
->table('User')
->where('UID', '=', $passwordReset->user_id)

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -6,7 +6,6 @@ namespace Engelsystem\Migrations;
use Carbon\Carbon;
use Engelsystem\Database\Migration\Migration;
use Engelsystem\Models\Worklog;
use Illuminate\Database\Schema\Blueprint;
use stdClass;
@ -20,7 +19,7 @@ class CreateWorklogsTable extends Migration
*/
public function up(): void
{
$this->schema->create('worklogs', function (Blueprint $table) {
$this->schema->create('worklogs', function (Blueprint $table): void {
$table->increments('id');
$this->referencesUser($table);
$this->references($table, 'users', 'creator_id');
@ -38,18 +37,20 @@ class CreateWorklogsTable extends Migration
->get();
foreach ($previousRecords as $previousRecord) {
$room = new Worklog([
$worked_at = Carbon::createFromTimestamp($previousRecord->work_timestamp);
$created_at = Carbon::createFromTimestamp($previousRecord->created_timestamp);
$this->schema->getConnection()
->table('worklogs')
->insert([
'id' => $previousRecord->id,
'user_id' => $previousRecord->user_id,
'creator_id' => $previousRecord->created_user_id,
'worked_at' => $previousRecord->work_timestamp,
'worked_at' => $worked_at,
'hours' => $previousRecord->work_hours,
'comment' => $previousRecord->comment,
'created_at' => $created_at,
'updated_at' => $created_at,
]);
$created_at = Carbon::createFromTimestamp($previousRecord->created_timestamp);
$room->setAttribute('id', $previousRecord->id);
$room->setAttribute('created_at', $created_at);
$room->setAttribute('updated_at', $created_at);
$room->save();
}
$this->changeReferences(
@ -68,7 +69,9 @@ class CreateWorklogsTable extends Migration
*/
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');
$this->referencesUser($table);
$table->integer('work_timestamp');
@ -78,19 +81,18 @@ class CreateWorklogsTable extends Migration
$table->integer('created_timestamp')->index();
});
foreach (Worklog::all() as $record) {
/** @var Worklog $record */
$this->schema
->getConnection()
foreach ($connection->table('worklogs')->get() as $record) {
/** @var stdClass $record */
$connection
->table('UserWorkLog')
->insert([
'id' => $record->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,
'comment' => $record->comment,
'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
declare(strict_types=1);
namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration;
@ -9,7 +11,7 @@ class CreateWelcomeAngelPermissionsGroup extends Migration
/**
* Run the migration
*/
public function up()
public function up(): void
{
if (!$this->schema->hasTable('Groups')) {
return;
@ -38,7 +40,7 @@ class CreateWelcomeAngelPermissionsGroup extends Migration
/**
* Reverse the migration
*/
public function down()
public function down(): void
{
if (!$this->schema->hasTable('Groups')) {
return;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration;
@ -7,33 +9,25 @@ use Illuminate\Database\Schema\Blueprint;
class OauthChangeTokensToText extends Migration
{
use Reference;
/**
* Run the migration
*/
public function up()
public function up(): void
{
$this->schema->table(
'oauth',
function (Blueprint $table) {
$this->schema->table('oauth', function (Blueprint $table): void {
$table->text('access_token')->change();
$table->text('refresh_token')->change();
}
);
});
}
/**
* Reverse the migration
*/
public function down()
public function down(): void
{
$this->schema->table(
'oauth',
function (Blueprint $table) {
$this->schema->table('oauth', function (Blueprint $table): void {
$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
declare(strict_types=1);
namespace Engelsystem\Migrations;
use Engelsystem\Config\Config;
use Engelsystem\Database\Migration\Migration;
use Engelsystem\Helpers\Authenticator;
use Engelsystem\Models\User\User;
use Illuminate\Database\Schema\Builder as SchemaBuilder;
use stdClass;
class SetAdminPassword extends Migration
{
use Reference;
/** @var Authenticator */
protected $auth;
/** @var Config */
protected $config;
/**
* @param SchemaBuilder $schemaBuilder
* @param Authenticator $auth
* @param Config $config
*/
public function __construct(SchemaBuilder $schemaBuilder, Authenticator $auth, Config $config)
public function __construct(SchemaBuilder $schemaBuilder, protected Config $config)
{
parent::__construct($schemaBuilder);
$this->auth = $auth;
$this->config = $config;
}
/**
* Run the migration
*/
public function up()
public function up(): void
{
/** @var User $admin */
$admin = $this->auth->authenticate('admin', 'asdfasdf');
$db = $this->schema->getConnection();
/** @var stdClass $admin */
$admin = $db->table('users')->where('name', 'admin')->first();
$setupPassword = $this->config->get('setup_admin_password');
if (!$admin || !$setupPassword) {
if (
!$admin
|| !password_verify('asdfasdf', $admin->password)
|| !$setupPassword
) {
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
declare(strict_types=1);
namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration;
@ -9,7 +11,7 @@ class AddShirtEditPermissions extends Migration
/**
* Run the migration
*/
public function up()
public function up(): void
{
if (!$this->schema->hasTable('GroupPrivileges')) {
return;
@ -40,7 +42,7 @@ class AddShirtEditPermissions extends Migration
/**
* Reverse the migration
*/
public function down()
public function down(): void
{
if (!$this->schema->hasTable('GroupPrivileges')) {
return;

View File

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

View File

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

View File

@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration;
@ -10,9 +12,9 @@ class IncreaseSessionsTablePayloadSize extends 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();
});
}
@ -20,9 +22,9 @@ class IncreaseSessionsTablePayloadSize extends 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();
});
}

View File

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

View File

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

View File

@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration;
@ -13,9 +15,9 @@ class IncreaseTshirtFieldWidth extends 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();
});
}
@ -23,9 +25,9 @@ class IncreaseTshirtFieldWidth extends 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();
});
}

View File

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

View File

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