Jump to content

Mikkel-T

Clients
  • Posts

    57
  • Joined

  • Last visited

About Mikkel-T

Recent Profile Visitors

The recent visitors block is disabled and is not being shown to other users.

Mikkel-T's Achievements

  1. @TAMAN I can't seem to find <script src="https://unpkg.com/swiper/js/swiper.min.js"></script> Anywhere. It seems to be in the ta_includeBody which is not in the older version of the template. How can I upgrade from one version to another, without having to redo all my settings for the theme?
    Would be very nice if this mod showed the user group icon, in addition to the group name, so it could work and be compatible with the remove group name. This way you could just display the group icons, but not the names, and specify exactly which groups you want to display 🙂 Otherwise great mod, thanks! Al
  2. Hi, After writing a custom login handler, a new issue appeared: What about unique emails? Our application allows a single user to have multiple identities. Say they have one super account, and many sub accounts. The super account contains information such as email, first & last name, password, etc. The sub account contains information such as nickname/username. Because of this model, many "nicknames" may have the same email. When a user authenticates with the custom login handler, I see 3 things I could do: Prompt the user for the email they want to use. I don't know what will happen if they pick one that's already in use. Probably they will be denied, or asked to merge the accounts, neither of which are preferable. I provide the email in my custom handler. Again, I don't know what will happen if I provide the same email on multiple users I provide a dummy unique email. This will however disable all email features of the forum. Desired option: Make emails not unique to a user. I don't know if this is possible at all. How do you see these things, what are your for's and against's?
  3. I tried creating a sample application, and added a hook to it: //<?php /* To prevent PHP errors (extending class does not exist) revealing path */ if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) ) { exit; } abstract class reborn_hook_RebornLoginHandler extends _HOOK_CLASS_ { public static function handlerClasses() { $return = parent::handlerClasses(); $return[] = 'IPS\mycustomloginhandler\MyLoginHandler'; return $return; } } Then I created "MyCustomLoginHandler.php" in the root of my newly created application directory: <?php /** * @brief Standard Internal Database Login Handler * @author <a href='https://www.invisioncommunity.com'>Invision Power Services, Inc.</a> * @copyright (c) Invision Power Services, Inc. * @license https://www.invisioncommunity.com/legal/standards/ * @package Invision Community * @since 12 May 2017 */ namespace IPS\mycustomloginhandler; /* To prevent PHP errors (extending class does not exist) revealing path */ use IPS\Login\Handler\UsernamePasswordHandler; if (!\defined('\IPS\SUITE_UNIQUE_KEY')) { header((isset($_SERVER['SERVER_PROTOCOL']) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0') . ' 403 Forbidden'); exit; } /** * Standard Internal Database Login Handler */ class _MyCustomLoginHandler extends \IPS\Login\Handler { use UsernamePasswordHandler; /** * Get title * * @return string */ public static function getTitle() { return 'login_handler_Reborn'; } /** * @brief Can we have multiple instances of this handler? */ public static $allowMultiple = false; /** * ACP Settings Form * * @param string $url URL to redirect user to after successful submission * @return array List of settings to save - settings will be stored to core_login_handlers.login_settings DB field * @code * return array( 'savekey' => new \IPS\Helpers\Form\[Type]( ... ), ... ); * @endcode */ public function acpForm() { return array( 'reborn_api_endpoint' => new \IPS\Helpers\Form\Text( 'reborn_api_endpoint', ( isset( $this->settings['reborn_api_endpoint'] ) ) ? $this->settings['reborn_api_endpoint'] : '', TRUE ), 'reborn_api_key' => new \IPS\Helpers\Form\Text( 'reborn_api_key', ( isset( $this->settings['reborn_api_key'] ) ) ? $this->settings['reborn_api_key'] : '', TRUE ), ); } /** * Authenticate * * @param \IPS\Login $login The login object * @param string $usernameOrEmail The username or email address provided by the user * @param object $password The plaintext password provided by the user, wrapped in an object that can be cast to a string so it doesn't show in any logs * @return \IPS\Member * @throws \IPS\Login\Exception */ public function authenticateUsernamePassword(\IPS\Login $login, $usernameOrEmail, $password) { /* Get member(s) */ if (!$this->authType() & \IPS\Login::AUTH_TYPE_USERNAME) { throw new \IPS\Login\Exception(\IPS\Member::loggedIn()->language()-> addToStack('login_err_no_account', FALSE, array('sprintf' => array(\IPS\Member::loggedIn()->language() ->addToStack('Some settings are messed up')))), \IPS\Login\Exception::NO_ACCOUNT ); } $response = $this->authRequest($usernameOrEmail, $password); if ($response->code != '200') { throw new \IPS\Login\Exception('login_err_bad_password', \IPS\Login\Exception::BAD_PASSWORD, NULL); } $forumId = (int) $response->content->forum_id; $accountId = (int) $response->content->id; $forumUsername = $response->content->nickname; try { $member = \IPS\Member::load($forumId); $member->name = $forumUsername; $member->save(); return $member; } catch (\OutOfRangeException $e) { $member = new \IPS\Member; $member->member_group_id = \IPS\Settings::i()->member_group; $member->name = $usernameOrEmail; $member->save(); //send update to master server, we got a forum_id for this guy! $this->updateForumId($accountId, $member->member_id); return $member; } } /** * Authenticate * * @param \IPS\Member $member The member * @param object $password The plaintext password provided by the user, wrapped in an object that can be cast to a string so it doesn't show in any logs * @return bool */ public function authenticatePasswordForMember(\IPS\Member $member, $password) { $request = $this->authRequest($member->name, $password); return $request->code == 200 ? true : false; } private function authRequest($username, $password) { $url = $this->rebornEndPoint . '/api/forum/account/auth'; $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, "api_key={$this->rebornApiKey}&username={$username}&password={$password}"); // Receive server response ... curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); $server_output = curl_exec($ch); curl_close($ch); $response = json_decode($server_output); return $response; } private function updateForumId($accountId, $forumId) { $url = $this->rebornEndPoint . '/api/forum/account/auth'; $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, "api_key={$this->rebornApiKey}&accountId={$accountId}&forumId={$forumId}"); // Receive server response ... curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); $server_output = curl_exec($ch); curl_close($ch); $response = json_decode($server_output); return $response; } /** * Can this handler process a login for a member? * * @return bool */ public function canProcess(\IPS\Member $member) { return (bool)$member->members_pass_hash; } /** * Can this handler process a password change for a member? * * @return bool */ public function canChangePassword(\IPS\Member $member) { return false; } /** * Change Password * * @param \IPS\Member $member The member * @param object $newPassword New Password wrapped in an object that can be cast to a string so it doesn't show in any logs * @return void */ public function changePassword(\IPS\Member $member, $newPassword) { //$member->setLocalPassword( $newPassword ); //$member->save(); } /** * Show in Account Settings? * * @param \IPS\Member|NULL $member The member, or NULL for if it should show generally * @return bool */ public function showInUcp(\IPS\Member $member = NULL) { return FALSE; } } But upon trying to create a new handler from the adminCP, I still encounter this error: But at least I'm no longer modifying the original files 😛 I also tried changing the hook to return $return[] = 'IPS\mycustomloginhandler\MyCustomLoginHandler'; as this seemed more correct to me, but it gave same results.
  4. True, added the file. It's just a POC, but couldn't get far enough to test it :C
  5. Hi, I'm working on migrating us from vbulletin to IPB. In order to do this, we need a custom login handler, to handle logins via our API. What I did so far: Read (although it seems somewhat outdated, there is still some good info) Enabled DEV mode Created the appropiate file structure: Using the following namespace: namespace IPS\Login\Handler; And class name: class _Reborn extends \IPS\Login\Handler Extended the handler array in Handler.php with: 'IPS\Login\Handler\Reborn', I get the following error when trying to add my login handler: Quite possibly I'm missing a few steps, but would anyone know? I tried to search for up-to-date documentation but find it hard to find, and the only few links I managed to find, doesn't seem to be valid any more. Content of the Reborn.php file: <?php /** * @brief Standard Internal Database Login Handler * @author <a href='https://www.invisioncommunity.com'>Invision Power Services, Inc.</a> * @copyright (c) Invision Power Services, Inc. * @license https://www.invisioncommunity.com/legal/standards/ * @package Invision Community * @since 12 May 2017 */ namespace IPS\Login\Handler; /* To prevent PHP errors (extending class does not exist) revealing path */ if (!\defined('\IPS\SUITE_UNIQUE_KEY')) { header((isset($_SERVER['SERVER_PROTOCOL']) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0') . ' 403 Forbidden'); exit; } /** * Standard Internal Database Login Handler */ class _Reborn extends \IPS\Login\Handler { use UsernamePasswordHandler; /** * Get title * * @return string */ public static function getTitle() { return 'login_handler_Reborn'; } /** * ACP Settings Form * * @param string $url URL to redirect user to after successful submission * @return array List of settings to save - settings will be stored to core_login_handlers.login_settings DB field * @code * return array( 'savekey' => new \IPS\Helpers\Form\[Type]( ... ), ... ); * @endcode */ public function acpForm() { return array( 'reborn_api_endpoint' => new \IPS\Helpers\Form\Text( 'reborn_api_endpoint', ( isset( $this->settings['reborn_api_endpoint'] ) ) ? $this->settings['reborn_api_endpoint'] : '', TRUE ), 'reborn_api_key' => new \IPS\Helpers\Form\Text( 'reborn_api_key', ( isset( $this->settings['reborn_api_key'] ) ) ? $this->settings['reborn_api_key'] : '', TRUE ), ); } /** * Authenticate * * @param \IPS\Login $login The login object * @param string $usernameOrEmail The username or email address provided by the user * @param object $password The plaintext password provided by the user, wrapped in an object that can be cast to a string so it doesn't show in any logs * @return \IPS\Member * @throws \IPS\Login\Exception */ public function authenticateUsernamePassword(\IPS\Login $login, $usernameOrEmail, $password) { /* Get member(s) */ if (!$this->authType() & \IPS\Login::AUTH_TYPE_USERNAME) { throw new \IPS\Login\Exception(\IPS\Member::loggedIn()->language()-> addToStack('login_err_no_account', FALSE, array('sprintf' => array(\IPS\Member::loggedIn()->language() ->addToStack('Some settings are messed up')))), \IPS\Login\Exception::NO_ACCOUNT ); } $response = $this->authRequest($usernameOrEmail, $password); if ($response->code != '200') { throw new \IPS\Login\Exception('login_err_bad_password', \IPS\Login\Exception::BAD_PASSWORD, NULL); } $forumId = (int) $response->content->forum_id; $accountId = (int) $response->content->id; $forumUsername = $response->content->nickname; try { $member = \IPS\Member::load($forumId); $member->name = $forumUsername; $member->save(); return $member; } catch (\OutOfRangeException $e) { $member = new \IPS\Member; $member->member_group_id = \IPS\Settings::i()->member_group; $member->name = $usernameOrEmail; $member->save(); //send update to master server, we got a forum_id for this guy! $this->updateForumId($accountId, $member->member_id); return $member; } } /** * Authenticate * * @param \IPS\Member $member The member * @param object $password The plaintext password provided by the user, wrapped in an object that can be cast to a string so it doesn't show in any logs * @return bool */ public function authenticatePasswordForMember(\IPS\Member $member, $password) { $request = $this->authRequest($member->name, $password); return $request->code == 200 ? true : false; } private function authRequest($username, $password) { $url = $this->rebornEndPoint . '/api/forum/account/auth'; $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, "api_key={$this->rebornApiKey}&username={$username}&password={$password}"); // Receive server response ... curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); $server_output = curl_exec($ch); curl_close($ch); $response = json_decode($server_output); return $response; } private function updateForumId($accountId, $forumId) { $url = $this->rebornEndPoint . '/api/forum/account/auth'; $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, "api_key={$this->rebornApiKey}&accountId={$accountId}&forumId={$forumId}"); // Receive server response ... curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); $server_output = curl_exec($ch); curl_close($ch); $response = json_decode($server_output); return $response; } /** * Can this handler process a login for a member? * * @return bool */ public function canProcess(\IPS\Member $member) { return (bool)$member->members_pass_hash; } /** * Can this handler process a password change for a member? * * @return bool */ public function canChangePassword(\IPS\Member $member) { return false; } /** * Change Password * * @param \IPS\Member $member The member * @param object $newPassword New Password wrapped in an object that can be cast to a string so it doesn't show in any logs * @return void */ public function changePassword(\IPS\Member $member, $newPassword) { //$member->setLocalPassword( $newPassword ); //$member->save(); } /** * Show in Account Settings? * * @param \IPS\Member|NULL $member The member, or NULL for if it should show generally * @return bool */ public function showInUcp(\IPS\Member $member = NULL) { return FALSE; } }
  6. Hi, I started migrating from vb4, but running the converter is extremely slow. I started migrating our 9 million members, and this process took 10 days. While extremely slow, I thought this was okay, now I just need to put the forums in read-only mode, and the tool can finish up migrating the users, messages and so on, that was created in those 2 weeks. I contacted support assistance, but to my big surprise this is not a feature. I have to run the migration all in one go, and keep the original boards in a read-only state while doing so (if I wanted to make sure everything got converted). This doesn't work for me, as we have many posts and threads being written everyday, and the forums are an important tool for quite many stakeholders including volunteers, marketing teams, bug reports, and so on. In addition to this, putting the forums in a "read-only" mode is not possible. We run an online game, and everytime a new user signs up, they are also created on the forums (and as you might have guessed, this happens quite often). So I would like to keep the amount of users we are not able to migrate, to a minimum. Do any of you have a suggestion for how to deal with this? - Shutting down forums for 3 weeks while this migration is on-going is not an option.
  7. @HeadStand I guess what I want is a root tab, with 2 sub menus. I'm not sure I understand the part of the menu builder. Currently it can only link to a single item (my extension), and I cannot add sub-menus to that one, using the manager.
  8. I tried to create a front navigation extension, but I'm having troubles creating "sub menus" for it. Example: I have a feeling I see I should be using the children method, but it returns an array, I'm not too sure of what..?
  9. ^This Also, is there support for ProMenu? -
  10. Using this "Wizard" is generally a bad idea, as the users don't know what question will be next, and they will end up misplacing information in wrong places. If you insist on making this "Wizard", you should include the option to show all questions at once, or your might turn down some customers.
  11. Hi, Can you make it possible to post the topic as a poll, and add options like "accept me" and then "yes/no" as choices :)
×
×
  • Create New...