/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed 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.keycloak.events.jpa;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.jboss.logging.Logger;
import org.keycloak.events.Event;
import org.keycloak.events.EventQuery;
import org.keycloak.events.EventStoreProvider;
import org.keycloak.events.EventType;
import org.keycloak.events.admin.AdminEvent;
import org.keycloak.events.admin.AdminEventQuery;
import org.keycloak.events.admin.AuthDetails;
import org.keycloak.events.admin.OperationType;
import org.keycloak.events.admin.ResourceType;
import javax.persistence.EntityManager;
import java.io.IOException;
import java.util.Map;
import java.util.UUID;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public class JpaEventStoreProvider implements EventStoreProvider {
private static final ObjectMapper mapper = new ObjectMapper();
private static final TypeReference<Map<String, String>> mapType = new TypeReference<Map<String, String>>() {
};
private static final Logger logger = Logger.getLogger(JpaEventStoreProvider.class);
private EntityManager em;
public JpaEventStoreProvider(EntityManager em) {
this.em = em;
}
@Override
public EventQuery createQuery() {
return new JpaEventQuery(em);
}
@Override
public void clear() {
em.createQuery("delete from EventEntity").executeUpdate();
}
@Override
public void clear(String realmId) {
em.createQuery("delete from EventEntity where realmId = :realmId").setParameter("realmId", realmId).executeUpdate();
}
@Override
public void clear(String realmId, long olderThan) {
em.createQuery("delete from EventEntity where realmId = :realmId and time < :time").setParameter("realmId", realmId).setParameter("time", olderThan).executeUpdate();
}
@Override
public void onEvent(Event event) {
em.persist(convertEvent(event));
}
@Override
public AdminEventQuery createAdminQuery() {
return new JpaAdminEventQuery(em);
}
@Override
public void clearAdmin() {
em.createQuery("delete from AdminEventEntity").executeUpdate();
}
@Override
public void clearAdmin(String realmId) {
em.createQuery("delete from AdminEventEntity where realmId = :realmId").setParameter("realmId", realmId).executeUpdate();
}
@Override
public void clearAdmin(String realmId, long olderThan) {
em.createQuery("delete from AdminEventEntity where realmId = :realmId and time < :time").setParameter("realmId", realmId).setParameter("time", olderThan).executeUpdate();
}
@Override
public void onEvent(AdminEvent event, boolean includeRepresentation) {
em.persist(convertAdminEvent(event, includeRepresentation));
}
@Override
public void close() {
}
static EventEntity convertEvent(Event event) {
EventEntity eventEntity = new EventEntity();
eventEntity.setId(UUID.randomUUID().toString());
eventEntity.setTime(event.getTime());
eventEntity.setType(event.getType().toString());
eventEntity.setRealmId(event.getRealmId());
eventEntity.setClientId(event.getClientId());
eventEntity.setUserId(event.getUserId());
eventEntity.setSessionId(event.getSessionId());
eventEntity.setIpAddress(event.getIpAddress());
eventEntity.setError(event.getError());
try {
eventEntity.setDetailsJson(mapper.writeValueAsString(event.getDetails()));
} catch (IOException ex) {
logger.error("Failed to write log details", ex);
}
return eventEntity;
}
static Event convertEvent(EventEntity eventEntity) {
Event event = new Event();
event.setTime(eventEntity.getTime());
event.setType(EventType.valueOf(eventEntity.getType()));
event.setRealmId(eventEntity.getRealmId());
event.setClientId(eventEntity.getClientId());
event.setUserId(eventEntity.getUserId());
event.setSessionId(eventEntity.getSessionId());
event.setIpAddress(eventEntity.getIpAddress());
event.setError(eventEntity.getError());
try {
Map<String, String> details = mapper.readValue(eventEntity.getDetailsJson(), mapType);
event.setDetails(details);
} catch (IOException ex) {
logger.error("Failed to read log details", ex);
}
return event;
}
static AdminEventEntity convertAdminEvent(AdminEvent adminEvent, boolean includeRepresentation) {
AdminEventEntity adminEventEntity = new AdminEventEntity();
adminEventEntity.setId(UUID.randomUUID().toString());
adminEventEntity.setTime(adminEvent.getTime());
adminEventEntity.setRealmId(adminEvent.getRealmId());
setAuthDetails(adminEventEntity, adminEvent.getAuthDetails());
adminEventEntity.setOperationType(adminEvent.getOperationType().toString());
if (adminEvent.getResourceType() != null) {
adminEventEntity.setResourceType(adminEvent.getResourceType().toString());
}
adminEventEntity.setResourcePath(adminEvent.getResourcePath());
adminEventEntity.setError(adminEvent.getError());
if(includeRepresentation) {
adminEventEntity.setRepresentation(adminEvent.getRepresentation());
}
return adminEventEntity;
}
static AdminEvent convertAdminEvent(AdminEventEntity adminEventEntity) {
AdminEvent adminEvent = new AdminEvent();
adminEvent.setTime(adminEventEntity.getTime());
adminEvent.setRealmId(adminEventEntity.getRealmId());
setAuthDetails(adminEvent, adminEventEntity);
adminEvent.setOperationType(OperationType.valueOf(adminEventEntity.getOperationType()));
if (adminEventEntity.getResourceType() != null) {
adminEvent.setResourceType(ResourceType.valueOf(adminEventEntity.getResourceType()));
}
adminEvent.setResourcePath(adminEventEntity.getResourcePath());
adminEvent.setError(adminEventEntity.getError());
if(adminEventEntity.getRepresentation() != null) {
adminEvent.setRepresentation(adminEventEntity.getRepresentation());
}
return adminEvent;
}
private static void setAuthDetails(AdminEventEntity adminEventEntity, AuthDetails authDetails) {
adminEventEntity.setAuthRealmId(authDetails.getRealmId());
adminEventEntity.setAuthClientId(authDetails.getClientId());
adminEventEntity.setAuthUserId(authDetails.getUserId());
adminEventEntity.setAuthIpAddress(authDetails.getIpAddress());
}
private static void setAuthDetails(AdminEvent adminEvent, AdminEventEntity adminEventEntity) {
AuthDetails authDetails = new AuthDetails();
authDetails.setRealmId(adminEventEntity.getAuthRealmId());
authDetails.setClientId(adminEventEntity.getAuthClientId());
authDetails.setUserId(adminEventEntity.getAuthUserId());
authDetails.setIpAddress(adminEventEntity.getAuthIpAddress());
adminEvent.setAuthDetails(authDetails);
}
}