I've been struggling with creating a simple form that will later store data in the database, using Yii framework and none of the tutorials I have been following have been explanatory enough. The idea is that I am editing an existing Yii project and I need to add user registration functionality to the following project. So Gii is out of the option.
To my understanding I have created:
User controller (controllers/UserController.php)
User model (models/User.php)
Register view (/views/register.php)
What is the general idea that I should follow in order to create a form in the view, and add data from that form on the database?
On the controller so far I have:
class UserController extends LSYii_Controller {
public function actionIndex() { }}
The model:
public static function insertUser($new_user, $new_pass,$new_full_name,$parent_user,$new_email)
{
$oUser = new self;
$oUser->users_name = $new_user;
$oUser->password = hash('sha256', $new_pass);
$oUser->full_name = $new_full_name;
$oUser->parent_id = $parent_user;
$oUser->lang = 'auto';
$oUser->email = $new_email;
if ($oUser->save())
{
return $oUser->uid;
}
else{
return false;
}
}
and on the view I have nothing since I am not sure on how to proceed.
Any help will be greatly appreciated.
One of the nice things about Yii is it's plugin architecture. There is a user registration and management module that will do all of this for you. It's free and available from:
http://yii-user.2mx.org/
Features:
Login from User Name or Email
Registration
Activation accounts (verification email)
Recovery password (send recovery key to user email)
User profile page
Manage Users
Manage Profile Fields
Profile field widget for view, edit and save data (FieldWidget)
Date widget (jQueryUI datepicker)
File upload widget
Profile Relation Widget
API
You can edit the User class to add other fields or store those additional fields in another table if you didn't want to mess with the yii-user code/configuration.
Related
I have two entities, the first is called Registration and is intended to store the user data while a confirmation email is used to activate the account. The second one is called Account and is the actual entity storing the user data that was previously in Registration.
I want this second entity to be created/persisted in the DB only after the user confirms its registration, at that stage the Registration entity will turn its flag isActive to true and will transfer the required data to the be persisted Account.
How to do that using the API platform?
Well, I found a way, although I don't know if it is the best approach: using a custom state processor.
Say we have two entities: Registration and Account. Registration will store the attempt to create an account while Account will store relevant data about the account once it is created. The are not related in any 'declared' way but the second depends on the first.
The logic is here: "How to use a custom state processor to create an entity when another is updating"
#[ApiResource]
#[Patch(
//...
processor: ActivateAccount::class
)]
class Registration
{
//...
}
and here is the ActivateAccount class:
class ActivateAccount implements ProcessorInterface
{
private ProcessorInterface $decorated;
private EntityManagerInterface $manager;
public function __construct(
ProcessorInterface $decorated,
EntityManagerInterface $manager
) {
$this->decorated = $decorated;
$this->manager = $manager;
}
public function process(
mixed $data,
Operation $operation,
array $uriVariables = [],
array $context = []
) {
if (!$data->isIsActive()) // we only want to create a new account if current registration is inactive
{
$account = new Account();
$account->setEmail($data->getEmail()); // get the email from the registration data
$account->setPassword($data->getPassword()); // get password from registration data, already hashed
$this->manager->persist($account); // save the account to DB
$this->manager->flush();
$data->setIsActive(true); // update the registration to prevent the attempt to create another caacount with this data
}
$this->decorated->process(
$data,
$operation,
$uriVariables,
$context
); // finally process the registration, this really means save the updated entity
}
}
This custom processor needs to be wired in services configuration:
services:
App\State\ActivateAccount:
bind:
$decorated: '#api_platform.doctrine.orm.state.persist_processor'
And the job is done!
Previously in asp.net webforms I was used to save current user id, their department id, branch id (in case of multiple branches of organisation), branch name etc in cookies and was using this information to avoid extra server calls while saving, updating, retrieving or deleting record and also for tracking that who deleted, updated or created a specific record. But now in asp.net core 2.0, 3.0+ I wander how to handle this thing. I am thinking to handle this by creating claim and saving this information in claims and then using it for good. Am I doing it wisely or Is there any other effective/efficient way of doing this whole practice ? Can I use JWT for this purpose or not ?
You can create a class (e.g.,) MyUserClaimsFactory that inherits from UserClaimsPrincipalFactory<User, Role> where User and Role are you custom classes that derive from IdentityUser and IdentityRole.
In that class, override the CreateAsync method
public async override Task<ClaimsPrincipal> CreateAsync(User user)
{
var principal = await base.CreateAsync(user);
// Add all the claims you need here.
((ClaimsIdentity)principal.Identity).AddClaims(new[] { new Claim(ClaimTypes.GivenName, user.Name) });
return principal;
}
Instead of ClaimTypes you can also use a string as key.
Add the class via dependency injection:
services.AddScoped<IUserClaimsPrincipalFactory<User>, MyUserClaimsFactory>();
You can retrieve the claims in a Controller via this.User.Identity
var givenName = (this.User.Identity as ClaimsIdentity).FirstOrNull(ClaimTypes.GivenName);
In Sylius (Symfony3 bundle), I have customized the register form to add some fields, in particular 'type of account' (pro or private). According to the type, some functionalities will not be enabled. In order to do that, I was thinking about giving users different roles.
As the authentication is made by Sylius, I was wondering how to override the default behavior to set the role according to the type data ?
Thanks for your help !
Sylius has no built-in roles or rbac system - whole security configuration is done with standard Symfony security system. So if you need to differentiate functionalities based on User role, just base on $roles parameter from User model, and override Sylius security configuration with your custom firewalls, as it's said in Symfony tutorial. Hope it will help ;)
What I have done :
In Sylius, there is an event sylius.customer.post_register fired after registration. I have created a listener (defined in services.yml) :
app.registration_listener:
class: AppBundle\EventListener\RegistrationListener
tags:
- { name: kernel.event_listener, event: sylius.customer.post_register, method: setUserRole }
arguments:
- "#sylius.manager.shop_user"
The ShopUserManager is passed as an argument to the setUserRole method.
public function __construct(ObjectManager $userManager) {
$this->userManager = $userManager;
}
In the listener, I get the $user object as the 'subject' of the event :
public function setUserRole(GenericEvent $event)
{
$customer = $event->getSubject();
$user = $customer->getUser();
....
$this->userManager->persist($user);
$this->userManager->flush();
}
Then I can modify the $user (add my role) and save it with the ShopUserManager.
I'm new to Cuba Platform and I'm trying to add functionality to copy a record in a table. Essentially the same functionality as found in the Administration -> Users -> Copy User screen.
The button action for this is usersTable.copy
Adding a similar action for example booksTable.copy doesn't seem to work natively. What method do I need to add or anything else to get this to work?
I've gone through the documentation and there's only an example using usersTable.
Many thanks in advance
The users copy action is not something that is generally available (like the create action). But you can look at the implementation from the copy action of the users browser.
Basically it just copies the data from the old user (roles, security group etc.) and prefills the data and then just opens the normal editor of the user like this:
public void copy() {
// fetches the selected user
Set<User> selected = usersTable.getSelected();
User selectedUser = selected.iterator().next();
selectedUser = dataSupplier.reload(selectedUser, "user.edit");
// creates a new user
User newUser = metadata.create(User.class);
// copies the roles and other stuff
if (selectedUser.getUserRoles() != null) {
List<UserRole> userRoles = new ArrayList<>();
for (UserRole oldUserRole : selectedUser.getUserRoles()) {
//...
userRoles.add(role);
}
newUser.setUserRoles(userRoles);
}
newUser.setGroup(selectedUser.getGroup());
// opens the editor with the pre filled data from the other user
AbstractEditor editor = openEditor("sec$User.edit", newUser //...
}
My solution with Cuba-Platform Tools:
public void copy() {
Books selected = booksDs.getItem();
CommitContext context = new CommitContext();
Books copy = metadata.getTools().deepCopy(selected);
copy.setId(uuidSource.createUuid());
copy.setBookName("(COPY) " + booksDs.getItem().getBookName());
context.addInstanceToCommit(copy);
dataManager.commit(copy);
booksDs.refresh();
}
I have a login button in the header of the website. This header's html is programmed into Zend framework views/layouts/home.phtml.
I have a hidden form in this layout that is triggered by jQuery thickbox inline content display integration. Reason, I dont want to make a ajax call to just fetch a small login form.
I create the form using Zend_Form and the problem is that I have to do it in all the controllers after checking if the user is logged in or not. I want to place this form generation in one single place, say in bootstrap and then have a logic in bootstrap to say that if user is logged in dont generate the form.
I don't know if bootstrap is the right place to do so or should I do it in some other place.
So, where should I instantiate the form so that its available everywhere if user is not logged in.
Create your own base controller which extends Zend_Controller_Action then have your controllers extend off of your base controller. I don't know what "jQuery thickbox inline content display integration" is...but you have several sections you can put it in depending when you need your code to run. init(), preDispatch(), postDispatch() etc... Just make sure when you extend off your base controller that you do sthing like:
parent::init()
parent::preDispatch()
parent::postDispatch()
etc... within each section so that the base code runs as well...
Be careful about Pradeep Sharma's solution (the answer he wrote himself and accepted below).
All the code code below is for ZF 1.12, and not ZF 2.0
In the bootstrap, Zend_Layout's MVC instance might not have been created yet. You should use Zend_Layout::startMvc() instead :
$view = Zend_Layout::startMvc()->getView() ;
And tbh I prefer executing this code in the preDispatch() function. New users of ZF might be interested in this :
application/plugins/HeaderForm.php :
class Application_Plugin_HeaderForm extends Zend_Controller_Plugin_Abstract
{
public function preDispatch(Zend_Controller_Request_Abstract $request)
{
$view = Zend_Layout::startMvc()->getView() ;
$view->headerForm = new Application_Form_HeaderForm() ;
}
}
Calling new Application_Form_HeaderForm() will autoload by default into application/forms/ folder. You can also create the form directly into the plugin with new Zend_Form(), and addElement() etc. but it won't be reusable.
Of course, you need to register this plugin in your bootstrap!
application/Bootstrap.php :
class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
{
protected function _initPlugin()
{
$front = Zend_Controller_Front::getInstance() ;
$front->registerPlugin(new Application_Plugin_HeaderForm()) ;
}
}
Calling new Application_Plugin_HeaderForm() will autoload by default into application/plugins/ folder
I did it in a different way, extendingZend_Controller_Plugin_Abstract to implement a plugin and register it with front controller.
public function routeStartup(Zend_Controller_Request_Abstract $request) { }
generated the form inside the above mentioned method and by setting the form in $view object.
$view can be retrived using :
$view = Zend_Layout :: getMvcInstance()->getView();