create user in moodle through web services php - php

I am trying to create a user through web services in Moodle by using PHP and I am using ws function: core_user_create_users. but it gives me an error.
{"exception":"webservice_access_exception","errorcode":"accessexception","message":"Access control exception"}
i am using moodle ver3.4.
Can you tell me how to add capabilities to the current token with respect to the user if its problem of web service function? if its other problem please tell me.
Thanks,

I will give a full answer on how to do this. First, we will start by creating a role for web services (it's not necessary, but I love to do it this way to keep the instance clean for administrators).
But first, there is a quick solution to your problem. Add the authorized user to the list of administrators of your website and you are free to call any function with the generated token.
I. Create a new role for web services
You can do that by going to Site administration > Users > Permissions > Define roles. You will find a button to add a new role Add a new role. After you click on that button, you will get a form where you can use defined (or default) roles or archetype to define your new role. You can also create your role using an exported file from another Moodle instance. Anyway, we will choose Continue to define our custom role. Now, we can fill the necessary information like (short name, custom full name, custom description).In the context part, choose System to assign this role from everywhere in the system.
Now scroll down all the way to the capabilities. Search in the Filter search box your capabilities (in our case creating users). You can see the needed capabilities when you create the web service and add the function to it. Each function needs a user with specific capabilities to execute.
You can find function capabilities either from admin dashboard by going to Site administration > Plugins > Web services > External services and create a new external service and add your function and you will see the list of capabilities int he Required capabilities column of your service table. Just type core_user_create_users in the functions drop-down list. Click on Add functions button and now you can see the Required capabilities. In this case, it's only moodle/user:create. So we can use this in our role by checking allow checkbox next to each capability we want.
After you finish your role configuration, click on Create this role.
II. Assign a user to the new role
Now we can assign our user to the new role.
Go to Site administrator > Users > Permissions > Assign system roles.
Choose our new role.
Add the user to the list of existing users.
III. Add user to authorized users
This is only required if you checked the Only authorized users option when you created your external service.
Go to Site administrator > Plugins > Web services > External services.
Click on Authorized users link on your web service.
Add the user to the list of Authorized users.
Check the warning under the form. If your user doesn't have some capabilities, Moodle will signal that as a warning under the form. You can fix that by adding the missing capabilities to the role that we created earlier.
IV. Create a token
Now we can go to the token manager and generate a new token to our user for our external web service.
BS: Don't forget to enable web services first. Enable REST protocol or whatever protocol you are willing to use.
Update: How to call the function?
Following the details requested in the comments of this answer, I will provide an example on how to call these web services functions (in this example create_users).
In this example, we will use cURL class provided by the core team of Moodle to make things easier for us. You can find this class in the repository of their web service client example here. I will be using the curl.php file in the PHP-REST folder in this repository. All the PHP folder in this repositories have the same curl.php file. The client.php file is the only difference.
$token = 'replace it with your web service token';
$domainname = 'http://your_moodle_domain.ltd';
$functionname = 'core_user_create_users';
$restformat = 'json';
$user = array(
"username" => "username of your new user", // must be unique.
"password" => "password must respect moodle policies",
"firstname" => "first name",
"lastname" => "last name",
"email" => "your_user#email.com",
"auth" => 'authentication method can be email, manual, registred ..',
"customfields" => array ( // If you have custom fields in your system.
array(
"type" => "birthdate",
"value" => strtotime("01/01/1990")
),
array(
"type" => "something_else",
"value" => "0"
)
)
);
$users = array($user); // must be wrapped in an array because it's plural.
$param = array("users" => $users); // the paramater to send
$serverurl = $domainname . '/webservice/rest/server.php'. '?wstoken=' .
$token . '&wsfunction='.$functionname;
require_once('curl.php'); // You can put it in the top.
$curl = new curl;
$restformat = ($restformat == 'json')?'&moodlewsrestformat=' .
$restformat:'';
$resp = $curl->post($serverurl . $restformat, $param);

Related

Laravel: keep login (authenticated status) manually

My website has multiple authentications for different purposes. Authorization is not proper here because for each kind of authentication different data required, so for each kind of authentication separate database tables uses.
E. g. all that admins are need is email and password: email uses as ID for authentication. Now, to look theirs sites in development, which is currently a part of my own site, customers needs also order ID, customer's name, website name, and alias data. For example:
Future website domain: stivenson-gym.com
Website name: Stevenson's gym
Order ID: StivensonGym
Customer: Michael Stivenson
Subwebsite top page's url: www.webmaster-example.com/orders/stivenson-gym/index.html
This order's alias (part of above url): stivenson-gym
Unlike the authentication of admins, here is Order ID (not customer's name) uses for signing in.
I already realized:
Manual OrderID and password checking
Routing with dynamic alias building for each order id.
Now I need to keep customer logging in during he browses his website.
Why Auth::attempt(['orderID' => $orderID, 'password' => $password]) will not use? Because this method refers to Users table, but I need Orders table. I can't change globally table for Auth because admins needs the different table for authentication.
In the theory, the solution will be:
Write in the session that certain customer currently browses he's subwebsite.
When the customer change the internal page of he's subwebsite, first it's required to check the above recording in the session.
When the customer leaves his subsite - clear the section.
I will add my current code without authorization:
class LoginToSitesInDevelopmentZoneController extends Controller {
const SITE_IN_DEVELOPMENT_TABLE_NAME = 'site_in_dev';
const ORDER_ID_FIELD_NAME = 'order_id';
const PASSWORD_FIELD_NAME = 'password';
const SITENAME_FIELD_NAME = 'sitename';
const CUSTOMER_NAME_FIELD_NAME = 'customer_name';
const ALIAS_FIELD_NAME = 'alias';
public function login(Request $request) {
$inputtedOrderId = $request->input('order_id'); // from login form
// manual check is this order exists
$orderIdInDB = DB::table(self::SITE_IN_DEVELOPMENT_TABLE_NAME)
->where(self::ORDER_ID_FIELD_NAME, $inputtedOrderId)->first();
if (is_null($orderIdInDB)) {
return Redirect::route('loginToSitesInDevelopmentZonePage')->withErrors(['wrongOrderId' => true])->withInput();
}
// from login form
$inputtedPassword = $request->input('password');
// manual check the order id and password compilance
$bcryptedPasswordFromDB = DB::table(self::SITE_IN_DEVELOPMENT_TABLE_NAME)
->where(self::ORDER_ID_FIELD_NAME, $inputtedOrderId)->value(self::PASSWORD_FIELD_NAME);
if (!Hash::check($inputtedPassword,$bcryptedPasswordFromDB)) {
return Redirect::route('loginToSitesInDevelopmentZonePage')->withErrors(['wrongPassword' => true]);
}
// get respective alias
$alias = DB::table(self::SITE_IN_DEVELOPMENT_TABLE_NAME)
->where(self::ORDER_ID_FIELD_NAME, $inputtedOrderId)->value(self::ALIAS_FIELD_NAME);
// here I need to provide acess of the customer to all pages above 'sites_in_development_zone/'.$alias
return redirect('sites_in_development_zone/'.$alias.'/index.html');
}
}
Thanks in advance for any help.

Limiting Taxonomy Terms in Dropdowns in Drupal content forms based on roles and user id

I am trying to find a way to limit Drupal Taxonomy Terms that appear on Content Add form based on their Role permissions but also on their user id. I have a taxonomy set called Departments (IT, Marketing, Accounting, etc).
On this specific content add form, there is a dropdown which asks you to assign the department that the content will belong to. I would like it to be the full dropdown list if the role is set as Admin however if the it is a regular user, I want it to instead be defaulted or locked to the department that they are assigned to in their user profile.
I looked around and have found multiple suggestions online such as setting up an entity reference field and using Taxonomy Access Control module but I can't seem to set it up correctly. Any suggestions?
Thanks!
I think the easiest way to achieve this would be a little code in a custom module.
First I would use hook_permisision to create a new permission called manually_set_department.
It is preferable to check for permissions not roles as roles can change and it is more flexible once a permission is set up as you can apply it to other roles if needed.
To do this use:
function MY_MODULE_permission() {
return array(
'manually_set_department' => array(
'title' => t('Manually set department'),
'description' => t('Allows users to manually set their department'),
),
);
}
Now we need to cut down the list of departments if the user does not have the above permission. To do this we can use hook_form_alter. In this example I'm assuming your content type is called page:
function MY_MODULE_form_alter(&$form, &$form_state, $form_id) {
drupal_set_message("Form ID is : " . $form_id);
switch($form_id) {
case 'page_node_form':
// dpm($form); // dpm (supplied by the devel module) is always useful for inspecting arrays
if(!user_access('manually_set_department')) { // check the permission we created earlier
global $user;
$account = user_load($user->uid); // load the users account
//dpm($account);
$deparment_tid = $account->field_department[LANGUAGE_NONE][0]['tid']; // get their department tid
foreach($form['field_department'][LANGUAGE_NONE]['#options'] as $k => $v) {
if($k != $deparment_tid) unset($form['field_department'][LANGUAGE_NONE]['#options'][$k]); // unset any but their own departments
}
}
break;
}
}

Admin login as another user with Symfony2 Security

I have a system, that has 2 roles (admins and users). Authentication made using Security Symfony2 component. Admin doesn't know user password. But he should be able to login into the system as user. I have a grid with all users and want to add buttons like "Login as this user". How can I make it?
I have tried, but no prfit:
$userRepo = $this->getDoctrine()->getRepository('FrameFoxBackEndBundle:User');
$this->get('security.context')->getToken()->setUser($userRepo->find(1));
Why not use built-in switch user option?
I use this code :
// use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken
$entity = $userRepo->find(1);
// Authentication
// create the authentication token
$token = new UsernamePasswordToken(
$entity,
null,
'user_db',
$entity->getRoles());
// give it to the security context
$this->container->get('security.context')->setToken($token);
I would use Symfony core support for that manner.
Have a look at:
http://symfony.com/doc/current/cookbook/security/impersonating_user.html.
You define a role which is allowed to switch user, and a parameter in the url that allows you to switch the user.

combining cakephp's auth with hybridauth (oauth)

I suppose I'm just looking for a bit of guidance as to how to set up my User + Authentication area on my website with cakephp 2.0.
I have a basic login and register functionality set up within my UserController.php, which also contains functions for looking up and displaying other users.
I also want to use the hybridauth plugin to allow for users to login/register using their social media / oauth account (allowing for more than one social account per user in the database, so that the same user could use either their twitter or facebook details, for example). I'm only having 3 providers at this time, so I plan to just create 6 columns in my user database, with the token and outhid in the same user row. This is in another controller - HybridauthController.php.
I have the hybridauth set up so that it creates its 'hybridauth' object from the account details, which is fine - but I want to be able to merge the whole 'authentication' together, so that my cakephp session contains the hybridauth session data (object) creating my general "current user" array that I can use, and set some generic variables within, depending on whether they are from oauth or not.
I don't currently store sessions in a database, and ideally I would like for allow persistent sessions for all, whether they use an oauth account or not. I don't really understand how persistent sessions are supposed to work with hybridauth, because how in this example would the $current_user_id be filled in when the user returns the next day? Not via a cookie, surely?
http://hybridauth.sourceforge.net/userguide/HybridAuth_Sessions.html
So in summary I'm looking for a simple solution to combine all of my 'session' / 'auth' / 'user' data into one simple array in the users session. Hopefully that all makes sense!
Thanks
Late to answer, but hopefully it'll help you or someone else searching.
I had a tough time integrating HybridAuth into a preexisting CakePHP (1.3) app that was already using Cake Sessions and the Auth component. I initially tried using the Cake example that I downloaded from the HybridAuth website, but that did not work for me.
Our preexisting User controller already had a bunch of logic in it including a beforeFilter method. That's where I inserted my session_start() as opposed to above the class declaration in the HybridAuth Cake example:
class UsersController extends AppController {
...
var $components = array('Session','Auth','Email');
...
public function beforeFilter(){
// following two lines may not be necessary for your setup
$this->Auth->allow('oauth', 'oauthLogout');
$excludeBeforeFilter = array('oauth', 'oauthLogout');
if ( ! in_array($this->action, $excludeBeforeFilter) ) {
// preexisting Auth logic -- I had to bypass it because
// calling `session_start` was messing up Cake's Auth
...
} else {
/* THIS IS NECCESSARY FOR HYBRIDAUTH (OAUTH) */
/* setting the session ID made it so users could NOT log
in from a 3rd party and our site */
session_id($_COOKIE['CAKEPHP']);
session_start();
}
}
...
public function oauth($provider){
$this->autoRender = false;
// include HybridAuth
require_once( WWW_ROOT . 'hybridauth/Hybrid/Auth.php' );
try {
// I stored my provider config in a Cake config file
// It's essentially a copy from the site/Cake example
$hybridAuth = new Hybrid_Auth(Configure::read('HAuth.config'));
$adapter = $hybridAuth->authenticate($provider);
$userProfile = $adapter->getUserProfile();
// method on the User model to find or create the 3rd party user
$user = $this->User->findOrCreate($userProfile, $provider);
if ( ! $user ) {
echo 'Unable to find/create user';
} else {
// configure your fields as necessary
$this->Auth->fields = array(...);
$this->Auth->login($user);
}
} catch (Exception $e) {
echo $e->getMessage();
}
}
}
At this point the 3rd party (HybridAuth) user is accessible in the Auth Component. This way a user was only logged in one 3rd party service or the preexisting login (but not both).
I also had an issue logging out. To do that I basically destroyed all sessions/cookies to be safe. In the oauthLogout method of the UsersController:
// probably overkill/paranoia
$this->Auth->logout();
$this->Session->destroy();
session_destroy($_COOKIE['CAKEPHP']);
/* these two seemed to make the difference
especially the 4th parameter */
setcookie( 'PHPSESSID', '', 1, '/' );
setcookie( 'CAKEPHP', '', 1, '/' );
Seems super hacky -- sorry for that. Hope it helps though!

Creating New Accounts Remotely with Drupal

I am building a paid subscription site using Drupal. After searching through the Drupal modules I have not been able to find anything that will allow me to create a new Drupal account once the user has visited my landing page, decided they want to subscribe, and provided their valid credit card information. I would like to redirect them to the subscription site with a newly created account once their credit card info has been validated.
Is anyone familiar with a module or a methodology for remotely creating a user account with Drupal? OpenID is a possibility but I would like to give the user a little more freedom in selecting their username.
Why not extend Drupal's registration form with some extra fields and validation functions?
You could have a hook, function, or build an xml-rpc interface to a function that created a new user account after the user has entered their details.
For example, on the form that they fill out, you could have in the _submit of the form:
formname_sumbit($form, &$form_state) {
// Do form stuff here
// Now do user_save stuff
$password = user_password();
$mail = $form_state['values']['email_address'];
// Use blank account object as we are creating a new account
$account = array();
$properties = array('name' => 'someusername', 'pass' => $password, 'mail' => $mail, $roles => array('authenticated user', 'some other role'));
$this_user = user_save($account, $properties);
}
That should take care of creating the user. I'm not sure about how to login them automatically, but a global $user; $user = $this_user; might work. The user should be notified of their new account via email by the user_save function, but you might want to let them know with a drupal_set_message as well.
http://api.drupal.org/api/function/user_save/6

Categories