blob: 9ebb0eceb3bd69366a13d3d741b0d664ec42d21e [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.syncope.core.persistence.jpa.dao;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.Query;
import javax.persistence.TypedQuery;
import org.apache.syncope.common.lib.types.AnyTypeKind;
import org.apache.syncope.core.persistence.api.dao.AnyMatchDAO;
import org.apache.syncope.core.persistence.api.search.SearchCondConverter;
import org.apache.syncope.core.persistence.api.dao.RoleDAO;
import org.apache.syncope.core.persistence.api.dao.AnySearchDAO;
import org.apache.syncope.core.persistence.api.dao.DelegationDAO;
import org.apache.syncope.core.persistence.api.entity.Privilege;
import org.apache.syncope.core.persistence.api.entity.Realm;
import org.apache.syncope.core.persistence.api.entity.Role;
import org.apache.syncope.core.persistence.api.entity.user.User;
import org.apache.syncope.core.persistence.api.search.SearchCondVisitor;
import org.apache.syncope.core.persistence.jpa.entity.JPARole;
import org.apache.syncope.core.persistence.jpa.entity.user.JPAUser;
import org.apache.syncope.core.provisioning.api.event.AnyCreatedUpdatedEvent;
import org.apache.syncope.core.spring.security.AuthContextUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
@Repository
public class JPARoleDAO extends AbstractDAO<Role> implements RoleDAO {
public static final String DYNMEMB_TABLE = "DynRoleMembers";
@Autowired
private AnyMatchDAO anyMatchDAO;
@Autowired
private ApplicationEventPublisher publisher;
@Autowired
private AnySearchDAO searchDAO;
@Autowired
private DelegationDAO delegationDAO;
@Autowired
private SearchCondVisitor searchCondVisitor;
@Override
public int count() {
Query query = entityManager().createQuery(
"SELECT COUNT(e) FROM " + JPARole.class.getSimpleName() + " e");
return ((Number) query.getSingleResult()).intValue();
}
@Override
public Role find(final String key) {
return entityManager().find(JPARole.class, key);
}
@Override
public List<Role> findByRealm(final Realm realm) {
TypedQuery<Role> query = entityManager().createQuery(
"SELECT e FROM " + JPARole.class.getSimpleName() + " e WHERE :realm MEMBER OF e.realms", Role.class);
query.setParameter("realm", realm);
return query.getResultList();
}
@Override
public List<Role> findByPrivilege(final Privilege privilege) {
TypedQuery<Role> query = entityManager().createQuery(
"SELECT e FROM " + JPARole.class.getSimpleName() + " e WHERE :privilege MEMBER OF e.privileges",
Role.class);
query.setParameter("privilege", privilege);
return query.getResultList();
}
@Override
public List<Role> findAll() {
TypedQuery<Role> query = entityManager().createQuery(
"SELECT e FROM " + JPARole.class.getSimpleName() + " e ", Role.class);
return query.getResultList();
}
@Override
public Role save(final Role role) {
return entityManager().merge(role);
}
@Override
public Role saveAndRefreshDynMemberships(final Role role) {
Role merged = save(role);
// refresh dynamic memberships
clearDynMembers(merged);
if (merged.getDynMembership() != null) {
List<User> matching = searchDAO.search(
SearchCondConverter.convert(searchCondVisitor, merged.getDynMembership().getFIQLCond()),
AnyTypeKind.USER);
matching.forEach((user) -> {
Query insert = entityManager().createNativeQuery("INSERT INTO " + DYNMEMB_TABLE + " VALUES(?, ?)");
insert.setParameter(1, user.getKey());
insert.setParameter(2, merged.getKey());
insert.executeUpdate();
publisher.publishEvent(new AnyCreatedUpdatedEvent<>(this, user, AuthContextUtils.getDomain()));
});
}
return merged;
}
@Override
public void delete(final Role role) {
TypedQuery<User> query = entityManager().createQuery(
"SELECT e FROM " + JPAUser.class.getSimpleName() + " e WHERE :role MEMBER OF e.roles", User.class);
query.setParameter("role", role);
query.getResultList().forEach(user -> {
user.getRoles().remove(role);
publisher.publishEvent(new AnyCreatedUpdatedEvent<>(this, user, AuthContextUtils.getDomain()));
});
clearDynMembers(role);
delegationDAO.findByRole(role).forEach(delegation -> delegation.getRoles().remove(role));
entityManager().remove(role);
}
@Override
public void delete(final String key) {
Role role = find(key);
if (role == null) {
return;
}
delete(role);
}
@Override
@SuppressWarnings("unchecked")
public List<String> findDynMembers(final Role role) {
if (role.getDynMembership() == null) {
return List.of();
}
Query query = entityManager().createNativeQuery("SELECT any_id FROM " + DYNMEMB_TABLE + " WHERE role_id=?");
query.setParameter(1, role.getKey());
List<String> result = new ArrayList<>();
query.getResultList().stream().map(key -> key instanceof Object[]
? (String) ((Object[]) key)[0]
: ((String) key)).
forEach(user -> result.add((String) user));
return result;
}
@Override
public void clearDynMembers(final Role role) {
Query delete = entityManager().createNativeQuery("DELETE FROM " + DYNMEMB_TABLE + " WHERE role_id=?");
delete.setParameter(1, role.getKey());
delete.executeUpdate();
}
@Transactional
@Override
public void refreshDynMemberships(final User user) {
Query query = entityManager().createNativeQuery(
"SELECT role_id FROM " + DYNMEMB_TABLE + " WHERE any_id=?");
query.setParameter(1, user.getKey());
findAll().stream().filter(role -> role.getDynMembership() != null).forEach(role -> {
boolean matches = anyMatchDAO.matches(
user, SearchCondConverter.convert(searchCondVisitor, role.getDynMembership().getFIQLCond()));
Query find = entityManager().createNativeQuery(
"SELECT any_id FROM " + DYNMEMB_TABLE + " WHERE role_id=?");
find.setParameter(1, role.getKey());
boolean existing = !find.getResultList().isEmpty();
if (matches && !existing) {
Query insert = entityManager().createNativeQuery(
"INSERT INTO " + DYNMEMB_TABLE + " VALUES(?, ?)");
insert.setParameter(1, user.getKey());
insert.setParameter(2, role.getKey());
insert.executeUpdate();
} else if (!matches && existing) {
Query delete = entityManager().createNativeQuery(
"DELETE FROM " + DYNMEMB_TABLE + " WHERE role_id=? AND any_id=?");
delete.setParameter(1, role.getKey());
delete.setParameter(2, user.getKey());
delete.executeUpdate();
}
});
}
@Override
public void removeDynMemberships(final String key) {
Query delete = entityManager().createNativeQuery("DELETE FROM " + DYNMEMB_TABLE + " WHERE any_id=?");
delete.setParameter(1, key);
delete.executeUpdate();
}
}