Modx redirect user to a specific page after manager login - modx

I've found this plugin code:
<!--?php
if ($modx--->event->name == 'OnManagerLogin') {
$path = $modx->getOption('base_url',null,MODX_BASE_URL);
$modx->sendRedirect($path.'manager/?a=69');
}
but I cannot manage to make it work with MODX Revolution 2.5.0-pl.
It seems that OnManagerLogin does not work at all.
Am I the only one? Is it related to this?
https://github.com/modxcms/revolution/issues/11848
I've also tried this:
$e = $modx->event;
switch( $e->name ) {
case 'OnManagerLogin':
$modx->sendRedirect('http://modx.com',array('responseCode' => 'HTTP/1.1 301 Moved Permanently'));
}
but it did not work. Can anyone help?

Solution is here
With this code :
$url = 'http://www.example.com/manager/';
$groups = array(
'admin_ceremonie' => 'http://www.example.com/manager/?a=resource/update&id=1138',
);
$userId = $user->get('id');
$searchCriteria = array(
'user' => $userId,
'key' => 'LoginResourceUrl',
);
$userSetting = $modx->getObject('modUserSetting', $searchCriteria);
if ($userSetting) {
$url = $userSetting->get('value');
}
else {
foreach($groups as $groupName => $pageUrl) {
if ($user->isMember($groupName)) {
$url = $pageUrl;
break;
}
}
}
$modx->sendRedirect($url);

Related

Login to many context in modx using api functions

I am working in facebook login, after successful facebook authentication i want to login user using modx api, i am able to login him using below code. But i am not getting how to login to multiple contexts, i tried to pass "login_context" parameter but still it only login him in "web" context and not other contexts.
$c = array(
'login_context' => 'tech,data,finance',
'username' => $username,
'password' => $password,
'returnUrl' => 'http://www.mydomain.com',
);
$response = $modx->runProcessor('security/login', $c);
loginContext its for only one context, if you need to login to multiple contexts - use add_contexts option.
This is just basic code to give you simple idea how it can be done.
if(isset($_POST) && count($_POST)){
$username = $_POST['uname'];
$password = $_POST['upass'];
$c = array(
'login_context' => 'web', // main context
'add_contexts' => 'profile,gallery,videos', // other contexts
'username' => $username,
'password' => $password
);
$response = $modx->runProcessor('security/login',$c);
if($response){
if (!$response->isError()) {
if($response->response['success'] == 1){
echo json_encode(array("success"=>1));
}else{
echo json_encode($response->response);
}
}else{
echo json_encode($response->response);
}
}
}

create whmcs domain registrar module to sell domains with the tld of my country

