package nl.minicom.gitolite.manager.models; import java.util.Comparator; import nl.minicom.gitolite.manager.exceptions.ModificationException; import nl.minicom.gitolite.manager.models.Recorder.Modification; import org.apache.commons.lang3.builder.EqualsBuilder; import org.apache.commons.lang3.builder.HashCodeBuilder; import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableMultimap; import com.google.common.collect.TreeMultimap; /** * This class represents a repository in Gitolite. You can set access permissions * for {@link User}s who should be able to access the represented repository. * * @author Michael de Jong <<a href="mailto:michaelj@minicom.nl">michaelj@minicom.nl</a>> */ public final class Repository { static final Comparator<Repository> SORT_BY_NAME = new Comparator<Repository>() { @Override public int compare(Repository arg0, Repository arg1) { return arg0.getName().compareTo(arg1.getName()); } }; private final String name; private final TreeMultimap<Permission, Identifiable> rights; private final Recorder recorder; /** * Constructs a new {@link Repository} object with the specified name. * * @param name * The name of the {@link Repository}. * * @param recorder * The {@link Recorder} to use when recording changes of this {@link Repository}. */ Repository(String name, Recorder recorder) { Preconditions.checkNotNull(name); Preconditions.checkArgument(!name.isEmpty()); Preconditions.checkNotNull(recorder); this.name = name; this.recorder = recorder; this.rights = TreeMultimap.create(Permission.SORT_ON_ORDINAL, Identifiable.SORT_BY_TYPE_AND_NAME); } /** * @return * The name of the repository */ public String getName() { return name; } /** * This method sets the {@link Permission} level for a specified {@link User}. * * @param user * The {@link User} to set the permission for. * * @param level * The {@link Permission} which the specified {@link User} should have. */ public void setPermission(User user, final Permission level) { Preconditions.checkNotNull(user); Preconditions.checkNotNull(level); synchronized (rights) { rights.put(level, user); } final String userName = user.getName(); recorder.append(new Modification("Setting permission for user: '%s' to repository: '%s'", userName, getName()) { @Override public void apply(Config config) throws ModificationException { Repository repo = config.getRepository(getName()); User user = config.getUser(userName); repo.setPermission(user, level); } }); } /** * This method sets the {@link Permission} level for a specified {@link Group}. * * @param group * The {@link Group} to set the permission for. * * @param level * The {@link Permission} which the specified {@link Group} should have. */ public void setPermission(Group group, final Permission level) { Preconditions.checkNotNull(group); Preconditions.checkNotNull(level); synchronized (rights) { rights.put(level, group); } final String groupName = group.getName(); recorder.append(new Modification("Setting permission for: '%s' to: '%s'", groupName, getName()) { @Override public void apply(Config config) throws ModificationException { Repository repo = config.getRepository(getName()); Group group = config.getGroup(groupName); repo.setPermission(group, level); } }); } /** * This method revokes all rights on this {@link Repository} for the * specified {@link User}. * * @param user * The {@link User} whose permissions need to be revoked. */ public void revokePermissions(User user) { synchronized (rights) { for (Permission permission : Permission.values()) { rights.remove(permission, user); } } final String userName = user.getName(); recorder.append(new Modification("Revoking permission for: '%s' from: '%s'", userName, getName()) { @Override public void apply(Config config) throws ModificationException { Repository repo = config.getRepository(getName()); if (repo == null) { throw new ModificationException(); } User user = config.getUser(userName); if (user == null) { throw new ModificationException(); } repo.revokePermissions(user); } }); } /** * This method revokes all rights on this {@link Repository} for the * specified {@link Group}. * * @param group * The {@link Group} whose permissions need to be revoked. */ public void revokePermissions(Group group) { synchronized (rights) { for (Permission permission : Permission.values()) { rights.remove(permission, group); } } final String groupName = group.getName(); recorder.append(new Modification("Revoking permission for: '%s' to: '%s'", groupName, getName()) { @Override public void apply(Config config) throws ModificationException { Repository repo = config.getRepository(getName()); if (repo == null) { throw new ModificationException(); } Group group = config.getGroup(groupName); if (group == null) { throw new ModificationException(); } repo.revokePermissions(group); } }); } /** * @return * An {@link ImmutableMultimap} containing all the {@link User}s and {@link Group}s * who have some kind of access on this {@link Repository} object. They're ordered * by highest {@link Permission} to lowest {@link Permission}, and each permission * contains one or more {@link User}s and {@link Group}s. */ public ImmutableMultimap<Permission, Identifiable> getPermissions() { synchronized (rights) { return ImmutableMultimap.copyOf(rights); } } @Override public int hashCode() { return new HashCodeBuilder() .append(name) .toHashCode(); } @Override public boolean equals(Object other) { if (!(other instanceof Repository)) { return false; } return new EqualsBuilder() .append(name, ((Repository) other).name) .isEquals(); } }