Added/updated comments

This commit is contained in:
Igor Scheller 2024-04-06 16:14:30 +02:00 committed by xuwhite
parent 9bf9bd2823
commit 905d91d6ed
27 changed files with 93 additions and 41 deletions

View File

@ -28,7 +28,7 @@ The Engelsystem may be installed manually or by using the provided [docker setup
* MySQL-Server >= 5.7.8 or MariaDB-Server >= 10.2.2
* Webserver, i.e. lighttpd, nginx, or Apache
From experience 2 cores and 2GB ram are roughly enough for about 1000 Angels (~700 arrived + 500 arrived but not working) during an event.
From previous experience, 2 cores and 2GB ram are roughly enough for up to 1000 Angels (~700 arrived + 500 arrived but not working) during an event.
### Download
* Go to the [Releases](https://github.com/engelsystem/engelsystem/releases) page and download the latest stable release file.
@ -42,7 +42,14 @@ From experience 2 cores and 2GB ram are roughly enough for about 1000 Angels (~7
* Recommended: Directory Listing should be disabled.
* There must be a MySQL database set up with a user who has full rights to that database.
* If necessary, create a `config/config.php` to override values from `config/config.default.php`.
* To disable/remove values from the `themes`, `tshirt_sizes`, `headers`, `header_items`, `footer_items`, or `locales` lists, set the value of the entry to `null`.
* To disable/remove values from the following lists, set the value of the entry to `null`:
* `themes`
* `tshirt_sizes`
* `headers`
* `header_items`
* `footer_items`
* `locales`
* `contact_options`
* To import the database, the `bin/migrate` script has to be run. If you can't execute scripts, you can use the `initial-install.sql` file from the release zip.
* In the browser, login with credentials `admin` : `asdfasdf` and change the password.

View File

@ -128,11 +128,14 @@ function User_get_shifts_sum_query()
'
COALESCE(SUM(
(1 + (
/* Starts during night */
HOUR(shifts.start) >= %1$d AND HOUR(shifts.start) < %2$d
/* Ends during night */
OR (
HOUR(shifts.end) > %1$d
|| HOUR(shifts.end) = %1$d AND MINUTE(shifts.end) > 0
) AND HOUR(shifts.end) <= %2$d
/* Starts before and ends after night */
OR HOUR(shifts.start) <= %1$d AND HOUR(shifts.end) >= %2$d
))
* (UNIX_TIMESTAMP(shifts.end) - UNIX_TIMESTAMP(shifts.start))

View File

@ -6,6 +6,7 @@ use Engelsystem\Application;
use Engelsystem\Middleware\Dispatcher;
use Psr\Http\Message\ServerRequestInterface;
// Include app bootstrapping
require_once realpath(__DIR__ . '/../includes/engelsystem.php');
/** @var Application $app */
@ -18,4 +19,5 @@ $middleware = $app->getMiddleware();
$dispatcher = new Dispatcher($middleware);
$dispatcher->setContainer($app);
// Handle the request
$dispatcher->handle($request);

View File

@ -14,9 +14,16 @@ class ConfigServiceProvider extends ServiceProvider
{
protected array $configFiles = ['app.php', 'config.default.php', 'config.php'];
# remember to update ConfigServiceProviderTest, config.default.php, and README.md
protected array $configVarsToPruneNulls
= ['themes', 'tshirt_sizes', 'headers', 'header_items', 'footer_items', 'locales', 'contact_options'];
// Remember to update ConfigServiceProviderTest, config.default.php, and README.md
protected array $configVarsToPruneNulls = [
'themes',
'tshirt_sizes',
'headers',
'header_items',
'footer_items',
'locales',
'contact_options',
];
public function __construct(Application $app, protected ?EventConfig $eventConfig = null)
{
@ -29,6 +36,7 @@ class ConfigServiceProvider extends ServiceProvider
$this->app->instance(Config::class, $config);
$this->app->instance('config', $config);
// Load configuration from files
foreach ($this->configFiles as $file) {
$file = $this->getConfigPath($file);
@ -47,6 +55,7 @@ class ConfigServiceProvider extends ServiceProvider
throw new Exception('Configuration not found');
}
// Prune values with null to remove them
foreach ($this->configVarsToPruneNulls as $key) {
$config->set($key, array_filter($config->get($key), function ($v) {
return !is_null($v);

View File

@ -98,6 +98,7 @@ class LocationsController extends BaseController
$location->neededAngelTypes()->getQuery()->delete();
$angelsInfo = '';
// Associate angel types with the room
foreach ($angelTypes as $angelType) {
$count = $data['angel_type_' . $angelType->id];
if (!$count) {

View File

@ -113,6 +113,7 @@ class ShiftTypesController extends BaseController
$shiftType->save();
$shiftType->neededAngelTypes()->delete();
// Associate angel types with the shift type
$angelsInfo = '';
foreach ($angelTypes as $angelType) {
$count = $data['angel_type_' . $angelType->id];

View File

@ -69,6 +69,7 @@ class UserWorkLogController extends BaseController
'comment' => 'required|max:200',
]);
// Search / create worklog
if (isset($worklogId)) {
$worklog = $this->worklog->findOrFail((int) $worklogId);

View File

@ -70,6 +70,7 @@ class FeedController extends BaseController
$shift = $entry->shift;
// Data required for the Fahrplan app integration https://github.com/johnjohndoe/engelsystem
// See engelsystem-base/src/main/kotlin/info/metadude/kotlin/library/engelsystem/models/Shift.kt
// Explicitly typecasts used to stay consistent
// ! All attributes not defined in $data might change at any time !
$data = [
// Name of the shift (type)

View File

@ -171,7 +171,7 @@ class MessagesController extends BaseController
if ($msg->user_id == $currentUser->id) {
$msg->delete();
} else {
throw new HttpForbidden('You can not delete a message you haven\'t send');
throw new HttpForbidden();
}
return $this->redirect->to('/messages/' . $otherUserId . '#newest');

View File

@ -225,7 +225,7 @@ class Controller extends BaseController
}
/**
* Ensure that the if the request is authorized
* Ensure that the request is authorized
*/
protected function checkAuth(bool $isJson = false): void
{

View File

@ -51,6 +51,7 @@ class OAuthController extends BaseController
throw new HttpNotFound('oauth.' . $request->get('error'));
}
// Initial request redirects to provider
if (!$request->has('code')) {
$authorizationUrl = $provider->getAuthorizationUrl(
[
@ -64,6 +65,7 @@ class OAuthController extends BaseController
return $this->redirect->to($authorizationUrl);
}
// Redirected URL got called a second time
if (
!$this->session->get('oauth2_state')
|| $request->get('state') !== $this->session->get('oauth2_state')
@ -75,6 +77,7 @@ class OAuthController extends BaseController
throw new HttpNotFound('oauth.invalid-state');
}
// Fetch access token
$accessToken = null;
try {
$accessToken = $provider->getAccessToken(
@ -87,6 +90,7 @@ class OAuthController extends BaseController
$this->handleOAuthError($e, $providerName);
}
// Load resource identifier
$resourceOwner = null;
try {
$resourceOwner = $provider->getResourceOwner($accessToken);
@ -95,6 +99,7 @@ class OAuthController extends BaseController
}
$resourceId = $this->getId($providerName, $resourceOwner);
// Fetch existing oauth state
/** @var OAuth|null $oauth */
$oauth = $this->oauth
->query()
@ -105,6 +110,7 @@ class OAuthController extends BaseController
->where('identifier', '===', (string) $resourceId)
->first();
// Update oauth state
$expirationTime = $accessToken->getExpires();
$expirationTime = $expirationTime ? Carbon::createFromTimestamp($expirationTime) : null;
if ($oauth) {
@ -115,6 +121,7 @@ class OAuthController extends BaseController
$oauth->save();
}
// Load user
$user = $this->auth->user();
if ($oauth && $user && $user->id != $oauth->user_id) {
throw new HttpNotFound('oauth.already-connected');
@ -122,6 +129,7 @@ class OAuthController extends BaseController
$connectProvider = $this->session->get('oauth2_connect_provider');
$this->session->remove('oauth2_connect_provider');
// Connect user with oauth
if (!$oauth && $user && $connectProvider && $connectProvider == $providerName) {
$oauth = new OAuth([
'provider' => $providerName,
@ -141,6 +149,7 @@ class OAuthController extends BaseController
$this->addNotification('oauth.connected');
}
// Load user data
$resourceData = $resourceOwner->toArray();
if (!empty($config['nested_info'])) {
$resourceData = Arr::dot($resourceData);
@ -148,6 +157,7 @@ class OAuthController extends BaseController
$userdata = new Collection($resourceData);
if (!$oauth) {
// User authenticated but has no account
return $this->redirectRegister(
$providerName,
(string) $resourceId,
@ -307,11 +317,13 @@ class OAuthController extends BaseController
throw new HttpNotFound('oauth.not-found');
}
// Set registration form field data
$this->session->set('form-data-username', $userdata->get($config['username']));
$this->session->set('form-data-email', $userdata->get($config['email']));
$this->session->set('form-data-firstname', $userdata->get($config['first_name']));
$this->session->set('form-data-lastname', $userdata->get($config['last_name']));
// Define OAuth state
$this->session->set('oauth2_groups', $userdata->get($config['groups'], []));
$this->session->set('oauth2_connect_provider', $providerName);
$this->session->set('oauth2_user_id', $providerUserIdentifier);

View File

@ -115,7 +115,7 @@ class RegistrationController extends BaseController
}
/**
* @return Array<string, 1> Checkbox field name/Id 1
* @return Array<string, 1> Checkbox field name/id 1
*/
private function determinePreselectedAngelTypes(): array
{

View File

@ -210,6 +210,7 @@ class User
*/
private function createUser(array $data, array $rawData): EngelsystemUser
{
// Ensure all user entries got created before saving
$this->dbConnection->beginTransaction();
$user = new EngelsystemUser([
@ -274,6 +275,7 @@ class User
->associate($user)
->save();
// Handle OAuth registration
if ($this->session->has('oauth2_connect_provider') && $this->session->has('oauth2_user_id')) {
$oauth = new OAuth([
'provider' => $this->session->get('oauth2_connect_provider'),

View File

@ -4,15 +4,12 @@ declare(strict_types=1);
namespace Engelsystem\Helpers;
use Engelsystem\Helpers\Carbon;
class DayOfEvent
{
/**
* @return The current day of the event.
* If "event_has_day0" is set to true in config,
* the first day of the event will be 0, else 1.
* Returns null if "event_start" is not set.
* @return ?int The current day of the event.
* If `event_has_day0` is set to true in config, the first day of the event will be 0, else 1.
* Returns null if "event_start" is not set.
*/
public static function get(Carbon $date = null): int | null
{

View File

@ -18,11 +18,14 @@ class Shifts
/** @see User_get_shifts_sum_query to keep it in sync */
return $config['enabled'] && (
// Starts during night
$start->hour >= $config['start'] && $start->hour < $config['end']
// Ends during night
|| (
$end->hour > $config['start']
|| $end->hour == $config['start'] && $end->minute > 0
) && $end->hour <= $config['end']
// Starts before and ends after night
|| $start->hour <= $config['start'] && $end->hour >= $config['end']
);
}

View File

@ -72,24 +72,27 @@ class TranslationServiceProvider extends ServiceProvider
public function getTranslator(string $locale): GettextTranslator
{
if (!isset($this->translators[$locale])) {
$names = ['default', 'additional'];
/** @var Translations $translations */
$translations = $this->app->call([Translations::class, 'create']);
$path = $this->app->get('path.lang');
foreach ($names as $name) {
$file = $this->getFile($locale, $path, $name);
$translations = $this->loadFile($file, $translations);
}
$file = $this->getFile($locale, $this->app->get('path.config') . '/lang', 'custom');
$translations = $this->loadFile($file, $translations);
$translator = GettextTranslator::createFromTranslations($translations);
$this->translators[$locale] = $translator;
if (isset($this->translators[$locale])) {
return $this->translators[$locale];
}
$names = ['default', 'additional'];
/** @var Translations $translations */
$translations = $this->app->call([Translations::class, 'create']);
$path = $this->app->get('path.lang');
foreach ($names as $name) {
$file = $this->getFile($locale, $path, $name);
$translations = $this->loadFile($file, $translations);
}
$file = $this->getFile($locale, $this->app->get('path.config') . '/lang', 'custom');
$translations = $this->loadFile($file, $translations);
/** @var GettextTranslator $translator */
$translator = GettextTranslator::createFromTranslations($translations);
$this->translators[$locale] = $translator;
return $this->translators[$locale];
}

View File

@ -21,7 +21,7 @@ class Uuid
mt_rand(0, 0xffff),
// first bit is the uuid version, here 4
mt_rand(0, 0x0fff) | 0x4000,
// variant
// variant, here OSF DCE UUID
mt_rand(0, 0x3fff) | 0x8000,
mt_rand(0, 0xffffffffffff)
);
@ -53,7 +53,7 @@ class Uuid
Str::substr($value, 8, 4),
// first bit is the uuid version, here 4
'4' . Str::substr($value, 13, 3),
// first bit is the variant (0x8-0xb)
// first bit is the variant (0x8-0xb), here OSF DCE UUID
dechex(8 + (hexdec(Str::substr($value, 16, 1)) % 4))
. Str::substr($value, 17, 3),
Str::substr($value, 20, 12)

View File

@ -41,7 +41,7 @@ class UrlGenerator implements UrlGeneratorInterface
}
/**
* Prepend the auto detected or configured app base path and domain
* Prepend the auto-detected or configured app base path and domain
*
* @param $path
*/

View File

@ -37,6 +37,7 @@ class Validator
$value = isset($data[$key]) ? $data[$key] : null;
$values = explode('|', $values);
// Rules that have side effects on others like inverting the result with not and making them optional
$packing = [];
foreach ($this->nestedRules as $rule) {
if (in_array($rule, $values)) {

View File

@ -12,6 +12,9 @@ use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;
/**
* Wraps a callable to be used to respond / as a middleware
*/
class CallableHandler implements MiddlewareInterface, RequestHandlerInterface
{
/** @var callable */

View File

@ -43,7 +43,7 @@ class Dispatcher implements MiddlewareInterface, RequestHandlerInterface
/**
* Handle the request and return a response.
*
* It calls all configured middleware and handles their response
* It calls all configured middlewares and handles their response
*/
public function handle(ServerRequestInterface $request): ResponseInterface
{

View File

@ -22,7 +22,7 @@ class ErrorHandler implements MiddlewareInterface
protected string $viewPrefix = 'errors/';
/**
* A list of inputs that are not saved from form input
* A list of inputs that are not saved from input
*
* @var array<string>
*/
@ -42,7 +42,7 @@ class ErrorHandler implements MiddlewareInterface
}
/**
* Handles any error messages
* Handles any error messages / http exceptions / validation errors
*
* Should be added at the beginning
*/
@ -50,6 +50,7 @@ class ErrorHandler implements MiddlewareInterface
ServerRequestInterface $request,
RequestHandlerInterface $handler
): ResponseInterface {
// Handle response
try {
$response = $handler->handle($request);
} catch (HttpException $e) {
@ -75,6 +76,7 @@ class ErrorHandler implements MiddlewareInterface
$contentType = 'text/html';
}
// Handle response based on status
if (
$statusCode < 400
|| !$response instanceof Response

View File

@ -13,6 +13,9 @@ use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;
/**
* Middleware to support the old routing / pages from includes
*/
class LegacyMiddleware implements MiddlewareInterface
{
/** @var array<string> */
@ -33,7 +36,7 @@ class LegacyMiddleware implements MiddlewareInterface
/**
* Handle the request the old way
*
* Should be used before a 404 is send
* Should be used before a 404 is sent
*/
public function process(
ServerRequestInterface $request,
@ -42,6 +45,7 @@ class LegacyMiddleware implements MiddlewareInterface
/** @var Request $appRequest */
$appRequest = $this->container->get('request');
$page = $appRequest->query->get('p');
// Support old URL scheme
if (empty($page)) {
$page = $appRequest->path();
$page = str_replace('-', '_', $page);

View File

@ -24,6 +24,7 @@ class RequestHandler implements MiddlewareInterface
/**
* Process an incoming server request and return a response, optionally delegating
* response creation to a handler.
* Implements basic permission checking if the controller supports it.
*/
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
{

View File

@ -35,7 +35,6 @@ class TrimInput implements MiddlewareInterface
$request = $request->withParsedBody($trimmedParsedBody);
}
return $handler->handle($request);
}

View File

@ -39,11 +39,10 @@ class Globals extends TwigExtension implements GlobalsInterface
{
$user = $this->auth->user();
$themes = config('themes');
$themeId = config('theme');
$userMessages = null;
if ($user === null) {
$themeId = config('theme');
} else {
if ($user) {
$themeId = $user->settings->theme;
$userMessages = $user
->messagesReceived()

View File

@ -26,6 +26,7 @@ class Url extends TwigExtension
public function getUrl(string $path, array $parameters = []): string
{
// Fix legacy URLs
$path = str_replace('_', '-', $path);
return $this->urlGenerator->to($path, $parameters);