package se.bjurr.prnfb.service;
import static com.atlassian.bitbucket.permission.Permission.PROJECT_ADMIN;
import static com.atlassian.bitbucket.permission.Permission.REPO_ADMIN;
import static com.atlassian.bitbucket.permission.Permission.SYS_ADMIN;
import static com.google.common.base.Strings.emptyToNull;
import static com.google.common.base.Throwables.propagate;
import static com.google.common.collect.Iterables.filter;
import static org.slf4j.LoggerFactory.getLogger;
import static se.bjurr.prnfb.settings.USER_LEVEL.ADMIN;
import static se.bjurr.prnfb.settings.USER_LEVEL.EVERYONE;
import java.util.List;
import javax.annotation.Nullable;
import org.slf4j.Logger;
import com.atlassian.bitbucket.permission.PermissionService;
import com.atlassian.bitbucket.project.Project;
import com.atlassian.bitbucket.project.ProjectService;
import com.atlassian.bitbucket.repository.Repository;
import com.atlassian.bitbucket.repository.RepositoryService;
import com.atlassian.bitbucket.user.SecurityService;
import com.atlassian.bitbucket.util.Operation;
import com.atlassian.sal.api.user.UserKey;
import com.atlassian.sal.api.user.UserManager;
import com.atlassian.sal.api.user.UserProfile;
import com.google.common.annotations.VisibleForTesting;
import se.bjurr.prnfb.settings.Restricted;
import se.bjurr.prnfb.settings.USER_LEVEL;
public class UserCheckService {
private static final Logger LOG = getLogger(UserCheckService.class);
private final PermissionService permissionService;
private final ProjectService projectService;
private final RepositoryService repositoryService;
private final SecurityService securityService;
private final SettingsService settingsService;
private final UserManager userManager;
public UserCheckService(
PermissionService permissionService,
UserManager userManager,
SettingsService settingsService,
RepositoryService repositoryService,
ProjectService projectService,
SecurityService securityService) {
this.userManager = userManager;
this.settingsService = settingsService;
this.permissionService = permissionService;
this.projectService = projectService;
this.repositoryService = repositoryService;
this.securityService = securityService;
}
public <R extends Restricted> Iterable<R> filterAllowed(USER_LEVEL adminRestriction, List<R> r) {
return filter(
r,
(c) ->
isAllowed( //
adminRestriction, //
c.getProjectKey().orNull(), //
c.getRepositorySlug().orNull()));
}
public <R extends Restricted> Iterable<R> filterAdminAllowed(List<R> list) {
return filter(list, (r) -> isAdminAllowed(r));
}
@VisibleForTesting
private Project getProject(String projectKey) {
try {
return securityService //
.withPermission(SYS_ADMIN, "Getting project") //
.call(
new Operation<Project, Exception>() {
@Override
public Project perform() throws Exception {
return projectService.getByKey(projectKey);
}
});
} catch (Exception e) {
throw propagate(e);
}
}
@VisibleForTesting
Repository getRepo(String projectKey, String repositorySlug) {
try {
return securityService //
.withPermission(SYS_ADMIN, "Getting repo") //
.call(
new Operation<Repository, Exception>() {
@Override
public Repository perform() throws Exception {
return repositoryService.getBySlug(projectKey, repositorySlug);
}
});
} catch (Exception e) {
throw propagate(e);
}
}
public boolean isAdmin(UserKey userKey, String projectKey, String repositorySlug) {
boolean isAdmin = userManager.isAdmin(userKey);
if (isAdmin) {
return isAdmin;
}
projectKey = emptyToNull(projectKey);
repositorySlug = emptyToNull(repositorySlug);
if (projectKey != null && repositorySlug == null) {
Project project = getProject(projectKey);
if (project == null) {
LOG.error("Button with project " + projectKey + " configured. But no such project exists!");
return false;
}
boolean isAllowed = permissionService.hasProjectPermission(project, PROJECT_ADMIN);
if (isAllowed) {
return true;
}
}
if (projectKey != null && repositorySlug != null) {
Repository repository = getRepo(projectKey, repositorySlug);
if (repository == null) {
LOG.error(
"Button with project "
+ projectKey
+ " and repo "
+ repositorySlug
+ " configured. But no such repo exists!");
return false;
}
return permissionService.hasRepositoryPermission(repository, REPO_ADMIN);
}
return false;
}
public boolean isAdminAllowed(Restricted restricted) {
USER_LEVEL adminRestriction = settingsService.getPrnfbSettingsData().getAdminRestriction();
String projectKey = restricted.getProjectKey().orNull();
String repositorySlug = restricted.getRepositorySlug().orNull();
return isAllowed(adminRestriction, projectKey, repositorySlug);
}
public boolean isAllowed(
USER_LEVEL userLevel, @Nullable String projectKey, @Nullable String repositorySlug) {
UserKey userKey = userManager.getRemoteUser().getUserKey();
boolean isAdmin = isAdmin(userKey, projectKey, repositorySlug);
boolean isSystemAdmin = isSystemAdmin(userKey);
return isAllowed(userLevel, isAdmin, isSystemAdmin);
}
boolean isAllowed(USER_LEVEL userLevel, boolean isAdmin, boolean isSystemAdmin) {
return userLevel == EVERYONE //
|| isSystemAdmin //
|| isAdmin && userLevel == ADMIN;
}
public boolean isSystemAdmin(UserKey userKey) {
return userManager.isSystemAdmin(userKey);
}
public boolean isViewAllowed() {
UserProfile user = userManager.getRemoteUser();
if (user == null) {
return false;
}
return true;
}
}