/*
* Copyright (C) 2011 Jan Pokorsky
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package cz.cas.lib.proarc.common.user;
import cz.cas.lib.proarc.common.config.AppConfiguration;
import cz.cas.lib.proarc.common.dao.DaoFactory;
import cz.cas.lib.proarc.common.fedora.RemoteStorage;
import java.io.File;
import java.io.IOException;
import java.math.BigInteger;
import java.net.URI;
import java.security.MessageDigest;
import java.util.Arrays;
import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.regex.Pattern;
import javax.sql.DataSource;
/**
*
* @author Jan Pokorsky
*/
public final class UserUtil {
static final String IMPORT_FOLDER_NAME = "import";
static final String EXPORT_FOLDER_NAME = "export";
static final String EDIT_FOLDER_NAME = "images";
/** allows only lower case characters to prevent confusion */
static final Pattern USERNAME_PATTERN = Pattern.compile("[a-z][a-z0-9_-]{4,}");
/** The pattern to replace forbidden chars in remote user names. */
static final Pattern USERNAME_REPLACE_PATTERN = Pattern.compile("[^a-zA-Z0-9_-]+");
private static final Pattern GROUP_PATTERN = Pattern.compile(
"^" + FedoraGroupDao.PID_PREFIX + "[a-z][a-z0-9_-]{4,}$");
private static UserManager MANGER = null;
public static UserManager createUserManagerPostgressImpl(
AppConfiguration config, DataSource source, DaoFactory daos) throws IOException {
return new UserManagerSql(source,
config.getDefaultUsersHome(),
RemoteStorage.getInstance(config),
daos);
}
public static UserManager getDefaultManger() {
return MANGER;
}
public static void setDefaultManger(UserManager manger) {
UserUtil.MANGER = manger;
}
/**
* creates new user folder
* @param userName
* @param userHomePath
* @param allUsersHome
* @return
* @throws IOException
*/
public static File createUserHome(String userName, String userHomePath, File allUsersHome) throws IOException {
File userHome;
if (userHomePath == null) {
String fileNameBase = userName.toLowerCase();
userHome = new File(allUsersHome, fileNameBase);
for (int index = 1; !userHome.mkdir(); index++) {
userHome = new File(allUsersHome, fileNameBase + "_" + index);
}
} else {
userHome = new File(userHomePath);
if (userHome.exists() && !userHome.isDirectory()) {
throw new IOException(String.format("Not a folder: '%s'!", userHome));
}
}
userHome = userHome.getCanonicalFile();
return userHome;
}
public static void createUserSubfolders(File userHome) {
File importHome = new File(userHome, IMPORT_FOLDER_NAME);
File exportHome = new File(userHome, EXPORT_FOLDER_NAME);
File imagesHome = new File(userHome, EDIT_FOLDER_NAME);
importHome.mkdirs();
exportHome.mkdir();
imagesHome.mkdir();
}
/**
* Translates platform specific path to independent form as URI
*
* @param folderpath platform specific path as <pre>UNIX: /tmp/imports/</pre>
* or <pre>MS Win: c:\imports</pre> or <pre>UNC MS Win: \\laptop\My Documents\</pre>
* are valid options
* @return an abstract path
*/
static URI toUri(File folder) {
if (folder.exists() && !folder.isDirectory()) {
throw new IllegalArgumentException("Invalid folder path: '" + folder + '\'');
}
// File.toURI always terminates folder path with slash but the folder must exists
return folder.toURI().normalize();
}
public static void validateUsername(String userName) {
if (!isValidUserName(userName)) {
throw new IllegalArgumentException("Invalid user name: " + userName);
}
}
static boolean isValidUserName(String name) {
return name != null && name.length() + FedoraUserDao.PID_PREFIX.length() <= 64
&& USERNAME_PATTERN.matcher(name).matches();
}
/** Replaces forbidden chars in remoteName and fixes length. */
public static String toUserName(String remoteName) {
return toUserName("", remoteName);
}
/** Replaces forbidden chars in remoteName and fixes length. */
public static String toUserName(String remotePrefix, String remoteName) {
if (remoteName == null || remoteName.isEmpty()) {
throw new IllegalArgumentException(remoteName);
}
String name = remoteName;
// fedora PID max length 64
int maxLength = 64 - FedoraUserDao.PID_PREFIX.length() - 4;
if (remoteName.length() > maxLength) {
name = remoteName.substring(0, maxLength);
}
name = USERNAME_REPLACE_PATTERN.matcher(name).replaceAll("_");
name = name.replaceFirst("^_+", ""); // remove heading '_'
name = name.toLowerCase();
if (name.length() == 0 || name.isEmpty()) {
// replace unfriendly name with unsigned hash code
name = 'u' + String.valueOf(remoteName.hashCode() & 0x00000000ffffffffL);
}
if (remotePrefix != null && !remotePrefix.isEmpty()) {
name = remotePrefix + '_' + name;
}
return name;
}
static String getDigist(String s) {
try {
MessageDigest instance = MessageDigest.getInstance("SHA");
byte[] digest = instance.digest(s.getBytes("UTF-8"));
String toHex = toHex(digest);
return toHex;
} catch (Exception ex) {
throw new IllegalStateException(ex);
}
}
public static String toHex(byte[] bytes) {
BigInteger bi = new BigInteger(1, bytes);
return String.format("%0" + (bytes.length << 1) + "x", bi);
}
public static void initDefaultAdmin() {
UserManager mgr = getDefaultManger();
final String proarcName = "proarc";
final String logMsg = "Init ProArc.";
Group gadmin = mgr.findGroup(1);
if (gadmin == null) {
gadmin = Group.create("admin", "Administrátoři");
gadmin = mgr.addGroup(gadmin, Arrays.asList(Permissions.ADMIN), proarcName, logMsg);
assert gadmin.getId() == 1;
}
UserProfile admin = mgr.find(proarcName);
if (admin == null) {
admin = UserProfile.create(proarcName, "proarcAdmin", "Administrátor");
mgr.add(admin, Arrays.asList(gadmin), admin.getUserName(), logMsg);
}
Set<Permission> adminPermissions = mgr.findUserPermissions(admin.getId());
if (!adminPermissions.contains(Permissions.ADMIN)) {
mgr.setPermissions(gadmin.getId(), Permissions.ADMIN);
}
}
public static Collection<String> toGroupPid(Collection<Group> groups) {
LinkedHashSet<String> result = new LinkedHashSet<String>(groups.size());
for (Group group : groups) {
result.add(toGroupPid(group));
}
return result;
}
public static String toGroupPid(Group group) {
return group.getName();
}
public static String toGroupPid(String groupObjectId) {
return FedoraGroupDao.PID_PREFIX + groupObjectId;
}
public static boolean isValidGroupPid(String pid) {
return pid != null && pid.length() <= 64 && GROUP_PATTERN.matcher(pid).matches();
}
public static String toUserPid(UserProfile user) {
return FedoraUserDao.PID_PREFIX + user.getUserName();
}
}