How can is possible to attach different roles to users in the exact moment of registration? - laravel-8

before starting I premise and humbly apologize: I am a neophyte regarding the use of Laravel framework. I Searched eveywhere even the documentation but without results.
My question is if it is possible to assign a role at registration time using the Laratrust library. We want for example that the first 4/5 users who register are administrators, from the fifth onwards are normal users with restricted permissions.
This is the code regarding the Controller for registration.
RegisterController.php
/**
* Create a new user instance after a valid registration.
*
* #param array $data
* #return \App\Models\User
*/
protected function create(array $data)
{
$user = User::create([
'name' => $data['name'],
'email' => $data['email'],
'password' => Hash::make($data['password']),
]);
if(Auth::id() < 4 ){
$user->attachRole('administrator');
}
else{
$user->attachRole('user');
}
return $user;
}
This is the method that aims to register the user from the form, for some reason when I go to take the current id of the user, the condition in the if statement is bypassed, in fact in the database in the table roles i always have users that are administrators. I am thinking that maybe the real problem is Auth Class beacuse if i understood correctly this class is used when a user is already logged.

protected function create(array $data)
{
$user = User::create([
'name' => $data['name'],
'email' => $data['email'],
'password' => Hash::make($data['password']),
]);
$checklatestid = User::latest()->pluck('id')->first();
if($checklatestid < 4 ){
$user->attachRole('administrator');
//Ruolo amministratore impianto scii
}
else{
$user->attachRole('user');
//Ruolo cliente impianto scii
}
return $user;
}
If understand you correctly

Related

Laravel array of object update failing for unique email

I am using Laravel 6.I have an API that sends an array of staff, some are existing objects that need to be updated and some are new objects that need to be created. The creation part works but update fails due to "DUPLICATE ENTRY for UNIQUE EMAIL".I am using a function in controller
class AdminController extends Controller
{
public function userTransfer()
{
$caremanagementUserData = Admin::on('validated')->get();
$caremanagementUserData->each(function($userData)
{
if(User::where('email', '=', $userData['email'])->exists()) {
User::on('mysql')->where('id', '=',$userData['id'])->update([
'username' => $userData['username'],
'email' => $userData['email'],
'password' => $userData['password']
]);
} else {
User::on('mysql')->insert([
'username' => $userData['username'],
'email' => $userData['email'],
'password' => $userData['password']
]);
}
});
}
}
Help me about how to send email in the update array to solve the unique email error.
I found a way to get around the problem. Because email is unique and if email existence is being checked by
if(User::where('email', '=', $userData['email'])->exists())
{}
email update should be omitted from array of object, and if a new email is send it will be inserted as new data. It works for me !

AuthenticationService error in TYPO 3: "updateLoginTimestamp () must be of the type integer, null given"

I would like to implement a login at TYPO3 v8.7. Here it is so that the data comes from a foreign provider who should log in automatically with his login data of his system at TYPO3. I developed something for that.
What is wrong?
// Authentication Service
\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addService(
$_EXTKEY,
'auth',
'TEST\\Tests\\Service\\AuthenticationService',
array(
'title' => 'User authentication service',
'description' => 'Authentication with username',
'subtype' => 'getUserFE, authUserFE',
'available' => true,
'priority' => 90,
'quality' => 90,
'os' => '',
'exec' => '',
'className' => 'TEST\\Tests\\Service\\AuthenticationService',
)
);
This is in ext_localconf.php
class AuthenticationService extends \TYPO3\CMS\Sv\AuthenticationService
{
function init() {
$available = parent::init();
return $available;
}
public function getUser(){
$remoteUser = $this->getRemoteUser();
$user = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows(
'*',
'fe_users',
'username = '.$GLOBALS['TYPO3_DB']->fullQuoteStr($remoteUser, 'fe_users') . ' AND deleted = 0'
);
return $user;
}
public function authUser($user)
{
$userData = $user[0];
foreach ($user[0] as $item => $key) {
if (is_numeric($key)) {
$result_array[$item] = (int) $key;
} else {
$result_array[$item] = $key;
}
}
$this->login = $loginData = array(
'uname' => $userData["username"],
'uident_text' => $userData['password'],
'status' => 'login'
);
$ok = $this->compareUident($result_array, $loginData);
if($ok == 1) {
return 200;
}
return 100;
}
/**
* Returns the remote user.
*
* #return string
*/
protected function getRemoteUser()
{
[...]
return $user;
}
}
Is that all right, what am I doing?
In the function remoteUser I get the username of the third party provider.
Whenever I enter the GET parameter, the AuthService is triggered. However, I get the following error message:
"updateLoginTimestamp () must be of the type integer, null given"
Unfortunately I do not find the mistake I make. Hence my question if anyone sees where this is?
The getUser() Method should Return an Array of the User reccord
which is equal to a database row of fe_users
i am Guessing there is no existing fe_user for the username you get from getRemoteUser thus its the job of the Authentication service to create/update a record for this user in the table fe_users.
so in a more step by stepp manner your service should follow the following steps
in get user:
1. get Remote Username
2. check if Remote Username exists in fe_users table
3. if not create an new entry for Remote Username in fe_users
4. select the entry of Remote Username from fe_users and return the row.

