I made a plugin to allow wordpress login with external api.
Everything works, now what I have to do is that when a user logs in for the first time, the plugin checks to see if it is already present on wp, and where it was not already present, it creates a new user by taking behind username, email and password.
The new user is created but I would like it to bring with it also the id field from the external api saving it in an ACF field.
This is the code created so far:
function au_auth($user, $username, $password)
{
$options = get_option('au_options');
$endpoint = $options['au_apiurl'];
$user_email_key = 'email';
$password_key = 'password';
// Makes sure there is an endpoint set as well as username and password
if (!$endpoint || $user !== null || (empty($username) && empty($password))) {
return false;
}
// Check user exists locally
$user_exists = wp_authenticate_username_password(null, $username, $password);
if ($user_exists && $user_exists instanceof WP_User) {
$user = new WP_User($user_exists);
return $user;
}
// Build the POST request
$login_data = array(
$user_email_key => $username,
$password_key => $password
);
$auth_args = array(
'method' => 'POST',
'headers' => array(
'Content-type: application/x-www-form-urlencoded'
),
'sslverify' => false,
'body' => $login_data
);
$response = wp_remote_post($endpoint, $auth_args);
// Token if success; Not used right now
$response_token = json_decode($response['response']['token'], true);
$response_code = $response['response']['code'];
if ($response_code == 400) {
// User does not exist, send back an error message
$user = new WP_Error('denied', __("<strong>Error</strong>: Your username or password are incorrect."));
} else if ($response_code == 200) {
// External user exists, try to load the user info from the WordPress user table
$userobj = new WP_User();
// Does not return a WP_User object but a raw user object
$user = $userobj->get_data_by('email', $username);
if ($user && $user->ID) {
// Attempt to load the user with that ID
$user = new WP_User($user->ID);
}
} else {
// The user does not currently exist in the WordPress user table.
// Setup the minimum required user information
$userdata = array(
'user_email' => $username,
'user_login' => $username,
'user_pass' => $password
);
// A new user has been created
$new_user_id = wp_insert_user($userdata);
// Assign editor role to the new user (so he can access protected articles)
wp_update_user(
array(
'ID' => $new_user_id,
'role' => 'editor'
)
);
// Load the new user info
$user = new WP_User ($new_user_id);
}
}
// Useful for times when the external service is offline
remove_action('authenticate', 'wp_authenticate_username_password', 20);
return $user;
}
Anyone have any way how to help me?
Resolved! I hope this will help those who have found themselves in the same situation as me:
add_filter('authenticate', 'au_auth', 10, 3);
add_filter('register_new_user', 'au_registration', 10, 3);
// add_filter('profile_update', 'au_profile_update', 10, 3);
// add_filter('edit_user_profile_update', 'au_profile_edit', 10, 3);
function au_auth($user, $username, $password)
{
$options = get_option('au_options');
$endpoint = $options['au_apiurl'];
// Makes sure there is an endpoint set as well as username and password
if (!$endpoint || $user !== null || (empty($username) && empty($password))) {
return false;
}
$auth_args = [
'method' => 'POST',
'headers' => [
'Content-type: application/x-www-form-urlencoded',
],
'sslverify' => false,
'body' => [
'email' => $username,
'password' => $password,
],
];
$response = wp_remote_post($endpoint, $auth_args);
// Token if success; Not used right now
$response_token = json_decode($response['response']['token'], true);
$body = json_decode($response['body'], true);
$response_status_code = $response['response']['code'];
$success = $body !== 'KO';
if (!$success) {
// User does not exist, send back an error message
$user = new WP_Error('denied', __('<strong>Error</strong>: Your username
or password are incorrect.'));
} elseif ($success) {
$idExternal = $body['Id'];
$nome = $body['Name'];
$cognome = $body['Surname'];
$email = $body['Email'];
$userobj = new WP_User();
$user = $userobj->get_data_by('email', $email);
if ($user && $user->ID) {
$user = new WP_User($user->ID);
} else {
$userdata = [
'user_email' => $email,
'user_login' => join(' ', [$name, $surname]),
'user_pass' => '----',
];
$new_user_id = wp_insert_user($userdata);
$new_user_composite_id = 'user_' . $new_user_id;
update_field('field_60084ad3970a8', $idExternal, $new_user_composite_id);
update_field('field_5f22ca201c7b0', $name, $new_user_composite_id);
update_field('field_5f22ccd498f40', $surname, $new_user_composite_id);
update_field('field_5f22ce7b7c1db', $email, $new_user_composite_id);
$user = new WP_User($new_user_id);
}
}
remove_action('authenticate', 'wp_authenticate_username_password', 20);
return $user;
}
Related
i try to make API authentication with my WP app
i have write the add the below code to add new fields and upon login it send data to External API if it user exist in API return login or create new WP user if not just don't do anything or gives an error, but i have the issue with Cookie now and get the "Error: Cookies are blocked due to unexpected output."
here is my code:
add_action('login_form', 'businessId', 10, 1);
function businessId()
{
?>
<div class="businessid_wrap">
<label for="businessId">business ID</label>
<input type="text" id="businessId" name="businessId" value=""/>
</div>
<?php
}
function au_auth($user, $username, $password)
{
$endpoint = 'will be my API endpoint url';
// Makes sure there is an endpoint set as well as username and password
if (!$endpoint || $user !== null || (empty($username) && empty($password))) {
return false;
}
$auth_args = [
'method' => 'POST',
'headers' => [
'Content-type: application/json',
],
'sslverify' => false,
'body' => [
'businessId' => $_POST['businessId'],
'userLogin' => $username,
'userPassword' => $password,
],
];
$response = wp_remote_post($endpoint, $auth_args);
$body = json_decode($response['body'], true);
var_dump ($response);
if (!$response) {
// User does not exist, send back an error message
$user = new WP_Error('denied', __('<strong>Error</strong>: Your username or password are incorrect.'));
} elseif ($response) {
/for now i just dumping the return data to check
var_dump ($response);
}
remove_action('authenticate', 'wp_authenticate_username_password', 20);
return $user;
}
add_filter('authenticate', 'au_auth', 10, 3);
Could someone tell me what i am missing to send an HTML email using Drupal's function? Here is my call:
try{
drupal_mail('my_module', 'forgot', $node->field_email_address['und'][0]['value'], language_default(), array('reset_key' => $key),'do-not-reply#myemailaddress.com');
}catch(Exception $e){
print_r($e->getMessage());die();
}
And here is the function:
function my_module_mail($key, &$message, $params) {
$body = '<p>Click the link below to reset your password.</p>
<p>Click this link to reset your password</p>
';
// $headers = array(
// 'MIME-Version' => '1.0',
// 'Content-Type' => 'text/html; charset=UTF-8; format=flowed',
// 'Content-Transfer-Encoding' => '8Bit',
// 'X-Mailer' => 'Drupal'
// );
// $message['headers'] = $headers;
$message['subject'] = 'Why wont this send html??';
$message['headers']['Content-Type'] = 'text/html; charset=UTF-8;';
$message['body'][] = $body;
$message['from'] = 'do-not-reply#myemailaddress.com';
}
I tired just the html header and the full set that is commented out. What am I missing? The email sends fine but it's plain text. Thanks and let me know!
You can use this function
function my_module_custom_drupal_mail($target = NULL, $from = null, $subject, $message, $attachment = NULL){
$my_module = 'my_module';
$my_mail_token = microtime();
$message = array(
'id' => $my_module . '_' . $my_mail_token,
'to' => $target,
'subject' => $subject,
'body' => array($message),
'module' => $my_module,
'key' => $my_mail_token,
'from' => "$from <email#email.com>",
'headers' => array(
'From' => "$from <email#email.com>",
'Sender' => "$from <email#email.com>",
'Return-Path' => "$from <email#email.com>",
'Content-Type' => 'text/html; charset=utf-8'
),
);
if ($attachment) {
$file_content = file_get_contents($attachment[0]);
$message['params']['attachments'][] = array(
'filecontent' => $file_content,
'filename' => $attachment[1],
'filemime' => $attachment[2],
);
}
$system = drupal_mail_system($my_module, $my_mail_token);
$message = $system->format($message);
if ($system->mail($message)) {
return TRUE;
}
else {
return FALSE;
}
}
AND call it like :
$body = '<p>Click the link below to reset your password.</p>
<p>Click this link to reset your password</p>
';
$subject ='Why wont this send html??';
$from = 'myemail#email.com';
$sent = my_module_custom_drupal_mail($node->field_email_address['und'][0]['value'], $from, $subject, $body);
Customize it like you want ! :)
A few things need to be done:
/**
* Class SomeCustomModuleMailSystem Implements MailSystemInterface.
*
* Used to enable HTML email to be sent.
*/
class SomeCustomModuleMailSystem extends DefaultMailSystem {
public function format(array $message) {
$message['body'] = implode("\n\n", $message['body']);
$message['body'] = drupal_wrap_mail($message['body']);
return $message;
}
}
This to be done one time, so probably in a hook_enable or hook_update:
$current = variable_get('mail_system', ['default-system' => 'DefaultMailSystem']);
$addition = ['some_custom_module' => 'SomeCustomModuleMailSystem'];
variable_set('mail_system', array_merge($current, $addition));
Invoke hook_mail as normal, e.g.
/**
* Implements hook_mail().
*/
function some_custom_module_mail($key, &$message, $params) {
switch ($key) {
case 'some_mail_key':
$message['headers']['Content-Type'] = 'text/html; charset=UTF-8;';
$message['subject'] = $params['subject'];
$message['body'][] = $params['body'];
break;
}
}
Finally call it with something like this:
// Set variables required for the email.
$module = 'some_custom_module';
$key = 'some_mail_key';
$to = $email = 'thetoaddress#something.com';
$language = language_default();
$params['subject'] = 'Email subject';
$params['body'] = '<html><body>The HTML!</body></html>';
$from = 'thefromaddress#something.com';
$send = TRUE;
// Send the mail and log the result.
$result = drupal_mail($module, $key, $to, $language, $params, $from, $send);
if ($result['result'] === TRUE) {
watchdog('some_custom_module', 'HTML email successfully sent.', [], WATCHDOG_INFO);
}
else {
watchdog('some_custom_module', 'HTML email failed to send', [], WATCHDOG_ERROR);
}
Here is the funcion im using
public function sendCredentialsEmailMessage(UserInterface $user)
{
$template = 'Emails/afterRegister.html.twig';
$rendered = $this->templating->render($template, array(
'user' => $user,
));
$this->sendEmailMessage($rendered,
$this->parameters['from_email']['confirmation'], $user->getEmail());
}
Basically I want the auto-mailer to send my template along with the login name. When i create a new user nothing is being sent. My email template is located in app>resources>views>emails>
and this controller file is located in src>myname>userbundle>mailer>
protected function sendEmailMessage($renderedTemplate, $fromEmail, $toEmail)
{
// Render the email, use the first line as the subject, and the rest as the body
$renderedLines = explode("\n", trim($renderedTemplate));
$subject = array_shift($renderedLines);
$body = implode("\n", $renderedLines);
$message = (new \Swift_Message())
->setSubject($subject)
->setFrom($fromEmail)
->setTo($toEmail)
->setBody($body);
$this->mailer->send($message);
}
Also this works for sure:
public function sendResettingEmailMessage(UserInterface $user)
{
$template = $this->parameters['resetting.template'];
$url = $this->router->generate('fos_user_resetting_reset', array('token' => $user->getConfirmationToken()),
UrlGeneratorInterface::ABSOLUTE_URL);
$rendered = $this->templating->render($template, array(
'user' => $user,
'confirmationUrl' => $url,
));
$this->sendEmailMessageCustom($rendered, $this->from, (string)$user->getEmail(),'Password resseting');
}
I would like register_rest_field to return a certain field for a user only when a specific user is being requested (i.e. the request is /user/$user_id) -- not when /users or other endpoints are used.
One way I can think of to sort of do this would be to check the API request URL in the register_rest_field function and conditionally change the return value depending on the endpoint, but I don't know how to access that URL.
What would be the best way to do this?
You can use $request->get_url_params(); to check if request has $user_id or not.
Ref:
https://developer.wordpress.org/rest-api/extending-the-rest-api/adding-custom-endpoints/#arguments
<?php
add_filter( 'rest_prepare_user', 'mo_user_json', 10, 3);
function mo_user_json( $data, $user, $request ) {
$response_data = $data->get_data();
// for remove fields
unset($response_data['avatar_urls']);
unset($response_data['url']);
unset($response_data['description']);
// array user meta
$usermetas = [];
$metas = [
'field1',
'field2',
'field3',
'field4',
'field5',
'field6',
];
foreach ($metas as $meta) {
if(!empty(get_user_meta( $user->ID, $meta))){
$info = get_user_meta( $user->ID, $meta);
$usermetas[$meta] = $info[0];
}
}
// format json
$nodes = [
'field1' => $usermetas['field1']
'field2' => $usermetas['field2']
'field3' => $usermetas['field3'],
'field4' => [
'field4' => $usermetas['field4']
'field5' => $usermetas['field5']
'field6' => $usermetas['field6']
]
];
foreach ($nodes as $key => $node) {
$response_data['meta'][$key] = $node;
}
// add fields formated in json
$data->set_data( $response_data );
return $data;
}
I am new in testing.I want to test my function.I have successfully installed phpUnit. I check many tutorials on internet.But I could not get the proper information regarding testing. Here is the my function code:
public function loginAction(Request $request)
{
$session = $this->getRequest()->getSession();
if( $session->get('userId') && $session->get('userId') != '' && $session->get('type') == '2')
{
//if user is login then it will be redirect to login page
return $this->redirect($this->generateUrl('registrarGeneral_dashboard'));
}
$em = $this->getDoctrine()->getEntityManager();
$repository = $em->getRepository('DRPAdminBundle:User');
if ($request->getMethod() == 'POST')
{
$session->clear();
$userName = $request->get('username');
$password = md5($request->get('password'));
//find email, password type and status of User
$user = $repository->findOneBy(array('username' => $userName, 'password' => $password,'type'=>2,'status'=>1 ));
$userEmail = $repository->findOneBy(array('email' => $userName, 'password' => $password,'type'=>2,'status'=>1 ));
if ($user)
{
//set session of User login
$session->set('userId', $user->getId());
$session->set('type', 2);
$session->set('nameRegistrar', $user->getFirstName());
$session->set('pictureRegistrar', $user->getPicture());
//echo "<pre>";print_r($session->get('picture'));die;
return $this->redirect($this->generateUrl('registrarGeneral_dashboard'));
}
if ($userEmail)
{
$session->set('type', 2);
$session->set('userId', $userEmail->getId());
$session->set('nameRegistrar', $userEmail->getFirstName());
$session->set('pictureRegistrar', $userEmail->getPicture());
//echo "<pre>";print_r($session->get('picture'));die;
return $this->redirect($this->generateUrl('registrarGeneral_dashboard'));
}
else
{
return $this->render('DRPRegistrarGeneralBundle:Pages:login.html.twig', array('name' => 'Invalid Email/Password'));
}
}
return $this->render('DRPRegistrarGeneralBundle:Pages:login.html.twig');
}
how to test this function? Please help
I don't know what you want to test but here is an exemple of what you can do to test user fonctionnalities :
public function testUserPageDown()
{
$client = static::createClient();
$client->request('GET', '/user/login');
$this->assertTrue($client->getResponse()->isSuccessful());
$client->request('GET', '/user/register');
$this->assertTrue($client->getResponse()->isSuccessful());
}
public function testUserFirewall()
{
$client = static::createClient();
//Trying go to user routes without being logged
$client->request('GET', '/user/profile');
$this->assertTrue($client->getResponse()->isRedirect());
$client->request('GET', '/user/profile/edit');
$this->assertTrue($client->getResponse()->isRedirect());
$client->request('GET', '/user/profile/editpassword');
$this->assertTrue($client->getResponse()->isRedirect());
}
public function testUserFormRegister()
{
$client = static::createClient();
$crawler = $client->request('GET', '/user/register');
$buttonCrawlerNode = $crawler->selectButton('submit_user_register');
$form = $buttonCrawlerNode->form();
$testForm = array(
'wineot_databundle_user[username]' => 'test',
'wineot_databundle_user[firstname]' => 'test',
'wineot_databundle_user[lastname]' => 'test',
'wineot_databundle_user[mail]' => 'test#mail.fr',
'wineot_databundle_user[plain_password][first]' => 'blabla321',
'wineot_databundle_user[plain_password][second]' => 'blabla321'
);
$response = $client->getResponse();
$client->submit($form, $testForm);
//If the submit is true that mean that the register is ok
$this->assertTrue($response->isSuccessful());
}
I hope that will help you do undestand how to test.