Extend user of Cuba platform with new attribute "Manager"

I would like to extend sec$User with a new attribute so that each user of our system can have a manager assigned to him (not mandatory, not all users have a manager).

I want to do this because we have a “Training” object and I want an “Employee” who is logged in and in UserSession to be able to press a button to send a Training request mail to his manager. However, right now I can’t get to that info because all I have been able to reach is the User object related to the current UserSession but this doesn’t provide me access to the Manager object associated with that Employee so if I could add my manager object as an attribute of Cuba project’s User object that would resolve my problem. How do I do this?

Thanks in advance!

Hi @nsrwissam,

The problem you are trying to solve is very close to what this sample project shows. There is no need to extend the system user in this case. However, if you still would like to take the way of creating an ext user, please, have a look at this sample.

Regards,
Aleksey

Hi Aleksey,

I took a look at your sample project, thanks a lot by the way! Although the link that seemed most interesting to me doesn’t seem to work on this project page:

Functional Overview
The application retrieves information about the related business user for a logged-in user and adds it into the session attribures, so it can be taken from it at any time. Find the implementation of this part here.

the link refered to by “here” returns a 404 could not be found on github.

If this is fixed that would be great as that is exactly what I need !

Ha! You are right! In fact, I was updating the implementation in accordance with the new features of the platform. Now it all should work!

Hi,

I appreciate the help a lot but got stuck a little.

I used your code as a reference and created a similar file and placed it in the same location but I have no idea if it is loaded into the project and how to retrieve the attribute.

I would like to use the “Manager”'s email attribute to send an email using a button in an edit screen. This “Manager” is an attribute in Employee because each Employee in my system has a shared or unique superior. “Employee” is a user so it has a user association. Now how do I reach the email attribute of the “Manager” object associated with a logged in Employee using UserSession? because using UserSession only delivers me a User object atm. but no Employee object related to the current logged in user

private void sendByEmail(String requestmail) {
        User currentUser= AppBeans.get(UserSessionSource.class).getUserSession().getUser();
        
        String userMgrMail = AppBeans.get(UserSessionSource.class).getUserSession().getAttribute("manager");
        
        String trainingDesc = trainingDs.getItem().getDescription();
        UUID trainingID = trainingDs.getItem().getId();

        EmailInfo emailInfo = new EmailInfo(

                requestmail, // recipients
                "Training Request: "+ trainingDesc, // subject
                null, // the "from" address will be taken from the "cuba.email.fromAddress" app property

                "Training request for: \n"+"Full name: " + currentUser.getName()
                        +"\nuser ID: "+ currentUser.getLogin() + "\n Training :" + trainingDesc + "\n Training UUID:" + trainingID// body template


        );
        emailService.sendEmailAsync(emailInfo);
    }

sorry if this isn’t that clear. I can elaborate if needed.

Can you please share the event handler where you add your attribute to the user session?

package com.company.hrtrainingplatform.core;

import com.company.hrtrainingplatform.entity.Employee;
import com.haulmont.cuba.core.global.DataManager;
import com.haulmont.cuba.core.global.LoadContext;
import com.haulmont.cuba.security.app.Authentication;
import com.haulmont.cuba.security.auth.events.UserLoggedInEvent;
import com.haulmont.cuba.security.entity.User;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;

import javax.inject.Inject;

/**
 * Created by Aleksey Stukalov on 17/12/2017.
 */

@Component
public class AfterUserLoginEventListener implements ApplicationListener<UserLoggedInEvent> {

    @Inject
    private DataManager dataManager;

    @Inject
    private Authentication auth;

    @Override
    public void onApplicationEvent(UserLoggedInEvent event) {
        if (event.getUserSession() != null && !event.getUserSession().isSystem()) {
            auth.withSystemUser(() -> {
                User user = event.getUserSession().getUser();
                LoadContext<Employee> loadContext = LoadContext.create(Employee.class)
                        .setQuery(
                                LoadContext.createQuery("select e from hrtrainingplatform$Employee e where e.user.id = :user")
                                        .setParameter("user", user)
                        )
                        .setView("employee-view");


                Employee employee = dataManager.load(loadContext);

                if (employee != null)
                    event.getUserSession().setAttribute("employee", employee);
                return null;
            });
        }
    }
}

how can I use the getAttribute method to retrieve the email attribute from the user object inside the manager object inside the employee object associated to the UserSession User object is actually in short what I am trying to figure out.

Thanks a bunch !

Just get your employee and e-mail by calling something like

Employee employee = userSessionSource.getUserSession().getAttribute("employee"); String managerEmail = employee.getManager().getEmail();

exactly as it is shown in the sample project here.

And make sure that employee-view has manager attribute in it with the email field included.

Thank you from the bottom of my heart! It worked.

Hi there.

I wonder if I might ask a question about the sample project.

Why is the link between the BusinessUser and the User set up as a many-to-one? I was expecting it to be one-to-one.

Hi @ray1,

This is a good question. In fact, it is done due to the limitation that you cannot change the User entity, as it is precompiled. One2One would require adding the reverse link attribute to the User entity, however, it is not possible. Still, you can achieve One2One relation by extending the sec$User entity and adding the reverse link to the BusinesUser entity there.

Regards,
Aleksey

Thanks. That’s good to know. I’ve seen it in a few examples and I thought I was missing something.

:slight_smile: