Rename user to account, push operation to write operation, pull

operation to read operation.
This commit is contained in:
robin shine 2013-07-29 22:56:46 +08:00
parent b3bf4e00ad
commit 85382d6d5f
48 changed files with 371 additions and 387 deletions

View File

@ -11,33 +11,33 @@ import org.apache.shiro.authz.Permission;
import com.pmease.commons.persistence.dao.GeneralDao;
import com.pmease.commons.security.AbstractRealm;
import com.pmease.gitop.core.entitymanager.RoleManager;
import com.pmease.gitop.core.entitymanager.TeamManager;
import com.pmease.gitop.core.entitymanager.UserManager;
import com.pmease.gitop.core.model.Team;
import com.pmease.gitop.core.model.User;
import com.pmease.gitop.core.model.Account;
@Singleton
public class UserRealm extends AbstractRealm<User> {
public class AccountRealm extends AbstractRealm<Account> {
private final TeamManager teamManager;
private final UserManager userManager;
private final RoleManager roleManager;
@Inject
public UserRealm(GeneralDao generalDao, CredentialsMatcher credentialsMatcher,
TeamManager teamManager, UserManager userManager) {
public AccountRealm(GeneralDao generalDao, CredentialsMatcher credentialsMatcher,
TeamManager teamManager, RoleManager roleManager) {
super(generalDao, credentialsMatcher);
this.teamManager = teamManager;
this.userManager = userManager;
this.roleManager = roleManager;
}
@Override
protected Collection<Permission> permissionsOf(Long userId) {
protected Collection<Permission> permissionsOf(Long accountId) {
Collection<Permission> permissions = new ArrayList<Permission>();
permissions.add(userManager.load(userId).getAuthorization().getRole());
for (Team team: teamManager.getTeams(userId))
permissions.add(team);
permissions.addAll(roleManager.getRoles(accountId));
permissions.addAll(teamManager.getTeams(accountId));
return permissions;
}

View File

@ -19,7 +19,7 @@ public class CoreModule extends AbstractPluginModule {
super.configure();
bind(AbstractWicketConfig.class).to(WicketConfig.class);
bind(AbstractRealm.class).to(UserRealm.class);
bind(AbstractRealm.class).to(AccountRealm.class);
bindConstant().annotatedWith(AppName.class).to(PRODUCT_NAME);

View File

@ -15,7 +15,7 @@ import com.pmease.commons.jetty.extensionpoints.ServletContextConfigurator;
import com.pmease.commons.loader.AbstractPlugin;
import com.pmease.commons.persistence.AbstractEntity;
import com.pmease.commons.persistence.extensionpoints.ModelContribution;
import com.pmease.gitop.core.model.User;
import com.pmease.gitop.core.model.Account;
import com.pmease.gitop.core.web.asset.AssetLocator;
public class CorePlugin extends AbstractPlugin {
@ -42,7 +42,7 @@ public class CorePlugin extends AbstractPlugin {
public Collection<Class<? extends AbstractEntity>> getModelClasses() {
Collection<Class<? extends AbstractEntity>> modelClasses =
new HashSet<Class<? extends AbstractEntity>>();
modelClasses.add(User.class);
modelClasses.add(Account.class);
return modelClasses;
}
});

View File

@ -6,7 +6,7 @@ import javax.ws.rs.Path;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import com.pmease.commons.security.SecurityHelper;
import com.pmease.gitop.core.model.User;
import com.pmease.gitop.core.model.Account;
@Path("/hello")
public class HelloResource {
@ -14,7 +14,7 @@ public class HelloResource {
@GET
@RequiresPermissions("write")
public String whoami() {
return "Hello " + SecurityHelper.getUserDisplayName(User.class, "Guest");
return "Hello " + SecurityHelper.getUserDisplayName(Account.class, "Guest");
}
}

View File

@ -0,0 +1,17 @@
package com.pmease.gitop.core.entitymanager;
import com.google.inject.ImplementedBy;
import com.pmease.commons.persistence.dao.GenericDao;
import com.pmease.gitop.core.entitymanager.impl.DefaultAccountManager;
import com.pmease.gitop.core.model.Account;
@ImplementedBy(DefaultAccountManager.class)
public interface AccountManager extends GenericDao<Account> {
/**
* Find root account in the system.
*
* @return
* root account of the system, or null if root account has not been populated
*/
Account getRootAccount();
}

View File

@ -10,6 +10,6 @@ import com.pmease.gitop.core.model.Team;
@ImplementedBy(DefaultTeamManager.class)
public interface TeamManager extends GenericDao<Team> {
Collection<Team> getTeams(Long userId);
Collection<Team> getTeams(Long accountId);
}

View File

@ -1,17 +0,0 @@
package com.pmease.gitop.core.entitymanager;
import com.google.inject.ImplementedBy;
import com.pmease.commons.persistence.dao.GenericDao;
import com.pmease.gitop.core.entitymanager.impl.DefaultUserManager;
import com.pmease.gitop.core.model.User;
@ImplementedBy(DefaultUserManager.class)
public interface UserManager extends GenericDao<User> {
/**
* Find root user in the system.
*
* @return
* root user of the system, or null if root user has not been populated
*/
User getRootUser();
}

View File

@ -0,0 +1,41 @@
package com.pmease.gitop.core.entitymanager.impl;
import javax.inject.Provider;
import javax.inject.Singleton;
import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.criterion.Order;
import com.google.common.base.Preconditions;
import com.pmease.commons.persistence.Transactional;
import com.pmease.commons.persistence.dao.DefaultGenericDao;
import com.pmease.commons.persistence.dao.GeneralDao;
import com.pmease.gitop.core.entitymanager.AccountManager;
import com.pmease.gitop.core.model.Account;
@Singleton
public class DefaultAccountManager extends DefaultGenericDao<Account> implements AccountManager {
private volatile Account rootAccount;
public DefaultAccountManager(GeneralDao generalDao, Provider<Session> sessionProvider) {
super(generalDao, sessionProvider);
}
@Transactional
@Override
public Account getRootAccount() {
if (rootAccount == null) {
Criteria criteria = getSession().createCriteria(Account.class).addOrder(Order.asc("id"));
/* the first created account should be root account */
criteria.setFirstResult(0);
criteria.setMaxResults(1);
rootAccount = (Account) criteria.uniqueResult();
Preconditions.checkNotNull(rootAccount);
}
return rootAccount;
}
}

View File

@ -12,25 +12,25 @@ import com.pmease.commons.persistence.Transactional;
import com.pmease.commons.persistence.dao.DefaultGenericDao;
import com.pmease.commons.persistence.dao.GeneralDao;
import com.pmease.gitop.core.entitymanager.TeamManager;
import com.pmease.gitop.core.entitymanager.UserManager;
import com.pmease.gitop.core.entitymanager.AccountManager;
import com.pmease.gitop.core.model.Team;
import com.pmease.gitop.core.model.Membership;
@Singleton
public class DefaultTeamManager extends DefaultGenericDao<Team> implements TeamManager {
private final UserManager userManager;
private final AccountManager accountManager;
public DefaultTeamManager(GeneralDao generalDao, Provider<Session> sessionProvider, UserManager userManager) {
public DefaultTeamManager(GeneralDao generalDao, Provider<Session> sessionProvider, AccountManager accountManager) {
super(generalDao, sessionProvider);
this.userManager = userManager;
this.accountManager = accountManager;
}
@Transactional
@Override
public Collection<Team> getTeams(Long userId) {
public Collection<Team> getTeams(Long accountId) {
Collection<Team> teams = new ArrayList<Team>();
for (Membership membership: userManager.load(userId).getMemberships())
for (Membership membership: accountManager.load(accountId).getMemberships())
teams.add(membership.getTeam());
return teams;

View File

@ -1,41 +0,0 @@
package com.pmease.gitop.core.entitymanager.impl;
import javax.inject.Provider;
import javax.inject.Singleton;
import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.criterion.Order;
import com.google.common.base.Preconditions;
import com.pmease.commons.persistence.Transactional;
import com.pmease.commons.persistence.dao.DefaultGenericDao;
import com.pmease.commons.persistence.dao.GeneralDao;
import com.pmease.gitop.core.entitymanager.UserManager;
import com.pmease.gitop.core.model.User;
@Singleton
public class DefaultUserManager extends DefaultGenericDao<User> implements UserManager {
private volatile User rootUser;
public DefaultUserManager(GeneralDao generalDao, Provider<Session> sessionProvider) {
super(generalDao, sessionProvider);
}
@Transactional
@Override
public User getRootUser() {
if (rootUser == null) {
Criteria criteria = getSession().createCriteria(User.class).addOrder(Order.asc("id"));
/* the first created user should be root user */
criteria.setFirstResult(0);
criteria.setMaxResults(1);
rootUser = (User) criteria.uniqueResult();
Preconditions.checkNotNull(rootUser);
}
return rootUser;
}
}

View File

@ -3,12 +3,7 @@ package com.pmease.gitop.core.model;
import java.util.Collection;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.JoinColumn;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import org.hibernate.annotations.FetchMode;
import com.pmease.commons.security.AbstractUser;
@ -25,16 +20,13 @@ import com.pmease.commons.security.AbstractUser;
@Entity
@org.hibernate.annotations.Cache(
usage=org.hibernate.annotations.CacheConcurrencyStrategy.READ_WRITE)
public class User extends AbstractUser {
public class Account extends AbstractUser {
@OneToMany(mappedBy="user")
@OneToMany(mappedBy="account")
private Collection<Membership> memberships;
@OneToOne(fetch=FetchType.EAGER)
@org.hibernate.annotations.Fetch(FetchMode.SELECT)
@JoinColumn(nullable=false)
@org.hibernate.annotations.ForeignKey(name="FK_USER_AUTH")
private Authorization authorization;
@OneToMany(mappedBy="account")
private Collection<Authorization> authorizations;
public Collection<Membership> getMemberships() {
return memberships;
@ -44,12 +36,12 @@ public class User extends AbstractUser {
this.memberships = memberships;
}
public Authorization getAuthorization() {
return authorization;
public Collection<Authorization> getAuthorizations() {
return authorizations;
}
public void setAuthorization(Authorization authorization) {
this.authorization = authorization;
public void setAuthorizations(Collection<Authorization> authorizations) {
this.authorizations = authorizations;
}
}

View File

@ -3,33 +3,41 @@ package com.pmease.gitop.core.model;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.JoinColumn;
import javax.persistence.OneToOne;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;
import org.hibernate.annotations.FetchMode;
import com.pmease.commons.persistence.AbstractEntity;
import com.pmease.gitop.core.model.role.Role;
@SuppressWarnings("serial")
@Entity
@Table(uniqueConstraints={
@UniqueConstraint(columnNames={"account", "role"})
})
@org.hibernate.annotations.Cache(
usage=org.hibernate.annotations.CacheConcurrencyStrategy.READ_WRITE)
public class Authorization extends AbstractEntity {
@OneToOne(fetch=FetchType.EAGER)
@ManyToOne(fetch=FetchType.EAGER)
@org.hibernate.annotations.Fetch(FetchMode.SELECT)
@JoinColumn(nullable=false)
@org.hibernate.annotations.ForeignKey(name="FK_AUTH_USER")
private User user;
@org.hibernate.annotations.ForeignKey(name="FK_AUTH_ACC")
private Account account;
@ManyToOne(fetch=FetchType.EAGER)
@org.hibernate.annotations.Fetch(FetchMode.SELECT)
@JoinColumn(nullable=false)
@org.hibernate.annotations.ForeignKey(name="FK_AUTH_ROLE")
private Role role;
public User getUser() {
return user;
public Account getAccount() {
return account;
}
public void setUser(User user) {
this.user = user;
public void setAccount(Account account) {
this.account = account;
}
public Role getRole() {

View File

@ -14,7 +14,7 @@ import com.pmease.commons.persistence.AbstractEntity;
@SuppressWarnings("serial")
@Entity
@Table(uniqueConstraints={
@UniqueConstraint(columnNames={"user", "team"})
@UniqueConstraint(columnNames={"account", "team"})
})
@org.hibernate.annotations.Cache(
usage=org.hibernate.annotations.CacheConcurrencyStrategy.READ_WRITE)
@ -23,8 +23,8 @@ public class Membership extends AbstractEntity {
@ManyToOne(fetch=FetchType.EAGER)
@org.hibernate.annotations.Fetch(FetchMode.SELECT)
@JoinColumn(nullable=false)
@org.hibernate.annotations.ForeignKey(name="FK_MEM_USER")
private User user;
@org.hibernate.annotations.ForeignKey(name="FK_MEM_ACC")
private Account account;
@ManyToOne(fetch=FetchType.EAGER)
@org.hibernate.annotations.Fetch(FetchMode.SELECT)
@ -32,12 +32,12 @@ public class Membership extends AbstractEntity {
@org.hibernate.annotations.ForeignKey(name="FK_MEM_TEAM")
private Team team;
public User getUser() {
return user;
public Account getAccount() {
return account;
}
public void setUser(User user) {
this.user = user;
public void setAccount(Account account) {
this.account = account;
}
public Team getTeam() {

View File

@ -16,7 +16,7 @@ import com.pmease.commons.persistence.AbstractEntity;
@org.hibernate.annotations.Cache(
usage=org.hibernate.annotations.CacheConcurrencyStrategy.READ_WRITE)
@Table(uniqueConstraints={
@UniqueConstraint(columnNames={"owner", "name"})
@UniqueConstraint(columnNames={"account", "name"})
})
@SuppressWarnings("serial")
public class Repository extends AbstractEntity {
@ -29,8 +29,8 @@ public class Repository extends AbstractEntity {
@ManyToOne(fetch=FetchType.EAGER)
@org.hibernate.annotations.Fetch(FetchMode.SELECT)
@JoinColumn(nullable=false)
@org.hibernate.annotations.ForeignKey(name="FK_REPO_OWNER")
private User owner;
@org.hibernate.annotations.ForeignKey(name="FK_REPO_ACC")
private Account account;
public String getName() {
return name;
@ -48,12 +48,12 @@ public class Repository extends AbstractEntity {
this.description = description;
}
public User getOwner() {
return owner;
public Account getAccount() {
return account;
}
public void setOwner(User owner) {
this.owner = owner;
public void setAccount(Account account) {
this.account = account;
}
}

View File

@ -1,6 +1,7 @@
package com.pmease.gitop.core.model;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import javax.persistence.Column;
@ -8,6 +9,7 @@ import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;
@ -16,12 +18,12 @@ import org.hibernate.annotations.FetchMode;
import com.google.common.base.Optional;
import com.pmease.commons.persistence.AbstractEntity;
import com.pmease.gitop.core.model.projectpermission.OperationOfRepositorySet;
import com.pmease.gitop.core.model.projectpermission.PrivilegedOperation;
import com.pmease.gitop.core.model.projectpermission.ProjectOperation;
import com.pmease.gitop.core.model.projectpermission.ProjectPermission;
import com.pmease.gitop.core.model.projectpermission.PullFromProject;
import com.pmease.gitop.core.model.projectpermission.WholeProjectOperation;
import com.pmease.gitop.core.model.permission.account.AccountOperation;
import com.pmease.gitop.core.model.permission.account.AccountPermission;
import com.pmease.gitop.core.model.permission.account.AccountWideOperation;
import com.pmease.gitop.core.model.permission.account.OperationOfRepositorySet;
import com.pmease.gitop.core.model.permission.account.PrivilegedOperation;
import com.pmease.gitop.core.model.permission.account.ReadFromAccount;
/**
* Every user can define its teams to authorize permissions to his/her repositories.
@ -34,7 +36,7 @@ import com.pmease.gitop.core.model.projectpermission.WholeProjectOperation;
@org.hibernate.annotations.Cache(
usage=org.hibernate.annotations.CacheConcurrencyStrategy.READ_WRITE)
@Table(uniqueConstraints={
@UniqueConstraint(columnNames={"project", "name"})
@UniqueConstraint(columnNames={"account", "name"})
})
@SuppressWarnings("serial")
public class Team extends AbstractEntity implements Permission {
@ -44,15 +46,18 @@ public class Team extends AbstractEntity implements Permission {
private String description;
private Optional<? extends WholeProjectOperation> authorizedWholeProjectAction = Optional.of(new PullFromProject());
private Optional<? extends AccountWideOperation> authorizedAccountWideOperation = Optional.of(new ReadFromAccount());
private List<OperationOfRepositorySet> authorizedRepositoryActions = new ArrayList<OperationOfRepositorySet>();
private List<OperationOfRepositorySet> authorizedRepositoryOperations = new ArrayList<OperationOfRepositorySet>();
@ManyToOne(fetch=FetchType.EAGER)
@org.hibernate.annotations.Fetch(FetchMode.SELECT)
@JoinColumn(nullable=false)
@org.hibernate.annotations.ForeignKey(name="FK_TEAM_PROJ")
private User project;
@org.hibernate.annotations.ForeignKey(name="FK_TEAM_ACC")
private Account account;
@OneToMany(mappedBy="team")
private Collection<Membership> memberships;
public String getName() {
return name;
@ -70,44 +75,52 @@ public class Team extends AbstractEntity implements Permission {
this.description = description;
}
public User getProject() {
return project;
public Account getAccount() {
return account;
}
public void setProject(User project) {
this.project = project;
public void setAccount(Account account) {
this.account = account;
}
public Optional<? extends WholeProjectOperation> getAuthorizedWholeProjectAction() {
return authorizedWholeProjectAction;
public Collection<Membership> getMemberships() {
return memberships;
}
public void setAuthorizedWholeProjectAction(
Optional<? extends WholeProjectOperation> authorizedWholeProjectAction) {
this.authorizedWholeProjectAction = authorizedWholeProjectAction;
public void setMemberships(Collection<Membership> memberships) {
this.memberships = memberships;
}
public List<OperationOfRepositorySet> getAuthorizedRepositoryActions() {
return authorizedRepositoryActions;
public Optional<? extends AccountWideOperation> getAuthorizedAccountWideOperation() {
return authorizedAccountWideOperation;
}
public void setAuthorizedRepositoryActions(
List<OperationOfRepositorySet> authorizedRepositoryActions) {
this.authorizedRepositoryActions = authorizedRepositoryActions;
public void setAuthorizedAccountWideOperation(
Optional<? extends AccountWideOperation> authorizedAccountWideOperation) {
this.authorizedAccountWideOperation = authorizedAccountWideOperation;
}
public List<OperationOfRepositorySet> getAuthorizedRepositoryOperations() {
return authorizedRepositoryOperations;
}
public void setAuthorizedRepositoryOperations(
List<OperationOfRepositorySet> authorizedRepositoryOperations) {
this.authorizedRepositoryOperations = authorizedRepositoryOperations;
}
@Override
public boolean implies(Permission permission) {
if (permission instanceof ProjectPermission) {
ProjectPermission projectPermission = (ProjectPermission) permission;
if (projectPermission.getProject().getId().equals(getProject().getId())) {
if (getAuthorizedWholeProjectAction().isPresent()) {
ProjectOperation projectAction = getAuthorizedWholeProjectAction().get();
if (projectAction.can(projectPermission.getOperation()))
if (permission instanceof AccountPermission) {
AccountPermission accountPermission = (AccountPermission) permission;
if (accountPermission.getAccount().getId().equals(getAccount().getId())) {
if (getAuthorizedAccountWideOperation().isPresent()) {
AccountOperation accountAction = getAuthorizedAccountWideOperation().get();
if (accountAction.can(accountPermission.getOperation()))
return true;
}
for (PrivilegedOperation action: getAuthorizedRepositoryActions()) {
if (action.can(projectPermission.getOperation()))
for (PrivilegedOperation action: getAuthorizedRepositoryOperations()) {
if (action.can(accountPermission.getOperation()))
return true;
}

View File

@ -0,0 +1,18 @@
package com.pmease.gitop.core.model.permission.account;
/**
* Account administrators can do anything inside an account.
*
* @author robin
*
*/
public class AccountAdministration implements AccountWideOperation {
@Override
public boolean can(PrivilegedOperation operation) {
return operation instanceof AccountAdministration
|| new WriteToAccount().can(operation);
}
}

View File

@ -0,0 +1,5 @@
package com.pmease.gitop.core.model.permission.account;
public interface AccountOperation extends PrivilegedOperation {
}

View File

@ -0,0 +1,79 @@
package com.pmease.gitop.core.model.permission.account;
import com.pmease.gitop.core.model.Account;
/**
* This interface serves as a mark up interface to indicate that all permissions
* implementing this interface are project level permissions.
*
* @author robin
*
*/
public class AccountPermission {
private Account account;
private AccountOperation operation;
public AccountPermission(Account account, AccountOperation operation) {
this.account = account;
this.operation = operation;
}
public Account getAccount() {
return account;
}
public void setAccount(Account account) {
this.account = account;
}
public AccountOperation getOperation() {
return operation;
}
public void setOperation(AccountOperation operation) {
this.operation = operation;
}
public static AccountPermission ofAccountAdmin(Account account) {
return new AccountPermission(account, new AccountAdministration());
}
public static AccountPermission ofAccountRead(Account account) {
return new AccountPermission(account, new ReadFromAccount());
}
public static AccountPermission ofAccountWrite(Account account) {
return new AccountPermission(account, new WriteToAccount());
}
public static AccountPermission ofRepositoryAdmin(Account account, String repositoryName) {
return new AccountPermission(account, new OperationOfRepositorySet(repositoryName, new RepositoryAdministration()));
}
public static AccountPermission ofRepositoryRead(Account account, String repositoryName) {
return new AccountPermission(account, new OperationOfRepositorySet(repositoryName, new ReadFromRepository()));
}
public static AccountPermission ofRepositoryWrite(Account account, String repositoryName) {
return new AccountPermission(account, new OperationOfRepositorySet(repositoryName, new WriteToRepository()));
}
public static AccountPermission ofBranchAdmin(Account account, String repositoryName, String branchName) {
return new AccountPermission(account, new OperationOfRepositorySet(repositoryName, new OperationOfBranchSet(branchName, new BranchAdministration())));
}
public static AccountPermission ofBranchRead(Account account, String repositoryName, String branchName) {
return new AccountPermission(account, new OperationOfRepositorySet(repositoryName, new OperationOfBranchSet(branchName, new ReadFromBranch())));
}
public static AccountPermission ofBranchWrite(Account account, String repositoryName, String branchName) {
return new AccountPermission(account, new OperationOfRepositorySet(repositoryName, new OperationOfBranchSet(branchName, new WriteToBranch("**"))));
}
public static AccountPermission ofBranchWrite(Account account, String repositoryName, String branchName, String filePath) {
return new AccountPermission(account, new OperationOfRepositorySet(repositoryName, new OperationOfBranchSet(branchName, new WriteToBranch(filePath))));
}
}

View File

@ -0,0 +1,5 @@
package com.pmease.gitop.core.model.permission.account;
public interface AccountWideOperation extends AccountOperation {
}

View File

@ -1,4 +1,4 @@
package com.pmease.gitop.core.model.projectpermission;
package com.pmease.gitop.core.model.permission.account;
public class BranchAdministration implements BranchOperation {

View File

@ -1,4 +1,4 @@
package com.pmease.gitop.core.model.projectpermission;
package com.pmease.gitop.core.model.permission.account;
public interface BranchOperation extends PrivilegedOperation {

View File

@ -1,4 +1,4 @@
package com.pmease.gitop.core.model.projectpermission;
package com.pmease.gitop.core.model.permission.account;
import com.pmease.commons.util.StringUtils;

View File

@ -1,8 +1,8 @@
package com.pmease.gitop.core.model.projectpermission;
package com.pmease.gitop.core.model.permission.account;
import com.pmease.commons.util.StringUtils;
public class OperationOfRepositorySet implements PrivilegedOperation {
public class OperationOfRepositorySet implements AccountOperation {
private String repositoryNames;

View File

@ -1,4 +1,4 @@
package com.pmease.gitop.core.model.projectpermission;
package com.pmease.gitop.core.model.permission.account;
/**
* This interface stands for an operation requires permissions.
@ -6,7 +6,7 @@ package com.pmease.gitop.core.model.projectpermission;
*/
public interface PrivilegedOperation {
/**
* Whether or not users with permission to perform current operation can perform
* Whether or not accounts with permission to perform current operation can perform
* specified operation.
*/
boolean can(PrivilegedOperation operation);

View File

@ -0,0 +1,11 @@
package com.pmease.gitop.core.model.permission.account;
public class ReadFromAccount implements AccountWideOperation {
@Override
public boolean can(PrivilegedOperation operation) {
return operation instanceof ReadFromAccount
|| new OperationOfRepositorySet("*", new ReadFromRepository()).can(operation);
}
}

View File

@ -0,0 +1,10 @@
package com.pmease.gitop.core.model.permission.account;
public class ReadFromBranch implements BranchOperation {
@Override
public boolean can(PrivilegedOperation operation) {
return operation instanceof ReadFromBranch;
}
}

View File

@ -1,4 +1,4 @@
package com.pmease.gitop.core.model.projectpermission;
package com.pmease.gitop.core.model.permission.account;
public class RepositoryAdministration implements RepositoryOperation {

View File

@ -0,0 +1,4 @@
package com.pmease.gitop.core.model.permission.account;
public interface RepositoryOperation extends PrivilegedOperation {
}

View File

@ -0,0 +1,12 @@
package com.pmease.gitop.core.model.permission.account;
public class WriteToAccount implements AccountWideOperation {
@Override
public boolean can(PrivilegedOperation operation) {
return operation instanceof WriteToAccount
|| new ReadFromAccount().can(operation)
|| new OperationOfRepositorySet("*", new WriteToRepository()).can(operation);
}
}

View File

@ -0,0 +1,33 @@
package com.pmease.gitop.core.model.permission.account;
import com.pmease.commons.util.PathUtils;
public class WriteToBranch implements BranchOperation {
private String filePaths;
public WriteToBranch(String filePaths) {
this.filePaths = filePaths;
}
public String getFilePaths() {
return filePaths;
}
public void setFilePaths(String filePaths) {
this.filePaths = filePaths;
}
@Override
public boolean can(PrivilegedOperation operation) {
if (operation instanceof ReadFromBranch) {
return true;
} else if (operation instanceof WriteToBranch) {
WriteToBranch writeOperation = (WriteToBranch) operation;
return PathUtils.match(filePaths, writeOperation.getFilePaths());
} else {
return false;
}
}
}

View File

@ -1,9 +1,9 @@
package com.pmease.gitop.core.model.role;
package com.pmease.gitop.core.model.permission.system;
import org.apache.shiro.authz.Permission;
@SuppressWarnings("serial")
public class SystemAdministrator implements Role {
public class SystemAdministration implements SystemPermission {
@Override
public boolean implies(Permission p) {

View File

@ -0,0 +1,9 @@
package com.pmease.gitop.core.model.permission.system;
import java.io.Serializable;
import org.apache.shiro.authz.Permission;
public interface SystemPermission extends Permission, Serializable {
}

View File

@ -1,18 +0,0 @@
package com.pmease.gitop.core.model.projectpermission;
/**
* Project administrators can do anything inside a project.
*
* @author robin
*
*/
public class ProjectAdministration implements WholeProjectOperation {
@Override
public boolean can(PrivilegedOperation operation) {
return operation instanceof ProjectAdministration
|| new PushToProject().can(operation);
}
}

View File

@ -1,5 +0,0 @@
package com.pmease.gitop.core.model.projectpermission;
public interface ProjectOperation extends PrivilegedOperation {
}

View File

@ -1,39 +0,0 @@
package com.pmease.gitop.core.model.projectpermission;
import com.pmease.gitop.core.model.User;
/**
* This interface serves as a mark up interface to indicate that all permissions
* implementing this interface are project level permissions.
*
* @author robin
*
*/
public class ProjectPermission {
private User project;
private ProjectOperation operation;
public ProjectPermission(User project, ProjectOperation operation) {
this.project = project;
this.operation = operation;
}
public User getProject() {
return project;
}
public void setProject(User project) {
this.project = project;
}
public ProjectOperation getOperation() {
return operation;
}
public void setOperation(ProjectOperation operation) {
this.operation = operation;
}
}

View File

@ -1,10 +0,0 @@
package com.pmease.gitop.core.model.projectpermission;
public class PullFromBranch implements BranchOperation {
@Override
public boolean can(PrivilegedOperation operation) {
return operation instanceof PullFromBranch;
}
}

View File

@ -1,11 +0,0 @@
package com.pmease.gitop.core.model.projectpermission;
public class PullFromProject implements WholeProjectOperation {
@Override
public boolean can(PrivilegedOperation operation) {
return operation instanceof PullFromProject
|| new OperationOfRepositorySet("*", new OperationOfBranchSet("**", new PullFromBranch())).can(operation);
}
}

View File

@ -1,33 +0,0 @@
package com.pmease.gitop.core.model.projectpermission;
import com.pmease.commons.util.PathUtils;
public class PushToBranch implements BranchOperation {
private String filePaths;
public PushToBranch(String filePaths) {
this.filePaths = filePaths;
}
public String getFilePaths() {
return filePaths;
}
public void setFilePaths(String filePaths) {
this.filePaths = filePaths;
}
@Override
public boolean can(PrivilegedOperation operation) {
if (operation instanceof PullFromBranch) {
return true;
} else if (operation instanceof PushToBranch) {
PushToBranch pushOperation = (PushToBranch) operation;
return PathUtils.match(filePaths, pushOperation.getFilePaths());
} else {
return false;
}
}
}

View File

@ -1,12 +0,0 @@
package com.pmease.gitop.core.model.projectpermission;
public class PushToProject implements WholeProjectOperation {
@Override
public boolean can(PrivilegedOperation operation) {
return operation instanceof PushToProject
|| new PullFromProject().can(operation)
|| new OperationOfRepositorySet("*", new OperationOfBranchSet("**", new PushToBranch("**"))).can(operation);
}
}

View File

@ -1,4 +0,0 @@
package com.pmease.gitop.core.model.projectpermission;
public interface RepositoryOperation extends ProjectOperation {
}

View File

@ -1,5 +0,0 @@
package com.pmease.gitop.core.model.projectpermission;
public interface WholeProjectOperation extends ProjectOperation {
}

View File

@ -1,24 +0,0 @@
package com.pmease.gitop.core.model.role;
import org.apache.shiro.authz.Permission;
/**
* Limited users can only browse the system without any other permissions.
* <p>
* They are not permitted to create repositories and teams.
* Since they can not create repositories, they will not be able to fork existing
* repositories even if those repositories are allowed to be forked.
*
* @author robin
*
*/
@SuppressWarnings("serial")
public class LimitedUser implements Role {
@Override
public boolean implies(Permission permission) {
return permission instanceof LimitedUser;
}
}

View File

@ -1,24 +0,0 @@
package com.pmease.gitop.core.model.role;
import org.apache.shiro.authz.Permission;
/**
* Normal users have all permissions of restricted users, and can also create their
* own repositories as well as being able to create teams.
* <p>
* They will be able to fork existing repositories if those repositories are allowed
* to be forked.
*
* @author robin
*
*/
@SuppressWarnings("serial")
public class NormalUser implements Role {
@Override
public boolean implies(Permission permission) {
return permission instanceof NormalUser
|| new LimitedUser().implies(permission);
}
}

View File

@ -1,22 +0,0 @@
package com.pmease.gitop.core.model.role;
import org.apache.shiro.authz.Permission;
/**
* Power users can do anything as system administrator except that they can not
* manage other user accounts and can not access repositories not authorized by
* the owners.
*
* @author robin
*
*/
@SuppressWarnings("serial")
public class PowerUser implements Role {
@Override
public boolean implies(Permission permission) {
return permission instanceof PowerUser
|| new NormalUser().implies(permission);
}
}

View File

@ -1,9 +0,0 @@
package com.pmease.gitop.core.model.role;
import java.io.Serializable;
import org.apache.shiro.authz.Permission;
public interface Role extends Permission, Serializable {
}

View File

@ -11,7 +11,7 @@ import org.apache.wicket.model.AbstractReadOnlyModel;
import com.pmease.commons.security.SecurityHelper;
import com.pmease.commons.web.asset.bootstrap.BootstrapResourceReference;
import com.pmease.gitop.core.model.User;
import com.pmease.gitop.core.model.Account;
@SuppressWarnings("serial")
public class HomePage extends WebPage {
@ -24,7 +24,7 @@ public class HomePage extends WebPage {
@Override
public String getObject() {
return SecurityHelper.getUserDisplayName(User.class, "Guest");
return SecurityHelper.getUserDisplayName(Account.class, "Guest");
}
}));

View File

@ -5,7 +5,8 @@ import org.junit.Test;
public class PermissionTest {
@Test
public void shouldOnlyPermitAuthorizedOperations() {
public void shouldPermitPullIfAllowedAnyPush() {
Team team = new Team();
}
}

View File

@ -26,7 +26,7 @@ import com.pmease.commons.loader.AbstractPlugin;
import com.pmease.commons.persistence.dao.GeneralDao;
import com.pmease.commons.util.FileUtils;
import com.pmease.commons.util.StringUtils;
import com.pmease.gitop.core.model.User;
import com.pmease.gitop.core.model.Account;
public class Product extends AbstractPlugin {
@ -115,10 +115,10 @@ public class Product extends AbstractPlugin {
@Override
public void postStartDependents() {
DetachedCriteria criteria = DetachedCriteria.forClass(User.class);
DetachedCriteria criteria = DetachedCriteria.forClass(Account.class);
criteria.add(Restrictions.eq("loginName", "admin"));
if (generalDao.find(criteria) == null) {
User user = new User();
Account user = new Account();
user.setName("admin");
user.setPasswordHash(passwordService.encryptPassword("12345"));
user.setFullName("Administrator");