6 private string $ddUser =
'dbxUser';
7 private string $ddGroup =
'dbxUser_groups';
8 private string $pendingRole =
'registerd';
9 private string $confirmedRole =
'member';
11 private function user_exists($uname, $email =
'') {
12 $db =
dbx()->get_system_obj(
'dbxDB');
16 $uname = trim((
string)$uname);
18 $parts[] =
"uname='" .
$db->escape($uname,
$server) .
"'";
21 $email = trim((
string)$email);
23 $parts[] =
"email='" .
$db->escape($email,
$server) .
"'";
30 return $db->count($this->ddUser, implode(
' OR ', $parts));
33 private function ensure_pending_group() {
34 $db =
dbx()->get_system_obj(
'dbxDB');
36 $name =
$db->escape($this->pendingRole,
$server);
38 if (
$db->count($this->ddGroup,
"name='$name'") > 0) {
42 $db->insert($this->ddGroup, array(
43 'name' => $this->pendingRole,
44 'description' =>
'Registriert, E-Mail noch nicht bestaetigt',
49 private function new_token() {
50 return bin2hex(random_bytes(32));
53 private function settings_with_token(array $settings,
string $token) {
54 $settings[
'register_confirm'] = array(
55 'token_hash' => hash(
'sha256', $token),
56 'expires' => time() + (48 * 3600),
57 'sent' => date(
'Y-m-d H:i:s'),
59 return json_encode($settings, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
62 private function decode_settings($settings) {
63 $data = json_decode((
string)$settings,
true);
64 return is_array($data) ? $data : array();
67 private function confirm_url($uid, $token) {
68 return rtrim(
dbx()->get_base_url(),
'/') .
'/?dbx_modul=dbxLogin&dbx_run1=register&dbx_run2=confirm&uid=' . (int)$uid .
'&token=' . rawurlencode($token);
71 private function current_domain() {
72 $domain = (string)(
$_SERVER[
'HTTP_HOST'] ??
$_SERVER[
'SERVER_NAME'] ??
'dbxApp');
73 $domain = preg_replace(
'/[^a-zA-Z0-9.\-_:]/',
'', $domain);
74 return $domain ?:
'dbxApp';
77 private function send_confirm_mail(array $user,
string $token) {
78 $url = $this->confirm_url((
int)$user[
'id'], $token);
79 $tpl =
dbx()->get_system_obj(
'dbxTPL');
81 'name' => htmlspecialchars((
string)($user[
'name'] ?: $user[
'uname']), ENT_QUOTES,
'UTF-8'),
82 'uname' => htmlspecialchars((
string)$user[
'uname'], ENT_QUOTES,
'UTF-8'),
83 'confirm_url' => htmlspecialchars($url, ENT_QUOTES,
'UTF-8'),
86 $html = $tpl->get_tpl(
'dbxLogin|mail-register-confirm', $data);
87 $text =
"Hallo " . (string)($user[
'name'] ?: $user[
'uname']) .
"\n\n"
88 .
"bitte bestaetige deine E-Mail-Adresse:\n" . $url .
"\n\n"
89 .
"Erst danach erhaelt dein Konto die Rolle " . $this->confirmedRole .
".\n";
91 $ok =
dbx()->send_mail(
93 (
string)$user[
'email'],
94 'dbxApp Registrierung bestaetigen',
98 array(
'text' => $text)
102 dbx()->sys_msg(
'error',
'register', (
int)$user[
'id'],
'register confirm mail failed', (
string)$user[
'email']);
108 private function confirmed_roles($roles) {
109 $parts = array_filter(array_map(
'trim', explode(
',', (
string)$roles)));
112 foreach ($parts as $role) {
113 if ($role === $this->pendingRole) {
119 $out[$this->confirmedRole] = $this->confirmedRole;
120 return implode(
',', array_values($out));
123 private function h($value) {
124 return htmlspecialchars((
string)$value, ENT_QUOTES,
'UTF-8');
127 private function confirm_page(
string $status,
string $title,
string $message,
string $detail,
string $icon =
'bi-patch-check',
string $detailIcon =
'bi-envelope-check') {
128 $tpl =
dbx()->get_system_obj(
'dbxTPL');
129 return $tpl->get_tpl(
'dbxLogin|register-confirm', array(
130 'status' => $this->h($status),
131 'kicker' => $status ===
'error' ?
'Bestaetigung' :
'Willkommen',
133 'message' => $message,
135 'icon' => $this->h($icon),
136 'detail_icon' => $this->h($detailIcon),
140 private function confirm() {
141 $uid = (int)
dbx()->get_modul_var(
'uid', 0,
'int');
142 $token = (string)
dbx()->get_modul_var(
'token',
'',
'varchar|max=128');
144 if ($uid <= 0 || $token ===
'') {
145 return $this->confirm_page(
'error',
'Bestaetigungslink ungueltig',
'Der Link konnte nicht eindeutig zugeordnet werden.',
'Bitte pruefe den Link aus der E-Mail oder registriere dich erneut.',
'bi-exclamation-triangle',
'bi-link-45deg');
148 $db =
dbx()->get_system_obj(
'dbxDB');
149 $user =
$db->select1($this->ddUser, $uid,
'*', 0);
151 if (!is_array($user) || empty($user[
'id'])) {
152 return $this->confirm_page(
'error',
'Benutzer nicht gefunden',
'Zu diesem Bestaetigungslink wurde kein Benutzerkonto gefunden.',
'Bitte registriere dich erneut oder wende dich an den Administrator.',
'bi-person-x',
'bi-search');
155 if ((
int)($user[
'is_confirm'] ?? 0) === 1 && preg_match(
'/(^|,)' . preg_quote($this->confirmedRole,
'/') .
'(,|$)/', (
string)($user[
'roles'] ??
''))) {
156 $name = (string)($user[
'name'] ?: $user[
'uname'] ??
'');
157 return $this->confirm_page(
'success',
'Willkommen zurueck' . ($name ?
', ' . $name :
''),
'Deine E-Mail-Adresse ist bereits bestaetigt.',
'Dein Konto ist freigeschaltet. Du kannst dich jetzt anmelden.',
'bi-patch-check',
'bi-person-check');
160 $settings = $this->decode_settings($user[
'settings'] ??
'');
161 $confirm = $settings[
'register_confirm'] ?? array();
162 $hash = (string)($confirm[
'token_hash'] ??
'');
163 $expires = (int)($confirm[
'expires'] ?? 0);
165 if ($hash ===
'' || !hash_equals($hash, hash(
'sha256', $token))) {
166 return $this->confirm_page(
'error',
'Bestaetigungslink ungueltig',
'Der Token passt nicht zu diesem Benutzerkonto.',
'Bitte nutze den neuesten Link aus deiner E-Mail oder registriere dich erneut.',
'bi-exclamation-triangle',
'bi-shield-x');
169 if ($expires > 0 && $expires < time()) {
170 return $this->confirm_page(
'error',
'Bestaetigungslink abgelaufen',
'Dieser Link ist nicht mehr gueltig.',
'Bitte registriere dich erneut oder fordere einen neuen Link an.',
'bi-hourglass-split',
'bi-clock-history');
173 unset($settings[
'register_confirm']);
174 $settingsJson = $settings ? json_encode($settings, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) :
'{}';
175 $ok =
$db->update($this->ddUser, array(
176 'roles' => $this->confirmed_roles($user[
'roles'] ??
''),
178 'settings' => $settingsJson,
179 ), $uid, 0, 1, 1, 1);
182 dbx()->sys_msg(
'info',
'register', $uid,
'user email confirmed', (
string)($user[
'uname'] ??
''));
183 $name = (string)($user[
'name'] ?: $user[
'uname'] ??
'');
184 return $this->confirm_page(
'success',
'Willkommen' . ($name ?
', ' . $name :
''),
'Deine E-Mail-Adresse ist bestaetigt.',
'Dein Konto ist jetzt als member freigeschaltet. Du kannst dich direkt anmelden.',
'bi-patch-check',
'bi-stars');
187 return $this->confirm_page(
'error',
'Bestaetigung nicht gespeichert',
'Die Bestaetigung konnte technisch nicht gespeichert werden.',
'Bitte versuche es erneut oder wende dich an den Administrator.',
'bi-exclamation-triangle',
'bi-database-x');
190 private function resend_confirm() {
191 if (strtoupper((
string)(
$_SERVER[
'REQUEST_METHOD'] ??
'GET')) !==
'POST') {
192 return $this->confirm_page(
'error',
'Aktion nicht erlaubt',
'Der Bestaetigungslink kann nur ueber das Formular erneut angefordert werden.',
'Bitte melde dich erneut an und nutze den Button zum erneuten Versand.',
'bi-exclamation-triangle',
'bi-shield-x');
195 $postedToken = (string)($_POST[
'dbx_token'] ??
'');
196 if (!
dbx()->check_action_token(
'dbxLogin.resend_confirm', $postedToken)) {
197 dbx()->sys_msg(
'security',
'register',
'',
'invalid resend confirm token',
$_SERVER[
'REMOTE_ADDR'] ??
'');
198 return $this->confirm_page(
'error',
'Sicherheitspruefung fehlgeschlagen',
'Der erneute Versand konnte nicht gestartet werden.',
'Bitte melde dich erneut an und versuche es noch einmal.',
'bi-exclamation-triangle',
'bi-shield-lock');
201 $uid = (int)
dbx()->get_session_var(
'pending_confirm_uid', 0,
'confirm',
'dbxLogin');
203 return $this->confirm_page(
'error',
'Anmeldung abgelaufen',
'Die zu bestaetigende Anmeldung wurde nicht mehr gefunden.',
'Bitte melde dich erneut mit Benutzername und Passwort an.',
'bi-hourglass-split',
'bi-person-x');
206 $currentUid = (int)
dbx()->user();
207 if ($currentUid > 0 && $currentUid !== $uid) {
208 dbx()->delete_session_var(
'pending_confirm_uid',
'confirm',
'dbxLogin');
209 dbx()->sys_msg(
'security',
'register', $uid,
'resend confirm user mismatch',
'current=' . $currentUid .
' ip=' . (
$_SERVER[
'REMOTE_ADDR'] ??
''));
210 return $this->confirm_page(
'error',
'Anmeldung passt nicht',
'Der erneute Versand passt nicht zu deiner aktuellen Sitzung.',
'Bitte melde dich erneut mit dem betroffenen Benutzerkonto an.',
'bi-exclamation-triangle',
'bi-person-x');
213 $db =
dbx()->get_system_obj(
'dbxDB');
214 $user =
$db->select1($this->ddUser, $uid,
'*', 0);
215 if (!is_array($user) || empty($user[
'id'])) {
216 dbx()->delete_session_var(
'pending_confirm_uid',
'confirm',
'dbxLogin');
217 return $this->confirm_page(
'error',
'Benutzer nicht gefunden',
'Das Benutzerkonto konnte nicht mehr geladen werden.',
'Bitte registriere dich erneut oder wende dich an den Administrator.',
'bi-person-x',
'bi-search');
220 if ((
int)($user[
'is_confirm'] ?? 0) === 1) {
221 dbx()->delete_session_var(
'pending_confirm_uid',
'confirm',
'dbxLogin');
222 $name = (string)($user[
'name'] ?: $user[
'uname'] ??
'');
223 return $this->confirm_page(
'success',
'Willkommen zurueck' . ($name ?
', ' . $name :
''),
'Deine E-Mail-Adresse ist bereits bestaetigt.',
'Dein Konto ist freigeschaltet. Du kannst dich jetzt anmelden.',
'bi-patch-check',
'bi-person-check');
226 if (trim((
string)($user[
'email'] ??
'')) ===
'') {
227 return $this->confirm_page(
'error',
'Keine E-Mail-Adresse hinterlegt',
'Fuer dieses Benutzerkonto ist keine E-Mail-Adresse gespeichert.',
'Bitte wende dich an den Administrator, damit die Adresse korrigiert werden kann.',
'bi-exclamation-triangle',
'bi-envelope-x');
230 $token = $this->new_token();
231 $settings = $this->decode_settings($user[
'settings'] ??
'');
232 $ok =
$db->update($this->ddUser, array(
233 'settings' => $this->settings_with_token($settings, $token),
234 ), $uid, 0, 1, 1, 1);
237 return $this->confirm_page(
'error',
'Bestaetigungslink nicht gespeichert',
'Der neue Bestaetigungslink konnte technisch nicht gespeichert werden.',
'Bitte versuche es erneut oder wende dich an den Administrator.',
'bi-exclamation-triangle',
'bi-database-x');
240 $mailOk = $this->send_confirm_mail($user, $token);
242 return $this->confirm_page(
'error',
'E-Mail nicht gesendet',
'Der Bestaetigungslink wurde erzeugt, die E-Mail konnte aber nicht versendet werden.',
'Bitte pruefe die Mail-Konfiguration oder wende dich an den Administrator.',
'bi-exclamation-triangle',
'bi-envelope-x');
245 dbx()->sys_msg(
'info',
'register', $uid,
'confirm mail resent', (
string)($user[
'email'] ??
''));
246 return $this->confirm_page(
'success',
'Bestaetigungslink gesendet',
'Wir haben dir einen neuen Link zur E-Mail-Bestaetigung gesendet.',
'Bitte pruefe dein Postfach und auch den Spam-Ordner.',
'bi-envelope-check',
'bi-send-check');
250 $run2 =
dbx()->get_modul_var(
'dbx_run2',
'',
'parameter');
251 if ($run2 ===
'confirm') {
252 return $this->confirm();
254 if ($run2 ===
'resend_confirm') {
255 return $this->resend_confirm();
259 return dbx()->redirect(
'?dbx_modul=dbxUser&dbx_run1=user&dbx_run2=edit_profil', 1);
262 dbx()->set_system_var(
'dbx_title',
'Registrierung');
264 $oForm =
dbx()->get_system_obj(
'dbxForm');
265 $oForm->init(
'form-register');
266 $oForm->_fd =
'dbxLogin|register';
267 $oForm->_data = array(
270 $oForm->_action =
'?dbx_modul=dbxLogin&dbx_run1=register';
271 $oForm->_msg_info =
'Bei ' . $this->current_domain() .
' anmelden.';
272 $oForm->add_obj(
'login_link',
'obj-value',
'');
274 $oForm->add_fld(
'uname');
275 $oForm->add_fld(
'name');
276 $oForm->add_fld(
'email');
277 $oForm->add_fld(
'password');
278 $oForm->add_fld(
'password2');
279 $oForm->add_fld(
'language');
281 if ($oForm->submit()) {
282 if (!$oForm->errors()) {
283 $uname = $oForm->get_post(
'uname',
'',
'parameter|max=60');
284 $email = $oForm->get_post(
'email',
'',
'email|max=60');
285 $pass1 = $oForm->get_post_data(
'password',
'',
'varchar|max=128');
286 $pass2 = $oForm->get_post_data(
'password2',
'',
'varchar|max=128');
288 if ($pass1 !== $pass2) {
289 $oForm->add_fld_error(
'password2',
'Passwoerter stimmen nicht ueberein.');
290 $oForm->_msg_error =
'Passwoerter stimmen nicht ueberein.';
291 } elseif ($this->user_exists($uname, $email) > 0) {
292 $oForm->add_fld_error(
'uname',
'Benutzer oder E-Mail existiert bereits.');
293 $oForm->_msg_error =
'Benutzer oder E-Mail existiert bereits.';
295 $this->ensure_pending_group();
296 $db =
dbx()->get_system_obj(
'dbxDB');
297 $token = $this->new_token();
300 'name' => $oForm->get_post(
'name',
'',
'words|max=60'),
302 'pass' => password_hash($pass1, PASSWORD_DEFAULT),
303 'roles' => $this->pendingRole,
306 'language' => $oForm->get_post(
'language',
'de',
'parameter|min=2|max=3'),
307 'avatar' =>
'avatar-0.png',
308 'settings' => $this->settings_with_token(array(), $token),
311 $id = (
$db->insert($this->ddUser, $values, 0, 1, 1, 1) === 1) ?
$db->get_insert_id() : 0;
314 $mail_ok = $this->send_confirm_mail($values, $token);
315 dbx()->sys_msg(
'login',
'register', $id,
'new user registered', $uname);
317 $oForm->_msg_success =
'Registrierung gespeichert. Bitte bestaetige deine E-Mail-Adresse ueber den Link in der E-Mail.';
319 $oForm->_msg_error =
'Benutzer wurde angelegt, aber die Bestaetigungs-E-Mail konnte nicht gesendet werden.';
321 $oForm->add_obj(
'login_link',
'dbxLogin|register-login-button');
323 $oForm->_msg_error =
'Benutzer konnte nicht angelegt werden.';
327 $oForm->_msg_error =
'Pruefen sie bitte ihre Eingaben.';
331 return $oForm->run();