Skip to content

Commit

Permalink
feature: Add functionality to capture user events in the database and…
Browse files Browse the repository at this point in the history
… create views to display info in panoply
  • Loading branch information
DanielPalafox committed Oct 25, 2023
1 parent 498c987 commit 43baa3e
Show file tree
Hide file tree
Showing 21 changed files with 543 additions and 7 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package org.orcid.core.common.manager;

import org.orcid.core.utils.EventType;
import org.orcid.pojo.ajaxForm.RequestInfoForm;

import javax.servlet.http.HttpServletRequest;

/**
*
* @author Daniel Palafox
*
*/
public interface EventManager {

boolean removeEvents(String orcid);

void createEvent(String orcid, EventType eventType, HttpServletRequest request, RequestInfoForm requestInfoForm);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
package org.orcid.core.common.manager.impl;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang.StringUtils;
import org.orcid.core.common.manager.EventManager;
import org.orcid.core.constants.OrcidOauth2Constants;
import org.orcid.core.manager.ClientDetailsEntityCacheManager;
import org.orcid.core.utils.EventType;
import org.orcid.persistence.dao.EventDao;
import org.orcid.persistence.jpa.entities.ClientDetailsEntity;
import org.orcid.persistence.jpa.entities.EventEntity;
import org.orcid.pojo.ajaxForm.RequestInfoForm;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;

/**
*
* @author Daniel Palafox
*
*/
public class EventManagerImpl implements EventManager {

@Resource
private EventDao eventDao;

@Resource
private ClientDetailsEntityCacheManager clientDetailsEntityCacheManager;

@Override
public boolean removeEvents(String orcid) {
return eventDao.removeEvents(orcid);
}

@Override
public void createEvent(String orcid, EventType eventType, HttpServletRequest request, RequestInfoForm requestInfoForm) {
String label = null;
String clientId = null;
String redirectUrl = null;
String publicPage = null;

switch (eventType) {
case PUBLIC_PAGE:
publicPage = orcid;
orcid = null;
break;
case REAUTHORIZE:
clientId = requestInfoForm.getClientId();
redirectUrl = requestInfoForm.getRedirectUrl();
label = "OAuth " + requestInfoForm.getClientName();
break;
default:
if (request != null) {
Boolean isOauth2ScreensRequest = (Boolean) request.getSession().getAttribute(OrcidOauth2Constants.OAUTH_2SCREENS);
if (isOauth2ScreensRequest != null && isOauth2ScreensRequest) {
String queryString = (String) request.getSession().getAttribute(OrcidOauth2Constants.OAUTH_QUERY_STRING);
clientId = getParameterValue(queryString, "client_id");
redirectUrl = getParameterValue(queryString, "redirect_uri");
ClientDetailsEntity clientDetailsEntity = clientDetailsEntityCacheManager.retrieve(clientId);
label = "OAuth " + clientDetailsEntity.getClientName();
}
} else {
label = "Website";
}
}

EventEntity eventEntity = new EventEntity();

eventEntity.setOrcid(orcid);
eventEntity.setEventType(eventType.getValue());
eventEntity.setClientId(clientId);
eventEntity.setRedirectUrl(redirectUrl);
eventEntity.setLabel(label);
eventEntity.setPublicPage(publicPage);

eventDao.createEvent(eventEntity);
}

private String getParameterValue(String queryString, String parameter) {
if (StringUtils.isNotEmpty(queryString)) {
try {
queryString = URLDecoder.decode(queryString, StandardCharsets.UTF_8.toString());
} catch (UnsupportedEncodingException u) {
// l
}
String[] parameters = queryString.split("&");
for (String p : parameters) {
String[] keyValuePair = p.split("=");
if (parameter.equals(keyValuePair[0])) {
return keyValuePair[1];
}
}
}
return null;
}
}
3 changes: 3 additions & 0 deletions orcid-core/src/main/java/org/orcid/core/togglz/Features.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
import org.togglz.core.context.FeatureContext;

public enum Features implements Feature {
@Label("Track user events")
EVENTS,

@Label("Source sorting")
SOURCE_SORTING,

Expand Down
20 changes: 20 additions & 0 deletions orcid-core/src/main/java/org/orcid/core/utils/EventType.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package org.orcid.core.utils;

public enum EventType {
SIGN_IN("Sign-In"),
NEW_REGISTRATION("New-Registration"),
AUTHORIZE("Authorize"),
AUTHORIZE_DENY("Authorize-Deny"),
REAUTHORIZE("Reauthorize"),
PUBLIC_PAGE("Public-Page");

private final String value;

EventType(String v) {
value = v;
}

public String getValue() {
return value;
}
}
2 changes: 2 additions & 0 deletions orcid-core/src/main/resources/orcid-core-context.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1214,4 +1214,6 @@
<constructor-arg index="3" value="${org.orcid.core.utils.cache.redis.expiration_in_secs:600}" />
</bean>

<bean id="eventManager" class="org.orcid.core.common.manager.impl.EventManagerImpl"/>

</beans>
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package org.orcid.persistence.dao;

import org.orcid.persistence.jpa.entities.EventEntity;

import java.util.List;

/**
*
* @author Daniel Palafox
*
*/
public interface EventDao extends GenericDao<EventEntity, Long>{

boolean removeEvents(String orcid);

List<EventEntity> getEvents(String orcid);

void createEvent(EventEntity eventEntity);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package org.orcid.persistence.dao.impl;

import org.orcid.persistence.aop.UpdateProfileLastModified;
import org.orcid.persistence.dao.EventDao;
import org.orcid.persistence.jpa.entities.EmailEntity;
import org.orcid.persistence.jpa.entities.EventEntity;
import org.orcid.persistence.jpa.entities.SpamEntity;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.Query;
import javax.persistence.TypedQuery;
import java.util.List;

/**
* @author Daniel Palafox
*/
public class EventDaoImpl extends GenericDaoImpl<EventEntity, Long> implements EventDao {

public EventDaoImpl() {
super(EventEntity.class);
}

@Override
public List<EventEntity> getEvents(String orcid) {
TypedQuery<EventEntity> query = entityManager.createQuery("from EventEntity where orcid=:orcid", EventEntity.class);
query.setParameter("orcid", orcid);
List<EventEntity> results = query.getResultList();
return results.isEmpty() ? null : results;
}

@Override
@Transactional
public void createEvent(EventEntity eventEntity) {
entityManager.persist(eventEntity);
}

@Override
@Transactional
public boolean removeEvents(String orcid) {
Query query = entityManager.createQuery("delete from EventEntity where orcid = :orcid");
query.setParameter("orcid", orcid);
query.executeUpdate();
return query.executeUpdate() > 0;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package org.orcid.persistence.jpa.entities;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;

/**
*
* @author Daniel Palafox
*
*/
@Entity
@Table(name = "event")
public class EventEntity extends BaseEntity<Long> implements OrcidAware {
private static final long serialVersionUID = 1L;
private Long id;
private String orcid;
private String eventType;
private String clientId;
private String redirectUrl;
private String label;
private String publicPage;

@Id
@Column(name = "id")
@GeneratedValue(strategy = GenerationType.AUTO, generator = "event_seq")
@SequenceGenerator(name = "event_seq", sequenceName = "event_seq", allocationSize = 1)
public Long getId() {
return id;
}

public void setId(Long id) {
this.id = id;
}

@Column(name = "orcid")
public String getOrcid() {
return orcid;
}

public void setOrcid(String orcid) {
this.orcid = orcid;
}

@Column(name = "event_type")
public String getEventType() { return eventType; }

public void setEventType(String eventType) { this.eventType = eventType; }

@Column(name = "client_id")
public String getClientId() { return clientId; }

public void setClientId(String client_id) { this.clientId = client_id; }

@Column(name = "redirect_url")
public String getRedirectUrl() { return redirectUrl; }

public void setRedirectUrl(String redirect_url) { this.redirectUrl = redirect_url; }

@Column(name = "label")
public String getLabel() { return label; }

public void setLabel(String label) { this.label = label; }

@Column(name = "public_page")
public String getPublicPage() { return publicPage; }

public void setPublicPage(String public_page) { this.publicPage = public_page; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@
<class>org.orcid.persistence.jpa.entities.ResearchResourceItemEntity</class>
<class>org.orcid.persistence.jpa.entities.FindMyStuffHistoryEntity</class>
<class>org.orcid.persistence.jpa.entities.SpamEntity</class>
<class>org.orcid.persistence.jpa.entities.EventEntity</class>

<!-- OAuth entities -->
<class>org.orcid.persistence.jpa.entities.ClientDetailsEntity</class>
Expand Down Expand Up @@ -104,4 +105,4 @@

</persistence-unit>

</persistence>
</persistence>
4 changes: 3 additions & 1 deletion orcid-persistence/src/main/resources/db-master.xml
Original file line number Diff line number Diff line change
Expand Up @@ -373,4 +373,6 @@
<include file="/db/updates/statistics.xml" />
<include file="/db/updates/identifier-types/update-ethos-to-be-case-sensitive.xml" />
<include file="/db/updates/dw_client_details_add_user_obo_enabled.xml" />
</databaseChangeLog>
<include file="/db/updates/create_event_table.xml" />
<include file="/db/updates/dw_event.xml" />
</databaseChangeLog>
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-2.0.xsd">

<changeSet id="CREATE-EVENT-TABLE" author="Daniel Palafox">
<createTable tableName="event">
<column name="id" type="bigint">
<constraints nullable="false" primaryKey="true"
primaryKeyName="event_pkey"/>
</column>
<column name="orcid" type="VARCHAR(19)"/>
<column name="event_type" type="VARCHAR(20)"/>
<column name="client_id" type="VARCHAR(255)"/>
<column name="redirect_url" type="VARCHAR(255)"/>
<column name="label" type="VARCHAR(255)"/>
<column name="public_page" type="VARCHAR(19)"/>
<column name="date_created" type="TIMESTAMP WITH TIME ZONE"/>
<column name="last_modified" type="TIMESTAMP WITH TIME ZONE"/>
</createTable>

<addForeignKeyConstraint constraintName="event_orcid_fk" baseTableName="event"
baseColumnNames="orcid" referencedTableName="profile" referencedColumnNames="orcid"/>
</changeSet>

<changeSet id="CREATE-EVENT-SEQUENCES" author="Daniel Palafox" dbms="postgresql">
<preConditions onFail="MARK_RAN">
<not>
<sequenceExists sequenceName="event_seq"/>
</not>
</preConditions>
<createSequence sequenceName="event_seq"/>
</changeSet>

<changeSet id="CREATE-EVENT-AUTOCOLS" author="Daniel Palafox" dbms="hsqldb">
<addAutoIncrement tableName="event" columnName="id" columnDataType="bigint"/>
</changeSet>

<changeSet id="GRANT-READ-PERMISSIONS-TO-ORCIDRO-ON-EVENT" author="Daniel Palafox" dbms="postgresql">
<preConditions>
<sqlCheck expectedResult="1">SELECT 1 FROM pg_roles WHERE rolname='orcidro'</sqlCheck>
</preConditions>
<sql>GRANT SELECT ON event to orcidro;</sql>
</changeSet>

</databaseChangeLog>
Loading

0 comments on commit 43baa3e

Please sign in to comment.