/*
* This file is part of ARSnova Backend.
* Copyright (C) 2012-2017 The ARSnova Team
*
* ARSnova Backend 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.
*
* ARSnova Backend 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 de.thm.arsnova.security;
import com.github.leleuj.ss.oauth.client.authentication.OAuthAuthenticationToken;
import de.thm.arsnova.dao.IDatabaseDao;
import de.thm.arsnova.entities.InterposedQuestion;
import de.thm.arsnova.entities.Question;
import de.thm.arsnova.entities.Session;
import de.thm.arsnova.entities.User;
import de.thm.arsnova.exceptions.UnauthorizedException;
import org.scribe.up.profile.facebook.FacebookProfile;
import org.scribe.up.profile.google.Google2Profile;
import org.scribe.up.profile.twitter.TwitterProfile;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.access.PermissionEvaluator;
import org.springframework.security.authentication.AnonymousAuthenticationToken;
import org.springframework.security.core.Authentication;
import java.io.Serializable;
import java.util.Arrays;
/**
* Provides access control methods that can be used in annotations.
*/
public class ApplicationPermissionEvaluator implements PermissionEvaluator {
@Value("${security.admin-accounts}")
private String[] adminAccounts;
@Autowired
private IDatabaseDao dao;
@Override
public boolean hasPermission(
final Authentication authentication,
final Object targetDomainObject,
final Object permission
) {
final String username = getUsername(authentication);
if (checkAdminPermission(username)) {
return true;
} else if (
targetDomainObject instanceof Session
&& checkSessionPermission(username, ((Session) targetDomainObject).getKeyword(), permission)
) {
return true;
}
return false;
}
@Override
public boolean hasPermission(
final Authentication authentication,
final Serializable targetId,
final String targetType,
final Object permission
) {
final String username = getUsername(authentication);
if (checkAdminPermission(username)) {
return true;
} else if (
"session".equals(targetType)
&& checkSessionPermission(username, targetId, permission)) {
return true;
} else if (
"question".equals(targetType)
&& checkQuestionPermission(username, targetId, permission)
) {
return true;
} else if (
"interposedquestion".equals(targetType)
&& checkInterposedQuestionPermission(username, targetId, permission)
) {
return true;
}
return false;
}
private boolean checkAdminPermission(final String username) {
/* TODO: only allow accounts from arsnova db */
return Arrays.asList(adminAccounts).contains(username);
}
private boolean checkSessionPermission(
final String username,
final Serializable targetId,
final Object permission
) {
if (permission instanceof String && ("owner".equals(permission) || "write".equals(permission))) {
return dao.getSessionFromKeyword(targetId.toString()).getCreator().equals(username);
} else if (permission instanceof String && "read".equals(permission)) {
return dao.getSessionFromKeyword(targetId.toString()).isActive();
}
return false;
}
private boolean checkQuestionPermission(
final String username,
final Serializable targetId,
final Object permission
) {
if (permission instanceof String && "owner".equals(permission)) {
final Question question = dao.getQuestion(targetId.toString());
if (question != null) {
final Session session = dao.getSessionFromId(question.getSessionId());
return session != null && session.getCreator().equals(username);
}
}
return false;
}
private boolean checkInterposedQuestionPermission(
final String username,
final Serializable targetId,
final Object permission
) {
if (permission instanceof String && "owner".equals(permission)) {
final InterposedQuestion question = dao.getInterposedQuestion(targetId.toString());
if (question != null) {
// Does the creator want to delete his own question?
if (question.getCreator() != null && question.getCreator().equals(username)) {
return true;
}
// Allow deletion if requested by session owner
final Session session = dao.getSessionFromKeyword(question.getSessionId());
return session != null && session.getCreator().equals(username);
}
}
return false;
}
private String getUsername(final Authentication authentication) {
if (authentication == null || authentication instanceof AnonymousAuthenticationToken) {
throw new UnauthorizedException();
}
if (authentication instanceof OAuthAuthenticationToken) {
User user = null;
final OAuthAuthenticationToken token = (OAuthAuthenticationToken) authentication;
if (token.getUserProfile() instanceof Google2Profile) {
final Google2Profile profile = (Google2Profile) token.getUserProfile();
user = new User(profile);
} else if (token.getUserProfile() instanceof TwitterProfile) {
final TwitterProfile profile = (TwitterProfile) token.getUserProfile();
user = new User(profile);
} else if (token.getUserProfile() instanceof FacebookProfile) {
final FacebookProfile profile = (FacebookProfile) token.getUserProfile();
user = new User(profile);
}
if (user != null) {
return user.getUsername();
}
}
return authentication.getName();
}
}