Merge branch 'participo/docker-testing' of https://gitea.cwsvjudo.dedyn.io/marko/cwsvJudo into participo/docker-testing

This commit is contained in:
marko
2024-11-29 21:25:01 +01:00
19 changed files with 179 additions and 97 deletions

View File

@@ -20,7 +20,7 @@ dbConnector::connect(
); );
// authentication of the current user // authentication of the current user
participo::authentificate(); participo::authenticate();
if (!participo::isUserAdmin()) { if (!participo::isUserAdmin()) {
header('Location: /participo', true, 301); header('Location: /participo', true, 301);
} }

View File

@@ -14,7 +14,7 @@ dbConnector::connect(
$cwsvJudoConfig['db']['password'] $cwsvJudoConfig['db']['password']
); );
participo::authentificate(); participo::authenticate();
$eventId = $_POST['eventId'] ?? null; $eventId = $_POST['eventId'] ?? null;
$startingTypeId = $_POST['type'] ?? null; $startingTypeId = $_POST['type'] ?? null;

View File

@@ -14,7 +14,7 @@ dbConnector::connect(
$cwsvJudoConfig['db']['password'] $cwsvJudoConfig['db']['password']
); );
participo::authentificate(); participo::authenticate();
$starterId = $_POST['starterId'] ?? null; $starterId = $_POST['starterId'] ?? null;
$returnToUrl = $_POST['returnToUrl'] ?? 'participo/'; $returnToUrl = $_POST['returnToUrl'] ?? 'participo/';

View File

@@ -15,7 +15,7 @@ dbConnector::connect(
$cwsvJudoConfig['db']['password'] $cwsvJudoConfig['db']['password']
); );
participo::authentificate(); participo::authenticate();
$loginName = $_POST['loginName'] ?? null; $loginName = $_POST['loginName'] ?? null;
$name = $_POST['name'] ?? null; $name = $_POST['name'] ?? null;

View File

