/*
* JBoss, Home of Professional Open Source.
* Copyright 2012, Red Hat, Inc., and individual contributors
* as indicated by the @author tags. See the copyright.txt file in the
* distribution for a full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package com.gr.project.security.model;
import com.gr.project.model.Person;
import com.gr.project.security.authentication.TokenManager;
import com.gr.project.security.authentication.credential.Token;
import com.gr.project.security.authentication.credential.TokenCredentialStorage;
import org.picketlink.idm.IdentityManager;
import org.picketlink.idm.RelationshipManager;
import org.picketlink.idm.credential.Password;
import org.picketlink.idm.model.Account;
import org.picketlink.idm.model.basic.BasicModel;
import org.picketlink.idm.model.basic.Role;
import org.picketlink.idm.query.IdentityQuery;
import javax.inject.Inject;
import java.util.List;
import static com.gr.project.security.model.ApplicationRole.ADMINISTRATOR;
import static org.picketlink.idm.model.basic.BasicModel.hasRole;
/**
* <p>This class provides an abstraction point to the Identity Management operations required by the application./p>
*
* <p>The main objective of this class is avoid the spread use of the <code>IdentityManager</code> by different components of
* the application and code duplication, providing a centralized point of access for the most common operations like create/update/query users and so forth.</p>
*
* <p>Also it is very useful to understand how PicketLink Identity Management is being used and what is being used by the application from a IDM perspective.</p>
*
* <p>Please note that PicketLink IDM provides a very flexible and poweful identity model and API, from which you can extend and fulfill your own requirements.</p>
*
* @author Pedro Igor
*/
public class IdentityModelManager {
@Inject
private IdentityManager identityManager;
@Inject
private RelationshipManager relationshipManager;
@Inject
private TokenManager tokenManager;
public void createAdminAccount() {
// if admin exists dont create again
if(findByLoginName("admin@picketlink.org") != null) {
return;
}
Registration registration = new Registration();
registration.setEmail("admin@picketlink.org");
if (findByLoginName(registration.getEmail()) != null) {
return;
}
registration.setFirstName("Almight");
registration.setLastName("Administrator");
registration.setPassword("admin");
registration.setPasswordConfirmation("admin");
createAccount(registration);
MyUser admin = findByLoginName(registration.getEmail());
activateAccount(admin);
grantRole(admin, ADMINISTRATOR);
}
public MyUser createAccount(Registration request) {
if (!request.isValid()) {
throw new IllegalArgumentException("Insuficient information.");
}
Person person = new Person();
person.setEmail(request.getEmail());
person.setFirstName(request.getFirstName());
person.setLastName(request.getLastName());
MyUser newUser = new MyUser(request.getEmail());
newUser.setPerson(person);
disableAccount(newUser);
// String activationCode = UUID.randomUUID().toString();
String activationCode = "12345"; // testing purposes
newUser.setActivationCode(activationCode); // we set an activation code for future use.
this.identityManager.add(newUser);
updatePassword(newUser, request.getPassword());
return newUser;
}
public void updatePassword(Account account, String password) {
this.identityManager.updateCredential(account, new Password(password));
}
public Token issueToken(Account account) {
Token token = this.tokenManager.issue(account);
this.identityManager.updateCredential(account, token);
return token;
}
public void grantRole(MyUser account, ApplicationRole role) {
Role adminRole = BasicModel.getRole(this.identityManager, role.name());
BasicModel.grantRole(this.relationshipManager, account, adminRole);
}
public Token activateAccount(String activationCode) {
MyUser user = findUserByActivationCode(activationCode);
if (user == null) {
throw new IllegalArgumentException("Invalid activation code.");
}
user.setEnabled(true);
user.invalidateActivationCode();
this.identityManager.update(user);
return issueToken(user);
}
public void activateAccount(MyUser user) {
activateAccount(user.getActivationCode());
}
public MyUser findByLoginName(String loginName) {
if (loginName == null) {
throw new IllegalArgumentException("Invalid login name.");
}
IdentityQuery<MyUser> query = identityManager.createIdentityQuery(MyUser.class);
query.setParameter(MyUser.USER_NAME, loginName);
List<MyUser> result = query.getResultList();
if (!result.isEmpty()) {
return result.get(0);
}
return null;
}
public MyUser findUserByActivationCode(String activationCode) {
if (activationCode == null) {
throw new IllegalArgumentException("Invalid activation code.");
}
IdentityQuery<MyUser> query = identityManager.createIdentityQuery(MyUser.class);
List<MyUser> result = query
.setParameter(MyUser.ACTIVATION_CODE, activationCode.replaceAll("\"", ""))
.getResultList();
if (!result.isEmpty()) {
return result.get(0);
}
return null;
}
public String getToken(Account account) {
TokenCredentialStorage storage = this.identityManager.retrieveCurrentCredential(account, TokenCredentialStorage.class);
if (storage == null) {
return null;
}
return storage.getToken();
}
public Role getRole(ApplicationRole role) {
return BasicModel.getRole(this.identityManager, role.name());
}
public Role createRole(ApplicationRole applicationRole) {
Role role = getRole(applicationRole);
if (role == null) {
role = new Role(applicationRole.name());
this.identityManager.add(role);
}
return role;
}
public void disableAccount(MyUser user) {
if (hasRole(this.relationshipManager, user, getRole(ADMINISTRATOR))) {
throw new IllegalArgumentException("Administrators can not be disabled.");
}
user.setEnabled(false);
if (user.getId() != null) {
issueToken(user); // we invalidate the current token and create a new one. so any token stored by clients will be no longer valid.
this.identityManager.update(user);
}
}
public void enableAccount(MyUser user) {
if (hasRole(this.relationshipManager, user, getRole(ADMINISTRATOR))) {
throw new IllegalArgumentException("Administrators can not be enabled.");
}
user.setEnabled(true);
user.invalidateActivationCode();
if (user.getId() != null) {
this.identityManager.update(user);
}
}
}