Laravel 5.6 - creation user not working

my application used to working well with registration user but now it dont.
here a portion of my model User
protected $fillable = [
'prenom', 'nom', 'email','photo_path','password',
];
here my validation function :
protected function validator(array $data)
{
return Validator::make($data, [
'prenom' => 'required|string|max:255',
'nom' => 'required|string|max:255',
'email' => 'required|string|email|max:255|unique:users',
'photo_path' => 'required|image|mimes:jpeg,png,jpg,gif,svg|max:10000',
'password' => 'required|string|min:6|confirmed',
]);
}
here my create function :
protected function create(array $data)
{
dd($data);
$photoInput = request('photo_path');
$userPhotoPath='users';
$storagePhotoPath = Storage::disk('images')->put($userPhotoPath, $photoInput);
return User::create([
'prenom' => $data['prenom'],
'nom' => $data['nom'],
'email' => $data['email'],
'photo_path' => $storagePhotoPath,
'password' => Hash::make($data['password']),
]);
}
- POST request working ( return 302 ) but return back with input value
- Auth Route are declared in web.php
- Validation working well
but the php interpretor didnt get inside create function...
i just see in debugbar that information :
The given data was invalid./home/e7250/Laravel/ManageMyWorkLife/vendor/laravel/framework/src/Illuminate/Validation/Validator.php#306Illuminate\Validation\ValidationException
public function validate()
{
if ($this->fails()) {
throw new ValidationException($this);
}
$data = collect($this->getData())
but my validation working because i have error message near my InputTexte.
so i dont understand that error message ...
Do you have any clue ?
Well, you need to remove the dd(); function before you run something. Other wise it will end the execution of all other operations.
Check if your User Model has a constructor, if so remove it and check if the problem still accours. This fixed it for me.

How to retrieve associations together with authenticated user data?

I have a Users table and a UsersProfiles table - the two are obviously related and the user table stores basic user_id, username, password while the users_profiles table stores firstname, lastname, job_title etc.
In CakePHP 3, the call to Authentication Component on login returns the basic user table row. I would like to modify the same to also return the corresponding profile row. How can I do this?
I found a way to do it - but am not sure if there is a more elegant or simpler way.
public function login() {
if ($this->request->is('post')) {
$user = $this->Auth->identify();
if ($user) {
// load profile and associate with user object
$profile = $this->Users->UsersProfiles->get($user['id']);
$user['users_profile'] = $profile;
$this->Auth->setUser($user);
return $this->redirect($this->Auth->config('loginRedirect'));
}
$this->Flash->error(__('Invalid username or password, try again'));
}
}
The contain option
Before CakePHP 3.1, use the contain option
$this->loadComponent('Auth', [
'authenticate' => [
'Form' => [
'contain' => ['UsersProfiles']
]
]
]);
A custom finder
As of 3.1 you can use the finder option to define the finder to use for building the query that fetches the user data
$this->loadComponent('Auth', [
'authenticate' => [
'Form' => [
'finder' => 'auth'
]
]
]);
In your table class
public function findAuth(\Cake\ORM\Query $query, array $options)
{
return $query->contain(['UsersProfiles']);
}
Both solutions
will ensure that the data returned by AuthComponent::identify() will contain the associated UsersProfiles.
See also
Cookbook > ... Components > Authentication > Configuring Authentication Handlers
Cookbook > ... Components > Authentication > Customizing find query

ZF2 / doctrine ORM authentication different Entity

in my application (ZF2 / ORM) i have 3 Entities (with Single Table inheritance)
User
Owner extends User
Agent extends User
i want to make one single Authentication (Login) for the 3 Entity using
doctrine.authenticationservice.orm_default
module.config.php
//other doctrine config
'authentication' => array(
'orm_default' => array(
'object_manager' => 'Doctrine\ORM\EntityManager',
'identity_class' => 'Application\Entity\User',
'identity_property' => 'email',
'credential_property' => 'password',
'credential_callable' => function(User $user, $passwordGiven) {
return $user->getPassword() == md5($passwordGiven);
},
),
),
and the process of login
//LoginController.php
// ..data validation
$this->authService = $this->getServiceLocator()->get('doctrine.authenticationservice.orm_default');
$AuthAdapter = $this->authService->getAdapter();
$AuthAdapter->setIdentity($this->request->getPost('email'));
$AuthAdapter->setCredential(md5($this->request->getPost('password')));
$result = $this->authService->authenticate();
if($result->isValid()){
$identity = $result->getIdentity();
//continue
}
how can i do this process without caring about object type,
when i try to login with email of an Agent, i get this error
Catchable fatal error: Argument 1 passed to Application\Module::{closure}() must be an instance of User, instance of Application\Entity\Owner given
The error you mention is due to the type hint on:
function(User $user) {
Which leads me to believe that you have a missing namespace declaration in your config file; in which case you can either add it or use the FQCN.
function(\Application\Entity\User $user) {
Nevertheless, I don't think it's actually the problem. You can only define one 'identity_class' with doctrine authentication (which the adapter will use to load the entity from the entity manager). If you have multiple entity classes there is no way to have each of these tested with one adapter.
However, the configuration is really just creating a new authentication adapter, specifically DoctrineModule\Authentication\Adapter\ObjectRepository. One solution would be to create multiple ObjectRepository adapters, each with the correct configuration for the different entities and then loop through each of them while calling authenticate() on the Zend\Authentication\AuthenticationService.
For example :
public function methodUsedToAutheticate($username, $password)
{
// Assume we have an array of configured adapters in an array
foreach($adapters as $adapter) {
$adapter->setIdentity($username);
$adapter->setCredential($password);
// Authenticate using the new adapter
$result = $authService->authenticate($adapter);
if ($result->isValid()) {
// auth success
break;
}
}
return $result; // auth failed
}
As previously mentioned is the doctrine config will not allow for more than one adapter, so you would need to create them manually and remove your current configuration.
Another example
public function getServiceConfig()
{
return [
'factories' => [
'MyServiceThatDoesTheAuthetication' => function($sm) {
$service = new MyServiceThatDoesTheAuthetication();
// Assume some kind of api to add multiple adapters
$service->addAuthAdapter($sm->get('AuthAdapterUser'));
$service->addAuthAdapter($sm->get('AuthAdapterOwner'));
$service->addAuthAdapter($sm->get('AuthAdapterAgent'));
return $service;
},
'AuthAdapterAgent' => function($sm) {
return new DoctrineModule\Authentication\Adapter\ObjectRepository(array(
'object_manager' => $sm->get('ObjectManager'),
'identity_class' => 'Application\Entity\Agent',
'identity_property' => 'email',
'credential_property' => 'password'
));
},
'AuthAdapterOwner' => function($sm) {
return new DoctrineModule\Authentication\Adapter\ObjectRepository(array(
'object_manager' => $sm->get('ObjectManager'),
'identity_class' => 'Application\Entity\Owner',
'identity_property' => 'email',
'credential_property' => 'password'
));
},
// etc...
],
];
}
Hopefully this gives you some ideas as to what is required.
Lastly, if you would consider other modules, ZfcUser already has a 'chainable adapter' which actually does the above (but uses the event manager) so It might be worth taking a look at even if you don't use it.