Friendica Communications Platform (please note that this is a clone of the repository at github, issues are handled there) https://friendi.ca
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

384 lines
13 KiB

  1. <?php
  2. namespace Friendica\Module;
  3. use Friendica\BaseModule;
  4. use Friendica\Content\Text\BBCode;
  5. use Friendica\Core\Config;
  6. use Friendica\Core\Hook;
  7. use Friendica\Core\L10n;
  8. use Friendica\Core\L10n\L10n as L10nClass;
  9. use Friendica\Core\Logger;
  10. use Friendica\Core\Renderer;
  11. use Friendica\Core\Worker;
  12. use Friendica\Database\DBA;
  13. use Friendica\DI;
  14. use Friendica\Model;
  15. use Friendica\Util\Strings;
  16. /**
  17. * @author Hypolite Petovan <hypolite@mrpetovan.com>
  18. */
  19. class Register extends BaseModule
  20. {
  21. const CLOSED = 0;
  22. const APPROVE = 1;
  23. const OPEN = 2;
  24. /**
  25. * @brief Module GET method to display any content
  26. *
  27. * Extend this method if the module is supposed to return any display
  28. * through a GET request. It can be an HTML page through templating or a
  29. * XML feed or a JSON output.
  30. *
  31. * @return string
  32. */
  33. public static function content(array $parameters = [])
  34. {
  35. // logged in users can register others (people/pages/groups)
  36. // even with closed registrations, unless specifically prohibited by site policy.
  37. // 'block_extended_register' blocks all registrations, period.
  38. $block = Config::get('system', 'block_extended_register');
  39. if (local_user() && $block) {
  40. notice(L10n::t('Permission denied.'));
  41. return '';
  42. }
  43. if (local_user()) {
  44. $user = DBA::selectFirst('user', ['parent-uid'], ['uid' => local_user()]);
  45. if (!empty($user['parent-uid'])) {
  46. notice(L10n::t('Only parent users can create additional accounts.'));
  47. return '';
  48. }
  49. }
  50. if (!local_user() && (intval(Config::get('config', 'register_policy')) === self::CLOSED)) {
  51. notice(L10n::t('Permission denied.'));
  52. return '';
  53. }
  54. $max_dailies = intval(Config::get('system', 'max_daily_registrations'));
  55. if ($max_dailies) {
  56. $count = DBA::count('user', ['`register_date` > UTC_TIMESTAMP - INTERVAL 1 day']);
  57. if ($count >= $max_dailies) {
  58. Logger::log('max daily registrations exceeded.');
  59. notice(L10n::t('This site has exceeded the number of allowed daily account registrations. Please try again tomorrow.'));
  60. return '';
  61. }
  62. }
  63. $username = $_REQUEST['username'] ?? '';
  64. $email = $_REQUEST['email'] ?? '';
  65. $openid_url = $_REQUEST['openid_url'] ?? '';
  66. $nickname = $_REQUEST['nickname'] ?? '';
  67. $photo = $_REQUEST['photo'] ?? '';
  68. $invite_id = $_REQUEST['invite_id'] ?? '';
  69. if (local_user() || Config::get('system', 'no_openid')) {
  70. $fillwith = '';
  71. $fillext = '';
  72. $oidlabel = '';
  73. } else {
  74. $fillwith = L10n::t('You may (optionally) fill in this form via OpenID by supplying your OpenID and clicking "Register".');
  75. $fillext = L10n::t('If you are not familiar with OpenID, please leave that field blank and fill in the rest of the items.');
  76. $oidlabel = L10n::t('Your OpenID (optional): ');
  77. }
  78. if (Config::get('system', 'publish_all')) {
  79. $profile_publish = '<input type="hidden" name="profile_publish_reg" value="1" />';
  80. } else {
  81. $publish_tpl = Renderer::getMarkupTemplate('profile_publish.tpl');
  82. $profile_publish = Renderer::replaceMacros($publish_tpl, [
  83. '$instance' => 'reg',
  84. '$pubdesc' => L10n::t('Include your profile in member directory?'),
  85. '$yes_selected' => '',
  86. '$no_selected' => ' checked="checked"',
  87. '$str_yes' => L10n::t('Yes'),
  88. '$str_no' => L10n::t('No'),
  89. ]);
  90. }
  91. $ask_password = !DBA::count('contact');
  92. $tpl = Renderer::getMarkupTemplate('register.tpl');
  93. $arr = ['template' => $tpl];
  94. Hook::callAll('register_form', $arr);
  95. $tpl = $arr['template'];
  96. $tos = new Tos();
  97. $o = Renderer::replaceMacros($tpl, [
  98. '$invitations' => Config::get('system', 'invitation_only'),
  99. '$permonly' => intval(Config::get('config', 'register_policy')) === self::APPROVE,
  100. '$permonlybox' => ['permonlybox', L10n::t('Note for the admin'), '', L10n::t('Leave a message for the admin, why you want to join this node'), 'required'],
  101. '$invite_desc' => L10n::t('Membership on this site is by invitation only.'),
  102. '$invite_label' => L10n::t('Your invitation code: '),
  103. '$invite_id' => $invite_id,
  104. '$regtitle' => L10n::t('Registration'),
  105. '$registertext' => BBCode::convert(Config::get('config', 'register_text', '')),
  106. '$fillwith' => $fillwith,
  107. '$fillext' => $fillext,
  108. '$oidlabel' => $oidlabel,
  109. '$openid' => $openid_url,
  110. '$namelabel' => L10n::t('Your Full Name (e.g. Joe Smith, real or real-looking): '),
  111. '$addrlabel' => L10n::t('Your Email Address: (Initial information will be send there, so this has to be an existing address.)'),
  112. '$addrlabel2' => L10n::t('Please repeat your e-mail address:'),
  113. '$ask_password' => $ask_password,
  114. '$password1' => ['password1', L10n::t('New Password:'), '', L10n::t('Leave empty for an auto generated password.')],
  115. '$password2' => ['confirm', L10n::t('Confirm:'), '', ''],
  116. '$nickdesc' => L10n::t('Choose a profile nickname. This must begin with a text character. Your profile address on this site will then be "<strong>nickname@%s</strong>".', DI::baseUrl()->getHostname()),
  117. '$nicklabel' => L10n::t('Choose a nickname: '),
  118. '$photo' => $photo,
  119. '$publish' => $profile_publish,
  120. '$regbutt' => L10n::t('Register'),
  121. '$username' => $username,
  122. '$email' => $email,
  123. '$nickname' => $nickname,
  124. '$sitename' => DI::baseUrl()->getHostname(),
  125. '$importh' => L10n::t('Import'),
  126. '$importt' => L10n::t('Import your profile to this friendica instance'),
  127. '$showtoslink' => Config::get('system', 'tosdisplay'),
  128. '$tostext' => L10n::t('Terms of Service'),
  129. '$showprivstatement' => Config::get('system', 'tosprivstatement'),
  130. '$privstatement'=> $tos->privacy_complete,
  131. '$form_security_token' => BaseModule::getFormSecurityToken('register'),
  132. '$explicit_content' => Config::get('system', 'explicit_content', false),
  133. '$explicit_content_note' => L10n::t('Note: This node explicitly contains adult content'),
  134. '$additional' => !empty(local_user()),
  135. '$parent_password' => ['parent_password', L10n::t('Parent Password:'), '', L10n::t('Please enter the password of the parent account to legitimize your request.')]
  136. ]);
  137. return $o;
  138. }
  139. /**
  140. * @brief Module POST method to process submitted data
  141. *
  142. * Extend this method if the module is supposed to process POST requests.
  143. * Doesn't display any content
  144. */
  145. public static function post(array $parameters = [])
  146. {
  147. BaseModule::checkFormSecurityTokenRedirectOnError('/register', 'register');
  148. $a = DI::app();
  149. $arr = ['post' => $_POST];
  150. Hook::callAll('register_post', $arr);
  151. $additional_account = false;
  152. if (!local_user() && !empty($arr['post']['parent_password'])) {
  153. notice(L10n::t('Permission denied.'));
  154. return;
  155. } elseif (local_user() && !empty($arr['post']['parent_password'])) {
  156. try {
  157. Model\User::getIdFromPasswordAuthentication(local_user(), $arr['post']['parent_password']);
  158. } catch (\Exception $ex) {
  159. notice(L10n::t("Password doesn't match."));
  160. $regdata = ['nickname' => $arr['post']['nickname'], 'username' => $arr['post']['username']];
  161. DI::baseUrl()->redirect('register?' . http_build_query($regdata));
  162. }
  163. $additional_account = true;
  164. } elseif (local_user()) {
  165. notice(L10n::t('Please enter your password.'));
  166. $regdata = ['nickname' => $arr['post']['nickname'], 'username' => $arr['post']['username']];
  167. DI::baseUrl()->redirect('register?' . http_build_query($regdata));
  168. }
  169. $max_dailies = intval(Config::get('system', 'max_daily_registrations'));
  170. if ($max_dailies) {
  171. $count = DBA::count('user', ['`register_date` > UTC_TIMESTAMP - INTERVAL 1 day']);
  172. if ($count >= $max_dailies) {
  173. return;
  174. }
  175. }
  176. switch (Config::get('config', 'register_policy')) {
  177. case self::OPEN:
  178. $blocked = 0;
  179. $verified = 1;
  180. break;
  181. case self::APPROVE:
  182. $blocked = 1;
  183. $verified = 0;
  184. break;
  185. case self::CLOSED:
  186. default:
  187. if (empty($_SESSION['authenticated']) && empty($_SESSION['administrator'])) {
  188. notice(L10n::t('Permission denied.'));
  189. return;
  190. }
  191. $blocked = 1;
  192. $verified = 0;
  193. break;
  194. }
  195. $netpublish = !empty($_POST['profile_publish_reg']);
  196. $arr = $_POST;
  197. // Is there text in the tar pit?
  198. if (!empty($arr['email'])) {
  199. Logger::info('Tar pit', $arr);
  200. notice(L10n::t('You have entered too much information.'));
  201. DI::baseUrl()->redirect('register/');
  202. }
  203. // Overwriting the "tar pit" field with the real one
  204. $arr['email'] = $arr['field1'];
  205. if ($additional_account) {
  206. $user = DBA::selectFirst('user', ['email'], ['uid' => local_user()]);
  207. if (!DBA::isResult($user)) {
  208. notice(L10n::t('User not found.'));
  209. DI::baseUrl()->redirect('register');
  210. }
  211. $blocked = 0;
  212. $verified = 1;
  213. $arr['password1'] = $arr['confirm'] = $arr['parent_password'];
  214. $arr['repeat'] = $arr['email'] = $user['email'];
  215. }
  216. if ($arr['email'] != $arr['repeat']) {
  217. Logger::info('Mail mismatch', $arr);
  218. notice(L10n::t('Please enter the identical mail address in the second field.'));
  219. $regdata = ['email' => $arr['email'], 'nickname' => $arr['nickname'], 'username' => $arr['username']];
  220. DI::baseUrl()->redirect('register?' . http_build_query($regdata));
  221. }
  222. $arr['blocked'] = $blocked;
  223. $arr['verified'] = $verified;
  224. $arr['language'] = L10nClass::detectLanguage($_SERVER, $_GET, DI::config()->get('system', 'language'));
  225. try {
  226. $result = Model\User::create($arr);
  227. } catch (\Exception $e) {
  228. notice($e->getMessage());
  229. return;
  230. }
  231. $user = $result['user'];
  232. $base_url = DI::baseUrl()->get();
  233. if ($netpublish && intval(Config::get('config', 'register_policy')) !== self::APPROVE) {
  234. $url = $base_url . '/profile/' . $user['nickname'];
  235. Worker::add(PRIORITY_LOW, 'Directory', $url);
  236. }
  237. if ($additional_account) {
  238. DBA::update('user', ['parent-uid' => local_user()], ['uid' => $user['uid']]);
  239. info(L10n::t('The additional account was created.'));
  240. DI::baseUrl()->redirect('delegation');
  241. }
  242. $using_invites = Config::get('system', 'invitation_only');
  243. $num_invites = Config::get('system', 'number_invites');
  244. $invite_id = (!empty($_POST['invite_id']) ? Strings::escapeTags(trim($_POST['invite_id'])) : '');
  245. if (intval(Config::get('config', 'register_policy')) === self::OPEN) {
  246. if ($using_invites && $invite_id) {
  247. Model\Register::deleteByHash($invite_id);
  248. DI::pConfig()->set($user['uid'], 'system', 'invites_remaining', $num_invites);
  249. }
  250. // Only send a password mail when the password wasn't manually provided
  251. if (empty($_POST['password1']) || empty($_POST['confirm'])) {
  252. $res = Model\User::sendRegisterOpenEmail(
  253. L10n::withLang($arr['language']),
  254. $user,
  255. Config::get('config', 'sitename'),
  256. $base_url,
  257. $result['password']
  258. );
  259. if ($res) {
  260. info(L10n::t('Registration successful. Please check your email for further instructions.'));
  261. DI::baseUrl()->redirect();
  262. } else {
  263. notice(
  264. L10n::t('Failed to send email message. Here your accout details:<br> login: %s<br> password: %s<br><br>You can change your password after login.',
  265. $user['email'],
  266. $result['password'])
  267. );
  268. }
  269. } else {
  270. info(L10n::t('Registration successful.'));
  271. DI::baseUrl()->redirect();
  272. }
  273. } elseif (intval(Config::get('config', 'register_policy')) === self::APPROVE) {
  274. if (!strlen(Config::get('config', 'admin_email'))) {
  275. notice(L10n::t('Your registration can not be processed.'));
  276. DI::baseUrl()->redirect();
  277. }
  278. // Check if the note to the admin is actually filled out
  279. if (empty($_POST['permonlybox'])) {
  280. notice(L10n::t('You have to leave a request note for the admin.')
  281. . L10n::t('Your registration can not be processed.'));
  282. DI::baseUrl()->redirect('register/');
  283. }
  284. Model\Register::createForApproval($user['uid'], Config::get('system', 'language'), $_POST['permonlybox']);
  285. // invite system
  286. if ($using_invites && $invite_id) {
  287. Model\Register::deleteByHash($invite_id);
  288. DI::pConfig()->set($user['uid'], 'system', 'invites_remaining', $num_invites);
  289. }
  290. // send email to admins
  291. $admins_stmt = DBA::select(
  292. 'user',
  293. ['uid', 'language', 'email'],
  294. ['email' => explode(',', str_replace(' ', '', Config::get('config', 'admin_email')))]
  295. );
  296. // send notification to admins
  297. while ($admin = DBA::fetch($admins_stmt)) {
  298. \notification([
  299. 'type' => NOTIFY_SYSTEM,
  300. 'event' => 'SYSTEM_REGISTER_REQUEST',
  301. 'source_name' => $user['username'],
  302. 'source_mail' => $user['email'],
  303. 'source_nick' => $user['nickname'],
  304. 'source_link' => $base_url . '/admin/users/',
  305. 'link' => $base_url . '/admin/users/',
  306. 'source_photo' => $base_url . '/photo/avatar/' . $user['uid'] . '.jpg',
  307. 'to_email' => $admin['email'],
  308. 'uid' => $admin['uid'],
  309. 'language' => ($admin['language'] ?? '') ?: 'en',
  310. 'show_in_notification_page' => false
  311. ]);
  312. }
  313. DBA::close($admins_stmt);
  314. // send notification to the user, that the registration is pending
  315. Model\User::sendRegisterPendingEmail(
  316. $user,
  317. Config::get('config', 'sitename'),
  318. $base_url,
  319. $result['password']
  320. );
  321. info(L10n::t('Your registration is pending approval by the site owner.'));
  322. DI::baseUrl()->redirect();
  323. }
  324. return;
  325. }
  326. }