Hi everyoneI have a site with whmcs and i want to sell domains with the tld of my county that is .al and i've searched the web for this but all told me that i need to create a domain registrar module.I'v downloaded the template from the whmcs site but i don't know how to use it.Does anyone have any idea how can i achieve this.
<?php
function template_getConfigArray() {
$configarray = array(
"Username" => array( "Type" => "text", "Size" => "20", "Description" => "Enter your username here", ),
"Password" => array( "Type" => "password", "Size" => "20", "Description" => "Enter your password here", ),
"TestMode" => array( "Type" => "yesno", ),
);
return $configarray;
}
function template_GetNameservers($params) {
$username = $params["Username"];
$password = $params["Password"];
$testmode = $params["TestMode"];
$tld = $params["tld"];
$sld = $params["sld"];
# Put your code to get the nameservers here and return the values below
$values["ns1"] = $nameserver1;
$values["ns2"] = $nameserver2;
$values["ns3"] = $nameserver3;
$values["ns4"] = $nameserver4;
# If error, return the error message in the value below
$values["error"] = $error;
return $values;
}
function template_SaveNameservers($params) {
$username = $params["Username"];
$password = $params["Password"];
$testmode = $params["TestMode"];
$tld = $params["tld"];
$sld = $params["sld"];
$nameserver1 = $params["ns1"];
$nameserver2 = $params["ns2"];
$nameserver3 = $params["ns3"];
$nameserver4 = $params["ns4"];
# Put your code to save the nameservers here
# If error, return the error message in the value below
$values["error"] = $error;
return $values;
}
function template_GetRegistrarLock($params) {
$username = $params["Username"];
$password = $params["Password"];
$testmode = $params["TestMode"];
$tld = $params["tld"];
$sld = $params["sld"];
# Put your code to get the lock status here
if ($lock=="1") {
$lockstatus="locked";
} else {
$lockstatus="unlocked";
}
return $lockstatus;
}
function template_SaveRegistrarLock($params) {
$username = $params["Username"];
$password = $params["Password"];
$testmode = $params["TestMode"];
$tld = $params["tld"];
$sld = $params["sld"];
if ($params["lockenabled"]) {
$lockstatus="locked";
} else {
$lockstatus="unlocked";
}
# Put your code to save the registrar lock here
# If error, return the error message in the value below
$values["error"] = $Enom->Values["Err1"];
return $values;
}
This is a part of the code from the module template.
Well the first step would be determining which registrar you are going to use to register your domains. There are quite a few that already have modules pre-built and included in WHMCS. You can see the list here.
If you are using a registrar that does not already have a pre-built module in WHMCS, then you will need to create your own. The template you downloaded has all of the supported functions in WHMCS. Before you roll out your own module however, you will want to see if your registrar has an API. If they do not then building the module for WHMCS is pointless. If they do, read through their documentation. Once you are familiar with the registrar's functionality, then it's just a matter of connecting the dots between the WHMCS template you downloaded and the registrar's API.
Best of luck!

How to implement a pagination for a search module in Zend Framework 2?

