bugfix, profile picture WIP, profile frontend refactored

This commit is contained in:
2024-04-14 20:31:16 +02:00
parent c892ef5b6e
commit 29c72d13e7
25 changed files with 784 additions and 402 deletions

View File

@@ -18,11 +18,7 @@ namespace Core\API {
}
protected function verifyAuthData(AuthenticationData $authData): bool {
$settings = $this->context->getSettings();
// $relyingParty = $settings->getSiteName();
$domain = parse_url($settings->getBaseUrl(), PHP_URL_HOST);
// $domain = "localhost";
$domain = getCurrentHostName();
if (!$authData->verifyIntegrity($domain)) {
return $this->createError("mismatched rpIDHash. expected: " . hash("sha256", $domain) . " got: " . bin2hex($authData->getHash()));
} else if (!$authData->isUserPresent()) {
@@ -264,7 +260,7 @@ namespace Core\API\TFA {
$settings = $this->context->getSettings();
$relyingParty = $settings->getSiteName();
$sql = $this->context->getSQL();
$domain = parse_url($settings->getBaseUrl(), PHP_URL_HOST);
$domain = getCurrentHostName();
if (!$clientDataJSON || !$attestationObjectRaw) {
$challenge = null;
@@ -297,7 +293,6 @@ namespace Core\API\TFA {
$this->result["data"] = [
"challenge" => $challenge,
"id" => $currentUser->getId() . "@" . $domain, // <userId>@<domain>
"relyingParty" => [
"name" => $relyingParty,
"id" => $domain

View File

@@ -192,7 +192,7 @@ namespace Core\API\User {
foreach ($requestedGroups as $groupId) {
if (!isset($availableGroups[$groupId])) {
return $this->createError("Group with id=$groupId does not exist.");
} else if ($this->externalCall && $groupId === Group::ADMIN && !$currentUser->hasGroup(Group::ADMIN)) {
} else if ($this->isExternalCall() && $groupId === Group::ADMIN && !$currentUser->hasGroup(Group::ADMIN)) {
return $this->createError("You cannot create users with administrator groups.");
} else {
$groups[] = $groupId;
@@ -1311,38 +1311,43 @@ namespace Core\API\User {
return $this->createError("Error saving user token: " . $sql->getLastError());
}
$name = htmlspecialchars($currentUser->getFullName());
if (!$name) {
$name = htmlspecialchars($currentUser->getUsername());
}
$validHours = 1;
$settings = $this->context->getSettings();
$siteName = htmlspecialchars($settings->getSiteName());
$baseUrl = htmlspecialchars($settings->getBaseUrl());
$token = htmlspecialchars(urlencode($token));
$url = "$baseUrl/confirmGPG?token=$token";
$mailBody = "Hello $name,<br><br>" .
"you imported a GPG public key for end-to-end encrypted mail communication. " .
"To confirm the key and verify, you own the corresponding private key, please click on the following link. " .
"The link is active for one hour.<br><br>" .
"<a href='$url'>$url</a><br>Best Regards<br>$siteName Administration";
$baseUrl = $settings->getBaseUrl();
$siteName = $settings->getSiteName();
$req = new Render($this->context);
$this->success = $req->execute([
"file" => "mail/gpg_import.twig",
"parameters" => [
"link" => "$baseUrl/resetPassword?token=$token",
"site_name" => $siteName,
"base_url" => $baseUrl,
"username" => $currentUser->getDisplayName(),
"valid_time" => $this->formatDuration($validHours, "hour")
]
]);
$sendMail = new \Core\API\Mail\Send($this->context);
$this->success = $sendMail->execute(array(
"to" => $currentUser->getEmail(),
"subject" => "[$siteName] Confirm GPG-Key",
"body" => $mailBody,
"gpgFingerprint" => $gpgKey->getFingerprint()
));
$this->lastError = $sendMail->getLastError();
$this->lastError = $req->getLastError();
if ($this->success) {
$currentUser->gpgKey = $gpgKey;
if ($currentUser->save($sql, ["gpgKey"])) {
$this->result["gpgKey"] = $gpgKey->jsonSerialize();
} else {
return $this->createError("Error updating user details: " . $sql->getLastError());
$messageBody = $req->getResult()["html"];
$sendMail = new \Core\API\Mail\Send($this->context);
$this->success = $sendMail->execute(array(
"to" => $currentUser->getEmail(),
"subject" => "[$siteName] Confirm GPG-Key",
"body" => $messageBody,
"gpgFingerprint" => $gpgKey->getFingerprint()
));
$this->lastError = $sendMail->getLastError();
if ($this->success) {
$currentUser->gpgKey = $gpgKey;
if ($currentUser->save($sql, ["gpgKey"])) {
$this->result["gpgKey"] = $gpgKey->jsonSerialize();
} else {
return $this->createError("Error updating user details: " . $sql->getLastError());
}
}
}
@@ -1505,6 +1510,7 @@ namespace Core\API\User {
class UploadPicture extends UserAPI {
public function __construct(Context $context, bool $externalCall = false) {
// TODO: we should optimize the process here, we need an offset and size parameter to get a quadratic crop of the uploaded image
parent::__construct($context, $externalCall, [
"scale" => new Parameter("scale", Parameter::TYPE_FLOAT, true, NULL),
]);
@@ -1515,7 +1521,7 @@ namespace Core\API\User {
/**
* @throws ImagickException
*/
protected function onTransform(\Imagick $im, $uploadDir) {
protected function onTransform(\Imagick $im, $uploadDir): bool|string {
$minSize = 75;
$maxSize = 500;

View File

@@ -52,22 +52,28 @@ class MySQL extends SQL {
return true;
}
$this->connection = @mysqli_connect(
$this->connectionData->getHost(),
$this->connectionData->getLogin(),
$this->connectionData->getPassword(),
$this->connectionData->getProperty('database'),
$this->connectionData->getPort()
);
try {
$this->connection = @mysqli_connect(
$this->connectionData->getHost(),
$this->connectionData->getLogin(),
$this->connectionData->getPassword(),
$this->connectionData->getProperty('database'),
$this->connectionData->getPort()
);
if (mysqli_connect_errno()) {
if (mysqli_connect_errno()) {
$this->lastError = $this->logger->severe("Failed to connect to MySQL: " . mysqli_connect_error());
$this->connection = NULL;
return false;
}
mysqli_set_charset($this->connection, $this->connectionData->getProperty('encoding', 'UTF8'));
return true;
} catch (\Exception $ex) {
$this->lastError = $this->logger->severe("Failed to connect to MySQL: " . mysqli_connect_error());
$this->connection = NULL;
return false;
}
mysqli_set_charset($this->connection, $this->connectionData->getProperty('encoding', 'UTF8'));
return true;
}
public function disconnect() {

View File

@@ -26,33 +26,18 @@ return [
"username" => "Benutzername",
"username_or_email" => "Benutzername oder E-Mail",
"email" => "E-Mail Adresse",
"password" => "Passwort",
"password_confirm" => "Passwort bestätigen",
"password_old" => "Altes Passwort",
"password_new" => "Neues Passwort",
"full_name" => "Voller Name",
"remember_me" => "Eingeloggt bleiben",
"signing_in" => "Einloggen",
"sign_in" => "Einloggen",
"confirmed" => "Bestätigt",
"forgot_password" => "Passwort vergessen?",
"change_password" => "Passwort ändern",
"passwords_do_not_match" => "Die Passwörter stimmen nicht überein",
"back_to_login" => "Zurück zum Login",
"register_text" => "Noch keinen Account? Jetzt registrieren",
"6_digit_code" => "6-stelliger Code",
"2fa_title" => "Es werden weitere Informationen zum Einloggen benötigt",
"2fa_text" => "Stecke dein 2FA-Gerät ein. Möglicherweise wird noch eine Interaktion benötigt, z.B. durch Eingabe einer PIN oder durch Berühren des Geräts",
"confirming_email" => "Bestätige E-Mail Adresse",
"proceed_to_login" => "Weiter zum Login",
"invalid_link" => "Den Link den Sie besucht haben ist nicht länger gültig",
"confirm_success" => "Ihre E-Mail Adresse wurde erfolgreich bestätigt, Sie können sich jetzt einloggen",
"confirm_error" => "Fehler beim Bestätigen der E-Mail Adresse",
"gpg_key" => "GPG-Schlüssel",
"no_gpg_key_added" => "Kein GPG-Schlüssel hinzugefügt",
"download_gpg_key" => "GPG-Schlüssel herunterladen",
"2fa_token" => "Zwei-Faktor Authentifizierung (2FA)",
"profile_picture_of" => "Profilbild von",
"profile_of" => "Profil von",
"language" => "Sprache",
"profile" => "Benutzerprofil",
@@ -71,6 +56,10 @@ return [
"group" => "Gruppe",
"no_members" => "Keine Mitglieder in dieser Gruppe",
# profile picture
"change_picture" => "Profilbild ändern",
"profile_picture_of" => "Profilbild von",
# dialogs
"fetch_group_members_error" => "Fehler beim Holen der Gruppenmitglieder",
"remove_group_member_error" => "Fehler beim Entfernen des Gruppenmitglieds",
@@ -85,11 +74,18 @@ return [
"remove_group_member_text" => "Möchten Sie wirklich den Benutzer '%s' von dieser Gruppe entfernen?",
"add_group_member_title" => "Mitglied hinzufügen",
"add_group_member_text" => "Einen Benutzer suchen um ihn der Gruppe hinzuzufügen",
"edit_profile" => "Profil bearbeiten",
# GPG Key
"gpg_key_placeholder_text" => "GPG-Key im ASCII format reinziehen oder einfügen...",
"gpg_key" => "GPG-Schlüssel",
"no_gpg_key_added" => "Kein GPG-Schlüssel hinzugefügt",
"download_gpg_key" => "GPG-Schlüssel herunterladen",
# 2fa
"2fa_title" => "Es werden weitere Informationen zum Einloggen benötigt",
"2fa_text" => "Stecke dein 2FA-Gerät ein. Möglicherweise wird noch eine Interaktion benötigt, z.B. durch Eingabe einer PIN oder durch Berühren des Geräts",
"2fa_token" => "Zwei-Faktor Authentifizierung (2FA)",
"2fa_type_totp" => "Zeitbasiertes 2FA (TOTP)",
"2fa_type_fido" => "Schlüsselbasiertes 2FA",
"register_2fa_device" => "Ein 2FA-Gerät registrieren",
@@ -98,4 +94,19 @@ return [
"register_2fa_fido_text" => "Möglicherweise musst du mit dem Gerät interagieren, zum Beispiel durch Eingeben einer PIN oder durch Berühren des Geräts",
"remove_2fa" => "2FA-Token entfernen",
"remove_2fa_text" => "Gib dein aktuelles Passwort ein um das Entfernen des 2FA-Tokens zu bestätigen",
"6_digit_code" => "6-stelliger Code",
# password
"password" => "Passwort",
"password_confirm" => "Passwort bestätigen",
"password_old" => "Altes Passwort",
"password_new" => "Neues Passwort",
"forgot_password" => "Passwort vergessen?",
"change_password" => "Passwort ändern",
"passwords_do_not_match" => "Die Passwörter stimmen nicht überein",
"password_very_strong" => "Sehr stark",
"password_strong" => "Stark",
"password_ok" => "OK",
"password_weak" => "Schwach",
"password_very_weak" => "Sehr schwach",
];

View File

@@ -26,33 +26,19 @@ return [
"username" => "Username",
"username_or_email" => "Username or E-Mail",
"email" => "E-Mail Address",
"password" => "Password",
"password_confirm" => "Confirm Password",
"password_old" => "Old Password",
"password_new" => "New Password",
"full_name" => "Full Name",
"remember_me" => "Remember Me",
"signing_in" => "Signing in",
"sign_in" => "Sign In",
"confirmed" => "Confirmed",
"forgot_password" => "Forgot password?",
"change_password" => "Change password",
"register_text" => "Don't have an account? Sign Up",
"passwords_do_not_match" => "Your passwords did not match",
"back_to_login" => "Back to Login",
"6_digit_code" => "6-Digit Code",
"2fa_title" => "Additional information is required for logging in",
"2fa_text" => "Plugin your 2FA-Device. Interaction might be required, e.g. typing in a PIN or touching it.",
"confirming_email" => "Confirming email",
"proceed_to_login" => "Proceed to Login",
"invalid_link" => "The link you visited is no longer valid",
"confirm_success" => "Your e-mail address was successfully confirmed, you may now log in",
"confirm_error" => "Error confirming e-mail address",
"gpg_key" => "GPG Key",
"no_gpg_key_added" => "No GPG key added",
"download_gpg_key" => "Download GPG Key",
"2fa_token" => "Two-Factor Authentication (2FA)",
"profile_picture_of" => "Profile Picture of",
"profile_of" => "Profile of",
"language" => "Language",
"profile" => "User Profile",
@@ -70,6 +56,11 @@ return [
"active" => "Active",
"group" => "Group",
"no_members" => "No members in this group",
"edit_profile" => "Edit Profile",
# profile picture
"change_picture" => "Change profile picture",
"profile_picture_of" => "Profile Picture of",
# dialogs
"fetch_group_members_error" => "Error fetching group members",
@@ -87,9 +78,15 @@ return [
"add_group_member_text" => "Search a user to add to the group",
# GPG Key
"gpg_key" => "GPG Key",
"no_gpg_key_added" => "No GPG key added",
"download_gpg_key" => "Download GPG Key",
"gpg_key_placeholder_text" => "Paste or drag'n'drop your GPG-Key in ASCII format...",
# 2fa
"2fa_title" => "Additional information is required for logging in",
"2fa_text" => "Plugin your 2FA-Device. Interaction might be required, e.g. typing in a PIN or touching it.",
"2fa_token" => "Two-Factor Authentication (2FA)",
"2fa_type_totp" => "Time-Based 2FA (TOTP)",
"2fa_type_fido" => "Key-Based 2FA",
"register_2fa_device" => "Register a 2FA-Device",
@@ -98,4 +95,18 @@ return [
"register_2fa_fido_text" => "You may need to interact with your Device, e.g. typing in your PIN or touching to confirm the registration.",
"remove_2fa" => "Remove 2FA Token",
"remove_2fa_text" => "Enter your current password to confirm the removal of your 2FA Token",
"6_digit_code" => "6-Digit Code",
# password
"password" => "Password",
"password_confirm" => "Confirm Password",
"password_old" => "Old Password",
"password_new" => "New Password",
"forgot_password" => "Forgot password?",
"change_password" => "Change password",
"password_very_strong" => "Very strong",
"password_strong" => "Strong",
"password_ok" => "OK",
"password_weak" => "Weak",
"password_very_weak" => "Very weak",
];

View File

@@ -4,6 +4,7 @@ namespace Core\Objects;
use Core\Configuration\Configuration;
use Core\Configuration\Settings;
use Core\Driver\SQL\Column\Column;
use Core\Driver\SQL\Condition\Compare;
use Core\Driver\SQL\Condition\CondLike;
use Core\Driver\SQL\Condition\CondOr;
@@ -125,9 +126,9 @@ class Context {
if ($this->sql) {
$language = Language::findBy(Language::createBuilder($this->sql, true)
->where(new CondOr(
new CondLike("name", "%$lang%"), // english
new CondLike(new Column("name"), "%$lang%"), // english
new Compare("code", $lang), // de_DE
new CondLike("code", "{$lang}_%") // de -> de_%
new CondLike(new Column("code"), "{$lang}_%") // de -> de_%
))
);
if ($language) {

View File

@@ -38,8 +38,9 @@ class AuthenticationData extends ApiObject {
$credentialIdLength = unpack("n", substr($buffer, $offset, 4))[1]; $offset += 2;
$this->credentialID = substr($buffer, $offset, $credentialIdLength); $offset += $credentialIdLength;
if ($offset < $bufferLength) {
if ($bufferLength > $offset) {
$publicKeyData = $this->decode(substr($buffer, $offset));
var_dump($publicKeyData);
$this->publicKey = new PublicKey($publicKeyData);
// TODO: we should add $publicKeyData->length to $offset, but it's not implemented yet?;
}

View File

@@ -0,0 +1,9 @@
Hello {{ username }},<br>
you imported a GPG public key for end-to-end encrypted mail communication on {{ site_name }}. <br>
To confirm the key and verify, you own the corresponding private key, please click on the following link.
The link is active for one hour:<br><br>
<a href="{{ link }}">{{ link }}</a><br><br>
Best Regards<br>
{{ site_name }} Administration