Add the user name and email in the TeamCity database after authentication

Hello,

I'm developing a new plugin in order to make a new LDAP authentication corresponding to the specific needs of my company. I've used the documentation here: http://confluence.jetbrains.net/display/TCD5/Custom+Authentication+Module.

After the authentication, at this location:

// perform authentication

if (checkPassword(login, password)) {

// create ServerPrincipal and put it in the subject

mySubject.getPrincipals().add(new ServerPrincipal(null, login));

return true;

}



I retrieved the user data from the LDAP and I want to specify in the TeamCity database the username and email. I find only the following code which permit to make this kind of things:
User currentUser = myLoginModel.login(username, password, request);



               if(isEmpty(currentUser.getName()) || isEmpty(currentUser.getEmail())) {
                   SUser user = SessionUser.getUser(request);
                   user.updateUserAccount(currentUser.getUsername(), "John Doe", john.doe@jetbrains.com");
               }

However, in the case of Authentication method, I don't have access to the request object. So, could you help me, if it's possible, with the code to update the user account with his username and email ?

I have the same problem to get the PluginDescription object in order to retrieve some custom parameters from the teamcity-plugin.xml file in the same code location...?

Thanks in advance !

Regards,

Amine

11 comments
Comment actions Permalink

Hi Amine,

The request is indeed inaccessible in the login module, but I this there is a way around.
Since you have the username, you can try to find the corresponding user, or create a new one if it doesn't exist, and set the value.

What is the problem with PluginDescription?


--
Maxim

0
Comment actions Permalink

Thanks for your answer! However, I didn't understand the way you are describing. As I can't modify the user data in the Login Module, I must develop another plugin then ? If yes, which type of plugin I should create ? If no, could you give me more information about the way I should follow to make the user data modification.

Concerning the PluginDescription, I need to access it from the Login Module but I don't find documentation to retrieve it...

Regards,

Amine

0
Comment actions Permalink

I didn't mean you can't modify user data in the Login Module, you just can't have access to the request.

Let me describe the mechanism:
First of all, your plugin should provide LoginModuleDescriptor implementation (interface can be found in the package "jetbrains.buildServer.serverSide.auth"). It is an ordinary Spring bean, so you can access PluginDescriptor, UserModel and all other server beans in it.
Now in order to pass them to the LoginModule (the one you're implementing) there is a "getOptions()" method. The "LoginModule.initialize()" method will be passed the map of options returned by the descriptor.
If you do this right, your LoginModule will have references on PluginDescriptor, UserModel, etc.

Having the reference to UserModel, you can look up a user by username (see "findUserAccount()" method), or create a new one. And then set the email, display name.
But please be careful with changing the username: in this case a new username should be returned from the LoginModel using "ServerPrincipal" so that the core TeamCity was aware of what user has just authenticated.

--
Maxim

0
Comment actions Permalink

Thanks ! I understand better now. However, I need some more details. About the server beans, if I follow your mechanism, I should add PluginDescriptor and UserModel as properties of my custom LoginModuleDescriptor so they will be injected by Spring. Are the correct reference bean names of the both objects pluginDescriptor and userModel ?
Second detail needed, as the user is created automatically by TeamCity in the database with only the login. Should I modify the current behaviour in order to don't make TeamCity create the use automatically. Then, I have to create the user myself with the login, the username and the email. Or, it's possible to call the findUserAccount() just after the following code:

if (checkPassword(login, password)) {
            // create ServerPrincipal and put it in the subject
            mySubject.getPrincipals().add(new ServerPrincipal(PSA_LDAP_Realm, login));

Then, I could retrieve the user created in order to set is username and email ?

Concerning your warn: "But please be careful with changing the username: in this case a new  username should be returned from the LoginModel using "ServerPrincipal"  so that the core TeamCity was aware of what user has just authenticated.", as I'm modifying only the username and not the login, the behaviour of the core TeamCity will not be modified, right ?

0
Comment actions Permalink

> Are the correct reference bean names of the both objects pluginDescriptor and userModel ?
I think so. In fact, you don't need explicit declaration, if you add them as constructor arguments. They should be injected automatically.

Sorry, I didn't understand your idea. Your plugin may create/find/update users as it needs. TeamCity will create the user if necessary, but if you need SUser instance, you can do it. In this case TeamCity will do nothing.

> as I'm modifying only the username and not the login, the behaviour of the core TeamCity will not be modified, right ?
The "login" that you pass to the ServerPrincipal is the username that the core will use.
My point here is: make sure you return the correct username. In worst case TeamCity will try to find user by the old username, and since you changed it, user will be created yet again.


---
Maxim

0
Comment actions Permalink

Many thanks for your answers! It's really helpful to understand the TeamCity development logic.

Best regards,

Amine

0
Comment actions Permalink

You're welcome.
BTW I'm sure you know that we provide out-of-the-box LDAP plugin. If for some reason it doesn't suit you, please let us know: here or via issues at http://youtrack.jetbrains.net


--
Maxim

0
Comment actions Permalink

Yes sure I know there is a LDAP plugin. However, in my company, it's mandatory to use a specific java library when we want to interact with the LDAP.

Regards,

Amine.

0
Comment actions Permalink

Hello,

I continue Amine's works on the creation of the teamcity ldap plugin for my company. We managed to modify username and email in teamcity database.

Now we want to give the system administrator role to users according to they have a specific ldap group or not. I can’t found in the open api the method to retrieve the teamcity system administrator role key. By searching in the database I’ve found that the key is “SYSTEM_ADMIN”, so I could use it. But I found it’s a weird way and I think it would be a better solution to retrieve the system administrator role key by using the teamcity api. Can you help me?

Thanks in advance.

Best regards,

Bertrand

0
Comment actions Permalink

Hi Bertrand,

The recommended way of managing user permissions is through user groups (you can do that via direct roles assignment, but usually this is less convenient). This is what our LDAP plugin does.
You can find the API of doing so in the interface SUserGroup.


--
Maxim

0
Comment actions Permalink

Hi Maxim,

Thanks for your answer.
Now it's work

Bertrand

0

Please sign in to leave a comment.