I have a module Search in my ZF2 application. The user fills in a search form out and gets a list of courses.
Now I'm adding the pagination to the module. The paginator is basically working: I can retrieve data over it and the pagination is displayed correctly (pagelinks 1-7 for 70 found courses with the dafault setting 10 items per page).
But it's still not usable. When I click on a pagelink, the form POST data is lost. I know -- it cannot work the way, how I implemented it (see the code below). But I have no idea, how to do it correctly, in order to eep checking the form data and nonetheless be able to use pagination.
That is my code:
Table class Search\Model\CourseTable
class CourseTable {
...
// without pagination
// public function findAllByCriteria(CourseSearchInput $input) {
// with pagination
public function findAllByCriteria(CourseSearchInput $input, $pageNumber) {
...
$select = new Select();
$where = new Where();
$having = new Having();
...
// without pagination
// $resultSet = $this->tableGateway->selectWith($select);
// return $resultSet;
// with pagination
$adapter = new \MyNamespqce\Paginator\Adapter\DbSelect($select, $this->tableGateway->getAdapter());
$paginator = new \Zend\Paginator\Paginator($adapter);
$paginator->setCurrentPageNumber($pageNumber);
return $paginator;
}
...
}
Search\Controller\SearchController
class SearchController extends AbstractActionController {
public function searchCoursesAction() {
$form = $this->getServiceLocator()->get('Search\Form\CourseSearchForm');
$request = $this->getRequest();
if ($request->isPost()) {
$courseSearchInput = new CourseSearchInput();
$form->setInputFilter($courseSearchInput->getInputFilter());
$form->setData($request->getPost());
if ($form->isValid()) {
$courseSearchInput->exchangeArray($form->getData());
// without pagination
// $courses = $this->getCourseTable()->findAllByCriteria($courseSearchInput);
// with pagination
$page = $this->params()->fromRoute('page');
$paginator = $this->getCourseTable()->findAllByCriteria($courseSearchInput, $page);
} else {
$paginator = null;
}
} else {
$paginator = null;
}
return new ViewModel(array(
'form' => $form,
// without pagination
// 'courses' => $courses,
// with pagination
'paginator' => $paginator,
'cities' => ...
));
}
...
}
How to get it working?
I also have the same problem, and I have solved it. But this is not good way. May be the idea will help you.
I solved it as follow: (Search pagination for Zend tutorial album module)
I build two action in controller named "search" and "index".
Whenever the search form submitted, it always post the value to search action. Search action build the url with search parameters, and redirect to index to disply search result.
And when the pagination links clicked, then posted values are passed through url. So whenever index action ask for search parameters, it always get the values in same format.
I defined route as follows:
'album' => array(
'type' => 'segment',
'options' => array(
'route' => '/album[/:action][/:id][/page/:page][/order_by/:order_by][/:order][/search_by/:search_by]',
'constraints' => array(
'action' => '(?!\bpage\b)(?!\border_by\b)(?!\bsearch_by\b)[a-zA-Z][a-zA-Z0-9_-]*',
'id' => '[0-9]+',
'page' => '[0-9]+',
'order_by' => '[a-zA-Z][a-zA-Z0-9_-]*',
'order' => 'ASC|DESC',
),
'defaults' => array(
'controller' => 'Album\Controller\Album',
'action' => 'index',
),
),
),
There is a parameter named "search_by", which will keep all search parameters as a json string. This is the point, which is not good I know, but have not find any other way yet.
"Search" action build this string as -
public function searchAction()
{
$request = $this->getRequest();
$url = 'index';
if ($request->isPost()) {
$formdata = (array) $request->getPost();
$search_data = array();
foreach ($formdata as $key => $value) {
if ($key != 'submit') {
if (!empty($value)) {
$search_data[$key] = $value;
}
}
}
if (!empty($search_data)) {
$search_by = json_encode($search_data);
$url .= '/search_by/' . $search_by;
}
}
$this->redirect()->toUrl($url);
}
And next index action decode the string, do necessary action, and also send the json string to view.
public function indexAction() {
$searchform = new AlbumSearchForm();
$searchform->get('submit')->setValue('Search');
$select = new Select();
$order_by = $this->params()->fromRoute('order_by') ?
$this->params()->fromRoute('order_by') : 'id';
$order = $this->params()->fromRoute('order') ?
$this->params()->fromRoute('order') : Select::ORDER_ASCENDING;
$page = $this->params()->fromRoute('page') ? (int) $this->params()->fromRoute('page') : 1;
$select->order($order_by . ' ' . $order);
$search_by = $this->params()->fromRoute('search_by') ?
$this->params()->fromRoute('search_by') : '';
$where = new \Zend\Db\Sql\Where();
$formdata = array();
if (!empty($search_by)) {
$formdata = (array) json_decode($search_by);
if (!empty($formdata['artist'])) {
$where->addPredicate(
new \Zend\Db\Sql\Predicate\Like('artist', '%' . $formdata['artist'] . '%')
);
}
if (!empty($formdata['title'])) {
$where->addPredicate(
new \Zend\Db\Sql\Predicate\Like('title', '%' . $formdata['title'] . '%')
);
}
}
if (!empty($where)) {
$select->where($where);
}
$album = $this->getAlbumTable()->fetchAll($select);
$totalRecord = $album->count();
$itemsPerPage = 2;
$album->current();
$paginator = new Paginator(new paginatorIterator($album));
$paginator->setCurrentPageNumber($page)
->setItemCountPerPage($itemsPerPage)
->setPageRange(7);
$searchform->setData($formdata);
return new ViewModel(array(
'search_by' => $search_by,
'order_by' => $order_by,
'order' => $order,
'page' => $page,
'paginator' => $paginator,
'pageAction' => 'album',
'form' => $searchform,
'totalRecord' => $totalRecord
));
}
All the sorting and paging url contain that string.
If you know all the searching paarameters before, then you can define that at route, and pass like the same way without json string. As I have to build a common search, I have build a single string.
Source code for "Album search" is available in git hub at https://github.com/tahmina8765/zf2_search_with_pagination_example.
Live Demo: http://zf2pagination.lifencolor.com/public/album
#Sam & #automatix in the question comments are both right. My suggestion (though I'm looking for a simpler alternative) is to construct a segment route, which covers all of the options that you're likely to need and start with a standard form POST request.
Then, after the request is validated, pass the form data to the paginationControl helper as follows:
$resultsView = new ViewModel(array(
'paginator' => $paginator,
'routeParams' => array_filter($form->getData())
));
Then, in your view template, set the route parameters in the paginationControl view helper:
<?php echo $this->paginationControl($paginator, 'Sliding', 'paginator/default',
array('routeParams' => $routeParams)
) ?>
I've used array_filter here because it's a really simple way of removing any element from the form data that's null, empty or so on. That way you don't pass in extra data that you don't need.

login to modx from external/other server revolution 2.2.5

I am pissed off with this problem from 2 days.
I am using MODx Revolution 2.2.5 (traditional) and want to login to modx from external server just to fetch some user details.
1) I know that runprocessor method works only if i am logged in to manager (unfortunately, that's the only way i know to login user in) So i tried IFRAME method to avoid (cross scripting) it worked perfectly but i am not able to read the data from IFRAME using javascript because of same issue, cross domain access policy.
When i try to post data using some other method like CURL, Ajax using
header("Access-Control-Allow-Origin: *");
I am able to login (I see $response->response['success'] == 1) but cant access any data and it says
Fatal error: Call to a member function get() on a non-object
Below is the snippet code i am using
if(isset($_POST) && count($_POST)){
$c = array(
'username' => $_POST['username'],
'password' => $_POST['password']
);
$response = $modx->runProcessor('security/login',$c);
if($response->response['success'] == 1){
$user['id'] = $modx->user->get('id');
$profile = $modx->user->getOne('Profile');
$user['fullname'] = $profile->get('fullname');
$user['email'] = $profile->get('email');
echo json_encode($user);
}else{
echo json_encode($response->response);
}
}
2) I can use login snippet but it doesnt return output what i expect. We have ready site and we are already using login plugin so i cant even modify login plugin to respond with expected data
How can i login to modx using api or any other method ??
You are really attacking this problem completely wrong in my opinion. If you want to access a server/webpage from another, you don't iFrame and do it the way you are. That is hacking, and this hole will most likely be fixed in a future version.
What you SHOULD do is connecting to the database and just gather the information from the user-table.
No hacking, no "tricks", won't stop working and much safer.
Well, I sorted out this today, Below is the complete come that worked perfectly.
Pay attention to
header("Access-Control-Allow-Origin: http://www.xyz.com");
Using above CORS specification you can allow 2 servers to communication.
header("Access-Control-Allow-Origin: http://www.xyz.com");
if(isset($_POST['username']) && isset($_POST['password'])){
// get username and password from POST array
$username = $modx->sanitizeString($_POST['username']);
$password = $modx->sanitizeString($_POST['password']);
if(trim($username) != "" and trim($password) != ""){
// Load lexicons to show proper error messages
if (!isset($modx->lexicon) || !is_object($modx->lexicon)) {
$modx->getService('lexicon','modLexicon');
}
$modx->lexicon->load('login');
$loginContext= isset ($scriptProperties['login_context']) ? $scriptProperties['login_context'] :
$modx->context->get('key');
$addContexts= isset ($scriptProperties['add_contexts']) && !empty($scriptProperties['add_contexts']) ? explode(',', $scriptProperties['add_contexts']) : array();
$mgrEvents = ($loginContext == 'mgr');
$givenPassword = $password;
/** #var $user modUser */
$user= $modx->getObjectGraph('modUser', '{"Profile":{},"UserSettings":{}}', array ('modUser.username' => $username));
if (!$user) {
$ru = $modx->invokeEvent("OnUserNotFound", array(
'user' => &$user,
'username' => $username,
'password' => $password,
'attributes' => array(
'loginContext' => $loginContext,
)
));
if (!empty($ru)) {
foreach ($ru as $obj) {
if (is_object($obj) && $obj instanceof modUser) {
$user = $obj;
break;
}
}
}
if (!is_object($user) || !($user instanceof modUser)) {
//echo "cant locate account";
echo $modx->toJSON($modx->error->failure($modx->lexicon('login_cannot_locate_account')));
exit;
}
}
if (!$user->get('active')) {
//echo "inactivated accout";
echo $modx->toJSON($modx->error->failure($modx->lexicon('login_user_inactive')));
exit;
}
if (!$user->passwordMatches($givenPassword)) {
if (!array_key_exists('login_failed', $_SESSION)) {
$_SESSION['login_failed'] = 0;
}
if ($_SESSION['login_failed'] == 0) {
$flc = ((integer) $user->Profile->get('failedlogincount')) + 1;
$user->Profile->set('failedlogincount', $flc);
$user->Profile->save();
$_SESSION['login_failed']++;
} else {
$_SESSION['login_failed'] = 0;
}
//echo "wrong username pass";
echo $modx->toJSON($modx->error->failure($modx->lexicon('login_username_password_incorrect')));
exit;
}
$fullname = $user->Profile->get('fullname');
echo '{"success":true,"message":"Welcome '.$fullname.'!"}';
}else{
echo '{"success":false,"message":"Please enter username and password"}';
}
}

