├── .babelrc ├── .dockerignore ├── .editorconfig ├── .env.ci ├── .env.example ├── .gitattributes ├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md ├── dependabot.yml ├── pull_request_template.md └── workflows │ ├── ci-docker.yml │ ├── ci.yml │ ├── deploy-docs.yml │ ├── pull-locales.yml │ ├── update-bbb-recording-player.yml │ └── upload-locales.yml ├── .gitignore ├── .npmrc ├── .nvmrc ├── .nycrc.json ├── .opencode └── screenshots │ ├── de │ ├── app_settings.jpg │ ├── dashboard.jpg │ ├── home.jpg │ ├── login.jpg │ ├── profile_base.jpg │ ├── profile_security.jpg │ ├── roles.jpg │ ├── roles_detail.jpg │ ├── room_attendance.jpg │ ├── room_description.jpg │ ├── room_files.jpg │ ├── room_history.jpg │ ├── room_members.jpg │ ├── room_personalized_room_links.jpg │ ├── room_settings.jpg │ ├── room_stats.jpg │ ├── room_types.jpg │ ├── room_types_edit.jpg │ ├── room_types_edit_settings.jpg │ ├── running_meetings.jpg │ ├── server_pools.jpg │ ├── servers.jpg │ ├── servers_edit.jpg │ ├── settings.jpg │ └── users.jpg │ └── en │ ├── app_settings.jpg │ ├── dashboard.jpg │ ├── home.jpg │ ├── login.jpg │ ├── profile_base.jpg │ ├── profile_security.jpg │ ├── roles.jpg │ ├── roles_detail.jpg │ ├── room_attendance.jpg │ ├── room_description.jpg │ ├── room_files.jpg │ ├── room_history.jpg │ ├── room_members.jpg │ ├── room_personalized_room_links.jpg │ ├── room_settings.jpg │ ├── room_stats.jpg │ ├── room_types.jpg │ ├── room_types_edit.jpg │ ├── room_types_edit_settings.jpg │ ├── running_meetings.jpg │ ├── server_pools.jpg │ ├── servers.jpg │ ├── servers_edit.jpg │ ├── settings.jpg │ └── users.jpg ├── .prettierignore ├── .prettierrc ├── .styleci.yml ├── CODE_OF_CONDUCT.md ├── LICENSE ├── README.md ├── SECURITY.md ├── _ide_helper.php ├── app ├── Auth │ ├── ExternalUser.php │ ├── LDAP │ │ ├── LDAPController.php │ │ ├── LDAPProvider.php │ │ ├── LDAPServiceProvider.php │ │ ├── LDAPUser.php │ │ └── LDAPUserObject.php │ ├── Local │ │ └── LocalProvider.php │ ├── MissingAttributeException.php │ ├── Shibboleth │ │ ├── LogoutNotification.wsdl │ │ ├── ShibbolethController.php │ │ ├── ShibbolethProvider.php │ │ ├── ShibbolethServiceProvider.php │ │ ├── ShibbolethSessionDuplicateException.php │ │ ├── ShibbolethSessionMiddleware.php │ │ ├── ShibbolethUser.php │ │ └── SoapServerHandler.php │ └── config │ │ └── .gitignore ├── Console │ ├── Commands │ │ ├── CacheLocalesCommand.php │ │ ├── CheckDatabaseConnectionCommand.php │ │ ├── CleanupAttendanceCommand.php │ │ ├── CleanupRecordingsCommand.php │ │ ├── CleanupRoomsCommand.php │ │ ├── CleanupStatisticsCommand.php │ │ ├── CreateSuperuserCommand.php │ │ ├── DeleteObsoleteTokensCommand.php │ │ ├── DeleteUnverifiedNewUsersCommand.php │ │ ├── ExportLocalesCommand.php │ │ ├── ImportDatabaseCommand.php │ │ ├── ImportGreenlight2Command.php │ │ ├── ImportLocalesCommand.php │ │ ├── ImportRecordingsCommand.php │ │ ├── PollServerCommand.php │ │ ├── ProvisionCommand.php │ │ ├── TestEmailConfig.php │ │ ├── UpgradeDatabaseCommand.php │ │ └── UploadLocalesCommand.php │ └── Kernel.php ├── Enums │ ├── CustomStatusCodes.php │ ├── LinkButtonStyle.php │ ├── LinkTarget.php │ ├── RecordingAccess.php │ ├── RoomLobby.php │ ├── RoomSortingType.php │ ├── RoomUserRole.php │ ├── RoomVisibility.php │ ├── ServerHealth.php │ ├── ServerStatus.php │ └── TimePeriod.php ├── Events │ ├── RoomEnded.php │ └── RoomStarted.php ├── Exceptions │ ├── Handler.php │ ├── RecordingExtractionFailed.php │ └── RoomIdGenerationFailed.php ├── Exports │ └── AttendanceExport.php ├── Faker │ └── TextProvider.php ├── Http │ ├── Controllers │ │ ├── ApplicationController.php │ │ ├── Controller.php │ │ ├── FileController.php │ │ ├── MeetingController.php │ │ ├── RecordingController.php │ │ └── api │ │ │ └── v1 │ │ │ ├── ApplicationController.php │ │ │ ├── LocaleController.php │ │ │ ├── MeetingController.php │ │ │ ├── PermissionController.php │ │ │ ├── RecordingController.php │ │ │ ├── RecordingFormatController.php │ │ │ ├── RoleController.php │ │ │ ├── RoomController.php │ │ │ ├── RoomFileController.php │ │ │ ├── RoomMemberController.php │ │ │ ├── RoomStreamingController.php │ │ │ ├── RoomTokenController.php │ │ │ ├── RoomTypeController.php │ │ │ ├── RoomTypeStreamingController.php │ │ │ ├── ServerController.php │ │ │ ├── ServerPoolController.php │ │ │ ├── SessionController.php │ │ │ ├── SettingsController.php │ │ │ ├── StreamingController.php │ │ │ ├── UserController.php │ │ │ └── auth │ │ │ ├── ForgotPasswordController.php │ │ │ ├── LoginController.php │ │ │ ├── RegisterController.php │ │ │ ├── ResetPasswordController.php │ │ │ └── VerificationController.php │ ├── Kernel.php │ ├── Middleware │ │ ├── Authenticate.php │ │ ├── EncryptCookies.php │ │ ├── EnsureModelNotStale.php │ │ ├── LogContext.php │ │ ├── LoggedInUser.php │ │ ├── PreventRequestsDuringMaintenance.php │ │ ├── RedirectIfAuthenticated.php │ │ ├── RoomAuthenticate.php │ │ ├── RouteEnableIfConfig.php │ │ ├── SetApplicationLocale.php │ │ ├── StoreSessionData.php │ │ ├── TrimStrings.php │ │ ├── TrustHosts.php │ │ ├── TrustProxies.php │ │ └── VerifyCsrfToken.php │ ├── Requests │ │ ├── AddRoomMember.php │ │ ├── BulkDestroyRequest.php │ │ ├── BulkImportRequest.php │ │ ├── BulkUpdateRequest.php │ │ ├── ChangeEmailRequest.php │ │ ├── ChangeLocaleRequest.php │ │ ├── ChangePasswordRequest.php │ │ ├── CreateRoom.php │ │ ├── JoinMeeting.php │ │ ├── NewUserRequest.php │ │ ├── RoleRequest.php │ │ ├── RoomTokenRequest.php │ │ ├── RoomTypeDestroyRequest.php │ │ ├── RoomTypeRequest.php │ │ ├── ServerConnectionCheckRequest.php │ │ ├── ServerPoolRequest.php │ │ ├── ServerRequest.php │ │ ├── ShowRoomsRequest.php │ │ ├── StartMeeting.php │ │ ├── StoreRoomFile.php │ │ ├── TransferOwnershipRequest.php │ │ ├── UpdateRecordingRequest.php │ │ ├── UpdateRoomDescription.php │ │ ├── UpdateRoomFile.php │ │ ├── UpdateRoomMember.php │ │ ├── UpdateRoomSettings.php │ │ ├── UpdateRoomStreamingConfig.php │ │ ├── UpdateRoomTypeStreamingSettings.php │ │ ├── UpdateSettings.php │ │ ├── UpdateStreamingSettings.php │ │ ├── UserRequest.php │ │ └── VerifyEmailRequest.php │ └── Resources │ │ ├── Attendee.php │ │ ├── AttendeeSession.php │ │ ├── Config.php │ │ ├── LastMeeting.php │ │ ├── Meeting.php │ │ ├── MeetingStat.php │ │ ├── MeetingWithRoomAndServer.php │ │ ├── Permission.php │ │ ├── PermissionResourceCollection.php │ │ ├── PrivateRoomFile.php │ │ ├── RecordingFormatResource.php │ │ ├── RecordingResource.php │ │ ├── Role.php │ │ ├── RoleCollection.php │ │ ├── Room.php │ │ ├── RoomFile.php │ │ ├── RoomSettings.php │ │ ├── RoomStreaming.php │ │ ├── RoomStreamingConfig.php │ │ ├── RoomToken.php │ │ ├── RoomType.php │ │ ├── RoomTypeResourceCollection.php │ │ ├── RoomTypeStreamingSettings.php │ │ ├── RoomUser.php │ │ ├── Server.php │ │ ├── ServerPool.php │ │ ├── SessionResource.php │ │ ├── Settings.php │ │ ├── StreamingSettings.php │ │ ├── User.php │ │ └── UserSearch.php ├── Jobs │ ├── PollServerJob.php │ └── ProcessRecording.php ├── Listeners │ ├── ConfigureStreamingOnRoomStart.php │ ├── FailedLoginAttempt.php │ └── ResetStreamingOnRoomStop.php ├── Models │ ├── IncludedPermissionPermission.php │ ├── Meeting.php │ ├── MeetingAttendee.php │ ├── MeetingStat.php │ ├── Permission.php │ ├── PermissionRole.php │ ├── Recording.php │ ├── RecordingFormat.php │ ├── Role.php │ ├── RoleUser.php │ ├── Room.php │ ├── RoomFile.php │ ├── RoomStreaming.php │ ├── RoomToken.php │ ├── RoomType.php │ ├── RoomTypeStreamingSettings.php │ ├── RoomUser.php │ ├── Server.php │ ├── ServerPool.php │ ├── ServerStat.php │ ├── Session.php │ ├── SessionData.php │ ├── User.php │ └── VerifyEmail.php ├── Notifications │ ├── EmailChanged.php │ ├── PasswordChanged.php │ ├── PasswordReset.php │ ├── RoomExpires.php │ ├── TestEmail.php │ ├── UserWelcome.php │ └── VerifyEmail.php ├── Plugins │ ├── Contracts │ │ └── ServerLoadCalculationPluginContract.php │ ├── Custom │ │ └── .gitignore │ ├── Defaults │ │ └── ServerLoadCalculationPlugin.php │ └── PluginServiceProvider.php ├── Policies │ ├── MeetingPolicy.php │ ├── RolePolicy.php │ ├── RoomPolicy.php │ ├── RoomTypePolicy.php │ ├── ServerPolicy.php │ ├── ServerPoolPolicy.php │ └── UserPolicy.php ├── Providers │ ├── AppServiceProvider.php │ ├── AuthServiceProvider.php │ ├── BroadcastServiceProvider.php │ ├── EventServiceProvider.php │ ├── FakerServiceProvider.php │ ├── HorizonServiceProvider.php │ ├── RouteServiceProvider.php │ ├── TelescopeServiceProvider.php │ └── TranslationServiceProvider.php ├── Pulse │ └── Users.php ├── Rules │ ├── CustomCreateMeetingParameters.php │ ├── CustomJoinMeetingParameters.php │ ├── Password.php │ ├── ValidName.php │ └── ValidRoomType.php ├── Services │ ├── AuthenticationService.php │ ├── BigBlueButton │ │ └── LaravelHTTPClient.php │ ├── EmailVerification │ │ ├── EmailVerificationService.php │ │ └── NewVerifyEmailToken.php │ ├── LoadBalancingService.php │ ├── LocaleService.php │ ├── MeetingService.php │ ├── ProvisioningService.php │ ├── RoomAuthService.php │ ├── RoomFileService.php │ ├── RoomService.php │ ├── ServerService.php │ ├── StreamingService.php │ └── StreamingServiceFactory.php ├── Settings │ ├── BannerSettings.php │ ├── BigBlueButtonSettings.php │ ├── GeneralSettings.php │ ├── RecordingSettings.php │ ├── RoomSettings.php │ ├── StreamingSettings.php │ ├── ThemeSettings.php │ └── UserSettings.php ├── Support │ ├── CSPPolicy.php │ └── LaravelViteNonceGenerator.php └── Traits │ └── AddsModelNameTrait.php ├── artisan ├── bigbluebutton ├── pilos.yml └── pilos_post_publish.rb ├── bootstrap ├── app.php └── cache │ └── .gitignore ├── compose.test.ci.yml ├── compose.test.local.yml ├── compose.test.yml ├── composer.json ├── composer.lock ├── config ├── app.php ├── auth.php ├── bigbluebutton.php ├── broadcasting.php ├── cache.php ├── cors.php ├── csp.php ├── database.php ├── excel.php ├── filesystems.php ├── greenlight.php ├── hashing.php ├── horizon.php ├── ldap.php ├── logging.php ├── mail.php ├── permissions.php ├── plugins.php ├── pulse.php ├── queue.php ├── recording.php ├── sanctum.php ├── services.php ├── session.php ├── settings.php ├── streaming.php ├── telescope.php └── view.php ├── cypress.config.js ├── database ├── .gitignore ├── factories │ ├── .gitkeep │ ├── MeetingFactory.php │ ├── PermissionFactory.php │ ├── RecordingFactory.php │ ├── RecordingFormatFactory.php │ ├── RoleFactory.php │ ├── RoomFactory.php │ ├── RoomFileFactory.php │ ├── RoomTokenFactory.php │ ├── RoomTypeFactory.php │ ├── ServerFactory.php │ ├── ServerPoolFactory.php │ └── UserFactory.php ├── migrations │ ├── 2014_10_12_000000_create_users_table.php │ ├── 2014_10_12_100000_create_password_resets_table.php │ ├── 2018_08_08_100000_create_telescope_entries_table.php │ ├── 2019_08_19_000000_create_failed_jobs_table.php │ ├── 2019_12_14_000001_create_personal_access_tokens_table.php │ ├── 2022_07_21_000001_create_roles_table.php │ ├── 2022_07_21_000002_create_role_user_table.php │ ├── 2022_07_21_000003_create_permissions_table.php │ ├── 2022_07_21_000004_create_permissions_role_table.php │ ├── 2022_07_21_000005_create_included_permissions_table.php │ ├── 2022_07_21_000007_create_servers_table.php │ ├── 2022_07_21_000008_create_server_pools_table.php │ ├── 2022_07_21_000009_create_server_server_pool_table.php │ ├── 2022_07_21_000010_create_room_types_table.php │ ├── 2022_07_21_000011_create_role_room_type_table.php │ ├── 2022_07_21_000012_create_rooms_table.php │ ├── 2022_07_21_000013_create_room_users_table.php │ ├── 2022_07_21_000014_create_room_files_table.php │ ├── 2022_07_21_000015_create_room_tokens_table.php │ ├── 2022_07_21_000016_create_meetings_table.php │ ├── 2022_07_21_000017_create_meeting_attendees_table.php │ ├── 2022_07_21_000018_create_meeting_stats_table.php │ ├── 2022_07_21_000019_create_server_stats_table.php │ ├── 2022_09_27_193354_create_sessions_table.php │ ├── 2022_09_29_101046_create_verify_emails_table.php │ ├── 2023_04_13_151058_create_session_data_table.php │ ├── 2023_04_14_083707_create_settings_table.php │ ├── 2023_06_07_000001_create_pulse_tables.php │ ├── 2023_08_02_085644_add_meeting_id_to_rooms.php │ ├── 2023_08_03_070204_create_room_favorites_table.php │ ├── 2024_04_25_095728_create_recordings_table.php │ ├── 2024_04_25_141742_create_recording_formats_table.php │ ├── 2024_05_22_101114_add_create_parameters_to_room_types_table.php │ ├── 2024_11_06_171039_create_room_streamings_table.php │ ├── 2024_11_26_131851_create_room_type_streaming_settings_table.php │ ├── 2024_12_19_103013_make_server_name_unique.php │ ├── 2025_03_31_130245_add_external_image_hash_to_users_table.php │ ├── 2025_05_20_092623_add_last_login_to_users_table.php │ ├── 2025_05_20_153825_add_join_parameters_to_room_types_table.php │ ├── migrate-to-v4 │ │ ├── 2022_12_14_083707_refactor_settings_table.php │ │ ├── 2023_07_31_143604_add_short_description_to_rooms_table.php │ │ ├── 2023_11_24_135054_remove_short_from_room_types.php │ │ ├── 2024_01_30_194814_move_duration_and_participants_to_room_types_table.php │ │ ├── 2024_01_31_070902_add_require_access_code_to_room_types_table.php │ │ ├── 2024_01_31_071243_add_allow_record_attendace_to_room_types_table.php │ │ ├── 2024_02_15_084719_remove_password_in_meetings_table.php │ │ ├── 2024_02_28_140151_rename_description_in_room_types_table.php │ │ ├── 2024_02_29_091745_rename_columns_in_roles_table.php │ │ ├── 2024_03_06_152142_add_health_counters_to_servers_table.php │ │ ├── 2024_03_07_085720_add_disconnected_to_meetings_table.php │ │ ├── 2024_03_10_095259_add_description_to_room_types_table.php │ │ ├── 2024_03_10_102618_add_default_settings_for_rooms_to_room_types_table.php │ │ ├── 2024_03_13_183840_add_expert_mode_to_rooms_table.php │ │ ├── 2024_03_26_165418_add_load_to_servers_table.php │ │ ├── 2024_04_02_134419_rename_allow_record_attendance_in_room_types_table.php │ │ ├── 2024_04_02_141431_rename_allow_listing_in_room_types_table.php │ │ ├── 2024_04_05_084006_rename_listed_in_rooms_table.php │ │ ├── 2024_04_05_092032_rename_require_access_code_in_room_types_table.php │ │ ├── 2024_04_25_064823_add_record_to_rooms.php │ │ ├── 2024_04_25_064827_add_record_to_meetings.php │ │ ├── 2024_04_25_084656_add_allow_record_to_room_types_table.php │ │ └── 2024_04_25_094656_refactor_sessions_table.php │ └── v2 │ │ ├── 2014_10_12_000000_create_users_table.php │ │ ├── 2014_10_12_100000_create_password_resets_table.php │ │ ├── 2018_08_08_100000_create_telescope_entries_table.php │ │ ├── 2019_08_19_000000_create_failed_jobs_table.php │ │ ├── 2019_12_14_000001_create_personal_access_tokens_table.php │ │ ├── 2022_07_21_000001_create_roles_table.php │ │ ├── 2022_07_21_000002_create_role_user_table.php │ │ ├── 2022_07_21_000003_create_permissions_table.php │ │ ├── 2022_07_21_000004_create_permissions_role_table.php │ │ ├── 2022_07_21_000005_create_included_permissions_table.php │ │ ├── 2022_07_21_000006_create_settings_table.php │ │ ├── 2022_07_21_000007_create_servers_table.php │ │ ├── 2022_07_21_000008_create_server_pools_table.php │ │ ├── 2022_07_21_000009_create_server_server_pool_table.php │ │ ├── 2022_07_21_000010_create_room_types_table.php │ │ ├── 2022_07_21_000011_create_role_room_type_table.php │ │ ├── 2022_07_21_000012_create_rooms_table.php │ │ ├── 2022_07_21_000013_create_room_users_table.php │ │ ├── 2022_07_21_000014_create_room_files_table.php │ │ ├── 2022_07_21_000015_create_room_tokens_table.php │ │ ├── 2022_07_21_000016_create_meetings_table.php │ │ ├── 2022_07_21_000017_create_meeting_attendees_table.php │ │ ├── 2022_07_21_000018_create_meeting_stats_table.php │ │ ├── 2022_07_21_000019_create_server_stats_table.php │ │ ├── 2022_09_23_144227_add_description_to_rooms_table.php │ │ ├── 2022_09_27_193354_create_sessions_table.php │ │ ├── 2022_09_29_101046_create_verify_emails_table.php │ │ ├── 2023_04_04_090145_rename_username_field.php │ │ ├── 2023_04_13_151058_create_session_data_table.php │ │ ├── 2023_08_29_111743_rename_password_self_reset_enabled_setting.php │ │ ├── 2023_09_01_100006_revert_authenticator_bundling.php │ │ └── 2023_09_28_084531_rename_salt_to_secret_in_servers_table.php ├── seeders │ ├── DatabaseSeeder.php │ ├── Demo │ │ ├── CreateDemoSystem.php │ │ └── storage │ │ │ ├── abc-def-123 │ │ │ ├── anatomy-foot.pdf │ │ │ └── anatomy-introduction.pdf │ │ │ └── public │ │ │ └── profile_images │ │ │ ├── angela-jones.jpg │ │ │ ├── daniel-osorio.jpg │ │ │ └── john-doe.jpg │ ├── RolesAndPermissionsSeeder.php │ ├── RoomTypeSeeder.php │ ├── ServerPoolSeeder.php │ └── ServerSeeder.php └── settings │ ├── 2023_04_14_095406_create_general_settings.php │ ├── 2023_04_14_101741_create_banner_settings.php │ ├── 2023_04_14_102134_create_room_settings.php │ ├── 2023_04_14_103520_create_user_settings.php │ ├── 2023_04_14_103845_create_recording_settings.php │ ├── 2023_04_14_103858_create_big_blue_button_settings.php │ ├── 2024_05_24_135649_add_toast_life_time_to_general_settings.php │ ├── 2024_07_09_122330_add_theme_settings.php │ ├── 2024_07_10_090412_move_logo_to_theme_settings.php │ ├── 2024_09_27_065358_add_file_terms_of_use_to_room_settings.php │ ├── 2024_09_27_101218_add_no_welcome_page_to_general_settings.php │ ├── 2024_11_26_131704_create_streaming_settings.php │ ├── 2024_12_13_133315_add_dark_mode_logo_to_big_blue_button_settings.php │ └── 2025_01_09_135151_fix_invalid_link_button_style.php ├── docker-compose-dev.yml ├── docker-compose.yml ├── docker ├── app │ ├── Dockerfile │ ├── cron │ │ └── scheduler │ ├── entrypoint │ ├── ldap │ │ └── ldap.conf │ ├── nginx │ │ ├── sites-enabled │ │ │ └── default │ │ ├── snippets-available │ │ │ └── ssl │ │ └── templates │ │ │ └── nginx.template │ ├── php │ │ ├── opcache.ini │ │ ├── php.ini │ │ └── zz-docker.conf │ ├── pilos-cli │ ├── playback-player │ │ └── build.sh │ └── supervisord │ │ └── supervisord.conf └── openldap │ ├── acl.ldif │ └── bootstrap.ldif ├── docs ├── .gitignore ├── README.md ├── build.sh ├── docs │ ├── administration │ │ ├── 01-intro.md │ │ ├── 02-getting-started.md │ │ ├── 03-configuration.md │ │ ├── 04-pilos-cli.md │ │ ├── 05-upgrade.md │ │ ├── 06-greenlight.md │ │ ├── 07-backup.md │ │ ├── 08-advanced │ │ │ ├── 01-external-authentication.md │ │ │ ├── 02-roles-and-permissions.md │ │ │ ├── 03-recording.md │ │ │ ├── 04-streaming.md │ │ │ ├── 05-scaling.md │ │ │ ├── 06-migrate-greenlight.md │ │ │ ├── 07-provisioning.md │ │ │ └── _category_.json │ │ ├── 09-customisation │ │ │ ├── 01-default-setting.md │ │ │ ├── 02-locales.md │ │ │ ├── 03-components.md │ │ │ ├── 04-docker-image.md │ │ │ └── index.md │ │ └── 10-plugins │ │ │ ├── ServerLoadCalculationPlugin.md │ │ │ └── index.md │ └── development │ │ ├── 01-intro.md │ │ ├── 02-getting-started.md │ │ ├── 03-configuration.md │ │ ├── 04-workflow.md │ │ ├── 05-code-style.md │ │ ├── 06-documentation.md │ │ └── 07-testing.md ├── docusaurus.config.js ├── package-lock.json ├── package.json ├── sidebars.js ├── src │ ├── components │ │ └── HomepageFeatures │ │ │ ├── index.js │ │ │ └── styles.module.css │ ├── css │ │ └── custom.css │ └── pages │ │ ├── index.js │ │ ├── index.module.css │ │ └── markdown-page.md └── static │ ├── .nojekyll │ └── img │ ├── favicon.ico │ ├── laptop-code-solid.svg │ ├── logo-dark.svg │ ├── logo.svg │ ├── social-card.png │ └── toolbox-solid.svg ├── eslint.config.js ├── lang ├── de-gender │ ├── admin.php │ ├── app.php │ ├── auth.php │ ├── mail.php │ ├── meetings.php │ ├── pagination.php │ ├── passwords.php │ ├── rooms.php │ ├── system.php │ └── validation.php ├── de │ ├── admin.php │ ├── app.php │ ├── auth.php │ ├── home.php │ ├── mail.php │ ├── meetings.php │ ├── metadata.json │ ├── pagination.php │ ├── passwords.php │ ├── rooms.php │ ├── system.php │ └── validation.php ├── en │ ├── admin.php │ ├── app.php │ ├── auth.php │ ├── home.php │ ├── mail.php │ ├── meetings.php │ ├── metadata.json │ ├── pagination.php │ ├── passwords.php │ ├── rooms.php │ ├── system.php │ └── validation.php ├── fa │ ├── admin.php │ ├── app.php │ ├── auth.php │ ├── home.php │ ├── mail.php │ ├── meetings.php │ ├── metadata.json │ ├── pagination.php │ ├── passwords.php │ ├── rooms.php │ ├── system.php │ └── validation.php └── fr │ ├── admin.php │ ├── app.php │ ├── auth.php │ ├── home.php │ ├── mail.php │ ├── meetings.php │ ├── metadata.json │ ├── pagination.php │ ├── passwords.php │ ├── rooms.php │ ├── system.php │ └── validation.php ├── logo.svg ├── package-lock.json ├── package.json ├── phpunit.xml ├── pint.json ├── postcss.config.js ├── public ├── .htaccess ├── images │ ├── custom │ │ └── .gitignore │ ├── default_profile.png │ ├── favicon-dark.ico │ ├── favicon.ico │ ├── hero │ │ ├── hero1.jpg │ │ ├── hero2.jpg │ │ ├── hero3.jpg │ │ ├── hero4.jpg │ │ └── hero5.jpg │ ├── livestream_avatar.png │ ├── logo-dark.svg │ └── logo.svg ├── index.php ├── robots.txt └── vendor │ ├── horizon │ ├── app-dark.css │ ├── app.css │ ├── app.js │ ├── favicon.png │ ├── img │ │ ├── favicon.png │ │ ├── horizon.svg │ │ └── sprite.svg │ ├── manifest.json │ ├── mix-manifest.json │ ├── styles-dark.css │ └── styles.css │ └── telescope │ ├── app-dark.css │ ├── app.css │ ├── app.js │ ├── favicon.ico │ └── mix-manifest.json ├── publiccode.yml ├── resources ├── audio │ └── notification.mp3 ├── custom │ └── .gitignore ├── fonts │ └── open-sans │ │ ├── open-sans-300.woff2 │ │ ├── open-sans-300italic.woff2 │ │ ├── open-sans-500.woff2 │ │ ├── open-sans-500italic.woff2 │ │ ├── open-sans-600.woff2 │ │ ├── open-sans-600italic.woff2 │ │ ├── open-sans-700.woff2 │ │ ├── open-sans-700italic.woff2 │ │ ├── open-sans-800.woff2 │ │ ├── open-sans-800italic.woff2 │ │ ├── open-sans-italic.woff2 │ │ └── open-sans-regular.woff2 ├── js │ ├── app.js │ ├── components │ │ ├── AdminOverviewCard.vue │ │ ├── AdminPanel.vue │ │ ├── AdminStreamingRoomTypeEditButton.vue │ │ ├── AdminStreamingRoomTypeTable.vue │ │ ├── App.vue │ │ ├── AppBanner.vue │ │ ├── AppFooter.vue │ │ ├── ColorSelect.vue │ │ ├── FileInput.vue │ │ ├── FormError.vue │ │ ├── InlineNote.vue │ │ ├── LandingFeaturesSection.vue │ │ ├── LandingHeroCTA.vue │ │ ├── LandingHeroSection.vue │ │ ├── LandingHeroTitle.vue │ │ ├── LandingHeroTitleFlipWords.vue │ │ ├── LandingHeroTitleUnderlineWords.vue │ │ ├── LoadingRetryButton.vue │ │ ├── LocaleSelect.vue │ │ ├── LoginTabExternal.vue │ │ ├── LoginTabLdap.vue │ │ ├── LoginTabLocal.vue │ │ ├── MainNav.vue │ │ ├── MainNavDarkModeToggle.vue │ │ ├── OverlayComponent.vue │ │ ├── RawText.vue │ │ ├── RoleSelect.vue │ │ ├── RoomBrowserNotification.vue │ │ ├── RoomCard.vue │ │ ├── RoomCardSkeleton.vue │ │ ├── RoomCreateComponent.vue │ │ ├── RoomDeleteButton.vue │ │ ├── RoomDetailsList.vue │ │ ├── RoomFavoriteButton.vue │ │ ├── RoomHeader.vue │ │ ├── RoomJoinButton.vue │ │ ├── RoomMembershipButton.vue │ │ ├── RoomRecordingAccessBadge.vue │ │ ├── RoomRoleBadge.vue │ │ ├── RoomSettingEnforcedIcon.vue │ │ ├── RoomShareButton.vue │ │ ├── RoomTabDescription.vue │ │ ├── RoomTabDescriptionViewer.vue │ │ ├── RoomTabFiles.vue │ │ ├── RoomTabFilesDeleteButton.vue │ │ ├── RoomTabFilesEditButton.vue │ │ ├── RoomTabFilesUploadButton.vue │ │ ├── RoomTabFilesViewButton.vue │ │ ├── RoomTabHistory.vue │ │ ├── RoomTabHistoryAttendanceButton.vue │ │ ├── RoomTabHistoryStatisticButton.vue │ │ ├── RoomTabMembers.vue │ │ ├── RoomTabMembersAddButton.vue │ │ ├── RoomTabMembersAddSingleModal.vue │ │ ├── RoomTabMembersBulkDeleteButton.vue │ │ ├── RoomTabMembersBulkEditButton.vue │ │ ├── RoomTabMembersBulkImportList.vue │ │ ├── RoomTabMembersBulkImportModal.vue │ │ ├── RoomTabMembersDeleteButton.vue │ │ ├── RoomTabMembersEditButton.vue │ │ ├── RoomTabPersonalizedLinks.vue │ │ ├── RoomTabPersonalizedLinksAddButton.vue │ │ ├── RoomTabPersonalizedLinksCopyButton.vue │ │ ├── RoomTabPersonalizedLinksDeleteButton.vue │ │ ├── RoomTabPersonalizedLinksEditButton.vue │ │ ├── RoomTabRecordings.vue │ │ ├── RoomTabRecordingsDeleteButton.vue │ │ ├── RoomTabRecordingsDownloadButton.vue │ │ ├── RoomTabRecordingsEditButton.vue │ │ ├── RoomTabRecordingsViewButton.vue │ │ ├── RoomTabSection.vue │ │ ├── RoomTabSettings.vue │ │ ├── RoomTabSettingsAccessCodeInput.vue │ │ ├── RoomTabSettingsExpertModeButton.vue │ │ ├── RoomTabSettingsRadioGroup.vue │ │ ├── RoomTabSettingsRoomTypeSelect.vue │ │ ├── RoomTabSettingsSelectButton.vue │ │ ├── RoomTabSettingsTextArea.vue │ │ ├── RoomTabSettingsTextInput.vue │ │ ├── RoomTabSettingsToggleSwitch.vue │ │ ├── RoomTabStreaming.vue │ │ ├── RoomTabStreamingConfigButton.vue │ │ ├── RoomTransferOwnershipButton.vue │ │ ├── RoomTypeBadge.vue │ │ ├── RoomTypeChangeConfirmationModal.vue │ │ ├── RoomTypeCompareSettingsField.vue │ │ ├── RoomTypeDetails.vue │ │ ├── RoomTypeFeatureField.vue │ │ ├── RoomTypeSelect.vue │ │ ├── RoomTypeSettingsField.vue │ │ ├── SettingsFileSelector.vue │ │ ├── SettingsImageSelector.vue │ │ ├── SettingsRolesDeleteButton.vue │ │ ├── SettingsRoomTypesDeleteButton.vue │ │ ├── SettingsServerPoolsDeleteButton.vue │ │ ├── SettingsServersDeleteButton.vue │ │ ├── SettingsUsersDeleteButton.vue │ │ ├── SettingsUsersResetPasswordButton.vue │ │ ├── TextTruncate.vue │ │ ├── TimezoneSelect.vue │ │ ├── TipTapEditor.vue │ │ ├── TipTapImage.vue │ │ ├── TipTapLink.vue │ │ ├── TipTapMenu.vue │ │ ├── TipTapMenuDropdownButton.vue │ │ ├── TipTapMenuDropdownItem.vue │ │ ├── TipTapSource.vue │ │ ├── UserAvatar.vue │ │ ├── UserProfileImageSelector.vue │ │ ├── UserTabEmail.vue │ │ ├── UserTabOtherSettings.vue │ │ ├── UserTabProfile.vue │ │ ├── UserTabSection.vue │ │ ├── UserTabSecurity.vue │ │ ├── UserTabSecurityPasswordSection.vue │ │ ├── UserTabSecurityRolesAndPermissionsSection.vue │ │ └── UserTabSecuritySessionsSection.vue │ ├── composables │ │ ├── useActionColumn.js │ │ ├── useApi.js │ │ ├── useColors.js │ │ ├── useDateDiff.js │ │ ├── useFormErrors.js │ │ ├── usePaginator.js │ │ ├── useRoomHelpers.js │ │ ├── useRoomTypeSettings.js │ │ ├── useTheme.js │ │ ├── useToast.js │ │ └── useUserPermission.js │ ├── constants │ │ ├── events.js │ │ └── roomSettings.js │ ├── env.js │ ├── errors │ │ ├── ParameterMissingError.js │ │ ├── PolicyDoesNotExistsError.js │ │ └── WrongTypeError.js │ ├── font.js │ ├── i18n.js │ ├── plugins │ │ └── toast.js │ ├── policies │ │ ├── AdminPolicy.js │ │ ├── MeetingPolicy.js │ │ ├── RolePolicy.js │ │ ├── RoomPolicy.js │ │ ├── RoomTypePolicy.js │ │ ├── ServerPolicy.js │ │ ├── ServerPoolPolicy.js │ │ ├── SettingsPolicy.js │ │ ├── StreamingPolicy.js │ │ ├── SystemPolicy.js │ │ ├── UserPolicy.js │ │ └── index.js │ ├── router.js │ ├── services │ │ ├── Api.js │ │ └── EventBus.js │ ├── stores │ │ ├── auth.js │ │ ├── loading.js │ │ ├── locale.js │ │ └── settings.js │ └── views │ │ ├── AdminIndex.vue │ │ ├── AdminLayout.vue │ │ ├── AdminRolesIndex.vue │ │ ├── AdminRolesView.vue │ │ ├── AdminRoomTypesIndex.vue │ │ ├── AdminRoomTypesView.vue │ │ ├── AdminServerPoolsIndex.vue │ │ ├── AdminServerPoolsView.vue │ │ ├── AdminServersIndex.vue │ │ ├── AdminServersView.vue │ │ ├── AdminSettings.vue │ │ ├── AdminStreamingSettings.vue │ │ ├── AdminUsersIndex.vue │ │ ├── AdminUsersNew.vue │ │ ├── AdminUsersView.vue │ │ ├── ExternalLogin.vue │ │ ├── ForgotPassword.vue │ │ ├── Home.vue │ │ ├── Login.vue │ │ ├── Logout.vue │ │ ├── MeetingsIndex.vue │ │ ├── NotFound.vue │ │ ├── PasswordReset.vue │ │ ├── Profile.vue │ │ ├── RoomsIndex.vue │ │ ├── RoomsView.vue │ │ └── VerifyEmail.vue ├── sass │ ├── app.scss │ ├── app │ │ ├── _action-column.scss │ │ ├── _color-select.scss │ │ ├── _general.scss │ │ ├── _navigation.scss │ │ ├── _profile-image.scss │ │ ├── _room.scss │ │ ├── _streched-link.scss │ │ ├── _typography.scss │ │ └── app.scss │ └── override │ │ ├── _multiselect.scss │ │ ├── _toast.scss │ │ ├── _tooltip.scss │ │ └── override.scss └── views │ ├── application.blade.php │ ├── frontend-error.blade.php │ └── vendor │ ├── mail │ └── html │ │ └── themes │ │ └── default.css │ ├── notifications │ └── email.blade.php │ └── pulse │ └── dashboard.blade.php ├── routes ├── api.php ├── channels.php ├── console.php └── web.php ├── sail ├── ssl └── .gitignore ├── storage ├── app │ ├── .gitignore │ └── public │ │ └── .gitignore ├── framework │ ├── .gitignore │ ├── cache │ │ ├── .gitignore │ │ └── data │ │ │ └── .gitignore │ ├── sessions │ │ └── .gitignore │ ├── testing │ │ └── .gitignore │ └── views │ │ └── .gitignore ├── logs │ └── .gitignore ├── recordings-spool │ └── .gitignore └── recordings │ └── .gitignore ├── tailwind.config.js ├── tests ├── Backend │ ├── Feature │ │ ├── RoutingTest.php │ │ └── api │ │ │ └── v1 │ │ │ ├── ApplicationTest.php │ │ │ ├── ForgotPasswordTest.php │ │ │ ├── LdapLoginTest.php │ │ │ ├── LocalesTest.php │ │ │ ├── LoginTest.php │ │ │ ├── MeetingTest.php │ │ │ ├── PermissionTest.php │ │ │ ├── RecordingTest.php │ │ │ ├── ResetPasswordTest.php │ │ │ ├── RoleTest.php │ │ │ ├── Room │ │ │ ├── FileTest.php │ │ │ ├── MembershipTest.php │ │ │ ├── RoomDescriptionTest.php │ │ │ ├── RoomStatisticTest.php │ │ │ ├── RoomStreamingTest.php │ │ │ ├── RoomTest.php │ │ │ └── RoomTokenTest.php │ │ │ ├── RoomTypeTest.php │ │ │ ├── ServerPoolTest.php │ │ │ ├── ServerTest.php │ │ │ ├── SessionTest.php │ │ │ ├── SettingsTest.php │ │ │ ├── ShibbolethTest.php │ │ │ ├── StreamingTest.php │ │ │ └── UserTest.php │ ├── Fixtures │ │ ├── ChecksumError.xml │ │ ├── EndMeeting.xml │ │ ├── Failed.xml │ │ ├── GetApiVersion-Disabled.xml │ │ ├── GetApiVersion.xml │ │ ├── GetMeetings-1.xml │ │ ├── GetMeetings-2.xml │ │ ├── GetMeetings-3.xml │ │ ├── GetMeetings-Empty.xml │ │ ├── GetMeetings-End.xml │ │ ├── GetMeetings-MaxUsers.xml │ │ ├── GetMeetings-Start.xml │ │ ├── Locales │ │ │ ├── .gitignore │ │ │ ├── custom │ │ │ │ ├── de │ │ │ │ │ ├── app.php │ │ │ │ │ └── metadata.json │ │ │ │ ├── en │ │ │ │ │ ├── app.php │ │ │ │ │ └── metadata.json │ │ │ │ ├── es │ │ │ │ │ └── app.php │ │ │ │ └── fr │ │ │ │ │ └── app.php │ │ │ └── default │ │ │ │ ├── en │ │ │ │ ├── app.php │ │ │ │ └── metadata.json │ │ │ │ └── fr │ │ │ │ ├── app.php │ │ │ │ └── metadata.json │ │ ├── MeetingNotFound.xml │ │ ├── Recordings │ │ │ ├── invalid-recording.tar │ │ │ ├── multiple.tar │ │ │ ├── notes.tar │ │ │ └── other-file.txt │ │ ├── Success.xml │ │ ├── invalidDatabase.sql │ │ ├── profileImage-1.jpg │ │ ├── profileImage-2.jpg │ │ ├── provisioning_data.json │ │ ├── validDatabase-mysql.sql │ │ └── validDatabase-postgres.sql │ ├── Integration │ │ └── api │ │ │ └── v1 │ │ │ ├── RoomFileTest.php │ │ │ └── RoomTest.php │ ├── TestCase.php │ ├── Unit │ │ ├── AddsModelNameTraitTest.php │ │ ├── Console │ │ │ ├── CleanupAttendanceTest.php │ │ │ ├── CleanupRecordingsCommandTest.php │ │ │ ├── CleanupRoomsTest.php │ │ │ ├── CleanupStatisticsTest.php │ │ │ ├── CreateSuperuserTest.php │ │ │ ├── DeleteObsoleteTokensTest.php │ │ │ ├── DeleteUnverifiedNewUsersTest.php │ │ │ ├── ExportLocalesTest.php │ │ │ ├── ImportDatabaseTest.php │ │ │ ├── ImportGreenlight2Test.php │ │ │ ├── ImportLocalesTest.php │ │ │ ├── ImportRecordingsCommandTest.php │ │ │ ├── LocalesCacheTest.php │ │ │ ├── PollServerTest.php │ │ │ ├── ProvisionCommandTest.php │ │ │ ├── TestEmailConfigTest.php │ │ │ ├── UpgradeDatabaseTest.php │ │ │ ├── UploadLocalesTest.php │ │ │ └── helper │ │ │ │ ├── GreenlightRoom.php │ │ │ │ ├── GreenlightSharedAccess.php │ │ │ │ └── GreenlightUser.php │ │ ├── EnsureModelNotStaleTest.php │ │ ├── ExternalUserTest.php │ │ ├── Jobs │ │ │ └── ProcessRecordingTest.php │ │ ├── Listeners │ │ │ └── ResetStreamingOnRoomStop.php │ │ ├── LocaleServiceTest.php │ │ ├── MeetingServiceTest.php │ │ ├── MeetingTest.php │ │ ├── PermissionTest.php │ │ ├── ProvisioningServiceTest.php │ │ ├── RoomTest.php │ │ ├── RoomTokenTest.php │ │ ├── Rules │ │ │ ├── CustomCreateMeetingParametersTest.php │ │ │ ├── PasswordTest.php │ │ │ └── ValidRoomTypeTest.php │ │ ├── Seeder │ │ │ └── RolesAndPermissionsSeederTest.php │ │ ├── ServerLoadCalculationPluginTest.php │ │ ├── ServerPoolTest.php │ │ ├── ServerServiceTest.php │ │ ├── ServerTest.php │ │ ├── StreamingServiceFactoryTest.php │ │ ├── StreamingServiceTest.php │ │ └── UserTest.php │ └── Utils │ │ ├── AttendanceExcelImport.php │ │ ├── BigBlueButtonServerFaker.php │ │ ├── FileHelper.php │ │ └── ServerLoadCalculationPlugin.php ├── Frontend │ ├── e2e │ │ ├── AdminIndex.cy.js │ │ ├── AdminRolesEdit.cy.js │ │ ├── AdminRolesIndex.cy.js │ │ ├── AdminRolesIndexRoleActions.cy.js │ │ ├── AdminRolesNew.cy.js │ │ ├── AdminRolesView.cy.js │ │ ├── AdminRolesViewRoleActions.cy.js │ │ ├── AdminRoomTypesEdit.cy.js │ │ ├── AdminRoomTypesIndex.cy.js │ │ ├── AdminRoomTypesIndexRoomTypeActions.cy.js │ │ ├── AdminRoomTypesNew.cy.js │ │ ├── AdminRoomTypesView.cy.js │ │ ├── AdminRoomTypesViewRoomTypeActions.cy.js │ │ ├── AdminServerPoolsEdit.cy.js │ │ ├── AdminServerPoolsIndex.cy.js │ │ ├── AdminServerPoolsIndexServerPoolActions.cy.js │ │ ├── AdminServerPoolsNew.cy.js │ │ ├── AdminServerPoolsView.cy.js │ │ ├── AdminServerPoolsViewServerPoolActions.cy.js │ │ ├── AdminServersEdit.cy.js │ │ ├── AdminServersIndex.cy.js │ │ ├── AdminServersIndexServerActions.cy.js │ │ ├── AdminServersNew.cy.js │ │ ├── AdminServersView.cy.js │ │ ├── AdminServersViewServerActions.cy.js │ │ ├── AdminSettingsEdit.cy.js │ │ ├── AdminSettingsGeneral.cy.js │ │ ├── AdminSettingsView.cy.js │ │ ├── AdminStreamingEdit.cy.js │ │ ├── AdminStreamingView.cy.js │ │ ├── AdminUsersEdit.cy.js │ │ ├── AdminUsersEditBase.cy.js │ │ ├── AdminUsersEditEmail.cy.js │ │ ├── AdminUsersEditOthers.cy.js │ │ ├── AdminUsersEditSecurity.cy.js │ │ ├── AdminUsersIndex.cy.js │ │ ├── AdminUsersIndexUserActions.cy.js │ │ ├── AdminUsersNew.cy.js │ │ ├── AdminUsersView.cy.js │ │ ├── AdminUsersViewUserActions.cy.js │ │ ├── Banner.cy.js │ │ ├── Footer.cy.js │ │ ├── ForgotPassword.cy.js │ │ ├── GeneralApplication.cy.js │ │ ├── Login.cy.js │ │ ├── Logout.cy.js │ │ ├── MeetingsIndex.cy.js │ │ ├── PasswordReset.cy.js │ │ ├── RoomsIndex.cy.js │ │ ├── RoomsIndexCreateNewRoom.cy.js │ │ ├── RoomsViewBrowserNotification.cy.js │ │ ├── RoomsViewDescription.cy.js │ │ ├── RoomsViewDescriptionTipTapEditor.cy.js │ │ ├── RoomsViewFiles.cy.js │ │ ├── RoomsViewFilesFileActions.cy.js │ │ ├── RoomsViewGeneral.cy.js │ │ ├── RoomsViewHistory.cy.js │ │ ├── RoomsViewHistoryMeetingActions.cy.js │ │ ├── RoomsViewMeetings.cy.js │ │ ├── RoomsViewMembers.cy.js │ │ ├── RoomsViewMembersBulkActions.cy.js │ │ ├── RoomsViewMembersMemberActions.cy.js │ │ ├── RoomsViewPersonalizedLinks.cy.js │ │ ├── RoomsViewPersonalizedLinksTokenActions.cy.js │ │ ├── RoomsViewRecordings.cy.js │ │ ├── RoomsViewRecordingsRecordingActions.cy.js │ │ ├── RoomsViewSettings.cy.js │ │ ├── RoomsViewSettingsRoomTypeActions.cy.js │ │ ├── RoomsViewStreaming.cy.js │ │ ├── RoomsViewStreamingConfigActions.cy.js │ │ ├── UserProfile.cy.js │ │ ├── UserProfileBase.cy.js │ │ ├── UserProfileEmail.cy.js │ │ ├── UserProfileOthers.cy.js │ │ ├── UserProfileSecurity.cy.js │ │ └── VerifyEmail.cy.js │ ├── fixtures │ │ ├── config.json │ │ ├── currentUser.json │ │ ├── en.json │ │ ├── files │ │ │ ├── bbb_style.css │ │ │ ├── favicon-dark.ico │ │ │ ├── favicon.ico │ │ │ ├── logo-dark.svg │ │ │ ├── logo.svg │ │ │ ├── pause.jpg │ │ │ ├── profileImage.jpg │ │ │ ├── profileImagePreview.jpg │ │ │ ├── streaming.css │ │ │ ├── testFile.txt │ │ │ └── testFile2.txt │ │ ├── meetings.json │ │ ├── permissions.json │ │ ├── role.json │ │ ├── roles.json │ │ ├── room.json │ │ ├── roomFiles.json │ │ ├── roomFilesNoDetails.json │ │ ├── roomHistory.json │ │ ├── roomHistoryAttendance.json │ │ ├── roomHistoryStats.json │ │ ├── roomMembers.json │ │ ├── roomRecordings.json │ │ ├── roomSettings.json │ │ ├── roomStreamingConfig.json │ │ ├── roomStreamingStatus.json │ │ ├── roomTokens.json │ │ ├── roomType.json │ │ ├── roomTypeStreamingSettings.json │ │ ├── roomTypes.json │ │ ├── roomTypesWithSettings.json │ │ ├── rooms.json │ │ ├── server.json │ │ ├── serverPool.json │ │ ├── serverPools.json │ │ ├── servers.json │ │ ├── sessions.json │ │ ├── settings.json │ │ ├── streaming.json │ │ ├── superuserRole.json │ │ ├── timezones.json │ │ ├── userDataCurrentUser.json │ │ ├── userDataUser.json │ │ └── users.json │ └── support │ │ ├── commands │ │ ├── adminRolesCommands.js │ │ ├── adminRoomTypesCommands.js │ │ ├── adminSettingsCommands.js │ │ ├── generalCommands.js │ │ ├── interceptCommands.js │ │ └── roomCommands.js │ │ ├── component-index.html │ │ ├── component.js │ │ ├── e2e.js │ │ └── utils │ │ ├── fileHelper.js │ │ ├── formData.js │ │ ├── interceptIndefinitely.js │ │ ├── notificationFaker.js │ │ └── tiptapHelper.js ├── System │ ├── cypress.config.js │ ├── e2e │ │ ├── GeneralApplication.cy.js │ │ ├── Login.cy.js │ │ ├── RoomsIndex.cy.js │ │ └── RoomsViewGeneral.cy.js │ └── support │ │ ├── commands.js │ │ └── e2e.js ├── Utils │ ├── create-mariadb-testing-database.sh │ └── create-postgres-testing-database.sql └── Visual │ ├── .happo.js │ ├── cypress.config.js │ ├── e2e │ └── RoomsViewHistoryMeetingActions.cy.js │ ├── fixtures │ ├── config.json │ ├── currentUser.json │ ├── room.json │ ├── roomHistory.json │ ├── roomHistoryStats.json │ └── roomTypes.json │ └── support │ ├── commands.js │ ├── commands │ └── interceptCommands.js │ └── e2e.js ├── vite.config.common.js ├── vite.config.coverage.js └── vite.config.js /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "test": { 4 | "presets": [["@babel/preset-env"]], 5 | "retainLines": true 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | .git 2 | /.idea 3 | node_modules 4 | vendor 5 | .env 6 | .github 7 | .opencode 8 | *.md 9 | _ide_helper.php 10 | tests 11 | .eslintignore 12 | .eslintrc.js 13 | .gitattributes 14 | .gitignore 15 | .php-cs-fixer.php 16 | .phpunit.result.cache 17 | .styleci.yml 18 | phpunit.xml 19 | docs 20 | ssl 21 | db 22 | redis 23 | app/Auth/config 24 | app/Plugins/Custom 25 | public/hot 26 | 27 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | end_of_line = lf 6 | insert_final_newline = true 7 | indent_style = space 8 | indent_size = 4 9 | trim_trailing_whitespace = true 10 | 11 | [*.md] 12 | trim_trailing_whitespace = false 13 | 14 | [*.{yml,yaml,js,vue,json}] 15 | indent_size = 2 16 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto eol=lf 2 | *.{cmd,[cC][mM][dD]} text eol=crlf 3 | *.{bat,[bB][aA][tT]} text eol=crlf 4 | *.css linguist-vendored 5 | *.scss linguist-vendored 6 | *.js linguist-vendored 7 | CHANGELOG.md export-ignore 8 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: "" 5 | labels: "" 6 | assignees: "" 7 | --- 8 | 9 | **Is your feature request related to a problem? Please describe.** 10 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 11 | 12 | **Describe the solution you'd like** 13 | A clear and concise description of what you want to happen. 14 | 15 | **Describe alternatives you've considered** 16 | A clear and concise description of any alternative solutions or features you've considered. 17 | 18 | **Additional context** 19 | Add any other context or screenshots about the feature request here. 20 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules 2 | /public/hot 3 | /public/storage 4 | /storage/*.key 5 | /vendor 6 | .env 7 | .env.backup 8 | .phpunit.result.cache 9 | docker-compose.override.yml 10 | npm-debug.log 11 | yarn-error.log 12 | /.idea 13 | /.vscode 14 | .DS_Store 15 | /public/build 16 | /public/fonts 17 | .nyc_output 18 | coverage 19 | coverage.xml 20 | /db 21 | /redis 22 | version 23 | components.d.ts 24 | public/playback-player 25 | tests/Frontend/screenshots 26 | tests/Frontend/videos 27 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | engine-strict 2 | -------------------------------------------------------------------------------- /.nvmrc: -------------------------------------------------------------------------------- 1 | lts/* 2 | -------------------------------------------------------------------------------- /.nycrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "all": true, 3 | "excludeAfterRemap": false, 4 | "reporter": ["json"], 5 | "extension": [".js", ".vue"], 6 | "include": ["resources/js/*"] 7 | } 8 | -------------------------------------------------------------------------------- /.opencode/screenshots/de/app_settings.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THM-Health/PILOS/7ace1347300f486c0ce82903c0c5e46324b33f8d/.opencode/screenshots/de/app_settings.jpg -------------------------------------------------------------------------------- /.opencode/screenshots/de/dashboard.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THM-Health/PILOS/7ace1347300f486c0ce82903c0c5e46324b33f8d/.opencode/screenshots/de/dashboard.jpg -------------------------------------------------------------------------------- /.opencode/screenshots/de/home.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THM-Health/PILOS/7ace1347300f486c0ce82903c0c5e46324b33f8d/.opencode/screenshots/de/home.jpg -------------------------------------------------------------------------------- /.opencode/screenshots/de/login.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THM-Health/PILOS/7ace1347300f486c0ce82903c0c5e46324b33f8d/.opencode/screenshots/de/login.jpg -------------------------------------------------------------------------------- /.opencode/screenshots/de/profile_base.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THM-Health/PILOS/7ace1347300f486c0ce82903c0c5e46324b33f8d/.opencode/screenshots/de/profile_base.jpg -------------------------------------------------------------------------------- /.opencode/screenshots/de/profile_security.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THM-Health/PILOS/7ace1347300f486c0ce82903c0c5e46324b33f8d/.opencode/screenshots/de/profile_security.jpg -------------------------------------------------------------------------------- /.opencode/screenshots/de/roles.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THM-Health/PILOS/7ace1347300f486c0ce82903c0c5e46324b33f8d/.opencode/screenshots/de/roles.jpg -------------------------------------------------------------------------------- /.opencode/screenshots/de/roles_detail.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THM-Health/PILOS/7ace1347300f486c0ce82903c0c5e46324b33f8d/.opencode/screenshots/de/roles_detail.jpg -------------------------------------------------------------------------------- /.opencode/screenshots/de/room_attendance.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THM-Health/PILOS/7ace1347300f486c0ce82903c0c5e46324b33f8d/.opencode/screenshots/de/room_attendance.jpg -------------------------------------------------------------------------------- /.opencode/screenshots/de/room_description.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THM-Health/PILOS/7ace1347300f486c0ce82903c0c5e46324b33f8d/.opencode/screenshots/de/room_description.jpg -------------------------------------------------------------------------------- /.opencode/screenshots/de/room_files.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THM-Health/PILOS/7ace1347300f486c0ce82903c0c5e46324b33f8d/.opencode/screenshots/de/room_files.jpg -------------------------------------------------------------------------------- /.opencode/screenshots/de/room_history.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THM-Health/PILOS/7ace1347300f486c0ce82903c0c5e46324b33f8d/.opencode/screenshots/de/room_history.jpg -------------------------------------------------------------------------------- /.opencode/screenshots/de/room_members.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THM-Health/PILOS/7ace1347300f486c0ce82903c0c5e46324b33f8d/.opencode/screenshots/de/room_members.jpg -------------------------------------------------------------------------------- /.opencode/screenshots/de/room_personalized_room_links.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THM-Health/PILOS/7ace1347300f486c0ce82903c0c5e46324b33f8d/.opencode/screenshots/de/room_personalized_room_links.jpg -------------------------------------------------------------------------------- /.opencode/screenshots/de/room_settings.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THM-Health/PILOS/7ace1347300f486c0ce82903c0c5e46324b33f8d/.opencode/screenshots/de/room_settings.jpg -------------------------------------------------------------------------------- /.opencode/screenshots/de/room_stats.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THM-Health/PILOS/7ace1347300f486c0ce82903c0c5e46324b33f8d/.opencode/screenshots/de/room_stats.jpg -------------------------------------------------------------------------------- /.opencode/screenshots/de/room_types.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THM-Health/PILOS/7ace1347300f486c0ce82903c0c5e46324b33f8d/.opencode/screenshots/de/room_types.jpg -------------------------------------------------------------------------------- /.opencode/screenshots/de/room_types_edit.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THM-Health/PILOS/7ace1347300f486c0ce82903c0c5e46324b33f8d/.opencode/screenshots/de/room_types_edit.jpg -------------------------------------------------------------------------------- /.opencode/screenshots/de/room_types_edit_settings.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THM-Health/PILOS/7ace1347300f486c0ce82903c0c5e46324b33f8d/.opencode/screenshots/de/room_types_edit_settings.jpg -------------------------------------------------------------------------------- /.opencode/screenshots/de/running_meetings.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THM-Health/PILOS/7ace1347300f486c0ce82903c0c5e46324b33f8d/.opencode/screenshots/de/running_meetings.jpg -------------------------------------------------------------------------------- /.opencode/screenshots/de/server_pools.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THM-Health/PILOS/7ace1347300f486c0ce82903c0c5e46324b33f8d/.opencode/screenshots/de/server_pools.jpg -------------------------------------------------------------------------------- /.opencode/screenshots/de/servers.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THM-Health/PILOS/7ace1347300f486c0ce82903c0c5e46324b33f8d/.opencode/screenshots/de/servers.jpg -------------------------------------------------------------------------------- /.opencode/screenshots/de/servers_edit.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THM-Health/PILOS/7ace1347300f486c0ce82903c0c5e46324b33f8d/.opencode/screenshots/de/servers_edit.jpg -------------------------------------------------------------------------------- /.opencode/screenshots/de/settings.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THM-Health/PILOS/7ace1347300f486c0ce82903c0c5e46324b33f8d/.opencode/screenshots/de/settings.jpg -------------------------------------------------------------------------------- /.opencode/screenshots/de/users.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THM-Health/PILOS/7ace1347300f486c0ce82903c0c5e46324b33f8d/.opencode/screenshots/de/users.jpg -------------------------------------------------------------------------------- /.opencode/screenshots/en/app_settings.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THM-Health/PILOS/7ace1347300f486c0ce82903c0c5e46324b33f8d/.opencode/screenshots/en/app_settings.jpg -------------------------------------------------------------------------------- /.opencode/screenshots/en/dashboard.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THM-Health/PILOS/7ace1347300f486c0ce82903c0c5e46324b33f8d/.opencode/screenshots/en/dashboard.jpg -------------------------------------------------------------------------------- /.opencode/screenshots/en/home.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THM-Health/PILOS/7ace1347300f486c0ce82903c0c5e46324b33f8d/.opencode/screenshots/en/home.jpg -------------------------------------------------------------------------------- /.opencode/screenshots/en/login.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THM-Health/PILOS/7ace1347300f486c0ce82903c0c5e46324b33f8d/.opencode/screenshots/en/login.jpg -------------------------------------------------------------------------------- /.opencode/screenshots/en/profile_base.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THM-Health/PILOS/7ace1347300f486c0ce82903c0c5e46324b33f8d/.opencode/screenshots/en/profile_base.jpg -------------------------------------------------------------------------------- /.opencode/screenshots/en/profile_security.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THM-Health/PILOS/7ace1347300f486c0ce82903c0c5e46324b33f8d/.opencode/screenshots/en/profile_security.jpg -------------------------------------------------------------------------------- /.opencode/screenshots/en/roles.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THM-Health/PILOS/7ace1347300f486c0ce82903c0c5e46324b33f8d/.opencode/screenshots/en/roles.jpg -------------------------------------------------------------------------------- /.opencode/screenshots/en/roles_detail.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THM-Health/PILOS/7ace1347300f486c0ce82903c0c5e46324b33f8d/.opencode/screenshots/en/roles_detail.jpg -------------------------------------------------------------------------------- /.opencode/screenshots/en/room_attendance.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THM-Health/PILOS/7ace1347300f486c0ce82903c0c5e46324b33f8d/.opencode/screenshots/en/room_attendance.jpg -------------------------------------------------------------------------------- /.opencode/screenshots/en/room_description.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THM-Health/PILOS/7ace1347300f486c0ce82903c0c5e46324b33f8d/.opencode/screenshots/en/room_description.jpg -------------------------------------------------------------------------------- /.opencode/screenshots/en/room_files.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THM-Health/PILOS/7ace1347300f486c0ce82903c0c5e46324b33f8d/.opencode/screenshots/en/room_files.jpg -------------------------------------------------------------------------------- /.opencode/screenshots/en/room_history.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THM-Health/PILOS/7ace1347300f486c0ce82903c0c5e46324b33f8d/.opencode/screenshots/en/room_history.jpg -------------------------------------------------------------------------------- /.opencode/screenshots/en/room_members.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THM-Health/PILOS/7ace1347300f486c0ce82903c0c5e46324b33f8d/.opencode/screenshots/en/room_members.jpg -------------------------------------------------------------------------------- /.opencode/screenshots/en/room_personalized_room_links.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THM-Health/PILOS/7ace1347300f486c0ce82903c0c5e46324b33f8d/.opencode/screenshots/en/room_personalized_room_links.jpg -------------------------------------------------------------------------------- /.opencode/screenshots/en/room_settings.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THM-Health/PILOS/7ace1347300f486c0ce82903c0c5e46324b33f8d/.opencode/screenshots/en/room_settings.jpg -------------------------------------------------------------------------------- /.opencode/screenshots/en/room_stats.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THM-Health/PILOS/7ace1347300f486c0ce82903c0c5e46324b33f8d/.opencode/screenshots/en/room_stats.jpg -------------------------------------------------------------------------------- /.opencode/screenshots/en/room_types.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THM-Health/PILOS/7ace1347300f486c0ce82903c0c5e46324b33f8d/.opencode/screenshots/en/room_types.jpg -------------------------------------------------------------------------------- /.opencode/screenshots/en/room_types_edit.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THM-Health/PILOS/7ace1347300f486c0ce82903c0c5e46324b33f8d/.opencode/screenshots/en/room_types_edit.jpg -------------------------------------------------------------------------------- /.opencode/screenshots/en/room_types_edit_settings.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THM-Health/PILOS/7ace1347300f486c0ce82903c0c5e46324b33f8d/.opencode/screenshots/en/room_types_edit_settings.jpg -------------------------------------------------------------------------------- /.opencode/screenshots/en/running_meetings.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THM-Health/PILOS/7ace1347300f486c0ce82903c0c5e46324b33f8d/.opencode/screenshots/en/running_meetings.jpg -------------------------------------------------------------------------------- /.opencode/screenshots/en/server_pools.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THM-Health/PILOS/7ace1347300f486c0ce82903c0c5e46324b33f8d/.opencode/screenshots/en/server_pools.jpg -------------------------------------------------------------------------------- /.opencode/screenshots/en/servers.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THM-Health/PILOS/7ace1347300f486c0ce82903c0c5e46324b33f8d/.opencode/screenshots/en/servers.jpg -------------------------------------------------------------------------------- /.opencode/screenshots/en/servers_edit.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THM-Health/PILOS/7ace1347300f486c0ce82903c0c5e46324b33f8d/.opencode/screenshots/en/servers_edit.jpg -------------------------------------------------------------------------------- /.opencode/screenshots/en/settings.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THM-Health/PILOS/7ace1347300f486c0ce82903c0c5e46324b33f8d/.opencode/screenshots/en/settings.jpg -------------------------------------------------------------------------------- /.opencode/screenshots/en/users.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THM-Health/PILOS/7ace1347300f486c0ce82903c0c5e46324b33f8d/.opencode/screenshots/en/users.jpg -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | # Ignore artifacts: 2 | build 3 | coverage 4 | lang 5 | public 6 | storage 7 | composer.lock 8 | package-lock.json 9 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": ["prettier-plugin-tailwindcss"] 3 | } 4 | -------------------------------------------------------------------------------- /.styleci.yml: -------------------------------------------------------------------------------- 1 | php: 2 | preset: laravel 3 | disabled: 4 | - no_unused_imports 5 | finder: 6 | not-name: 7 | - index.php 8 | - server.php 9 | js: 10 | finder: 11 | not-name: 12 | - webpack.mix.js 13 | css: true 14 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Supported Versions 4 | 5 | We actively support PILOS through the matrix chat and through security updates. 6 | 7 | | Version | Supported | 8 | | ------- | ------------------ | 9 | | 4.x | :white_check_mark: | 10 | | 3.x | :x: | 11 | | 2.x | :x: | 12 | | 1.x | :x: | 13 | 14 | ## Reporting a Vulnerability 15 | 16 | If you believe you have found a security vunerability in PILOS please let us know directly by using GitHub's "Report a vulnerability" functionality on https://github.com/THM-Health/PILOS/security/advisories 17 | -------------------------------------------------------------------------------- /app/Auth/MissingAttributeException.php: -------------------------------------------------------------------------------- 1 | app->singleton(ShibbolethProvider::class, function (Application $app) { 16 | return new ShibbolethProvider; 17 | }); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /app/Auth/Shibboleth/ShibbolethSessionDuplicateException.php: -------------------------------------------------------------------------------- 1 | hashShibbolethSessionId($SessionID); 16 | $lookupSessions = SessionData::where('key', 'shibboleth_session_id')->where('value', $hashShibbolethSessionId)->get(); 17 | foreach ($lookupSessions as $lookupSession) { 18 | $lookupSession->session()->delete(); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /app/Auth/config/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore -------------------------------------------------------------------------------- /app/Enums/CustomStatusCodes.php: -------------------------------------------------------------------------------- 1 | 'Guest', 20 | RoomUserRole::USER => 'User', 21 | RoomUserRole::MODERATOR => 'Moderator', 22 | RoomUserRole::CO_OWNER => 'Co-Owner', 23 | RoomUserRole::OWNER => 'Owner', 24 | }; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/Enums/RoomVisibility.php: -------------------------------------------------------------------------------- 1 | room; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /app/Events/RoomStarted.php: -------------------------------------------------------------------------------- 1 | room; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /app/Exceptions/RecordingExtractionFailed.php: -------------------------------------------------------------------------------- 1 | generator->sentence($length, false), 0, $length); 20 | 21 | // Replace the last character of the text with '.' if it is ' ' 22 | if ($text[$length - 1] === ' ') { 23 | $text[$length - 1] = '.'; 24 | } 25 | 26 | return $text; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /app/Http/Controllers/ApplicationController.php: -------------------------------------------------------------------------------- 1 | download(); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/Http/Controllers/api/v1/ApplicationController.php: -------------------------------------------------------------------------------- 1 | withPermissions()->withoutRoles(); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /app/Http/Controllers/api/v1/PermissionController.php: -------------------------------------------------------------------------------- 1 | additional([ 19 | 'meta' => [ 20 | 'restrictions' => config('permissions.restrictions'), 21 | ], 22 | ]); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /app/Http/Controllers/api/v1/SessionController.php: -------------------------------------------------------------------------------- 1 | sessions()->orderByDesc('last_activity')->get()); 15 | } 16 | 17 | public function destroy() 18 | { 19 | $authService = new AuthenticationService(Auth::user()); 20 | $authService->logoutOtherSessions(session()->getId()); 21 | 22 | return response()->noContent(); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /app/Http/Middleware/Authenticate.php: -------------------------------------------------------------------------------- 1 | expectsJson() ? null : URL::to('/login'); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /app/Http/Middleware/EncryptCookies.php: -------------------------------------------------------------------------------- 1 | check()) { 24 | return (new Response('Guests only.'))->setStatusCode(420, 'Guests only'); 25 | } 26 | } 27 | 28 | return $next($request); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /app/Http/Middleware/TrimStrings.php: -------------------------------------------------------------------------------- 1 | 13 | */ 14 | public function hosts(): array 15 | { 16 | $url = parse_url(config('app.url'), PHP_URL_HOST); 17 | 18 | return [$url]; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /app/Http/Middleware/TrustProxies.php: -------------------------------------------------------------------------------- 1 | proxies = config('app.trusted_proxies'); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /app/Http/Middleware/VerifyCsrfToken.php: -------------------------------------------------------------------------------- 1 | ['required', 'integer', 'exists:App\Models\User,id', 15 | function ($attribute, $value, $fail) { 16 | if ($this->room->members()->find($value) or $this->room->owner->id == $value) { 17 | $fail(__('validation.custom.room.already_member')); 18 | } 19 | }], 20 | 'role' => ['required', Rule::in([RoomUserRole::USER, RoomUserRole::MODERATOR, RoomUserRole::CO_OWNER])], 21 | ]; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /app/Http/Requests/ChangeEmailRequest.php: -------------------------------------------------------------------------------- 1 | ['required', 'string', 'email', 'max:255', Rule::unique('users', 'email')->where(function ($query) { 20 | return $query->where('authenticator', '=', 'local')->where('id', '!=', $this->user->id); 21 | })], 22 | 'current_password' => $this->user->is(Auth::user()) ? ['required', 'current_password'] : [], 23 | ]; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /app/Http/Requests/ChangeLocaleRequest.php: -------------------------------------------------------------------------------- 1 | ['required', 'string', Rule::in(array_keys(config('app.enabled_locales')))], 19 | ]; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /app/Http/Requests/ChangePasswordRequest.php: -------------------------------------------------------------------------------- 1 | ['required', 'string', 'min:8', 'confirmed', new Password], 20 | 'current_password' => $this->user->is(Auth::user()) ? ['required', 'current_password'] : [], 21 | ]; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /app/Http/Requests/CreateRoom.php: -------------------------------------------------------------------------------- 1 | ['bail', 'required', 'integer', 'exists:App\Models\RoomType,id', new ValidRoomType(Auth::user())], 15 | 'name' => ['required', 'string', 'min:2', 'max:'.config('bigbluebutton.room_name_limit')], 16 | ]; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /app/Http/Requests/RoomTokenRequest.php: -------------------------------------------------------------------------------- 1 | ['required', 'min:2', 'max:50', new ValidName], 16 | 'lastname' => ['required', 'min:2', 'max:50', new ValidName], 17 | 'role' => ['required', Rule::in([RoomUserRole::USER, RoomUserRole::MODERATOR])], 18 | ]; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /app/Http/Requests/RoomTypeDestroyRequest.php: -------------------------------------------------------------------------------- 1 | ['nullable', Rule::requiredIf($this->roomType->rooms()->count() > 0), 'integer', 'exists:App\Models\RoomType,id', Rule::notIn([$this->roomType->id])], 14 | ]; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /app/Http/Requests/ServerConnectionCheckRequest.php: -------------------------------------------------------------------------------- 1 | ['required', 'url', 'string', 'max:255'], 13 | 'secret' => ['required', 'string', 'max:255'], 14 | ]; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /app/Http/Requests/ServerPoolRequest.php: -------------------------------------------------------------------------------- 1 | ['required', 'string', 'max:255', Rule::unique('server_pools', 'name')], 14 | 'description' => ['nullable', 'string', 'max:255'], 15 | 'servers' => 'array', 16 | 'servers.*' => ['distinct', 'integer', 'exists:App\Models\Server,id'], 17 | ]; 18 | 19 | if ($this->serverPool) { 20 | $rules['name'] = ['required', 'string', 'max:255', Rule::unique('server_pools', 'name')->ignore($this->serverPool->id)]; 21 | } 22 | 23 | return $rules; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /app/Http/Requests/StoreRoomFile.php: -------------------------------------------------------------------------------- 1 | ['required', 'file', 'max:'.(config('bigbluebutton.max_filesize') * 1000), 'mimes:'.config('bigbluebutton.allowed_file_mimes')], // https://github.com/bigbluebutton/bigbluebutton/blob/v2.2.x-release/bigbluebutton-html5/private/config/settings.yml 13 | ]; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /app/Http/Requests/UpdateRecordingRequest.php: -------------------------------------------------------------------------------- 1 | ['required', 'string', 'max:'.config('recording.description_limit')], 15 | 'access' => ['required', Rule::enum(RecordingAccess::class)], 16 | 'formats' => ['required', 'array'], 17 | 'formats.*.id' => ['required', 'distinct', Rule::in($this->recording->formats->pluck('id')->toArray())], 18 | 'formats.*.disabled' => ['required', 'boolean'], 19 | ]; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /app/Http/Requests/UpdateRoomDescription.php: -------------------------------------------------------------------------------- 1 | ['nullable', 'string', 'max:65000'], 13 | ]; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /app/Http/Requests/UpdateRoomFile.php: -------------------------------------------------------------------------------- 1 | ['required', 'boolean'], 13 | 'download' => ['required', 'boolean'], 14 | 'default' => ['required', 'boolean'], 15 | ]; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /app/Http/Requests/UpdateRoomMember.php: -------------------------------------------------------------------------------- 1 | ['required', Rule::in([RoomUserRole::USER, RoomUserRole::MODERATOR, RoomUserRole::CO_OWNER])], 15 | ]; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /app/Http/Requests/UpdateRoomTypeStreamingSettings.php: -------------------------------------------------------------------------------- 1 | ['required', 'boolean'], 18 | 'default_pause_image' => ['nullable', 'image', 'mimes:jpg,bmp,png,gif', 'max:5000', 'dimensions:width=1920,height=1080'], // 5 MB 19 | ]; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /app/Http/Requests/UpdateStreamingSettings.php: -------------------------------------------------------------------------------- 1 | ['nullable', 'image', 'mimes:jpg,bmp,png,gif', 'max:5000', 'dimensions:width=1920,height=1080'], // 5 MB 19 | 'css_file' => ['nullable', 'file', 'max:500', 'extensions:css'], 20 | 'join_parameters' => ['nullable', 'string', 'max:65000', new CustomJoinMeetingParameters], 21 | ]; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /app/Http/Requests/VerifyEmailRequest.php: -------------------------------------------------------------------------------- 1 | ['required', 'string'], 18 | 'email' => ['required', 'string'], 19 | ]; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /app/Http/Resources/Attendee.php: -------------------------------------------------------------------------------- 1 | $this['name'], 17 | 'email' => $this['email'], 18 | 'duration' => $this['duration'], 19 | 'sessions' => AttendeeSession::collection($this['sessions']), 20 | ]; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /app/Http/Resources/AttendeeSession.php: -------------------------------------------------------------------------------- 1 | $this['id'], 17 | 'join' => $this['join'], 18 | 'leave' => $this['leave'], 19 | 'duration' => $this['duration'], 20 | ]; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /app/Http/Resources/LastMeeting.php: -------------------------------------------------------------------------------- 1 | $this->start, 19 | 'end' => $this->end, 20 | 'detached' => $this->detached, 21 | 'usage' => $this->when($this->end == null, [ 22 | 'participant_count' => $this->room->participant_count, 23 | ]), 24 | 'server_connection_issues' => $this->end == null && $this->server->error_count > 0, 25 | ]; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /app/Http/Resources/Meeting.php: -------------------------------------------------------------------------------- 1 | $this->id, 20 | 'start' => $this->start, 21 | 'end' => $this->end, 22 | 'attendance' => $this->attendees()->count() > 0, 23 | 'statistical' => app(RecordingSettings::class)->meeting_usage_enabled && $this->stats()->count() > 0, 24 | ]; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/Http/Resources/MeetingStat.php: -------------------------------------------------------------------------------- 1 | $this->id, 19 | 'participant_count' => $this->participant_count, 20 | 'listener_count' => $this->listener_count, 21 | 'voice_participant_count' => $this->voice_participant_count, 22 | 'video_count' => $this->video_count, 23 | 'created_at' => $this->created_at, 24 | ]; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/Http/Resources/PermissionResourceCollection.php: -------------------------------------------------------------------------------- 1 | $this->collection->map(function (\App\Models\Permission $resource) { 18 | return (new Permission($resource))->withIncludedPermissions(); 19 | })->all(), 20 | ]; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /app/Http/Resources/PrivateRoomFile.php: -------------------------------------------------------------------------------- 1 | $this->id, 19 | 'filename' => $this->filename, 20 | 'download' => $this->download, 21 | 'use_in_meeting' => $this->use_in_meeting, 22 | 'default' => $this->default, 23 | 'uploaded' => $this->created_at, 24 | ]; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/Http/Resources/RecordingFormatResource.php: -------------------------------------------------------------------------------- 1 | $this->id, 18 | 'format' => $this->format, 19 | 'disabled' => $this->disabled, 20 | ]; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /app/Http/Resources/RecordingResource.php: -------------------------------------------------------------------------------- 1 | $this->id, 18 | 'start' => $this->start, 19 | 'end' => $this->end, 20 | 'description' => $this->description, 21 | 'access' => $this->access, 22 | 'formats' => RecordingFormatResource::collection($this->formats->sortBy('format')), 23 | ]; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /app/Http/Resources/RoomFile.php: -------------------------------------------------------------------------------- 1 | $this->id, 19 | 'filename' => $this->filename, 20 | 'uploaded' => $this->created_at, 21 | ]; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /app/Http/Resources/RoomStreaming.php: -------------------------------------------------------------------------------- 1 | 14 | */ 15 | public function toArray(Request $request): array 16 | { 17 | return [ 18 | 'enabled_for_current_meeting' => $this->enabled_for_current_meeting, 19 | 'status' => $this->status, 20 | 'fps' => $this->fps, 21 | ]; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /app/Http/Resources/RoomStreamingConfig.php: -------------------------------------------------------------------------------- 1 | 14 | */ 15 | public function toArray(Request $request): array 16 | { 17 | return [ 18 | 'enabled' => $this->enabled, 19 | 'url' => $this->url, 20 | 'pause_image' => $this->pause_image, 21 | 'room_type_default_pause_image' => $this->resource->room->roomType->streamingSettings->default_pause_image, 22 | 'system_default_pause_image' => app(\App\Settings\StreamingSettings::class)->default_pause_image, 23 | ]; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /app/Http/Resources/RoomToken.php: -------------------------------------------------------------------------------- 1 | $this->token, 19 | 'firstname' => $this->firstname, 20 | 'lastname' => $this->lastname, 21 | 'role' => $this->role, 22 | 'expires' => $this->expires, 23 | 'last_usage' => $this->last_usage, 24 | ]; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/Http/Resources/RoomTypeStreamingSettings.php: -------------------------------------------------------------------------------- 1 | 14 | */ 15 | public function toArray(Request $request): array 16 | { 17 | return [ 18 | 'enabled' => $this->enabled, 19 | 'default_pause_image' => $this->default_pause_image, 20 | ]; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /app/Http/Resources/RoomUser.php: -------------------------------------------------------------------------------- 1 | $this->id, 19 | 'firstname' => $this->firstname, 20 | 'lastname' => $this->lastname, 21 | 'email' => $this->email, 22 | 'role' => $this->pivot->role, 23 | 'image' => $this->imageUrl, 24 | ]; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/Http/Resources/SessionResource.php: -------------------------------------------------------------------------------- 1 | $this->last_activity, 19 | 'ip_address' => $this->ip_address, 20 | 'user_agent' => $this->user_agent, 21 | 'current' => $this->id === session()->getId(), 22 | ]; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /app/Listeners/FailedLoginAttempt.php: -------------------------------------------------------------------------------- 1 | guard == 'ldap') { 28 | Log::notice('External user '.$event->credentials['username'].' has failed authentication.', ['type' => 'ldap']); 29 | } else { 30 | Log::notice('Local user '.$event->credentials['email'].' has failed local authentication.'); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /app/Listeners/ResetStreamingOnRoomStop.php: -------------------------------------------------------------------------------- 1 | getRoom(); 25 | 26 | $room->streaming->status = null; 27 | $room->streaming->fps = null; 28 | $room->streaming->save(); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /app/Models/IncludedPermissionPermission.php: -------------------------------------------------------------------------------- 1 | 'integer', 18 | 'listener_count' => 'integer', 19 | 'voice_participant_count' => 'integer', 20 | 'video_count' => 'integer', 21 | ]; 22 | 23 | /** 24 | * Meeting the statistical data belongs to 25 | * 26 | * @return \Illuminate\Database\Eloquent\Relations\BelongsTo 27 | */ 28 | public function meeting() 29 | { 30 | return $this->belongsTo(Meeting::class); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /app/Models/PermissionRole.php: -------------------------------------------------------------------------------- 1 | 'boolean']; 10 | 11 | protected static function booted(): void 12 | { 13 | static::created(function () { 14 | User::$clearPermissionCache = true; 15 | }); 16 | 17 | static::deleted(function () { 18 | User::$clearPermissionCache = true; 19 | }); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /app/Models/RoomTypeStreamingSettings.php: -------------------------------------------------------------------------------- 1 | 'boolean', 24 | ]; 25 | 26 | protected $with = ['roomType']; 27 | 28 | public function roomType(): BelongsTo 29 | { 30 | return $this->belongsTo(RoomType::class, 'room_type_id', 'id'); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /app/Models/RoomUser.php: -------------------------------------------------------------------------------- 1 | RoomUserRole::class, 12 | ]; 13 | } 14 | -------------------------------------------------------------------------------- /app/Models/ServerStat.php: -------------------------------------------------------------------------------- 1 | 'integer', 11 | 'listener_count' => 'integer', 12 | 'voice_participant_count' => 'integer', 13 | 'video_count' => 'integer', 14 | 'meeting_count' => 'integer', 15 | ]; 16 | 17 | /** 18 | * Server the statistical data belongs to 19 | * 20 | * @return \Illuminate\Database\Eloquent\Relations\BelongsTo 21 | */ 22 | public function server() 23 | { 24 | return $this->belongsTo(Server::class); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/Models/Session.php: -------------------------------------------------------------------------------- 1 | 'datetime', 17 | ]; 18 | 19 | protected $dateFormat = 'U'; 20 | 21 | /** 22 | * User this session belongs to 23 | * 24 | * @return \Illuminate\Database\Eloquent\Relations\BelongsTo 25 | */ 26 | public function user() 27 | { 28 | return $this->belongsTo(User::class); 29 | } 30 | 31 | public function sessionData() 32 | { 33 | return $this->hasMany(SessionData::class); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /app/Models/SessionData.php: -------------------------------------------------------------------------------- 1 | belongsTo(Session::class); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /app/Models/VerifyEmail.php: -------------------------------------------------------------------------------- 1 | belongsTo(User::class); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /app/Plugins/Contracts/ServerLoadCalculationPluginContract.php: -------------------------------------------------------------------------------- 1 | can('meetings.viewAny'); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/Providers/BroadcastServiceProvider.php: -------------------------------------------------------------------------------- 1 | app->singleton(Generator::class, function () { 18 | $faker = Factory::create(); 19 | $faker->addProvider(new TextProvider($faker)); 20 | 21 | return $faker; 22 | }); 23 | } 24 | 25 | /** 26 | * Bootstrap services. 27 | */ 28 | public function boot(): void 29 | { 30 | // 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /app/Providers/HorizonServiceProvider.php: -------------------------------------------------------------------------------- 1 | can('system.monitor'); 28 | }); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /app/Providers/TranslationServiceProvider.php: -------------------------------------------------------------------------------- 1 | app->singleton('translation.loader', function ($app) { 18 | return new FileLoader($app['files'], [config('app.default_locale_dir'), config('app.custom_locale_dir')]); 19 | }); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /app/Rules/CustomCreateMeetingParameters.php: -------------------------------------------------------------------------------- 1 | verifyEmail = $verifyEmail; 16 | $this->plainTextToken = $plainTextToken; 17 | } 18 | 19 | public function getVerifyEmail(): VerifyEmail 20 | { 21 | return $this->verifyEmail; 22 | } 23 | 24 | public function getPlainTextToken(): string 25 | { 26 | return $this->plainTextToken; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /app/Services/StreamingServiceFactory.php: -------------------------------------------------------------------------------- 1 | add(Directive::BASE, Keyword::SELF) 16 | ->add(Directive::CONNECT, Keyword::SELF) 17 | ->add(Directive::DEFAULT, Keyword::SELF) 18 | ->add(Directive::FORM_ACTION, Keyword::SELF) 19 | ->add(Directive::IMG, ['*', 'data:', 'blob:']) 20 | ->add(Directive::MEDIA, Keyword::SELF) 21 | ->add(Directive::OBJECT, Keyword::NONE) 22 | ->add(Directive::STYLE, [Keyword::SELF, Keyword::UNSAFE_INLINE]) 23 | ->addNonce(Directive::SCRIPT); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /app/Support/LaravelViteNonceGenerator.php: -------------------------------------------------------------------------------- 1 | env('GREENLIGHT_COMPATIBILITY', false), 5 | 'base' => env('GREENLIGHT_PATH', 'b'), 6 | ]; 7 | -------------------------------------------------------------------------------- /config/permissions.php: -------------------------------------------------------------------------------- 1 | explode(',', env('PERMISSION_RESTRICTIONS', '')), 5 | ]; 6 | -------------------------------------------------------------------------------- /config/plugins.php: -------------------------------------------------------------------------------- 1 | explode(',', env('PLUGINS', '')), 5 | 'contracts' => [ 6 | \App\Plugins\Contracts\ServerLoadCalculationPluginContract::class, 7 | ], 8 | 'namespaces' => [ 9 | 'defaults' => 'App\Plugins\Defaults', 10 | 'custom' => 'App\Plugins\Custom', 11 | ], 12 | ]; 13 | -------------------------------------------------------------------------------- /config/recording.php: -------------------------------------------------------------------------------- 1 | env('RECORDING_PLAYER', '/playback/presentation/2.3'), 5 | 'spool-sub-directory' => env('RECORDING_SPOOL_SUB_DIRECTORY', ''), 6 | 'download_allowlist' => env('RECORDING_DOWNLOAD_ALLOWLIST', '.*'), 7 | 'max_retention_period' => (int) env('RECORDING_MAX_RETENTION_PERIOD', -1), 8 | 'description_limit' => (int) env('RECORDING_DESCRIPTION_LIMIT', 1000), 9 | 'import_before_hook' => env('RECORDING_IMPORT_BEFORE_HOOK', ''), 10 | ]; 11 | -------------------------------------------------------------------------------- /config/streaming.php: -------------------------------------------------------------------------------- 1 | (bool) env('STREAMING_ENABLED', false), 5 | 'api' => env('STREAMING_API'), 6 | 'server_timeout' => (int) env('STREAMING_SERVER_TIMEOUT', 10), 7 | 'server_connect_timeout' => (int) env('STREAMING_SERVER_CONNECT_TIMEOUT', 20), 8 | 'refresh_interval' => (int) env('STREAMING_REFRESH_INTERVAL', 10), 9 | 'show_fps' => (bool) env('STREAMING_SHOW_FPS', false), 10 | 'auth' => [ 11 | 'type' => env('STREAMING_AUTH_TYPE', 'none'), 12 | 'basic' => [ 13 | 'username' => env('STREAMING_AUTH_BASIC_USERNAME'), 14 | 'password' => env('STREAMING_AUTH_BASIC_PASSWORD'), 15 | ], 16 | ], 17 | ]; 18 | -------------------------------------------------------------------------------- /database/.gitignore: -------------------------------------------------------------------------------- 1 | *.sqlite* 2 | -------------------------------------------------------------------------------- /database/factories/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THM-Health/PILOS/7ace1347300f486c0ce82903c0c5e46324b33f8d/database/factories/.gitkeep -------------------------------------------------------------------------------- /database/factories/PermissionFactory.php: -------------------------------------------------------------------------------- 1 | $this->faker->unique()->word, 26 | ]; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /database/factories/RecordingFactory.php: -------------------------------------------------------------------------------- 1 | faker->numberBetween(1, 20000); 17 | $end = $this->faker->date('U'); 18 | 19 | return [ 20 | 'id' => $this->faker->uuid, 21 | 'room_id' => Room::factory(), 22 | 'description' => $this->faker->text, 23 | 'access' => RecordingAccess::OWNER, 24 | 'start' => date('Y-m-d H:i:s', $end - $length), 25 | 'end' => date('Y-m-d H:i:s', $end), 26 | ]; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /database/factories/RoleFactory.php: -------------------------------------------------------------------------------- 1 | $this->faker->unique()->word, 26 | 'superuser' => false, 27 | ]; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /database/factories/RoomTokenFactory.php: -------------------------------------------------------------------------------- 1 | $this->faker->firstName, 28 | 'lastname' => $this->faker->lastName, 29 | 'role' => RoomUserRole::USER, 30 | 'room_id' => Room::factory(), 31 | ]; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /database/factories/RoomTypeFactory.php: -------------------------------------------------------------------------------- 1 | $this->faker->word, 27 | 'color' => $this->faker->hexColor, 28 | 'server_pool_id' => ServerPool::factory(), 29 | ]; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /database/factories/ServerPoolFactory.php: -------------------------------------------------------------------------------- 1 | $this->faker->unique()->word, 26 | 'description' => $this->faker->text, 27 | ]; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /database/migrations/2014_10_12_100000_create_password_resets_table.php: -------------------------------------------------------------------------------- 1 | string('email')->index(); 18 | $table->string('token'); 19 | $table->timestamp('created_at')->nullable(); 20 | }); 21 | } 22 | 23 | /** 24 | * Reverse the migrations. 25 | * 26 | * @return void 27 | */ 28 | public function down() 29 | { 30 | Schema::dropIfExists('password_resets'); 31 | } 32 | }; 33 | -------------------------------------------------------------------------------- /database/migrations/2022_07_21_000003_create_permissions_table.php: -------------------------------------------------------------------------------- 1 | id(); 18 | $table->string('name')->unique(); 19 | $table->timestamps(); 20 | }); 21 | } 22 | 23 | /** 24 | * Reverse the migrations. 25 | * 26 | * @return void 27 | */ 28 | public function down() 29 | { 30 | Schema::dropIfExists('permissions'); 31 | } 32 | }; 33 | -------------------------------------------------------------------------------- /database/migrations/2022_07_21_000009_create_server_server_pool_table.php: -------------------------------------------------------------------------------- 1 | foreignId('server_id')->constrained()->onDelete('cascade'); 14 | $table->foreignId('server_pool_id')->constrained()->onDelete('cascade'); 15 | }); 16 | $seeder = new ServerPoolSeeder; 17 | $seeder->run(); 18 | } 19 | 20 | public function down() 21 | { 22 | Schema::dropIfExists('server_server_pool'); 23 | } 24 | }; 25 | -------------------------------------------------------------------------------- /database/migrations/2022_09_29_101046_create_verify_emails_table.php: -------------------------------------------------------------------------------- 1 | id(); 13 | $table->foreignId('user_id')->constrained()->onDelete('cascade'); 14 | $table->string('email'); 15 | $table->string('token'); 16 | $table->timestamps(); 17 | }); 18 | } 19 | 20 | public function down() 21 | { 22 | Schema::dropIfExists('verify_emails'); 23 | } 24 | }; 25 | -------------------------------------------------------------------------------- /database/migrations/2023_04_14_083707_create_settings_table.php: -------------------------------------------------------------------------------- 1 | id(); 13 | 14 | $table->string('group'); 15 | $table->string('name'); 16 | $table->boolean('locked')->default(false); 17 | $table->json('payload'); 18 | 19 | $table->timestamps(); 20 | 21 | $table->unique(['group', 'name']); 22 | }); 23 | } 24 | 25 | public function down() 26 | { 27 | Schema::dropIfExists('settings'); 28 | } 29 | }; 30 | -------------------------------------------------------------------------------- /database/migrations/2024_05_22_101114_add_create_parameters_to_room_types_table.php: -------------------------------------------------------------------------------- 1 | text('create_parameters')->nullable(); 16 | }); 17 | } 18 | 19 | /** 20 | * Reverse the migrations. 21 | */ 22 | public function down(): void 23 | { 24 | Schema::table('room_types', function (Blueprint $table) { 25 | $table->dropColumn('create_parameters'); 26 | 27 | }); 28 | } 29 | }; 30 | -------------------------------------------------------------------------------- /database/migrations/2024_12_19_103013_make_server_name_unique.php: -------------------------------------------------------------------------------- 1 | unique('name'); 16 | }); 17 | } 18 | 19 | /** 20 | * Reverse the migrations. 21 | */ 22 | public function down(): void 23 | { 24 | Schema::table('servers', function (Blueprint $table) { 25 | $table->dropUnique(['name']); 26 | }); 27 | } 28 | }; 29 | -------------------------------------------------------------------------------- /database/migrations/2025_03_31_130245_add_external_image_hash_to_users_table.php: -------------------------------------------------------------------------------- 1 | string('external_image_hash')->nullable()->after('image'); 16 | }); 17 | } 18 | 19 | /** 20 | * Reverse the migrations. 21 | */ 22 | public function down(): void 23 | { 24 | Schema::table('users', function (Blueprint $table) { 25 | $table->dropColumn('external_image_hash'); 26 | }); 27 | } 28 | }; 29 | -------------------------------------------------------------------------------- /database/migrations/2025_05_20_092623_add_last_login_to_users_table.php: -------------------------------------------------------------------------------- 1 | dateTime('last_login')->nullable(); 13 | }); 14 | } 15 | 16 | public function down(): void 17 | { 18 | Schema::table('users', function (Blueprint $table) { 19 | $table->dropColumn('last_login'); 20 | }); 21 | } 22 | }; 23 | -------------------------------------------------------------------------------- /database/migrations/2025_05_20_153825_add_join_parameters_to_room_types_table.php: -------------------------------------------------------------------------------- 1 | text('join_parameters')->nullable(); 13 | }); 14 | } 15 | 16 | public function down(): void 17 | { 18 | Schema::table('room_types', function (Blueprint $table) { 19 | $table->dropColumn('join_parameters'); 20 | }); 21 | } 22 | }; 23 | -------------------------------------------------------------------------------- /database/migrations/migrate-to-v4/2023_07_31_143604_add_short_description_to_rooms_table.php: -------------------------------------------------------------------------------- 1 | string('short_description', 300)->nullable(); 16 | }); 17 | } 18 | 19 | /** 20 | * Reverse the migrations. 21 | */ 22 | public function down(): void 23 | { 24 | Schema::table('rooms', function (Blueprint $table) { 25 | $table->dropColumn('short_description'); 26 | }); 27 | } 28 | }; 29 | -------------------------------------------------------------------------------- /database/migrations/migrate-to-v4/2023_11_24_135054_remove_short_from_room_types.php: -------------------------------------------------------------------------------- 1 | dropColumn('short'); 16 | }); 17 | } 18 | 19 | /** 20 | * Reverse the migrations. 21 | */ 22 | public function down(): void 23 | { 24 | Schema::table('room_types', function (Blueprint $table) { 25 | $table->string('short', 2)->nullable(); 26 | }); 27 | } 28 | }; 29 | -------------------------------------------------------------------------------- /database/migrations/migrate-to-v4/2024_01_31_070902_add_require_access_code_to_room_types_table.php: -------------------------------------------------------------------------------- 1 | boolean('require_access_code')->default(false); 16 | }); 17 | } 18 | 19 | /** 20 | * Reverse the migrations. 21 | */ 22 | public function down(): void 23 | { 24 | Schema::table('room_types', function (Blueprint $table) { 25 | $table->dropColumn('require_access_code'); 26 | }); 27 | } 28 | }; 29 | -------------------------------------------------------------------------------- /database/migrations/migrate-to-v4/2024_01_31_071243_add_allow_record_attendace_to_room_types_table.php: -------------------------------------------------------------------------------- 1 | boolean('allow_record_attendance')->default(true); 16 | }); 17 | } 18 | 19 | /** 20 | * Reverse the migrations. 21 | */ 22 | public function down(): void 23 | { 24 | Schema::table('room_types', function (Blueprint $table) { 25 | $table->dropColumn('allow_record_attendance'); 26 | }); 27 | } 28 | }; 29 | -------------------------------------------------------------------------------- /database/migrations/migrate-to-v4/2024_02_29_091745_rename_columns_in_roles_table.php: -------------------------------------------------------------------------------- 1 | renameColumn('default', 'superuser'); 16 | }); 17 | } 18 | 19 | /** 20 | * Reverse the migrations. 21 | */ 22 | public function down(): void 23 | { 24 | Schema::table('roles', function (Blueprint $table) { 25 | $table->renameColumn('superuser', 'default'); 26 | }); 27 | } 28 | }; 29 | -------------------------------------------------------------------------------- /database/migrations/migrate-to-v4/2024_03_07_085720_add_disconnected_to_meetings_table.php: -------------------------------------------------------------------------------- 1 | dateTime('detached')->nullable(); 16 | }); 17 | } 18 | 19 | /** 20 | * Reverse the migrations. 21 | */ 22 | public function down(): void 23 | { 24 | Schema::table('meetings', function (Blueprint $table) { 25 | $table->dropColumn('detached'); 26 | }); 27 | } 28 | }; 29 | -------------------------------------------------------------------------------- /database/migrations/migrate-to-v4/2024_03_10_095259_add_description_to_room_types_table.php: -------------------------------------------------------------------------------- 1 | string('description', 5000)->nullable(); 16 | }); 17 | } 18 | 19 | /** 20 | * Reverse the migrations. 21 | */ 22 | public function down(): void 23 | { 24 | Schema::table('room_types', function (Blueprint $table) { 25 | $table->dropColumn('description'); 26 | }); 27 | } 28 | }; 29 | -------------------------------------------------------------------------------- /database/migrations/migrate-to-v4/2024_04_25_064827_add_record_to_meetings.php: -------------------------------------------------------------------------------- 1 | boolean('record')->default(false); 16 | }); 17 | } 18 | 19 | /** 20 | * Reverse the migrations. 21 | */ 22 | public function down(): void 23 | { 24 | Schema::table('meetings', function (Blueprint $table) { 25 | $table->dropColumn('record'); 26 | }); 27 | } 28 | }; 29 | -------------------------------------------------------------------------------- /database/migrations/v2/2014_10_12_100000_create_password_resets_table.php: -------------------------------------------------------------------------------- 1 | string('email')->index(); 18 | $table->string('token'); 19 | $table->timestamp('created_at')->nullable(); 20 | }); 21 | } 22 | 23 | /** 24 | * Reverse the migrations. 25 | * 26 | * @return void 27 | */ 28 | public function down() 29 | { 30 | Schema::dropIfExists('password_resets'); 31 | } 32 | }; 33 | -------------------------------------------------------------------------------- /database/migrations/v2/2022_07_21_000003_create_permissions_table.php: -------------------------------------------------------------------------------- 1 | id(); 18 | $table->string('name')->unique(); 19 | $table->timestamps(); 20 | }); 21 | } 22 | 23 | /** 24 | * Reverse the migrations. 25 | * 26 | * @return void 27 | */ 28 | public function down() 29 | { 30 | Schema::dropIfExists('permissions'); 31 | } 32 | }; 33 | -------------------------------------------------------------------------------- /database/migrations/v2/2022_07_21_000006_create_settings_table.php: -------------------------------------------------------------------------------- 1 | increments('id'); 17 | $table->string('key')->index(); 18 | $table->text('value'); 19 | }); 20 | } 21 | 22 | /** 23 | * Reverse the migrations. 24 | * 25 | * @return void 26 | */ 27 | public function down() 28 | { 29 | Schema::drop('settings'); 30 | } 31 | }; 32 | -------------------------------------------------------------------------------- /database/migrations/v2/2022_07_21_000009_create_server_server_pool_table.php: -------------------------------------------------------------------------------- 1 | foreignId('server_id')->constrained()->onDelete('cascade'); 14 | $table->foreignId('server_pool_id')->constrained()->onDelete('cascade'); 15 | }); 16 | $seeder = new ServerPoolSeeder; 17 | $seeder->run(); 18 | } 19 | 20 | public function down() 21 | { 22 | Schema::dropIfExists('server_server_pool'); 23 | } 24 | }; 25 | -------------------------------------------------------------------------------- /database/migrations/v2/2022_09_23_144227_add_description_to_rooms_table.php: -------------------------------------------------------------------------------- 1 | text('description')->nullable(); 13 | }); 14 | } 15 | 16 | public function down() 17 | { 18 | Schema::table('rooms', function (Blueprint $table) { 19 | $table->dropColumn('description'); 20 | }); 21 | } 22 | }; 23 | -------------------------------------------------------------------------------- /database/migrations/v2/2022_09_29_101046_create_verify_emails_table.php: -------------------------------------------------------------------------------- 1 | id(); 13 | $table->foreignId('user_id')->constrained()->onDelete('cascade'); 14 | $table->string('email'); 15 | $table->string('token'); 16 | $table->timestamps(); 17 | }); 18 | } 19 | 20 | public function down() 21 | { 22 | Schema::dropIfExists('verify_emails'); 23 | } 24 | }; 25 | -------------------------------------------------------------------------------- /database/migrations/v2/2023_09_01_100006_revert_authenticator_bundling.php: -------------------------------------------------------------------------------- 1 | update(['authenticator' => 'ldap']); 14 | } 15 | 16 | /** 17 | * Reverse the migrations. 18 | */ 19 | public function down(): void 20 | { 21 | User::where('authenticator', 'ldap')->update(['authenticator' => 'external']); 22 | } 23 | }; 24 | -------------------------------------------------------------------------------- /database/migrations/v2/2023_09_28_084531_rename_salt_to_secret_in_servers_table.php: -------------------------------------------------------------------------------- 1 | renameColumn('salt', 'secret'); 16 | }); 17 | } 18 | 19 | /** 20 | * Reverse the migrations. 21 | */ 22 | public function down(): void 23 | { 24 | Schema::table('servers', function (Blueprint $table) { 25 | $table->renameColumn('secret', 'salt'); 26 | }); 27 | } 28 | }; 29 | -------------------------------------------------------------------------------- /database/seeders/DatabaseSeeder.php: -------------------------------------------------------------------------------- 1 | call(RoomTypeSeeder::class); 17 | $this->call(RolesAndPermissionsSeeder::class); 18 | $this->call(ServerPoolSeeder::class); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /database/seeders/Demo/storage/abc-def-123/anatomy-foot.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THM-Health/PILOS/7ace1347300f486c0ce82903c0c5e46324b33f8d/database/seeders/Demo/storage/abc-def-123/anatomy-foot.pdf -------------------------------------------------------------------------------- /database/seeders/Demo/storage/abc-def-123/anatomy-introduction.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THM-Health/PILOS/7ace1347300f486c0ce82903c0c5e46324b33f8d/database/seeders/Demo/storage/abc-def-123/anatomy-introduction.pdf -------------------------------------------------------------------------------- /database/seeders/Demo/storage/public/profile_images/angela-jones.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THM-Health/PILOS/7ace1347300f486c0ce82903c0c5e46324b33f8d/database/seeders/Demo/storage/public/profile_images/angela-jones.jpg -------------------------------------------------------------------------------- /database/seeders/Demo/storage/public/profile_images/daniel-osorio.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THM-Health/PILOS/7ace1347300f486c0ce82903c0c5e46324b33f8d/database/seeders/Demo/storage/public/profile_images/daniel-osorio.jpg -------------------------------------------------------------------------------- /database/seeders/Demo/storage/public/profile_images/john-doe.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THM-Health/PILOS/7ace1347300f486c0ce82903c0c5e46324b33f8d/database/seeders/Demo/storage/public/profile_images/john-doe.jpg -------------------------------------------------------------------------------- /database/seeders/ServerPoolSeeder.php: -------------------------------------------------------------------------------- 1 | count() == 0) { 20 | $default = ServerPool::create(['name' => 'Default', 'description' => '']); 21 | $default->servers()->sync(Server::all()); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /database/settings/2023_04_14_103520_create_user_settings.php: -------------------------------------------------------------------------------- 1 | migrator->add('user.password_change_allowed', true); 10 | } 11 | 12 | public function down(): void 13 | { 14 | $this->migrator->delete('user.password_change_allowed'); 15 | } 16 | }; 17 | -------------------------------------------------------------------------------- /database/settings/2023_04_14_103858_create_big_blue_button_settings.php: -------------------------------------------------------------------------------- 1 | migrator->add('bbb.logo'); 10 | $this->migrator->add('bbb.style'); 11 | $this->migrator->add('bbb.default_presentation'); 12 | } 13 | 14 | public function down(): void 15 | { 16 | $this->migrator->delete('bbb.logo'); 17 | $this->migrator->delete('bbb.style'); 18 | $this->migrator->delete('bbb.default_presentation'); 19 | } 20 | }; 21 | -------------------------------------------------------------------------------- /database/settings/2024_05_24_135649_add_toast_life_time_to_general_settings.php: -------------------------------------------------------------------------------- 1 | migrator->add('general.toast_lifetime', 5); 10 | } 11 | 12 | public function down(): void 13 | { 14 | $this->migrator->delete('general.toast_lifetime'); 15 | } 16 | }; 17 | -------------------------------------------------------------------------------- /database/settings/2024_07_09_122330_add_theme_settings.php: -------------------------------------------------------------------------------- 1 | migrator->add('theme.primary_color', '#14b8a6'); 10 | $this->migrator->add('theme.rounded', true); 11 | } 12 | 13 | public function down(): void 14 | { 15 | $this->migrator->delete('theme.primary_color'); 16 | $this->migrator->delete('theme.rounded'); 17 | } 18 | }; 19 | -------------------------------------------------------------------------------- /database/settings/2024_09_27_065358_add_file_terms_of_use_to_room_settings.php: -------------------------------------------------------------------------------- 1 | migrator->add('room.file_terms_of_use'); 10 | } 11 | 12 | public function down(): void 13 | { 14 | $this->migrator->delete('room.file_terms_of_use'); 15 | } 16 | }; 17 | -------------------------------------------------------------------------------- /database/settings/2024_09_27_101218_add_no_welcome_page_to_general_settings.php: -------------------------------------------------------------------------------- 1 | migrator->add('general.no_welcome_page', false); 10 | } 11 | 12 | public function down(): void 13 | { 14 | $this->migrator->delete('general.no_welcome_page'); 15 | } 16 | }; 17 | -------------------------------------------------------------------------------- /database/settings/2024_11_26_131704_create_streaming_settings.php: -------------------------------------------------------------------------------- 1 | migrator->add('streaming.default_pause_image'); 10 | $this->migrator->add('streaming.css_file'); 11 | $this->migrator->add('streaming.join_parameters'); 12 | } 13 | 14 | public function down(): void 15 | { 16 | $this->migrator->delete('streaming.default_pause_image'); 17 | $this->migrator->delete('streaming.css_file'); 18 | $this->migrator->delete('streaming.join_parameters'); 19 | } 20 | }; 21 | -------------------------------------------------------------------------------- /database/settings/2024_12_13_133315_add_dark_mode_logo_to_big_blue_button_settings.php: -------------------------------------------------------------------------------- 1 | migrator->add('bbb.logo_dark'); 10 | } 11 | 12 | public function down(): void 13 | { 14 | $this->migrator->delete('bbb.logo_dark'); 15 | } 16 | }; 17 | -------------------------------------------------------------------------------- /database/settings/2025_01_09_135151_fix_invalid_link_button_style.php: -------------------------------------------------------------------------------- 1 | migrator->update( 11 | 'banner.link_style', 12 | function (LinkButtonStyle $style) { 13 | return LinkButtonStyle::getDeprecationReplacement($style); 14 | } 15 | ); 16 | } 17 | }; 18 | -------------------------------------------------------------------------------- /docker/app/cron/scheduler: -------------------------------------------------------------------------------- 1 | SHELL=/bin/sh 2 | PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin 3 | 4 | # m h dom mon dow user command 5 | * * * * * cd /var/www/html/ && pilos-cli schedule:run --verbose --no-interaction > /proc/1/fd/1 2>/proc/1/fd/2 6 | -------------------------------------------------------------------------------- /docker/app/ldap/ldap.conf: -------------------------------------------------------------------------------- 1 | TLS_REQCERT never 2 | -------------------------------------------------------------------------------- /docker/app/nginx/snippets-available/ssl: -------------------------------------------------------------------------------- 1 | 2 | listen 443 ssl; 3 | 4 | ssl_certificate /local/certs/fullchain.pem; 5 | ssl_certificate_key /local/certs/privkey.pem; 6 | ssl_session_timeout 1d; 7 | ssl_session_cache shared:MozSSL:10m; 8 | ssl_session_tickets off; 9 | ssl_protocols TLSv1.2 TLSv1.3; 10 | ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384; 11 | ssl_prefer_server_ciphers off; 12 | -------------------------------------------------------------------------------- /docker/app/php/opcache.ini: -------------------------------------------------------------------------------- 1 | [opcache] 2 | opcache.enable=1 3 | opcache.memory_consumption=512 4 | opcache.interned_strings_buffer=64 5 | opcache.max_accelerated_files=32531 6 | opcache.save_comments=1 7 | opcache.fast_shutdown=0 8 | opcache.enable_cli=1 9 | opcache.validate_timestamps=1 10 | -------------------------------------------------------------------------------- /docker/app/php/php.ini: -------------------------------------------------------------------------------- 1 | [PHP] 2 | post_max_size = 1G 3 | upload_max_filesize = 1G 4 | variables_order = EGPCS 5 | -------------------------------------------------------------------------------- /docker/openldap/acl.ldif: -------------------------------------------------------------------------------- 1 | dn: olcDatabase={1}{{ LDAP_BACKEND }},cn=config 2 | changetype: modify 3 | delete: olcAccess 4 | - 5 | add: olcAccess 6 | olcAccess: to * by dn.exact=gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth manage by * break 7 | olcAccess: to attrs=userPassword,shadowLastChange by self write by dn="cn=admin,{{ LDAP_BASE_DN }}" write by anonymous auth by * none 8 | olcAccess: to * by self read by dn="cn=admin,{{ LDAP_BASE_DN }}" write by users read by * none 9 | -------------------------------------------------------------------------------- /docs/.gitignore: -------------------------------------------------------------------------------- 1 | # Dependencies 2 | /node_modules 3 | 4 | # Production 5 | /build 6 | 7 | # Generated files 8 | .docusaurus 9 | .cache-loader 10 | 11 | # Misc 12 | .DS_Store 13 | .env.local 14 | .env.development.local 15 | .env.test.local 16 | .env.production.local 17 | 18 | npm-debug.log* 19 | yarn-debug.log* 20 | yarn-error.log* 21 | -------------------------------------------------------------------------------- /docs/docs/administration/08-advanced/_category_.json: -------------------------------------------------------------------------------- 1 | { 2 | "label": "Advanced", 3 | "link": { 4 | "type": "generated-index" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /docs/docs/administration/09-customisation/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Customisation 3 | --- 4 | 5 | import DocCardList from '@theme/DocCardList'; 6 | 7 | 8 | -------------------------------------------------------------------------------- /docs/docs/development/01-intro.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Introduction 3 | --- 4 | 5 | Thanks that you want to contribute to our project. 6 | 7 | ## Code of conduct 8 | 9 | Everyone who want to contribute to this project including the owners must hold our [Code of Conduct](https://github.com/THM-Health/PILOS?tab=coc-ov-file). 10 | 11 | ## Setting up a development environment 12 | 13 | Follow the [Getting Started](./02-getting-started.md) guide to set up a development environment. 14 | -------------------------------------------------------------------------------- /docs/src/components/HomepageFeatures/styles.module.css: -------------------------------------------------------------------------------- 1 | .features { 2 | display: flex; 3 | align-items: center; 4 | padding: 2rem 0; 5 | width: 100%; 6 | } 7 | 8 | .featureSvg { 9 | color: var(--ifm-color-primary); 10 | height: 100px; 11 | width: 100px; 12 | } 13 | -------------------------------------------------------------------------------- /docs/src/pages/index.module.css: -------------------------------------------------------------------------------- 1 | /** 2 | * CSS files with the .module.css suffix will be treated as CSS modules 3 | * and scoped locally. 4 | */ 5 | 6 | .heroBanner { 7 | padding: 4rem 0; 8 | text-align: center; 9 | position: relative; 10 | overflow: hidden; 11 | } 12 | 13 | @media screen and (max-width: 996px) { 14 | .heroBanner { 15 | padding: 2rem; 16 | } 17 | } 18 | 19 | .buttons { 20 | display: flex; 21 | align-items: center; 22 | justify-content: center; 23 | } 24 | -------------------------------------------------------------------------------- /docs/src/pages/markdown-page.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Markdown page example 3 | --- 4 | 5 | # Markdown page example 6 | 7 | You don't need React to write simple standalone pages. 8 | -------------------------------------------------------------------------------- /docs/static/.nojekyll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THM-Health/PILOS/7ace1347300f486c0ce82903c0c5e46324b33f8d/docs/static/.nojekyll -------------------------------------------------------------------------------- /docs/static/img/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THM-Health/PILOS/7ace1347300f486c0ce82903c0c5e46324b33f8d/docs/static/img/favicon.ico -------------------------------------------------------------------------------- /docs/static/img/laptop-code-solid.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /docs/static/img/social-card.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THM-Health/PILOS/7ace1347300f486c0ce82903c0c5e46324b33f8d/docs/static/img/social-card.png -------------------------------------------------------------------------------- /docs/static/img/toolbox-solid.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /lang/de-gender/pagination.php: -------------------------------------------------------------------------------- 1 | 'Weiter »', 5 | 'previous' => '« Zurück', 6 | ]; 7 | -------------------------------------------------------------------------------- /lang/de-gender/passwords.php: -------------------------------------------------------------------------------- 1 | 'Das Passwort wurde zurückgesetzt!', 5 | 'sent' => 'Passworterinnerung wurde gesendet!', 6 | 'throttled' => 'Please wait before retrying.', 7 | 'token' => 'Der Passwort-Wiederherstellungs-Schlüssel ist ungültig oder abgelaufen.', 8 | 'user' => 'Es konnte leider kein Benutzer mit dieser E-Mail-Adresse gefunden werden.', 9 | ]; 10 | -------------------------------------------------------------------------------- /lang/de-gender/system.php: -------------------------------------------------------------------------------- 1 | [ 5 | 'horizon' => 'Horizon', 6 | 'pulse' => 'Pulse', 7 | 'telescope' => 'Telescope', 8 | 'title' => 'System Überwachung', 9 | ], 10 | ]; 11 | -------------------------------------------------------------------------------- /lang/de/pagination.php: -------------------------------------------------------------------------------- 1 | 'Weiter »', 5 | 'previous' => '« Zurück', 6 | ]; 7 | -------------------------------------------------------------------------------- /lang/de/passwords.php: -------------------------------------------------------------------------------- 1 | 'Das Passwort wurde zurückgesetzt!', 5 | 'sent' => 'Passworterinnerung wurde gesendet!', 6 | 'throttled' => 'Please wait before retrying.', 7 | 'token' => 'Der Passwort-Wiederherstellungs-Schlüssel ist ungültig oder abgelaufen.', 8 | 'user' => 'Es konnte leider kein Benutzer mit dieser E-Mail-Adresse gefunden werden.', 9 | ]; 10 | -------------------------------------------------------------------------------- /lang/de/system.php: -------------------------------------------------------------------------------- 1 | [ 5 | 'horizon' => 'Horizon', 6 | 'pulse' => 'Pulse', 7 | 'telescope' => 'Telescope', 8 | 'title' => 'System Überwachung', 9 | ], 10 | ]; 11 | -------------------------------------------------------------------------------- /lang/en/pagination.php: -------------------------------------------------------------------------------- 1 | 'Next »', 5 | 'previous' => '« Previous', 6 | ]; 7 | -------------------------------------------------------------------------------- /lang/en/passwords.php: -------------------------------------------------------------------------------- 1 | 'Your password has been reset!', 5 | 'sent' => 'We have emailed your password reset link!', 6 | 'throttled' => 'Please wait before retrying.', 7 | 'token' => 'This password reset token is invalid.', 8 | 'user' => 'We can\'t find a user with that email address.', 9 | ]; 10 | -------------------------------------------------------------------------------- /lang/en/system.php: -------------------------------------------------------------------------------- 1 | [ 5 | 'horizon' => 'Horizon', 6 | 'pulse' => 'Pulse', 7 | 'telescope' => 'Telescope', 8 | 'title' => 'System Monitoring', 9 | ], 10 | ]; 11 | -------------------------------------------------------------------------------- /lang/fa/pagination.php: -------------------------------------------------------------------------------- 1 | 'بعدی »', 5 | 'previous' => '« قبلی', 6 | ]; 7 | -------------------------------------------------------------------------------- /lang/fa/passwords.php: -------------------------------------------------------------------------------- 1 | 'رمز عبور شما بازنشانی شد!', 5 | 'sent' => 'لینک بازنشانی رمز عبور را برای شما ایمیل کردیم!', 6 | 'throttled' => 'لطفاً قبل از تلاش مجدد صبر کنید.', 7 | 'token' => 'این توکن بازنشانی رمز عبور نامعتبر است.', 8 | 'user' => 'کاربری با این آدرس ایمیل یافت نشد.', 9 | ]; 10 | -------------------------------------------------------------------------------- /lang/fa/system.php: -------------------------------------------------------------------------------- 1 | [ 5 | 'horizon' => 'Horizon', 6 | 'pulse' => 'Pulse', 7 | 'telescope' => 'Telescope', 8 | 'title' => 'پایش سیستم', 9 | ], 10 | ]; 11 | -------------------------------------------------------------------------------- /lang/fr/pagination.php: -------------------------------------------------------------------------------- 1 | 'Suivant »', 5 | 'previous' => '« Précédent', 6 | ]; 7 | -------------------------------------------------------------------------------- /lang/fr/passwords.php: -------------------------------------------------------------------------------- 1 | 'Votre mot de passe a été réinitialisé!', 5 | 'sent' => 'Nous avons envoyé un lien de réinitialisation de mot de passe par e-mail!', 6 | 'throttled' => 'Merci de patienter avant de réessayer.', 7 | 'token' => 'Ce jeton de réinitialisation de mot de passe n\'est pas valide.', 8 | 'user' => 'Nous ne trouvons pas d\'utilisateur avec cette adresse e-mail.', 9 | ]; 10 | -------------------------------------------------------------------------------- /lang/fr/system.php: -------------------------------------------------------------------------------- 1 | [ 5 | 'horizon' => 'Horizon', 6 | 'pulse' => 'Pulse', 7 | 'telescope' => 'Telescope', 8 | 'title' => 'Surveillance système', 9 | ], 10 | ]; 11 | -------------------------------------------------------------------------------- /pint.json: -------------------------------------------------------------------------------- 1 | { 2 | "exclude": [ 3 | "storage", 4 | "node_modules", 5 | "resources", 6 | "public", 7 | "docker", 8 | "db", 9 | "redis", 10 | "coverage" 11 | ] 12 | } 13 | -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | export default { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | }; 7 | -------------------------------------------------------------------------------- /public/.htaccess: -------------------------------------------------------------------------------- 1 | 2 | 3 | Options -MultiViews -Indexes 4 | 5 | 6 | RewriteEngine On 7 | 8 | # Handle Authorization Header 9 | RewriteCond %{HTTP:Authorization} . 10 | RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}] 11 | 12 | # Redirect Trailing Slashes If Not A Folder... 13 | RewriteCond %{REQUEST_FILENAME} !-d 14 | RewriteCond %{REQUEST_URI} (.+)/$ 15 | RewriteRule ^ %1 [L,R=301] 16 | 17 | # Send Requests To Front Controller... 18 | RewriteCond %{REQUEST_FILENAME} !-d 19 | RewriteCond %{REQUEST_FILENAME} !-f 20 | RewriteRule ^ index.php [L] 21 | 22 | -------------------------------------------------------------------------------- /public/images/custom/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /public/images/default_profile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THM-Health/PILOS/7ace1347300f486c0ce82903c0c5e46324b33f8d/public/images/default_profile.png -------------------------------------------------------------------------------- /public/images/favicon-dark.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THM-Health/PILOS/7ace1347300f486c0ce82903c0c5e46324b33f8d/public/images/favicon-dark.ico -------------------------------------------------------------------------------- /public/images/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THM-Health/PILOS/7ace1347300f486c0ce82903c0c5e46324b33f8d/public/images/favicon.ico -------------------------------------------------------------------------------- /public/images/hero/hero1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THM-Health/PILOS/7ace1347300f486c0ce82903c0c5e46324b33f8d/public/images/hero/hero1.jpg -------------------------------------------------------------------------------- /public/images/hero/hero2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THM-Health/PILOS/7ace1347300f486c0ce82903c0c5e46324b33f8d/public/images/hero/hero2.jpg -------------------------------------------------------------------------------- /public/images/hero/hero3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THM-Health/PILOS/7ace1347300f486c0ce82903c0c5e46324b33f8d/public/images/hero/hero3.jpg -------------------------------------------------------------------------------- /public/images/hero/hero4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THM-Health/PILOS/7ace1347300f486c0ce82903c0c5e46324b33f8d/public/images/hero/hero4.jpg -------------------------------------------------------------------------------- /public/images/hero/hero5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THM-Health/PILOS/7ace1347300f486c0ce82903c0c5e46324b33f8d/public/images/hero/hero5.jpg -------------------------------------------------------------------------------- /public/images/livestream_avatar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THM-Health/PILOS/7ace1347300f486c0ce82903c0c5e46324b33f8d/public/images/livestream_avatar.png -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | User-agent: * 2 | Disallow: 3 | -------------------------------------------------------------------------------- /public/vendor/horizon/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THM-Health/PILOS/7ace1347300f486c0ce82903c0c5e46324b33f8d/public/vendor/horizon/favicon.png -------------------------------------------------------------------------------- /public/vendor/horizon/img/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THM-Health/PILOS/7ace1347300f486c0ce82903c0c5e46324b33f8d/public/vendor/horizon/img/favicon.png -------------------------------------------------------------------------------- /public/vendor/horizon/mix-manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "/app.js": "/app.js?id=4999da9248177ed487693daec2a7d3fe", 3 | "/app-dark.css": "/app-dark.css?id=dcaca44a9f0f1d019e3cd3d76c3cb8fd", 4 | "/app.css": "/app.css?id=14e3bcd1f1b1cf88e63e945529c4d0ce", 5 | "/img/favicon.png": "/img/favicon.png?id=1542bfe8a0010dcbee710da13cce367f", 6 | "/img/horizon.svg": "/img/horizon.svg?id=904d5b5185fefb09035384e15bfca765", 7 | "/img/sprite.svg": "/img/sprite.svg?id=afc4952b74895bdef3ab4ebe9adb746f" 8 | } 9 | -------------------------------------------------------------------------------- /public/vendor/telescope/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THM-Health/PILOS/7ace1347300f486c0ce82903c0c5e46324b33f8d/public/vendor/telescope/favicon.ico -------------------------------------------------------------------------------- /public/vendor/telescope/mix-manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "/app.js": "/app.js?id=99e99836705c54c9dc04352a9907bc7f", 3 | "/app-dark.css": "/app-dark.css?id=1ea407db56c5163ae29311f1f38eb7b9", 4 | "/app.css": "/app.css?id=de4c978567bfd90b38d186937dee5ccf" 5 | } 6 | -------------------------------------------------------------------------------- /resources/audio/notification.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THM-Health/PILOS/7ace1347300f486c0ce82903c0c5e46324b33f8d/resources/audio/notification.mp3 -------------------------------------------------------------------------------- /resources/custom/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /resources/fonts/open-sans/open-sans-300.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THM-Health/PILOS/7ace1347300f486c0ce82903c0c5e46324b33f8d/resources/fonts/open-sans/open-sans-300.woff2 -------------------------------------------------------------------------------- /resources/fonts/open-sans/open-sans-300italic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THM-Health/PILOS/7ace1347300f486c0ce82903c0c5e46324b33f8d/resources/fonts/open-sans/open-sans-300italic.woff2 -------------------------------------------------------------------------------- /resources/fonts/open-sans/open-sans-500.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THM-Health/PILOS/7ace1347300f486c0ce82903c0c5e46324b33f8d/resources/fonts/open-sans/open-sans-500.woff2 -------------------------------------------------------------------------------- /resources/fonts/open-sans/open-sans-500italic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THM-Health/PILOS/7ace1347300f486c0ce82903c0c5e46324b33f8d/resources/fonts/open-sans/open-sans-500italic.woff2 -------------------------------------------------------------------------------- /resources/fonts/open-sans/open-sans-600.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THM-Health/PILOS/7ace1347300f486c0ce82903c0c5e46324b33f8d/resources/fonts/open-sans/open-sans-600.woff2 -------------------------------------------------------------------------------- /resources/fonts/open-sans/open-sans-600italic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THM-Health/PILOS/7ace1347300f486c0ce82903c0c5e46324b33f8d/resources/fonts/open-sans/open-sans-600italic.woff2 -------------------------------------------------------------------------------- /resources/fonts/open-sans/open-sans-700.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THM-Health/PILOS/7ace1347300f486c0ce82903c0c5e46324b33f8d/resources/fonts/open-sans/open-sans-700.woff2 -------------------------------------------------------------------------------- /resources/fonts/open-sans/open-sans-700italic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THM-Health/PILOS/7ace1347300f486c0ce82903c0c5e46324b33f8d/resources/fonts/open-sans/open-sans-700italic.woff2 -------------------------------------------------------------------------------- /resources/fonts/open-sans/open-sans-800.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THM-Health/PILOS/7ace1347300f486c0ce82903c0c5e46324b33f8d/resources/fonts/open-sans/open-sans-800.woff2 -------------------------------------------------------------------------------- /resources/fonts/open-sans/open-sans-800italic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THM-Health/PILOS/7ace1347300f486c0ce82903c0c5e46324b33f8d/resources/fonts/open-sans/open-sans-800italic.woff2 -------------------------------------------------------------------------------- /resources/fonts/open-sans/open-sans-italic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THM-Health/PILOS/7ace1347300f486c0ce82903c0c5e46324b33f8d/resources/fonts/open-sans/open-sans-italic.woff2 -------------------------------------------------------------------------------- /resources/fonts/open-sans/open-sans-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THM-Health/PILOS/7ace1347300f486c0ce82903c0c5e46324b33f8d/resources/fonts/open-sans/open-sans-regular.woff2 -------------------------------------------------------------------------------- /resources/js/components/AdminPanel.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /resources/js/components/FormError.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 19 | -------------------------------------------------------------------------------- /resources/js/components/InlineNote.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 15 | -------------------------------------------------------------------------------- /resources/js/components/LandingHeroCTA.vue: -------------------------------------------------------------------------------- 1 | 13 | -------------------------------------------------------------------------------- /resources/js/components/LandingHeroTitle.vue: -------------------------------------------------------------------------------- 1 | 14 | -------------------------------------------------------------------------------- /resources/js/components/LoadingRetryButton.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 24 | -------------------------------------------------------------------------------- /resources/js/components/LoginTabExternal.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 31 | -------------------------------------------------------------------------------- /resources/js/components/RawText.vue: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /resources/js/components/RoomSettingEnforcedIcon.vue: -------------------------------------------------------------------------------- 1 | 9 | -------------------------------------------------------------------------------- /resources/js/components/RoomTypeBadge.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 22 | -------------------------------------------------------------------------------- /resources/js/components/RoomTypeFeatureField.vue: -------------------------------------------------------------------------------- 1 | 21 | 22 | 37 | -------------------------------------------------------------------------------- /resources/js/components/TextTruncate.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 31 | -------------------------------------------------------------------------------- /resources/js/components/TipTapMenuDropdownItem.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | 24 | -------------------------------------------------------------------------------- /resources/js/composables/useApi.js: -------------------------------------------------------------------------------- 1 | import { Api } from "../services/Api.js"; 2 | 3 | export function useApi() { 4 | return new Api(); 5 | } 6 | -------------------------------------------------------------------------------- /resources/js/constants/events.js: -------------------------------------------------------------------------------- 1 | export const EVENT_UNAUTHORIZED = "unauthorized"; 2 | 3 | export const EVENT_FORBIDDEN = "forbidden"; 4 | -------------------------------------------------------------------------------- /resources/js/env.js: -------------------------------------------------------------------------------- 1 | export default { 2 | HTTP_UNAUTHORIZED: 401, 3 | HTTP_FORBIDDEN: 403, 4 | HTTP_NOT_FOUND: 404, 5 | HTTP_GONE: 410, 6 | HTTP_PRECONDITION_FAILED: 412, 7 | HTTP_PAYLOAD_TOO_LARGE: 413, 8 | HTTP_GUESTS_ONLY: 420, 9 | HTTP_UNPROCESSABLE_ENTITY: 422, 10 | HTTP_ROOM_NOT_RUNNING: 460, 11 | HTTP_NO_SERVER_AVAILABLE: 461, 12 | HTTP_ROOM_START_FAILED: 462, 13 | HTTP_ROOM_LIMIT_EXCEEDED: 463, 14 | HTTP_ROLE_DELETE_LINKED_USERS: 464, 15 | HTTP_ROLE_UPDATE_PERMISSION_LOST: 465, 16 | HTTP_FEATURE_DISABLED: 468, 17 | HTTP_MEETING_ATTENDANCE_NOT_ENDED: 469, 18 | HTTP_MEETING_ATTENDANCE_DISABLED: 470, 19 | HTTP_EMAIL_CHANGE_THROTTLE: 471, 20 | HTTP_JOIN_FAILED: 472, 21 | HTTP_ROOM_ALREADY_RUNNING: 474, 22 | HTTP_STALE_MODEL: 428, 23 | HTTP_TOO_MANY_REQUESTS: 429, 24 | HTTP_LOCKED: 423, 25 | HTTP_SERVICE_UNAVAILABLE: 503, 26 | }; 27 | -------------------------------------------------------------------------------- /resources/js/errors/ParameterMissingError.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Error that can be thrown if a necessary parameter of a function is missing. 3 | */ 4 | export default class ParameterMissingError extends Error { 5 | /** 6 | * Constructor that initializes the error message. 7 | * 8 | * @param parameters {String[]} Array of parameter names that are missing. 9 | * @param any {boolean} Indicates whether any or all parameters necessary. 10 | * @return undefined 11 | */ 12 | constructor(parameters = [], any = false) { 13 | if (typeof parameters === "string") { 14 | super(parameters); 15 | } else { 16 | super( 17 | `${any ? "One of the" : "The"} following parameters should be set: ${parameters.join(", ")}!`, 18 | ); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /resources/js/errors/PolicyDoesNotExistsError.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Error that can be thrown if a policy doesn't exists. 3 | */ 4 | export default class PolicyDoesNotExistsError extends Error { 5 | /** 6 | * Constructor that initializes the error message. 7 | * 8 | * @param policy {String} Policy that wasn't found. 9 | * @param method {String} Method of the missing policy was tried to call. 10 | * @return undefined 11 | */ 12 | constructor(policy, method) { 13 | super(`The policy method '${policy}.${method}' doesn't exists!`); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /resources/js/errors/WrongTypeError.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Error that can be thrown if a passed parameter hasn't the expected type. 3 | */ 4 | export default class WrongTypeError extends Error { 5 | /** 6 | * Constructor that initializes the error message. 7 | * 8 | * @param parameter {String} Parameter that had the wrong type. 9 | * @param type {String} Type that was expected for the parameter. 10 | */ 11 | constructor(parameter, type) { 12 | super(`Expected '${parameter}' to be of type '${type}'!`); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /resources/js/font.js: -------------------------------------------------------------------------------- 1 | import theme from "tailwindcss/defaultTheme"; 2 | export const sansFontFamily = ['"Open Sans"', ...theme.fontFamily.sans]; 3 | -------------------------------------------------------------------------------- /resources/js/plugins/toast.js: -------------------------------------------------------------------------------- 1 | import { setPrimeToastService } from "../composables/useToast"; 2 | import ToastService from "primevue/toastservice"; 3 | 4 | export default { 5 | install: (app) => { 6 | app.use(ToastService); 7 | const primeToastService = app.config.globalProperties.$toast; 8 | setPrimeToastService(primeToastService); 9 | }, 10 | }; 11 | -------------------------------------------------------------------------------- /resources/js/policies/AdminPolicy.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Policy for administration actions 3 | */ 4 | export default { 5 | /** 6 | * Returns a boolean that indicates whether the user view the admin panel 7 | * 8 | * @param user 9 | * @return {boolean} 10 | */ 11 | view(user) { 12 | return !user ? false : user.permissions.includes("admin.view"); 13 | }, 14 | }; 15 | -------------------------------------------------------------------------------- /resources/js/policies/MeetingPolicy.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Policy for meeting actions 3 | */ 4 | export default { 5 | viewAny(user) { 6 | return !user ? false : user.permissions.includes("meetings.viewAny"); 7 | }, 8 | }; 9 | -------------------------------------------------------------------------------- /resources/js/policies/SettingsPolicy.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Policy for application config actions 3 | */ 4 | export default { 5 | /** 6 | * Returns a boolean that indicates whether the user can view all application settings or not. 7 | * 8 | * @param user 9 | * @return {boolean} 10 | */ 11 | viewAny(user) { 12 | return !user ? false : user.permissions.includes("settings.viewAny"); 13 | }, 14 | 15 | /** 16 | * Returns a boolean that indicates whether the user can update the application settings or not. 17 | * 18 | * @param user 19 | * @return {boolean} 20 | */ 21 | update(user) { 22 | return !user ? false : user.permissions.includes("settings.update"); 23 | }, 24 | }; 25 | -------------------------------------------------------------------------------- /resources/js/policies/StreamingPolicy.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Policy for streaming config actions 3 | */ 4 | export default { 5 | /** 6 | * Returns a boolean that indicates whether the user can view all streaming settings or not. 7 | * 8 | * @param user 9 | * @return {boolean} 10 | */ 11 | viewAny(user) { 12 | return !user ? false : user.permissions.includes("streaming.viewAny"); 13 | }, 14 | 15 | /** 16 | * Returns a boolean that indicates whether the user can update the streaming settings or not. 17 | * 18 | * @param user 19 | * @return {boolean} 20 | */ 21 | update(user) { 22 | return !user ? false : user.permissions.includes("streaming.update"); 23 | }, 24 | }; 25 | -------------------------------------------------------------------------------- /resources/js/policies/SystemPolicy.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Policy for system actions 3 | */ 4 | export default { 5 | /** 6 | * Returns a boolean that indicates whether the user can monitor the system or not. 7 | * 8 | * @param user 9 | * @return {boolean} 10 | */ 11 | monitor(user) { 12 | return !user ? false : user.permissions.includes("system.monitor"); 13 | }, 14 | }; 15 | -------------------------------------------------------------------------------- /resources/js/policies/index.js: -------------------------------------------------------------------------------- 1 | import AdminPolicy from "./AdminPolicy"; 2 | import SettingsPolicy from "./SettingsPolicy"; 3 | import RolePolicy from "./RolePolicy"; 4 | import RoomPolicy from "./RoomPolicy"; 5 | import UserPolicy from "./UserPolicy"; 6 | import RoomTypePolicy from "./RoomTypePolicy"; 7 | import ServerPolicy from "./ServerPolicy"; 8 | import ServerPoolPolicy from "./ServerPoolPolicy"; 9 | import SystemPolicy from "./SystemPolicy"; 10 | import MeetingPolicy from "./MeetingPolicy"; 11 | import StreamingPolicy from "./StreamingPolicy"; 12 | 13 | export default { 14 | AdminPolicy, 15 | SettingsPolicy, 16 | RolePolicy, 17 | RoomPolicy, 18 | UserPolicy, 19 | RoomTypePolicy, 20 | ServerPolicy, 21 | ServerPoolPolicy, 22 | SystemPolicy, 23 | MeetingPolicy, 24 | StreamingPolicy, 25 | }; 26 | -------------------------------------------------------------------------------- /resources/js/services/EventBus.js: -------------------------------------------------------------------------------- 1 | import mitt from "mitt"; 2 | 3 | /** 4 | * Event bus that can be used to emit events between services and 5 | * other parts of the application. 6 | */ 7 | const EventBus = mitt(); 8 | 9 | // listen to all events in development mode 10 | if (import.meta.env.DEV) { 11 | EventBus.on("*", (type, e) => console.debug("[EventBus]", type, e)); 12 | } 13 | 14 | export default EventBus; 15 | -------------------------------------------------------------------------------- /resources/js/views/NotFound.vue: -------------------------------------------------------------------------------- 1 | 23 | -------------------------------------------------------------------------------- /resources/js/views/Profile.vue: -------------------------------------------------------------------------------- 1 | 18 | 19 | 24 | -------------------------------------------------------------------------------- /resources/sass/app/_color-select.scss: -------------------------------------------------------------------------------- 1 | .color-select { 2 | &:hover { 3 | transition: 0.3s; 4 | box-shadow: inset 0 0 2px #000000bf; 5 | } 6 | 7 | .overlay:hover { 8 | transition: 0.3s; 9 | background: rgba(0, 0, 0, 0.2); 10 | } 11 | 12 | &.selected { 13 | box-shadow: inset 0 0 10px rgba(0, 0, 0, 0.2); 14 | } 15 | 16 | .overlay { 17 | position: absolute; 18 | top: 0; 19 | left: 0; 20 | right: 0; 21 | bottom: 0; 22 | color: #fff; 23 | display: flex; 24 | align-items: center; 25 | justify-content: center; 26 | } 27 | 28 | .overlay i { 29 | text-shadow: 0 0 10px rgba(0, 0, 0, 0.5); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /resources/sass/app/_navigation.scss: -------------------------------------------------------------------------------- 1 | .p-menubar-mobile { 2 | justify-content: space-between; 3 | width: 100%; 4 | } 5 | -------------------------------------------------------------------------------- /resources/sass/app/_profile-image.scss: -------------------------------------------------------------------------------- 1 | .profile-image, 2 | .profile-image-column { 3 | width: 40px; 4 | } 5 | -------------------------------------------------------------------------------- /resources/sass/app/_streched-link.scss: -------------------------------------------------------------------------------- 1 | // 2 | // Stretched link 3 | // 4 | 5 | .stretched-link { 6 | &::after { 7 | position: absolute; 8 | top: 0; 9 | right: 0; 10 | bottom: 0; 11 | left: 0; 12 | z-index: 1; 13 | // Just in case `pointer-events: none` is set on a parent 14 | pointer-events: auto; 15 | content: ""; 16 | // IE10 bugfix, see https://stackoverflow.com/questions/16947967/ie10-hover-pseudo-class-doesnt-work-without-background-color 17 | background-color: rgba(0, 0, 0, 0); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /resources/sass/app/_typography.scss: -------------------------------------------------------------------------------- 1 | .text-ellipsis { 2 | overflow: hidden; 3 | text-overflow: ellipsis; 4 | white-space: nowrap; 5 | } 6 | 7 | .text-word-break { 8 | overflow-wrap: anywhere; 9 | word-break: normal; 10 | } 11 | -------------------------------------------------------------------------------- /resources/sass/app/app.scss: -------------------------------------------------------------------------------- 1 | @import "general"; 2 | @import "typography"; 3 | @import "navigation"; 4 | @import "action-column"; 5 | @import "room"; 6 | @import "profile-image"; 7 | @import "color-select"; 8 | @import "streched-link"; 9 | -------------------------------------------------------------------------------- /resources/sass/override/_toast.scss: -------------------------------------------------------------------------------- 1 | .p-toast-message-text { 2 | display: flex; 3 | flex-direction: column; 4 | gap: 0.25rem; 5 | .p-toast-detail { 6 | margin: 0; 7 | } 8 | } 9 | 10 | .p-toast-message-icon { 11 | overflow: visible; 12 | margin-top: 0.4rem; 13 | } 14 | 15 | @media (max-width: 639px) { 16 | .p-toast { 17 | width: 100%; 18 | right: unset !important; 19 | padding: 0 10px; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /resources/sass/override/_tooltip.scss: -------------------------------------------------------------------------------- 1 | .p-tooltip-text { 2 | white-space: normal; 3 | word-break: normal; 4 | overflow-wrap: break-word; 5 | } 6 | -------------------------------------------------------------------------------- /resources/sass/override/override.scss: -------------------------------------------------------------------------------- 1 | @import "multiselect"; 2 | @import "tooltip"; 3 | @import "toast"; 4 | -------------------------------------------------------------------------------- /resources/views/vendor/pulse/dashboard.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /routes/channels.php: -------------------------------------------------------------------------------- 1 | 2 | FAILED 3 | checksumError 4 | Checksums do not match 5 | -------------------------------------------------------------------------------- /tests/Backend/Fixtures/EndMeeting.xml: -------------------------------------------------------------------------------- 1 | 2 | SUCCESS 3 | sentEndMeetingRequest 4 | A request to end the meeting was sent. Please wait a few seconds, and then use the getMeetingInfo or isMeetingRunning API calls to verify that it was ended. 5 | -------------------------------------------------------------------------------- /tests/Backend/Fixtures/Failed.xml: -------------------------------------------------------------------------------- 1 | 2 | FAILED 3 | demoError 4 | This is a demo error message 5 | 6 | -------------------------------------------------------------------------------- /tests/Backend/Fixtures/GetApiVersion-Disabled.xml: -------------------------------------------------------------------------------- 1 | 2 | SUCCESS 3 | 2.0 4 | 5 | -------------------------------------------------------------------------------- /tests/Backend/Fixtures/GetApiVersion.xml: -------------------------------------------------------------------------------- 1 | 2 | SUCCESS 3 | 2.0 4 | 2.0 5 | 2.4-rc-7 6 | 7 | -------------------------------------------------------------------------------- /tests/Backend/Fixtures/GetMeetings-Empty.xml: -------------------------------------------------------------------------------- 1 | 2 | SUCCESS 3 | noMeetings 4 | no meetings were found on this server 5 | 6 | 7 | -------------------------------------------------------------------------------- /tests/Backend/Fixtures/GetMeetings-End.xml: -------------------------------------------------------------------------------- 1 | 2 | SUCCESS 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /tests/Backend/Fixtures/Locales/.gitignore: -------------------------------------------------------------------------------- 1 | /*.json -------------------------------------------------------------------------------- /tests/Backend/Fixtures/Locales/custom/de/app.php: -------------------------------------------------------------------------------- 1 | 'neuer_wert_1', 5 | ]; 6 | -------------------------------------------------------------------------------- /tests/Backend/Fixtures/Locales/custom/de/metadata.json: -------------------------------------------------------------------------------- 1 | { 2 | "dateTimeFormat": { 3 | "dateShort": { 4 | "year": "numeric", 5 | "month": "2-digit", 6 | "day": "2-digit" 7 | } 8 | }, 9 | "name": "Deutsch" 10 | } 11 | -------------------------------------------------------------------------------- /tests/Backend/Fixtures/Locales/custom/en/app.php: -------------------------------------------------------------------------------- 1 | 'new_value_1', 5 | ]; 6 | -------------------------------------------------------------------------------- /tests/Backend/Fixtures/Locales/custom/en/metadata.json: -------------------------------------------------------------------------------- 1 | { 2 | "dateTimeFormat": { 3 | "dateShort": { 4 | "year": "numeric", 5 | "month": "2-digit", 6 | "day": "2-digit" 7 | } 8 | }, 9 | "name": "English (US)" 10 | } 11 | -------------------------------------------------------------------------------- /tests/Backend/Fixtures/Locales/custom/es/app.php: -------------------------------------------------------------------------------- 1 | 'nuevo_valor_1', 5 | ]; 6 | -------------------------------------------------------------------------------- /tests/Backend/Fixtures/Locales/custom/fr/app.php: -------------------------------------------------------------------------------- 1 | 'nouvelle_valeur_1', 5 | ]; 6 | -------------------------------------------------------------------------------- /tests/Backend/Fixtures/Locales/default/en/app.php: -------------------------------------------------------------------------------- 1 | 'value_1', 5 | 'key_2' => 'value_2', 6 | 'key_3' => [ 7 | 'key_3_1' => 'value_3_1', 8 | 'key_3_2' => [ 9 | 'key_3_2_1' => 'value_3_2_1', 10 | ], 11 | ], 12 | 'key_4' => [ 13 | 'key_4_1' => 'value_4_1', 14 | 'key_4_2' => [ 15 | 'key_4_2_1' => 'value_4_2_1', 16 | 'key_4_2_2' => 'value_4_2_2', 17 | ], 18 | ], 19 | ]; 20 | -------------------------------------------------------------------------------- /tests/Backend/Fixtures/Locales/default/en/metadata.json: -------------------------------------------------------------------------------- 1 | { 2 | "dateTimeFormat": { 3 | "dateShort": { 4 | "year": "numeric", 5 | "month": "2-digit", 6 | "day": "2-digit" 7 | } 8 | }, 9 | "name": "English" 10 | } 11 | -------------------------------------------------------------------------------- /tests/Backend/Fixtures/Locales/default/fr/app.php: -------------------------------------------------------------------------------- 1 | 'valeur_1', 5 | 'key_4' => [ 6 | 'key_4_1' => 'valeur_4_1', 7 | 'key_4_2' => [ 8 | 'key_4_2_1' => 'valeur_4_2_1', 9 | ], 10 | ], 11 | ]; 12 | -------------------------------------------------------------------------------- /tests/Backend/Fixtures/Locales/default/fr/metadata.json: -------------------------------------------------------------------------------- 1 | { 2 | "dateTimeFormat": { 3 | "dateShort": { 4 | "year": "numeric", 5 | "month": "2-digit", 6 | "day": "2-digit" 7 | } 8 | }, 9 | "name": "Français" 10 | } 11 | -------------------------------------------------------------------------------- /tests/Backend/Fixtures/MeetingNotFound.xml: -------------------------------------------------------------------------------- 1 | 2 | FAILED 3 | notFound 4 | We could not find a meeting with that meeting ID 5 | -------------------------------------------------------------------------------- /tests/Backend/Fixtures/Recordings/invalid-recording.tar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THM-Health/PILOS/7ace1347300f486c0ce82903c0c5e46324b33f8d/tests/Backend/Fixtures/Recordings/invalid-recording.tar -------------------------------------------------------------------------------- /tests/Backend/Fixtures/Recordings/multiple.tar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THM-Health/PILOS/7ace1347300f486c0ce82903c0c5e46324b33f8d/tests/Backend/Fixtures/Recordings/multiple.tar -------------------------------------------------------------------------------- /tests/Backend/Fixtures/Recordings/notes.tar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THM-Health/PILOS/7ace1347300f486c0ce82903c0c5e46324b33f8d/tests/Backend/Fixtures/Recordings/notes.tar -------------------------------------------------------------------------------- /tests/Backend/Fixtures/Recordings/other-file.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THM-Health/PILOS/7ace1347300f486c0ce82903c0c5e46324b33f8d/tests/Backend/Fixtures/Recordings/other-file.txt -------------------------------------------------------------------------------- /tests/Backend/Fixtures/Success.xml: -------------------------------------------------------------------------------- 1 | 2 | SUCCESS 3 | 4 | -------------------------------------------------------------------------------- /tests/Backend/Fixtures/invalidDatabase.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE `test` ( 2 | `column-a` invalidColumType NOT NULL, 3 | `column-b` int(11) NOT NULL, 4 | `column-c` int(11) NOT NULL, 5 | `column-d` int(11) NOT NULL 6 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; 7 | COMMIT; 8 | -------------------------------------------------------------------------------- /tests/Backend/Fixtures/profileImage-1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THM-Health/PILOS/7ace1347300f486c0ce82903c0c5e46324b33f8d/tests/Backend/Fixtures/profileImage-1.jpg -------------------------------------------------------------------------------- /tests/Backend/Fixtures/profileImage-2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THM-Health/PILOS/7ace1347300f486c0ce82903c0c5e46324b33f8d/tests/Backend/Fixtures/profileImage-2.jpg -------------------------------------------------------------------------------- /tests/Backend/Fixtures/validDatabase-mysql.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE `test` ( 2 | `column-a` int(11) NOT NULL, 3 | `column-b` int(11) NOT NULL, 4 | `column-c` int(11) NOT NULL, 5 | `column-d` int(11) NOT NULL 6 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; 7 | COMMIT; 8 | -------------------------------------------------------------------------------- /tests/Backend/Fixtures/validDatabase-postgres.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE test ( 2 | "column-a" integer NOT NULL, 3 | "column-b" integer NOT NULL, 4 | "column-c" integer NOT NULL, 5 | "column-d" integer NOT NULL 6 | ); 7 | -------------------------------------------------------------------------------- /tests/Backend/Unit/AddsModelNameTraitTest.php: -------------------------------------------------------------------------------- 1 | assertEquals('FooBarQux', $object->getModelNameAttribute()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /tests/Backend/Unit/Console/helper/GreenlightSharedAccess.php: -------------------------------------------------------------------------------- 1 | id = $id; 19 | $this->room_id = $room_id; 20 | $this->user_id = $user_id; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /tests/Backend/Unit/Console/helper/GreenlightUser.php: -------------------------------------------------------------------------------- 1 | id = $id; 27 | $this->provider = $provider; 28 | $this->name = $name; 29 | $this->username = $username; 30 | $this->social_uid = $social_uid; 31 | $this->email = $email; 32 | $this->password_digest = $password_digest; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /tests/Backend/Unit/Listeners/ResetStreamingOnRoomStop.php: -------------------------------------------------------------------------------- 1 | create(); 14 | $room->streaming->status = 'running'; 15 | $room->streaming->fps = 30; 16 | $room->streaming->save(); 17 | 18 | // Emit event 19 | RoomEnded::dispatch($room); 20 | 21 | // Check if status and fps are reset 22 | $room->streaming->refresh(); 23 | $this->assertNull($room->streaming->status); 24 | $this->assertNull($room->streaming->fps); 25 | 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /tests/Backend/Unit/StreamingServiceFactoryTest.php: -------------------------------------------------------------------------------- 1 | create(); 18 | 19 | $factory = app(StreamingServiceFactory::class)::make($meeting); 20 | 21 | $this->assertEquals($factory::class, StreamingService::class); 22 | $this->assertTrue($factory->meeting->is($meeting)); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /tests/Backend/Utils/AttendanceExcelImport.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Components App 8 | 9 | 10 |
11 | 12 | 13 | -------------------------------------------------------------------------------- /tests/Frontend/support/utils/fileHelper.js: -------------------------------------------------------------------------------- 1 | export function _arrayBufferToBase64(buffer) { 2 | let binary = ""; 3 | const bytes = new Uint8Array(buffer); 4 | const len = bytes.byteLength; 5 | for (let i = 0; i < len; i++) { 6 | binary += String.fromCharCode(bytes[i]); 7 | } 8 | return btoa(binary); 9 | } 10 | 11 | export function getFileContentType(fileName) { 12 | const fileExtension = fileName.split(".").pop().toLowerCase(); 13 | 14 | const contentType = FILE_CONTENT_TYPES[fileExtension]; 15 | 16 | if (!contentType) { 17 | throw new Error( 18 | "No file content type listed for given file extension: " + fileExtension, 19 | ); 20 | } 21 | 22 | return contentType; 23 | } 24 | 25 | const FILE_CONTENT_TYPES = { 26 | svg: "image/svg+xml", 27 | ico: "image/vnd.microsoft.icon", 28 | }; 29 | -------------------------------------------------------------------------------- /tests/Frontend/support/utils/interceptIndefinitely.js: -------------------------------------------------------------------------------- 1 | export function interceptIndefinitely( 2 | methode, 3 | requestMatcher, 4 | response, 5 | alias, 6 | ) { 7 | let sendResponse; 8 | const trigger = new Promise((resolve) => { 9 | sendResponse = resolve; 10 | }); 11 | // eslint-disable-next-line cypress/no-assigning-return-values 12 | const intercept = cy.intercept(methode, requestMatcher, (request) => { 13 | return trigger.then(() => { 14 | request.reply(response); 15 | }); 16 | }); 17 | 18 | // Set an alias for the intercepted request 19 | if (alias) { 20 | intercept.as(alias); 21 | } 22 | return { sendResponse }; 23 | } 24 | -------------------------------------------------------------------------------- /tests/System/cypress.config.js: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "cypress"; 2 | 3 | export default defineConfig({ 4 | downloadsFolder: "downloads", 5 | fixturesFolder: "fixtures", 6 | screenshotsFolder: "screenshots", 7 | videosFolder: "videos", 8 | 9 | e2e: { 10 | baseUrl: "http://localhost:9080", 11 | experimentalStudio: true, 12 | supportFile: "support/e2e.{js,jsx,ts,tsx}", 13 | specPattern: "e2e/**/*.cy.{js,jsx,ts,tsx}", 14 | }, 15 | 16 | viewportWidth: 1280, 17 | viewportHeight: 800, 18 | }); 19 | -------------------------------------------------------------------------------- /tests/System/support/e2e.js: -------------------------------------------------------------------------------- 1 | // *********************************************************** 2 | // This example support/e2e.js is processed and 3 | // loaded automatically before your test files. 4 | // 5 | // This is a great place to put global configuration and 6 | // behavior that modifies Cypress. 7 | // 8 | // You can change the location of this file or turn off 9 | // automatically serving support files with the 10 | // 'supportFile' configuration option. 11 | // 12 | // You can read more here: 13 | // https://on.cypress.io/configuration 14 | // *********************************************************** 15 | 16 | // Import commands.js using ES2015 syntax: 17 | import "./commands.js"; 18 | 19 | // Alternatively you can use CommonJS syntax: 20 | // require('./commands') 21 | -------------------------------------------------------------------------------- /tests/Utils/create-mariadb-testing-database.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | mariadb --user=root --password="$MYSQL_ROOT_PASSWORD" <<-EOSQL 4 | CREATE DATABASE IF NOT EXISTS testing; 5 | GRANT ALL PRIVILEGES ON \`testing%\`.* TO '$MYSQL_USER'@'%'; 6 | EOSQL 7 | -------------------------------------------------------------------------------- /tests/Utils/create-postgres-testing-database.sql: -------------------------------------------------------------------------------- 1 | SELECT 'CREATE DATABASE testing' 2 | WHERE NOT EXISTS (SELECT FROM pg_database WHERE datname = 'testing')\gexec -------------------------------------------------------------------------------- /tests/Visual/.happo.js: -------------------------------------------------------------------------------- 1 | import { RemoteBrowserTarget } from "happo.io"; 2 | 3 | export default { 4 | apiKey: process.env.HAPPO_API_KEY, 5 | apiSecret: process.env.HAPPO_API_SECRET, 6 | 7 | targets: { 8 | "chrome-desktop": new RemoteBrowserTarget("chrome", { 9 | viewport: "1280x800", 10 | }), 11 | }, 12 | }; 13 | -------------------------------------------------------------------------------- /tests/Visual/fixtures/currentUser.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": { 3 | "id": 1, 4 | "firstname": "John", 5 | "lastname": "Doe", 6 | "user_locale": "en", 7 | "permissions": [], 8 | "timezone": "Europe/Berlin", 9 | "model_name": "User", 10 | "room_limit": -1 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /tests/Visual/fixtures/roomHistoryStats.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": [ 3 | { 4 | "id": 8, 5 | "participant_count": 5, 6 | "listener_count": 3, 7 | "voice_participant_count": 4, 8 | "video_count": 1, 9 | "created_at": "2021-06-18T07:13:49.000000Z" 10 | }, 11 | { 12 | "id": 9, 13 | "participant_count": 6, 14 | "listener_count": 4, 15 | "voice_participant_count": 5, 16 | "video_count": 2, 17 | "created_at": "2021-06-18T07:14:51.000000Z" 18 | } 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /tests/Visual/fixtures/roomTypes.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": [ 3 | { 4 | "id": 1, 5 | "name": "Lecture", 6 | "description": null, 7 | "color": "#80BA27", 8 | "model_name": "RoomType" 9 | }, 10 | { 11 | "id": 2, 12 | "name": "Meeting", 13 | "description": null, 14 | "color": "#4a5c66", 15 | "model_name": "RoomType" 16 | }, 17 | { 18 | "id": 3, 19 | "name": "Exam", 20 | "description": null, 21 | "color": "#9C132E", 22 | "model_name": "RoomType" 23 | }, 24 | { 25 | "id": 4, 26 | "name": "Seminar", 27 | "description": null, 28 | "color": "#00B8E4", 29 | "model_name": "RoomType" 30 | } 31 | ] 32 | } 33 | -------------------------------------------------------------------------------- /tests/Visual/support/commands/interceptCommands.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Intercept requests that are needed when visiting pages that require a logged in user 3 | * @memberof cy 4 | * @method init 5 | * @returns void 6 | */ 7 | Cypress.Commands.add("init", () => { 8 | cy.intercept("GET", "api/v1/currentUser", { fixture: "currentUser.json" }); 9 | 10 | cy.fixture("config.json").then((config) => { 11 | config.data.general.base_url = Cypress.config("baseUrl"); 12 | 13 | cy.intercept("GET", "api/v1/config", { 14 | statusCode: 200, 15 | body: config, 16 | }); 17 | }); 18 | }); 19 | -------------------------------------------------------------------------------- /tests/Visual/support/e2e.js: -------------------------------------------------------------------------------- 1 | // *********************************************************** 2 | // This example support/e2e.js is processed and 3 | // loaded automatically before your test files. 4 | // 5 | // This is a great place to put global configuration and 6 | // behavior that modifies Cypress. 7 | // 8 | // You can change the location of this file or turn off 9 | // automatically serving support files with the 10 | // 'supportFile' configuration option. 11 | // 12 | // You can read more here: 13 | // https://on.cypress.io/configuration 14 | // *********************************************************** 15 | 16 | // Import commands.js using ES2015 syntax: 17 | import "./commands.js"; 18 | import "./commands/interceptCommands.js"; 19 | -------------------------------------------------------------------------------- /vite.config.coverage.js: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "vite"; 2 | import commonConfig from "./vite.config.common"; 3 | import istanbul from "vite-plugin-istanbul"; 4 | export default ({ mode }) => { 5 | const config = commonConfig(mode); 6 | 7 | config.plugins.push( 8 | istanbul({ 9 | forceBuildInstrument: true, 10 | }), 11 | ); 12 | 13 | config.build.sourcemap = true; 14 | 15 | return defineConfig(config); 16 | }; 17 | -------------------------------------------------------------------------------- /vite.config.js: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "vite"; 2 | import commonConfig from "./vite.config.common"; 3 | export default ({ mode }) => { 4 | return defineConfig(commonConfig(mode)); 5 | }; 6 | --------------------------------------------------------------------------------