@@ -2,7 +2,7 @@
/// @file common settings and includes for the participo api /// @file common settings and includes for the participo api
/// - set locale to german /// - set locale to german
setlocale(LC_ALL, "de_DE@euro", "de_DE", "de", "ge"); setlocale(LC_ALL, "de_DE@euro", "de_DE", "de", "ge");
/// - extend the include search path for /// - extend the include search path for:
set_include_path(implode( set_include_path(implode(
PATH_SEPARATOR, PATH_SEPARATOR,
[ [

View File

@@ -21,7 +21,7 @@ setlocale(LC_ALL, 'de_DE@euro', 'de_DE', 'de', 'ge');
$cwsvJudoConfig['db']['password'] $cwsvJudoConfig['db']['password']
); );
participo::authentificate(); participo::authenticate();
$user = participo::sessionUser(); $user = participo::sessionUser();
$usersKids = getUsersKids(dbConnector::getDbConnection(), $_SESSION['user']['userId']); $usersKids = getUsersKids(dbConnector::getDbConnection(), $_SESSION['user']['userId']);

View File

@@ -6,7 +6,8 @@ require_once 'participoLib/event.php';
// Configs // Configs
require_once 'config/participo.php'; require_once 'config/participo.php';
require_once $config['basePath'] . '/config/cwsvJudo.config.php'; // @todo Switch to json saved settings
require_once $config['home'] . '/.local/cwsvJudo.config.php';
participo::init($cwsvJudoConfig); participo::init($cwsvJudoConfig);
@@ -24,9 +25,9 @@ participo::init($cwsvJudoConfig);
<!-- inits for the materializeCss --> <!-- inits for the materializeCss -->
<script src="events.js"></script> <script src="events.js"></script>
<title><?php echo($meta['title']); ?></title> <title><?php echo ($meta['title'] ?? "title missing"); ?></title>
<meta name="description" <meta name="description"
content="<?php echo($meta['description']); ?>" /> content="<?php echo ($meta['description'] ?? "description missing"); ?>" />
<link rel="icon" href="<? echo ($config['ressourceUrl']); ?>/graphiken/icons/cwsv.ico" /> <link rel="icon" href="<? echo ($config['ressourceUrl']); ?>/graphiken/icons/cwsv.ico" />
<link rel="apple-touch-icon" href="<? echo ($config['baseUrl']); ?>/apple-touch-icon.png"> <link rel="apple-touch-icon" href="<? echo ($config['baseUrl']); ?>/apple-touch-icon.png">

View File

@@ -22,7 +22,7 @@ dbConnector::connect(
$cwsvJudoConfig["db"]["password"] $cwsvJudoConfig["db"]["password"]
); );
participo::authentificate(); participo::authenticate();
$meta = [ $meta = [
"title" => "Event Planer", "title" => "Event Planer",

View File

@@ -4,7 +4,7 @@
<div class="nav-wrapper"> <div class="nav-wrapper">
<a href="/participo" class="breadcrumb">cwsvJudo-Apps</a> <a href="/participo" class="breadcrumb">cwsvJudo-Apps</a>
<a href="/participo/events" class="breadcrumb"> <a href="/participo/events" class="breadcrumb">
<?php echo($meta['title']); ?> <?php echo($meta['title'] ?? "missing title"); ?>
</a> </a>
<a class="right top-nav sidenav-trigger waves-effect waves-light hide-on-large-only" href="#" <a class="right top-nav sidenav-trigger waves-effect waves-light hide-on-large-only" href="#"
data-target="nav-mobile"> data-target="nav-mobile">

View File

@@ -32,4 +32,4 @@ dbConnector::connect(
); );
// authentication of the current user // authentication of the current user
participo::authentificate(); participo::authenticate();

View File

@@ -14,7 +14,7 @@
require_once $basePath . '/ressourcen/phpLib/parsedown/Parsedown.php'; require_once $basePath . '/ressourcen/phpLib/parsedown/Parsedown.php';
require_once $basePath . '/ressourcen/phpLib/Spyc/Spyc.php'; require_once $basePath . '/ressourcen/phpLib/Spyc/Spyc.php';
participo::authentificate(); participo::authenticate();
// get a list of all infoZettel // get a list of all infoZettel
$fileList = glob($basePath . '/infoZettel/*.md'); $fileList = glob($basePath . '/infoZettel/*.md');

View File

@@ -24,7 +24,7 @@ class EventPage
public function getHtmlNotFound() public function getHtmlNotFound()
{ {
return '<div>Der Event "' . return '<div>Der Event "' .
$this->id . $this->eventId .
'" existiert leider nicht!</div>' . '" existiert leider nicht!</div>' .
"<h2>Anstehende Termine</h2>" . "<h2>Anstehende Termine</h2>" .
eventPlaner::getHtmlEventTable(eventPlaner::getComingWkEvents()); eventPlaner::getHtmlEventTable(eventPlaner::getComingWkEvents());

View File

@@ -7,6 +7,7 @@ require_once "participoLib/eventPage.php";
require_once "participoLib/starter.php"; require_once "participoLib/starter.php";
require_once "participoLib/planer.php"; require_once "participoLib/planer.php";
/** /**
* FrameWork for the participoApp * FrameWork for the participoApp
*/ */
@@ -123,7 +124,7 @@ class participo
* *
* @retval void * @retval void
*/ */
public static function authentificate($action = "login") public static function authenticate($action = "login")
{ {
// Ensure a session is started // Ensure a session is started
session_start(); session_start();
@@ -147,15 +148,17 @@ class participo
logLoginsToJsonFile($user->getLoginName()); logLoginsToJsonFile($user->getLoginName());
// we're not logged in, but authorized for the stuff we want to do. So don't redirect // we're not logged in, but authorized for the stuff we want to do. So don't redirect
return; return;
} else {
participo::addMessage("error", "Api key invalid (e.g., deprecated)");
} }
} }
// if not returned yet: no login, no valid apiKey -> redirect to login page // if not returned yet: no login, no valid apiKey -> redirect to login page but remove the api key rom the query
if (!self::isLoginValid()) { if (!self::isLoginValid()) {
header( header(
"Location: login?returnToUrl=" . "Location: login?returnToUrl=" .
urlencode( urlencode(
$_SERVER["REQUEST_URI"] . ($_POST["fragment"] ?? "") participo::removeQueryParameter($_SERVER["REQUEST_URI"], "apiKey") . ($_POST["fragment"] ?? "")
), ),
true, true,
301 301
@@ -164,6 +167,38 @@ class participo
} }
} }
/**
* remove query parameter from an url
*
* @param [string] $url url to clean of a query parameter
* @param [string] $param query parameter to remove
*
* @return [string] input url with query parameter (key and value) removed
*/
public static function removeQueryParameter(string $url, string $param): string
{
if (str_contains($url, "?")) {
list($baseUrl, $urlQuery) = explode('?', $url, 2);
parse_str($urlQuery, $urlQueryArr);
unset($urlQueryArr[$param]);
if (count($urlQueryArr)) {
return $baseUrl . '?' . http_build_query($urlQueryArr);
}
}
return $url;
}
/**
* Store persistent data in the session data
*/
public static function shutdown(){
$_SESSION["participo"] = [
"messages" => participo::getMessages()
];
}
/** Initialize the participoApp /** Initialize the participoApp
* *
* - validate the login * - validate the login
@@ -174,13 +209,33 @@ class participo
*/ */
public static function init($config) public static function init($config)
{ {
self::authentificate(); // setup the storing of
register_shutdown_function("participo::shutdown");
// set up a database connection
self::initDb( self::initDb(
$config["db"]["host"], $config["db"]["host"],
$config["db"]["name"], $config["db"]["name"],
$config["db"]["user"], $config["db"]["user"],
$config["db"]["password"] $config["db"]["password"]
); );
// authenticate the user
self::authenticate();
// init the participo app
// - get stored messages from the session data
self::initMessages();
}
/**
* Move the messages from the session data into the participo app
*
* - move means the source gets deleted after copying
*/
private static function initMessages() : void
{
self::$message = $_SESSION["participo"]["messages"] ?? ["error" => null, "success" => null, "notice" => null];
unset($_SESSION["participo"]["messages"]);
} }
private static function initDb($host, $name, $user, $password) private static function initDb($host, $name, $user, $password)
@@ -194,12 +249,12 @@ class participo
* - Params in the request that aren't in given a parsing function aren't parsed and hence not returned. * - Params in the request that aren't in given a parsing function aren't parsed and hence not returned.
* *
* @param [array(paramName => parseFunction)] $params array of the name of the param and a sanitizer/parsing/input function * @param [array(paramName => parseFunction)] $params array of the name of the param and a sanitizer/parsing/input function
* @return array(parsedParam=>paramValue) Associative array of the name of the param and its parsed value * @return [array(parsedParam=>paramValue)] Associative array of the name of the param and its parsed value
*/ */
public static function parseParams($params) public static function parseParams($params)
{ {
$method = $_SERVER["REQUEST_METHOD"]; $method = $_SERVER["REQUEST_METHOD"];
$request = explode("/", substr(@$_SERVER["PATH_INFO"], 1)); // $request = explode("/", substr($_SERVER["PATH_INFO"], 1));
$parsedParams = []; $parsedParams = [];
foreach ($params as $paramName => $parseFunction) { foreach ($params as $paramName => $parseFunction) {
@@ -210,12 +265,12 @@ class participo
// break; // break;
case "POST": case "POST":
$parsedParams[$paramName] = $parseFunction( $parsedParams[$paramName] = $parseFunction(
$_POST[$paramName] $_POST[$paramName] ?? null
); );
break; break;
case "GET": case "GET":
$parsedParams[$paramName] = $parseFunction( $parsedParams[$paramName] = $parseFunction(
$_GET[$paramName] $_GET[$paramName] ?? null
); );
break; break;
default: default:
@@ -236,6 +291,11 @@ class participo
self::$message[$type] = (self::$message[$type] ?? "") . $message; self::$message[$type] = (self::$message[$type] ?? "") . $message;
} }
// public static function htmlEchoMessages(){
// echo(htmlRetMessage(participo::getMessages()));
// self::$message = null;
// }
/** check password for user /** check password for user
* *
* @param string $loginName user who wants to get in * @param string $loginName user who wants to get in
@@ -296,9 +356,7 @@ class participo
return self::hasUserAttribute($userId, "isAdmin"); return self::hasUserAttribute($userId, "isAdmin");
} }
public static function getUserId() public static function getUserId() {}
{
}
/** get current logged in users kids */ /** get current logged in users kids */
public static function getKids($userId = null) public static function getKids($userId = null)
@@ -619,7 +677,7 @@ function loadMarkdownFile($fileName)
{ {
// load the whole file // load the whole file
$fileText = file_get_contents($fileName); $fileText = file_get_contents($fileName);
// split at '---' to get ((),yamls,array) // split at '---' to get ((),yaml,array)
$fileParts = preg_split('/[\n]*[-]{3}[\n]/', $fileText, 3); $fileParts = preg_split('/[\n]*[-]{3}[\n]/', $fileText, 3);
// not all mdFiles have a yamlHeader, so the mdText can be at different indices // not all mdFiles have a yamlHeader, so the mdText can be at different indices
$yaml = []; $yaml = [];

View File

@@ -1,12 +1,10 @@
<?php <?php
require_once 'config/participo.php'; require_once 'config/participo.php';
require_once $config['home'] . '/.local/cwsvJudo.config.php';
require_once 'participoLib/participo.php'; require_once 'participoLib/participo.php';
require_once 'participoLib/apiKey.php'; require_once 'participoLib/apiKey.php';
require_once './local/dbConf.php';
require_once $config['home'] . '/.local/cwsvJudo.config.php';
$dbConnection = dbConnector::connect( $dbConnection = dbConnector::connect(
$cwsvJudoConfig['db']['host'], $cwsvJudoConfig['db']['host'],
@@ -14,9 +12,9 @@ $dbConnection = dbConnector::connect(
$cwsvJudoConfig['db']['user'], $cwsvJudoConfig['db']['user'],
$cwsvJudoConfig['db']['password'] $cwsvJudoConfig['db']['password']
); );
// Check, if the login is already set. If so move to the main page (or the returnToUrl) // Check, if the login is already set. If so move to the main page (or the returnToUrl)
if (isset($_SESSION['login'])) { if (isset($_SESSION) && isset($_SESSION['login'])) {
// @todo prevent self redirection
header('Location: http://' . ($_POST['returnToUrl'] ?? '.'), true, 301); header('Location: http://' . ($_POST['returnToUrl'] ?? '.'), true, 301);
} }
@@ -46,46 +44,49 @@ else {
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<!-- includes of neccessary libs --> <!-- includes of necessary libs -->
<?php readfile('./shared/imports.php'); ?> <?php readfile('./shared/imports.php'); ?>
<title>cwsvJudo Online Apps</title> <title>cwsvJudo Online Apps</title>
<meta name="description" content="Loginseite der Online-Apps der Judoka des CWSV"> <meta name="description" content="Login-Seite der Online-Apps der Judoka des CWSV">
</head> </head>
<body class="container">
<h1>Loginseite der Online-Apps der Judoka des CWSV</h1> <body>
<h1>Login-Seite der Online-Apps der Judoka des CWSV</h1>
<?php echo(htmlRetMessage(participo::getMessages())); ?> <?php echo(htmlRetMessage(participo::getMessages())); ?>
<form action="./login.php" method="post">
<fieldset> <div class="container">
<legend>Benutzerdaten</legend> <div class="row">
<div> <div class="col s6 offset-s3 z-depth-1">
<label for="username">Benutzername</label> <h2 id="title">Benutzerdaten</h2>
<form id="loginForm" action="./login.php" method="post">
<div class="input-field">
<input id="username" type="text" name="f[username]" <?php echo isset($_POST['f']['username']) ? ' value="' . htmlspecialchars($_POST['f']['username']) . '"' : '' ?> /> <input id="username" type="text" name="f[username]" <?php echo isset($_POST['f']['username']) ? ' value="' . htmlspecialchars($_POST['f']['username']) . '"' : '' ?> />
<label for="username">Benutzername</label>
</div> </div>
<div> <div class="input-field">
<label for="password">Kennnwort</label>
<input id="password" type="password" name="f[password]" /> <input id="password" type="password" name="f[password]" />
<label for="password">Kennwort</label>
</div> </div>
<?php if (isset($_GET['returnToUrl'])) { <?php # If a return url was given, add it as input to the form
if (isset($_GET['returnToUrl'])) {
echo('<input type="hidden" name="returnToUrl" value="' . htmlspecialchars($_GET['returnToUrl']) . '" />'); echo('<input type="hidden" name="returnToUrl" value="' . htmlspecialchars($_GET['returnToUrl']) . '" />');
} ?> }
<?php if (isset($_POST['returnToUrl'])) { ?>
echo('<input type="hidden" name="returnToUrl" value="' . htmlspecialchars($_POST['returnToUrl']) . '" />');
} ?>
<input id="fragment" type="hidden" name="fragment" /> <input id="fragment" type="hidden" name="fragment" />
<!-- add the fragment to the post data--> <!-- add the fragment (stuff behind the # in the url) to the post data -->
<script> <script>
if(window.location.hash){ if(window.location.hash){
document.getElementById("fragment").value=window.location.hash; document.getElementById("fragment").value=window.location.hash;
} }
</script> </script>
<!-- <p>
</fieldset> <input type="checkbox" id="remember"/>
<fieldset> <label for="remember" id="checkbox" >Remember me</label>
<div> </p> -->
<input type="submit" name="submit" value="Anmelden" /> <input type="submit" name="submit" value="Anmelden" class="waves-effect waves-light btn" id="submitButton" />
</div>
</fieldset>
<fieldset class="notice"><legend>Hinweise</legend> <fieldset class="notice"><legend>Hinweise</legend>
<ul style="padding-left: inherit;"> <ul style="padding-left: inherit;">
<li style="list-style-type: circle;" >Logindaten sollten vom Übungsleiter vergeben worden sein.</li> <li style="list-style-type: circle;" >Logindaten sollten vom Übungsleiter vergeben worden sein.</li>
@@ -94,5 +95,9 @@ else {
</ul> </ul>
</fieldset> </fieldset>
</form> </form>
</div>
</div>
</div>
</body> </body>
</html> </html>

View File

@@ -4,13 +4,13 @@
if (ini_get('session.use_cookies')) { if (ini_get('session.use_cookies')) {
$params = session_get_cookie_params(); $params = session_get_cookie_params();
setcookie( setcookie(
session_name(), $name=session_name(),
'', '',
time() - 42000, $expires=(time() - 42000),
$params['path'], $path=$params['path'] ?? "",
$params['domain'], $domain=$params['domain'] ?? "",
$params['secure"'], $params['secure"'] ?? false,
$params['httponly'] $params['httponly'] ?? false
); );
} }
session_destroy(); session_destroy();

View File

@@ -19,7 +19,7 @@ dbConnector::connect(
$cwsvJudoConfig['db']['password'] $cwsvJudoConfig['db']['password']
); );
participo::authentificate(); participo::authenticate();
$user = participo::sessionUser(); $user = participo::sessionUser();
$usersKids = getUsersKids(dbConnector::getDbConnection(), $_SESSION['user']['userId']); $usersKids = getUsersKids(dbConnector::getDbConnection(), $_SESSION['user']['userId']);

View File

@@ -4,3 +4,7 @@ password = "kodokan"
[url] [url]
home = "http://127.0.0.1/participo" home = "http://127.0.0.1/participo"
# home = "http://cwsvjudo.bplaced.net/participo"
[settings]
headless = true

View File

@@ -14,10 +14,12 @@ class Participo:
def __init__(self) -> None: def __init__(self) -> None:
from selenium.webdriver import Firefox, FirefoxOptions from selenium.webdriver import Firefox, FirefoxOptions
self.config = load_config()
options = FirefoxOptions() options = FirefoxOptions()
if self.config["settings"]["headless"]:
options.add_argument("-headless") options.add_argument("-headless")
self.config = load_config()
self.driver = Firefox(options=options) self.driver = Firefox(options=options)
self.delay = 5 self.delay = 5
@@ -33,8 +35,20 @@ class Participo:
self.driver.get(url=self.config["url"]["home"]) self.driver.get(url=self.config["url"]["home"])
def load_section(self, section: str): def load_section(self, section: str):
from urllib3.exceptions import ReadTimeoutError
section_url = "/".join((self.config["url"]["home"], section)) section_url = "/".join((self.config["url"]["home"], section))
try:
self.driver.get(url=section_url) self.driver.get(url=section_url)
except ReadTimeoutError as e:
logging.warning(
"\n".join(
(
f"TimeoutError loading {section} ({e} - {repr(e)})",
f"- Check for missing resources on section/page {section}",
)
)
)
def login(self): def login(self):
credentials = self.config["credentials"] credentials = self.config["credentials"]

View File

@@ -18,7 +18,7 @@ class TestParticipo(unittest.TestCase):
participo.login() participo.login()
self.assertTrue(participo.check_login()) self.assertTrue(participo.check_login())
sections = ("events", "infoZettel", "attendance", "user") sections = ("events", "infoZettel", "attendance", "user", "logout")
for section in sections: for section in sections:
with self.subTest(msg=f"- {section}"): with self.subTest(msg=f"- {section}"):
participo.load_section(section=section) participo.load_section(section=section)