assign users to group modx

How can i assign newly created user to the particular group in modx Programmaticaly ? Below is my code
if(isset($_POST) && count($_POST)){
$oUser = $modx->newObject('modUser');
$oUser->set('username', "test");
//$oUser->set('password', "test");
$oProfile = $modx->newObject('modUserProfile');
$oProfile->set('fullname', $_POST['fname']);
$oProfile->set('email', $_POST['email']);
$oUser->addOne($oProfile);
if($oUser->save()===false){
echo "Error";
}else
echo "Done";
}
I googled but all i find is graphical tutorial how to create groups and edit user and then assign roles, If you know any tutorial then also its fine.
Here is how I have been doing it, this is a posthook snippet that fires after a user registers [and the user is created]
<?php
$specialty = $hook->getValue('specialty');
$country = strtolower($hook->getValue('excountry'));
$username = $hook->getValue('username');
$staff = $hook->getValue('staff-or-resident'); //Staff | Resident
$joingroup = '';
$joinrole = '';
$blockuser = 'false';
switch ($specialty){
case 'Other' :
$joingroup = 15; // Other
$joinrole = 1; //member
$blockuser = 'true';
break;
// there are about 15 different groups and roles here...
default :
$joingroup = '0'; // none
$joinrole = '0'; // none
break;
}
if($joingroup > 0 && $joinrole > 0){
$user = $modx->getObject('modUser', array('username'=>$username));
$internalkey = $user->get('id');
$profile = $user->getOne('Profile',array('internalKey'=>$internalkey));
$user->joinGroup($joingroup, $joinrole);
if($blockuser == 'true'){ //block user if they belong to the "other" group
$profile->set('blocked',1);
}
if(!$user->save()){
return false;
};
}
return true;
The key is the: $user->joinGroup($joingroup, $joinrole); where joingroup is the group id ~ or name and the joinrole is the role id ~ or name. It's documented here: http://api.modx.com/revolution/2.1/_model_modx_moduser.class.html#%5CmodUser::joinGroup()
The best way to create/edit something in revo >2.2 this is use "Class-based Processors" - https://www.markhamstra.com/modx-blog/2012/2/getting-started-with-class-based-processors-2.2/ to add user to group use this processor https://github.com/modxcms/revolution/blob/develop/core/model/modx/processors/security/user/update.class.php with this -
http://rtfm.modx.com/display/revolution20/Using+runProcessor
$param = array(
'id' => 1, // user id
'groups' => array(
array(
"usergroup" => 1,
"name" => "Administrator",
"member" => 1,
"role" => 2,
"rolename" => "Super User",
"primary_group" => true,
"rank" => 0,
"menu" => null
),
array( .... )
)
);
$response = $modx->runProcessor('security/user/update',$param );
if ($response->isError()) {
return $response->getMessage();
}

Resources