| | |
| | | import com.gitblit.models.UserModel;
|
| | | import com.gitblit.utils.StringUtils;
|
| | |
|
| | | /**
|
| | | * FileUserService is Gitblit's default user service implementation.
|
| | | * |
| | | * Users and their repository memberships are stored in a simple properties file
|
| | | * which is cached and dynamically reloaded when modified.
|
| | | * |
| | | * @author James Moger
|
| | | * |
| | | */
|
| | | public class FileUserService extends FileSettings implements IUserService {
|
| | |
|
| | | private final Logger logger = LoggerFactory.getLogger(FileUserService.class);
|
| | |
| | | super(realmFile.getAbsolutePath());
|
| | | }
|
| | |
|
| | | /**
|
| | | * Setup the user service.
|
| | | * |
| | | * @param settings
|
| | | * @since 0.6.1
|
| | | */
|
| | | @Override
|
| | | public void setup(IStoredSettings settings) {
|
| | | }
|
| | |
|
| | | /**
|
| | | * Does the user service support cookie authentication?
|
| | | * |
| | | * @return true or false
|
| | | */
|
| | | @Override
|
| | | public boolean supportsCookies() {
|
| | | return true;
|
| | | }
|
| | |
|
| | | /**
|
| | | * Returns the cookie value for the specified user.
|
| | | * |
| | | * @param model
|
| | | * @return cookie value
|
| | | */
|
| | | @Override
|
| | | public char[] getCookie(UserModel model) {
|
| | | Properties allUsers = super.read();
|
| | |
| | | return cookie.toCharArray();
|
| | | }
|
| | |
|
| | | /**
|
| | | * Authenticate a user based on their cookie.
|
| | | * |
| | | * @param cookie
|
| | | * @return a user object or null
|
| | | */
|
| | | @Override
|
| | | public UserModel authenticate(char[] cookie) {
|
| | | String hash = new String(cookie);
|
| | |
| | | return model;
|
| | | }
|
| | |
|
| | | /**
|
| | | * Authenticate a user based on a username and password.
|
| | | * |
| | | * @param username
|
| | | * @param password
|
| | | * @return a user object or null
|
| | | */
|
| | | @Override
|
| | | public UserModel authenticate(String username, char[] password) {
|
| | | Properties allUsers = read();
|
| | |
| | | UserModel returnedUser = null;
|
| | | UserModel user = getUserModel(username);
|
| | | if (user.password.startsWith(StringUtils.MD5_TYPE)) {
|
| | | // password digest
|
| | | String md5 = StringUtils.MD5_TYPE + StringUtils.getMD5(new String(password));
|
| | | if (user.password.equalsIgnoreCase(md5)) {
|
| | | returnedUser = user;
|
| | | }
|
| | | } else if (user.password.startsWith(StringUtils.COMBINED_MD5_TYPE)) {
|
| | | // username+password digest
|
| | | String md5 = StringUtils.COMBINED_MD5_TYPE
|
| | | + StringUtils.getMD5(username.toLowerCase() + new String(password));
|
| | | if (user.password.equalsIgnoreCase(md5)) {
|
| | | returnedUser = user;
|
| | | }
|
| | | } else if (user.password.equals(new String(password))) {
|
| | | // plain-text password
|
| | | returnedUser = user;
|
| | | }
|
| | | return returnedUser;
|
| | | }
|
| | |
|
| | | /**
|
| | | * Retrieve the user object for the specified username.
|
| | | * |
| | | * @param username
|
| | | * @return a user object or null
|
| | | */
|
| | | @Override
|
| | | public UserModel getUserModel(String username) {
|
| | | Properties allUsers = read();
|
| | |
| | | // Permissions
|
| | | if (role.equalsIgnoreCase(Constants.ADMIN_ROLE)) {
|
| | | model.canAdmin = true;
|
| | | } else if (role.equalsIgnoreCase(Constants.NOT_FEDERATED_ROLE)) {
|
| | | model.excludeFromFederation = true;
|
| | | }
|
| | | break;
|
| | | default:
|
| | |
| | | return model;
|
| | | }
|
| | |
|
| | | /**
|
| | | * Updates/writes a complete user object.
|
| | | * |
| | | * @param model
|
| | | * @return true if update is successful
|
| | | */
|
| | | @Override
|
| | | public boolean updateUserModel(UserModel model) {
|
| | | return updateUserModel(model.username, model);
|
| | | }
|
| | |
|
| | | /**
|
| | | * Updates/writes and replaces a complete user object keyed by username.
|
| | | * This method allows for renaming a user.
|
| | | * |
| | | * @param username
|
| | | * the old username
|
| | | * @param model
|
| | | * the user object to use for username
|
| | | * @return true if update is successful
|
| | | */
|
| | | @Override
|
| | | public boolean updateUserModel(String username, UserModel model) {
|
| | | try {
|
| | |
| | | // Permissions
|
| | | if (model.canAdmin) {
|
| | | roles.add(Constants.ADMIN_ROLE);
|
| | | }
|
| | | if (model.excludeFromFederation) {
|
| | | roles.add(Constants.NOT_FEDERATED_ROLE);
|
| | | }
|
| | |
|
| | | StringBuilder sb = new StringBuilder();
|
| | |
| | | return false;
|
| | | }
|
| | |
|
| | | /**
|
| | | * Deletes the user object from the user service.
|
| | | * |
| | | * @param model
|
| | | * @return true if successful
|
| | | */
|
| | | @Override
|
| | | public boolean deleteUserModel(UserModel model) {
|
| | | return deleteUser(model.username);
|
| | | }
|
| | |
|
| | | /**
|
| | | * Delete the user object with the specified username
|
| | | * |
| | | * @param username
|
| | | * @return true if successful
|
| | | */
|
| | | @Override
|
| | | public boolean deleteUser(String username) {
|
| | | try {
|
| | |
| | | return false;
|
| | | }
|
| | |
|
| | | /**
|
| | | * Returns the list of all users available to the login service.
|
| | | * |
| | | * @return list of all usernames
|
| | | */
|
| | | @Override
|
| | | public List<String> getAllUsernames() {
|
| | | Properties allUsers = read();
|
| | |
| | | return list;
|
| | | }
|
| | |
|
| | | /**
|
| | | * Returns the list of all users who are allowed to bypass the access
|
| | | * restriction placed on the specified repository.
|
| | | * |
| | | * @param role
|
| | | * the repository name
|
| | | * @return list of all usernames that can bypass the access restriction
|
| | | */
|
| | | @Override
|
| | | public List<String> getUsernamesForRepository(String role) {
|
| | | public List<String> getUsernamesForRepositoryRole(String role) {
|
| | | List<String> list = new ArrayList<String>();
|
| | | try {
|
| | | Properties allUsers = read();
|
| | |
| | | return list;
|
| | | }
|
| | |
|
| | | /**
|
| | | * Sets the list of all uses who are allowed to bypass the access
|
| | | * restriction placed on the specified repository.
|
| | | * |
| | | * @param role
|
| | | * the repository name
|
| | | * @param usernames
|
| | | * @return true if successful
|
| | | */
|
| | | @Override
|
| | | public boolean setUsernamesForRepository(String role, List<String> usernames) {
|
| | | public boolean setUsernamesForRepositoryRole(String role, List<String> usernames) {
|
| | | try {
|
| | | Set<String> specifiedUsers = new HashSet<String>(usernames);
|
| | | Set<String> needsAddRole = new HashSet<String>(specifiedUsers);
|
| | |
| | | return false;
|
| | | }
|
| | |
|
| | | /**
|
| | | * Renames a repository role.
|
| | | * |
| | | * @param oldRole
|
| | | * @param newRole
|
| | | * @return true if successful
|
| | | */
|
| | | @Override
|
| | | public boolean renameRepositoryRole(String oldRole, String newRole) {
|
| | | try {
|
| | |
| | | return false;
|
| | | }
|
| | |
|
| | | /**
|
| | | * Removes a repository role from all users.
|
| | | * |
| | | * @param role
|
| | | * @return true if successful
|
| | | */
|
| | | @Override
|
| | | public boolean deleteRepositoryRole(String role) {
|
| | | try {
|
| | |
| | | return false;
|
| | | }
|
| | |
|
| | | /**
|
| | | * Writes the properties file.
|
| | | * |
| | | * @param properties
|
| | | * @throws IOException
|
| | | */
|
| | | private void write(Properties properties) throws IOException {
|
| | | // Update realm file
|
| | | // Write a temporary copy of the users file
|
| | | File realmFileCopy = new File(propertiesFile.getAbsolutePath() + ".tmp");
|
| | | FileWriter writer = new FileWriter(realmFileCopy);
|
| | | properties
|
| | | .store(writer,
|
| | | "# Gitblit realm file format: username=password,\\#permission,repository1,repository2...");
|
| | | writer.close();
|
| | | // If the write is successful, delete the current file and rename
|
| | | // the temporary copy to the original filename.
|
| | | if (realmFileCopy.exists() && realmFileCopy.length() > 0) {
|
| | | if (propertiesFile.delete()) {
|
| | | if (!realmFileCopy.renameTo(propertiesFile)) {
|
| | | throw new IOException(MessageFormat.format("Failed to rename {0} to {1}!",
|
| | | realmFileCopy.getAbsolutePath(), propertiesFile.getAbsolutePath()));
|
| | | if (propertiesFile.exists()) {
|
| | | if (!propertiesFile.delete()) {
|
| | | throw new IOException(MessageFormat.format("Failed to delete {0}!",
|
| | | propertiesFile.getAbsolutePath()));
|
| | | }
|
| | | } else {
|
| | | throw new IOException(MessageFormat.format("Failed to delete (0)!",
|
| | | propertiesFile.getAbsolutePath()));
|
| | | }
|
| | | if (!realmFileCopy.renameTo(propertiesFile)) {
|
| | | throw new IOException(MessageFormat.format("Failed to rename {0} to {1}!",
|
| | | realmFileCopy.getAbsolutePath(), propertiesFile.getAbsolutePath()));
|
| | | }
|
| | | } else {
|
| | | throw new IOException(MessageFormat.format("Failed to save {0}!",
|
| | |
| | | }
|
| | | }
|
| | |
|
| | | /**
|
| | | * Reads the properties file and rebuilds the in-memory cookie lookup table.
|
| | | */
|
| | | @Override
|
| | | protected synchronized Properties read() {
|
| | | long lastRead = lastRead();
|
| | | long lastRead = lastModified();
|
| | | Properties allUsers = super.read();
|
| | | if (lastRead != lastRead()) {
|
| | | if (lastRead != lastModified()) {
|
| | | // reload hash cache
|
| | | cookies.clear();
|
| | | for (String username : allUsers.stringPropertyNames()) {
|