/**
* Koya is an alfresco module that provides a corporate orientated dataroom.
*
* Copyright (C) Itl Developpement 2014
*
* This program is free software: you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* This program 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 Affero General Public License for more
* details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see `<http://www.gnu.org/licenses/>`.
*/
package fr.itldev.koya.services.impl;
import java.io.Serializable;
import java.net.MalformedURLException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.codehaus.jackson.type.TypeReference;
import org.springframework.web.client.RestClientException;
import fr.itldev.koya.model.exceptions.KoyaErrorCodes;
import fr.itldev.koya.model.impl.Activity;
import fr.itldev.koya.model.impl.Company;
import fr.itldev.koya.model.impl.Preferences;
import fr.itldev.koya.model.impl.User;
import fr.itldev.koya.model.json.AuthTicket;
import fr.itldev.koya.services.UserService;
import fr.itldev.koya.services.cache.CacheManager;
import fr.itldev.koya.services.exceptions.AlfrescoServiceException;
public class UserServiceImpl extends AlfrescoRestService implements UserService {
private static final String REST_GET_LOGIN = "/s/api/login.json?u={username}&pw={password}";
private static final String REST_POST_PERSONFROMMAIL = "/s/fr/itldev/koya/user/getbyauthkey?alf_ticket={alf_ticket}";
private static final String REST_DEL_LOGOUT = "/s/api/login/ticket/{ticket}?alf_ticket={alf_ticket}";
private static final String REST_POST_MODIFYDETAILS = "/s/fr/itldev/koya/user/modifydetails?alf_ticket={alf_ticket}";
private static final String REST_GET_FINDUSERS = "/s/fr/itldev/koya/user/find?"
+ "query={query}&maxResults={maxresults}&companyName={companyName}&roleFilter={roleFilter}&alf_ticket={alf_ticket}";
private static final String REST_POST_CHANGEPASSWORD = "/s/fr/itldev/koya/user/changepassword?alf_ticket={alf_ticket}";
private static final String REST_GET_GROUPS = "/s/fr/itldev/koya/user/groups?alf_ticket={alf_ticket}";
// ===== Preferences
private static final String REST_GET_PREFERENCES = "/s/api/people/{userid}/preferences?alf_ticket={alf_ticket}";
private static final String REST_POST_PREFERENCES = "/s/api/people/{userid}/preferences?alf_ticket={alf_ticket}";
private static final String REST_DELETE_PREFERENCES = "/s/api/people/{userid}/preferences?pf={preferencefilter?}&alf_ticket={alf_ticket}";
// ====== reset password BPM
private static final String REST_POST_RESET_PASSWORD_REQUEST = "/s/fr/itldev/koya/resetpassword/request";
private static final String REST_POST_RESET_PASSWORD_VALIDATION = "/s/fr/itldev/koya/resetpassword/validation";
// ====== user activities
private static final String REST_GET_ACTIVITIES = "/s/fr/itldev/koya/activities/feed/user?format=json&alf_ticket={alf_ticket}";
private static final String REST_GET_ACTIVITIES_MINFEED = "/s/fr/itldev/koya/activities/feed/user?format=json&minFeedId={minFeedId}&alf_ticket={alf_ticket}";
private CacheManager cacheManager;
public void setCacheManager(CacheManager cacheManager) {
this.cacheManager = cacheManager;
}
/**
* Authenticates user with authentication key that could be his login or
* email.
*
*
* TODO give md5 or other secured password instead of clear.
*
* @param authKey
* @param password
* @return
* @throws fr.itldev.koya.services.exceptions.AlfrescoServiceException
*/
@Override
public User login(String authKey, String password)
throws RestClientException, AlfrescoServiceException {
AuthTicket ticket = null;
try {
ticket = getTemplate().getForObject(
getAlfrescoServerUrl() + REST_GET_LOGIN, AuthTicket.class,
authKey, password);
} catch (Exception ex) {
throw ex;
}
// Get User Object
Map<String, Serializable> emailPostWrapper = new HashMap<>();
emailPostWrapper.put("authKey", authKey);
User user = getTemplate().postForObject(
getAlfrescoServerUrl() + REST_POST_PERSONFROMMAIL,
emailPostWrapper, User.class, ticket);
// Authentication ticket integration
user.setTicketAlfresco(ticket.toString());
// load users rest prefrences
loadPreferences(user);
//
user.setPassword(password);
return user;
}
@Override
public Boolean logout(User user) throws AlfrescoServiceException {
try {
getTemplate().delete(getAlfrescoServerUrl() + REST_DEL_LOGOUT,
user.getTicketAlfresco(), user.getTicketAlfresco());
} catch (RestClientException rce) {
throw new AlfrescoServiceException(rce.getMessage(),
KoyaErrorCodes.CANNOT_LOGOUT_USER);
}
// TODO treat returns
return null;
}
@Override
public void createUser(User userAdmin, User toCreate) {
// exception if doesn't work
}
/**
* Updates users preferences from alfresco server. Erases unsaved local
* preferences.
*
* @param user
*/
@Override
public void loadPreferences(User user) {
loadPreferences(user, user);
}
@Override
public void loadPreferences(User userLog, User userToGetPrefs) {
Preferences preferences = getTemplate().getForObject(
getAlfrescoServerUrl() + REST_GET_PREFERENCES,
Preferences.class, userToGetPrefs.getUserName(),
userLog.getTicketAlfresco());
userToGetPrefs.setPreferences(preferences);
}
/**
* Writes local preferences to alfresco server.
*
* @param user
* @throws fr.itldev.koya.services.exceptions.AlfrescoServiceException
*/
@Override
public void commitPreferences(User user) throws AlfrescoServiceException {
commitPreferences(user, user);
}
@Override
public void commitPreferences(User userLog, User userToCommitPrefs)
throws AlfrescoServiceException {
if (userToCommitPrefs.getPreferences() != null) {
// 1 - send new and modified keys
getTemplate().postForObject(
getAlfrescoServerUrl() + REST_POST_PREFERENCES,
userToCommitPrefs.getPreferences(), Preferences.class,
userToCommitPrefs.getUserName(),
userLog.getTicketAlfresco());
// 2 - updates preferences from server
Preferences prefsToCommit = userToCommitPrefs.getPreferences();
loadPreferences(userLog, userToCommitPrefs);
// 3 - if less preferences to commit than updates --> some keys have
// to be deleted.
if (prefsToCommit.size() < userToCommitPrefs.getPreferences()
.size()) {
String deleteFilter = "";
String sep = "";
for (String k : userToCommitPrefs.getPreferences().keySet()) {
if (!prefsToCommit.keySet().contains(k)) {
deleteFilter += sep + k;
sep = ",";
}
}
getTemplate().delete(
getAlfrescoServerUrl() + REST_DELETE_PREFERENCES,
userToCommitPrefs.getUserName(), deleteFilter,
userLog.getTicketAlfresco());
loadPreferences(userLog, userToCommitPrefs);
}
} else {
throw new AlfrescoServiceException("No user preference to commit",
0);
}
}
@Override
public void commitProperties(User user) throws AlfrescoServiceException {
commitProperties(user, user);
}
@Override
public void commitProperties(User userLog, User userToCommitProps)
throws AlfrescoServiceException {
getTemplate().postForObject(
getAlfrescoServerUrl() + REST_POST_MODIFYDETAILS,
userToCommitProps, String.class, userLog.getTicketAlfresco());
}
@Override
public void changePassword(User userLog, String username, String oldPassword,
String newPassword) throws AlfrescoServiceException,
MalformedURLException {
Map<String, String> params = new HashMap<String, String>();
if(username != null && !username.isEmpty())
params.put("userName", username);
params.put("oldPwd", oldPassword);
params.put("newPwd", newPassword);
getTemplate().postForObject(
getAlfrescoServerUrl() + REST_POST_CHANGEPASSWORD, params,
String.class, userLog.getTicketAlfresco());
}
/**
* find users list wich first/last name or email starts with query. Return
* list limitated by maxResults.
*
* if company is not null limit results to company scope. rolesFilter can
* refine results in this company context (not taken in account if no
* company is set)
*
* @param userLog
* @param query
* @param maxResults
* @param company
* @param rolesFilter
* @return
* @throws AlfrescoServiceException
*/
@Override
public List<User> find(User userLog, String query, Integer maxResults,
Company company, List<String> rolesFilter)
throws AlfrescoServiceException {
String companyName = "";
String roles = "";
if (company != null) {
companyName = company.getName();
}
if (rolesFilter != null && rolesFilter.size() > 0) {
String sep = "";
for (String r : rolesFilter) {
roles += sep + r;
sep = ",";
}
}
return fromJSON(
new TypeReference<List<User>>() {
},
getTemplate().getForObject(
getAlfrescoServerUrl() + REST_GET_FINDUSERS,
String.class, query, maxResults, companyName, roles,
userLog.getTicketAlfresco()));
}
/**
* Get user Object from email.
*
* @param user
* @param email
* @return
* @throws AlfrescoServiceException
*/
@Override
public User getUserFromEmail(User user, String email)
throws AlfrescoServiceException {
Map<String, Serializable> emailPostWrapper = new HashMap<>();
emailPostWrapper.put("authKey", email);
return fromJSON(
new TypeReference<User>() {
},
getTemplate().postForObject(
getAlfrescoServerUrl() + REST_POST_PERSONFROMMAIL,
emailPostWrapper, String.class,
user.getTicketAlfresco()));
}
@Override
public User getUserFromEmailFailProof(User user, String email) {
Map<String, Serializable> emailPostWrapper = new HashMap<>();
emailPostWrapper.put("authKey", email);
emailPostWrapper.put("failProof", true);
try {
return fromJSON(
new TypeReference<User>() {
},
getTemplate().postForObject(
getAlfrescoServerUrl() + REST_POST_PERSONFROMMAIL,
emailPostWrapper, String.class,
user.getTicketAlfresco()));
} catch (RestClientException e) {
return null;
}
}
/**
* Send Reset password request to alfresco server.
*
*
* @param userEmail
* @param resetUrl
* @throws AlfrescoServiceException
*/
@Override
public void sendResetPasswordRequest(String userEmail, String resetUrl)
throws AlfrescoServiceException {
Map<String, String> params = new HashMap<>();
params.put("userEmail", userEmail);
params.put("resetUrl", resetUrl);
getTemplate().postForObject(
getAlfrescoServerUrl() + REST_POST_RESET_PASSWORD_REQUEST,
params, String.class);
}
/**
* Validate password modification in reset password process.
*
* Authenticated by resetId + resetTicket.
*
* @param resetId
* @param resetTicket
* @param newPassword
* @throws AlfrescoServiceException
*/
@Override
public void validateNewPasswordfromResetProcess(String resetId,
String resetTicket, String newPassword)
throws AlfrescoServiceException {
Map<String, String> params = new HashMap<>();
params.put("resetId", resetId);
params.put("resetTicket", resetTicket);
params.put("newPassword", newPassword);
getTemplate().postForObject(
getAlfrescoServerUrl() + REST_POST_RESET_PASSWORD_VALIDATION,
params, String.class);
}
@Override
public List<String> getGroups(User user) {
List<String> groups = cacheManager.getUserGroups(user);
if (groups != null) {
return groups;
}
groups = fromJSON(
new TypeReference<List<String>>() {
},
getTemplate().getForObject(
getAlfrescoServerUrl() + REST_GET_GROUPS, String.class,
user.getTicketAlfresco()));
cacheManager.setUserGroups(user, groups);
return groups;
}
/**
* List available activities for user
*
* @param user
* @return
* @throws AlfrescoServiceException
*/
public List<Activity> listActivities(User user)
throws AlfrescoServiceException {
return fromJSON(
new TypeReference<List<Activity>>() {
},
getTemplate().getForObject(
getAlfrescoServerUrl() + REST_GET_ACTIVITIES,
String.class, user.getTicketAlfresco()));
}
/**
* List available activities for user
*
* @param user
* @return
* @throws AlfrescoServiceException
*/
public List<Activity> listActivities(User user,Integer minFeedId)
throws AlfrescoServiceException {
return fromJSON(
new TypeReference<List<Activity>>() {
},
getTemplate().getForObject(
getAlfrescoServerUrl() + REST_GET_ACTIVITIES_MINFEED,
String.class,minFeedId, user.getTicketAlfresco()));
}
}