Index: lams_admin/conf/language/lams/ApplicationResources.properties =================================================================== diff -u -rc368a79cdaf7adf21f3185b6bdccd024320982c9 -r5f82321c5864250c612773630ff209a45e71a3f1 --- lams_admin/conf/language/lams/ApplicationResources.properties (.../ApplicationResources.properties) (revision c368a79cdaf7adf21f3185b6bdccd024320982c9) +++ lams_admin/conf/language/lams/ApplicationResources.properties (.../ApplicationResources.properties) (revision 5f82321c5864250c612773630ff209a45e71a3f1) @@ -527,4 +527,11 @@ sysadmin.lesson.delete.title =Delete all lessons from course msg.delete.organisation.confirm =You are about to permanently remove a course. Are you sure want to do this? msg.delete.organisation.delete.lessons.confirm =The course or one of its subcourses still contains lessons. They need to be permanently deleted first. You will be redirected to a page where you can do it. +label.event.log=Event (Audit) Log +label.event.topic=Topic +label.event.type=Type of Event +label.select.topic=Select topic... +label.select.type=Select type... +label.date=Date +label.between.dates=Between dates #======= End labels: Exported 511 labels for en AU ===== Index: lams_admin/src/java/org/lamsfoundation/lams/admin/web/action/LogEventAction.java =================================================================== diff -u --- lams_admin/src/java/org/lamsfoundation/lams/admin/web/action/LogEventAction.java (revision 0) +++ lams_admin/src/java/org/lamsfoundation/lams/admin/web/action/LogEventAction.java (revision 5f82321c5864250c612773630ff209a45e71a3f1) @@ -0,0 +1,195 @@ +/**************************************************************** + * Copyright (C) 2006 LAMS Foundation (http://lamsfoundation.org) + * ============================================================= + * License Information: http://lamsfoundation.org/licensing/lams/2.0/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2.0 + * as published by the Free Software Foundation. + * + * This program 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + * + * http://www.gnu.org/licenses/gpl.txt + * **************************************************************** + */ +package org.lamsfoundation.lams.admin.web.action; + +import java.io.IOException; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.TimeZone; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; + +import org.apache.struts.action.ActionForm; +import org.apache.struts.action.ActionForward; +import org.apache.struts.action.ActionMapping; +import org.apache.tomcat.util.json.JSONArray; +import org.apache.tomcat.util.json.JSONException; +import org.apache.tomcat.util.json.JSONObject; +import org.lamsfoundation.lams.admin.service.AdminServiceProxy; +import org.lamsfoundation.lams.logevent.LogEvent; +import org.lamsfoundation.lams.logevent.LogEventType; +import org.lamsfoundation.lams.logevent.dto.LogEventTypeDTO; +import org.lamsfoundation.lams.logevent.service.ILogEventService; +import org.lamsfoundation.lams.usermanagement.Role; +import org.lamsfoundation.lams.usermanagement.User; +import org.lamsfoundation.lams.util.WebUtil; +import org.lamsfoundation.lams.web.action.LamsDispatchAction; +import org.lamsfoundation.lams.web.session.SessionManager; +import org.lamsfoundation.lams.web.util.AttributeNames; +import org.springframework.web.context.WebApplicationContext; +import org.springframework.web.context.support.WebApplicationContextUtils; + +/** + * Report on events in the log event table. Used for auditing. + */ +public class LogEventAction extends LamsDispatchAction { + + private static ILogEventService logEventService; + private static SimpleDateFormat START_DATE_FORMAT = new SimpleDateFormat("YYYY-MM-DD"); + + @Override + public ActionForward unspecified(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws Exception { + + // check permission + if (!request.isUserInRole(Role.SYSADMIN)) { + request.setAttribute("errorName", "EventLogAdmin"); + request.setAttribute("errorMessage", AdminServiceProxy.getMessageService(getServlet().getServletContext()) + .getMessage("error.authorisation")); + return mapping.findForward("error"); + } + + // user timezone + HttpSession ss = SessionManager.getSession(); + org.lamsfoundation.lams.usermanagement.dto.UserDTO user = (org.lamsfoundation.lams.usermanagement.dto.UserDTO) ss + .getAttribute(AttributeNames.USER); + TimeZone userTimeZone = user.getTimeZone(); + + logEventService = getLogEventService(); + + // get the log type data and return display for user selection. Also get the start and stop dates from the log. + // TODO check conversion the dates to the user's timezone + List types = logEventService.getEventTypes(); + List convertedTypes = new ArrayList(types.size()); + for ( LogEventType type : types ) { + // TODO get message from the I18N files + convertedTypes.add(new LogEventTypeDTO(type, type.getDescription().toLowerCase(), type.getArea().toLowerCase())); + } + request.setAttribute("eventLogTypes", convertedTypes); + + // jsp page expects date of the first audit log entry as YYYY-DD-MM. + Date oldestDate = logEventService.getOldestEventDate(); +// oldestDate = DateUtil.convertToTimeZoneFromDefault(userTimeZone, oldestDate); + request.setAttribute("startDate", START_DATE_FORMAT.format(oldestDate)); + return mapping.findForward("success"); + } + + /** + * The initial method for monitoring. List all users according to given Content ID. + * + * @param mapping + * @param form + * @param request + * @param response + * @return + * @return + * @throws JSONException + * @throws ServletException + * @throws IOException + */ + public ActionForward getEventLog(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws JSONException, ServletException, IOException { + + // check permission + if (!request.isUserInRole(Role.SYSADMIN)) { + request.setAttribute("errorName", "EventLogAdmin"); + request.setAttribute("errorMessage", AdminServiceProxy.getMessageService(getServlet().getServletContext()) + .getMessage("error.authorisation")); + return mapping.findForward("error"); + } + + logEventService = getLogEventService(); + + // paging parameters of tablesorter + int size = WebUtil.readIntParam(request, "size"); + int page = WebUtil.readIntParam(request, "page"); + Integer isSort1 = WebUtil.readIntParam(request, "column[0]", true); + String searchString = request.getParameter("fcol[0]"); + + int sorting = ILogEventService.SORT_BY_DATE_ASC; + if ((isSort1 != null) && isSort1.equals(1)) { + sorting = ILogEventService.SORT_BY_DATE_DESC; + } + + Long dateParameter = WebUtil.readLongParam(request, "startDate", true); + Date startDate = null; + if (dateParameter != null) { + startDate = new Date(dateParameter); + // TODO if using time zones then convert to server timezone +// HttpSession ss = SessionManager.getSession(); +// org.lamsfoundation.lams.usermanagement.dto.UserDTO teacher = (org.lamsfoundation.lams.usermanagement.dto.UserDTO) ss +// .getAttribute(AttributeNames.USER); +// TimeZone teacherTimeZone = teacher.getTimeZone(); +// tzSubmissionDeadline = DateUtil.convertFromTimeZoneToDefault(teacherTimeZone, submissionDeadline); + } + + dateParameter = WebUtil.readLongParam(request, "endDate", true); + Date endDate = null; + if (dateParameter != null) { + endDate = new Date(dateParameter); + } + + String area = WebUtil.readStrParam(request, "area", true); + Integer typeId = WebUtil.readIntParam(request, "typeId", true); + List events = logEventService.getEventsForTablesorter(page, size, sorting, null, startDate, endDate, area, typeId); + + JSONArray rows = new JSONArray(); + JSONObject responsedata = new JSONObject(); + responsedata.put("total_rows", logEventService.countEventsWithRestrictions(null, startDate, endDate, area, typeId)); + + for (LogEvent event: events) { + + JSONObject responseRow = new JSONObject(); + + responseRow.put("dateOccurred", event.getOccurredDateTime()); + responseRow.put("typeId", event.getLogEventTypeId()); + responseRow.put("description", event.getDescription()); + User user = event.getUser(); + if ( user != null ) { + responseRow.put("userPortraitId", user.getPortraitUuid()); + responseRow.put("userId", user.getUserId()); + responseRow.put("userName", user.getLogin()); + } + rows.put(responseRow); + } + responsedata.put("rows", rows); + response.setContentType("application/json;charset=utf-8"); + response.getWriter().print(new String(responsedata.toString())); + return null; + } + + private ILogEventService getLogEventService() throws ServletException { + if (logEventService == null) { + WebApplicationContext ctx = WebApplicationContextUtils + .getRequiredWebApplicationContext(getServlet().getServletContext()); + logEventService = (ILogEventService) ctx.getBean("logEventService"); + } + return logEventService; + } + +} Index: lams_admin/src/java/org/lamsfoundation/lams/admin/web/action/SysAdminStartAction.java =================================================================== diff -u -r21991bdc561db26de7c7e0687a10b2c2d7743074 -r5f82321c5864250c612773630ff209a45e71a3f1 --- lams_admin/src/java/org/lamsfoundation/lams/admin/web/action/SysAdminStartAction.java (.../SysAdminStartAction.java) (revision 21991bdc561db26de7c7e0687a10b2c2d7743074) +++ lams_admin/src/java/org/lamsfoundation/lams/admin/web/action/SysAdminStartAction.java (.../SysAdminStartAction.java) (revision 5f82321c5864250c612773630ff209a45e71a3f1) @@ -24,6 +24,7 @@ package org.lamsfoundation.lams.admin.web.action; import java.util.ArrayList; + import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -67,6 +68,7 @@ groupedLinks.add(new Object[]{AdminConstants.START_CONFIG_LINKS,links}); links = new ArrayList(); + links.add(new LinkBean("logevent.do", "label.event.log")); links.add(new LinkBean("cleanup.do", "sysadmin.batch.temp.file.delete")); links.add(new LinkBean("cleanupPreviewLessons.do", "sysadmin.batch.preview.lesson.delete")); links.add(new LinkBean("statistics.do", "admin.statistics.title")); Index: lams_admin/web/WEB-INF/struts-config.xml =================================================================== diff -u -r5f626596bbeb5bbbbd800be3ddf6ff7f1bdaeaa6 -r5f82321c5864250c612773630ff209a45e71a3f1 --- lams_admin/web/WEB-INF/struts-config.xml (.../struts-config.xml) (revision 5f626596bbeb5bbbbd800be3ddf6ff7f1bdaeaa6) +++ lams_admin/web/WEB-INF/struts-config.xml (.../struts-config.xml) (revision 5f82321c5864250c612773630ff209a45e71a3f1) @@ -875,6 +875,27 @@ /> + + + + + + + + + Index: lams_admin/web/logevent.jsp =================================================================== diff -u --- lams_admin/web/logevent.jsp (revision 0) +++ lams_admin/web/logevent.jsp (revision 5f82321c5864250c612773630ff209a45e71a3f1) @@ -0,0 +1,214 @@ +<%@ include file="/taglibs.jsp"%> + + + + + + + + + + + + + + + + + + + +

+ +
+   + +   +   + + +
+ +
+ + + + + + +
+ \ No newline at end of file Index: lams_build/lib/lams/lams.jar =================================================================== diff -u -r5fa265642903b837423bc95259ba3cef309cdf12 -r5f82321c5864250c612773630ff209a45e71a3f1 Binary files differ Index: lams_central/src/java/org/lamsfoundation/lams/authoring/service/AuthoringService.java =================================================================== diff -u -rca9d80700de0c2ded515b412500293f7e8c2c717 -r5f82321c5864250c612773630ff209a45e71a3f1 --- lams_central/src/java/org/lamsfoundation/lams/authoring/service/AuthoringService.java (.../AuthoringService.java) (revision ca9d80700de0c2ded515b412500293f7e8c2c717) +++ lams_central/src/java/org/lamsfoundation/lams/authoring/service/AuthoringService.java (.../AuthoringService.java) (revision 5f82321c5864250c612773630ff209a45e71a3f1) @@ -1746,7 +1746,7 @@ LogEvent logEvent = new LogEvent(); logEvent.setLogEventTypeId(LogEvent.TYPE_TEACHER_LEARNING_DESIGN_CREATE); - logEvent.setLearningDesignId(learningDesingID); + logEvent.setTargetId(learningDesingID); // TODO fix ids logEvent.setUser(user); logEvent.setOccurredDateTime(learningDesign.getCreateDateTime()); baseDAO.insert(logEvent); Index: lams_common/conf/hibernate/mappings/org/lamsfoundation/lams/logevent/LogEvent.hbm.xml =================================================================== diff -u -r8620cb3f29c4710a0ddfd597fdc1b676d4b2b4b0 -r5f82321c5864250c612773630ff209a45e71a3f1 --- lams_common/conf/hibernate/mappings/org/lamsfoundation/lams/logevent/LogEvent.hbm.xml (.../LogEvent.hbm.xml) (revision 8620cb3f29c4710a0ddfd597fdc1b676d4b2b4b0) +++ lams_common/conf/hibernate/mappings/org/lamsfoundation/lams/logevent/LogEvent.hbm.xml (.../LogEvent.hbm.xml) (revision 5f82321c5864250c612773630ff209a45e71a3f1) @@ -59,11 +59,11 @@ /> + + + + + + + + + + + + + + + \ No newline at end of file Index: lams_common/src/java/org/lamsfoundation/lams/commonContext.xml =================================================================== diff -u -ra4fd7ba340a2beac7436660039f13b9c8708f172 -r5f82321c5864250c612773630ff209a45e71a3f1 --- lams_common/src/java/org/lamsfoundation/lams/commonContext.xml (.../commonContext.xml) (revision a4fd7ba340a2beac7436660039f13b9c8708f172) +++ lams_common/src/java/org/lamsfoundation/lams/commonContext.xml (.../commonContext.xml) (revision 5f82321c5864250c612773630ff209a45e71a3f1) @@ -448,6 +448,7 @@ + Index: lams_common/src/java/org/lamsfoundation/lams/dbupdates/patch20180123.sql =================================================================== diff -u --- lams_common/src/java/org/lamsfoundation/lams/dbupdates/patch20180123.sql (revision 0) +++ lams_common/src/java/org/lamsfoundation/lams/dbupdates/patch20180123.sql (revision 5f82321c5864250c612773630ff209a45e71a3f1) @@ -0,0 +1,52 @@ +SET AUTOCOMMIT = 0; +set FOREIGN_KEY_CHECKS = 0; + +-- LDEV-4501 Revise audit log +ALTER TABLE lams_log_event_type +ADD COLUMN area VARCHAR(255) NULL; + +UPDATE lams_log_event_type +SET area = "LESSON"; + +INSERT INTO lams_log_event_type (log_event_type_id, description, area) VALUES(9, 'TYPE_ACTIVITY_EDIT', 'LESSON'); +INSERT INTO lams_log_event_type (log_event_type_id, description, area) VALUES(10, 'TYPE_USER_ORG_ADMIN', 'SECURITY'); +INSERT INTO lams_log_event_type (log_event_type_id, description, area) VALUES(11, 'TYPE_LOGIN_AS', 'SECURITY'); +INSERT INTO lams_log_event_type (log_event_type_id, description, area) VALUES(12, 'TYPE_PASSWORD_CHANGE', 'SECURITY'); +INSERT INTO lams_log_event_type (log_event_type_id, description, area) VALUES(13, 'TYPE_ROLE_FAILURE', 'SECURITY'); +INSERT INTO lams_log_event_type (log_event_type_id, description, area) VALUES(14, 'TYPE_ACCOUNT_LOCKED', 'SECURITY'); +INSERT INTO lams_log_event_type (log_event_type_id, description, area) VALUES(15, 'TYPE_NOTIFICATION', 'NOTIFICATION'); +INSERT INTO lams_log_event_type (log_event_type_id, description, area) VALUES(16, 'MARK_UPDATED', 'MARKS'); +INSERT INTO lams_log_event_type (log_event_type_id, description, area) VALUES(17, 'MARK_RELEASED', 'MARKS'); +INSERT INTO lams_log_event_type (log_event_type_id, description, area) VALUES(18, 'LEARNER_CONTENT_UPDATED', 'LEARNER_CONTENT'); +INSERT INTO lams_log_event_type (log_event_type_id, description, area) VALUES(19, 'LEARNER_CONTENT_SHOW_HIDE', 'LEARNER_CONTENT'); +INSERT INTO lams_log_event_type (log_event_type_id, description, area) VALUES(20, 'UNKNOWN', 'UNKNOWN'); + +ALTER TABLE lams_log_event +DROP FOREIGN KEY FK_lams_event_log_5, +DROP FOREIGN KEY FK_lams_event_log_4, +DROP FOREIGN KEY FK_lams_event_log_3, +DROP FOREIGN KEY FK_lams_event_log_2, +DROP FOREIGN KEY FK_lams_event_log_1; + +ALTER TABLE lams_log_event +CHANGE COLUMN learning_design_id target_id BIGINT(20) NULL DEFAULT NULL , +ADD COLUMN description TEXT, +DROP INDEX occurred_date_time , +ADD INDEX event_log_occurred_date_time (occurred_date_time ASC), +ADD INDEX FK_event_log_event_type_idx (log_event_type_id ASC), +DROP INDEX FK_lams_event_log_5 , +DROP INDEX FK_lams_event_log_4 , +DROP INDEX FK_lams_event_log_3 , +DROP INDEX user_id , +DROP INDEX FK_lams_event_log_1 ; + +ALTER TABLE lams_log_event +ADD CONSTRAINT FK_event_log_event_type + FOREIGN KEY (log_event_type_id) + REFERENCES lams_log_event_type (log_event_type_id) + ON DELETE RESTRICT + ON UPDATE RESTRICT; + +COMMIT; +SET AUTOCOMMIT = 1; +set FOREIGN_KEY_CHECKS = 1; Index: lams_common/src/java/org/lamsfoundation/lams/logevent/LogEvent.java =================================================================== diff -u -r453898dc3e1802c2280217b914be130fd19fe4d5 -r5f82321c5864250c612773630ff209a45e71a3f1 --- lams_common/src/java/org/lamsfoundation/lams/logevent/LogEvent.java (.../LogEvent.java) (revision 453898dc3e1802c2280217b914be130fd19fe4d5) +++ lams_common/src/java/org/lamsfoundation/lams/logevent/LogEvent.java (.../LogEvent.java) (revision 5f82321c5864250c612773630ff209a45e71a3f1) @@ -49,6 +49,19 @@ public static final int TYPE_LEARNER_ACTIVITY_FINISH = 6; public static final int TYPE_LEARNER_LESSON_COMPLETE = 7; public static final int TYPE_LEARNER_LESSON_MARK_SUBMIT = 8; + public static final int TYPE_ACTIVITY_EDIT = 9; // Audit Service + public static final int TYPE_USER_ORG_ADMIN = 10; + public static final int TYPE_LOGIN_AS = 11; + public static final int TYPE_PASSWORD_CHANGE = 12; + public static final int TYPE_ROLE_FAILURE = 13; + public static final int TYPE_ACCOUNT_LOCKED = 14; + public static final int TYPE_NOTIFICATION = 15; + public static final int MARK_UPDATED = 16; // Audit Service + public static final int MARK_RELEASED = 17; + public static final int LEARNER_CONTENT_UPDATED = 18; // Audit Service + public static final int LEARNER_CONTENT_SHOW_HIDE = 19; // Audit Service + public static final int UNKNOWN = 20; // catch all for conversion + /** *************************************************************** */ /** identifier field */ @@ -65,13 +78,15 @@ private Date occurredDateTime; /** */ - private Long learningDesignId; + private Long targetId; /** */ private Long lessonId; /** */ private Long activityId; + + private String description; /* * For the occurredDateTime fields, if the value is null, then it will default to the current time. @@ -134,12 +149,12 @@ /** * */ - public Long getLearningDesignId() { - return learningDesignId; + public Long getTargetId() { + return targetId; } - public void setLearningDesignId(Long learningDesignId) { - this.learningDesignId = learningDesignId; + public void setTargetId(Long targetId) { + this.targetId = targetId; } /** @@ -163,4 +178,12 @@ public void setActivityId(Long activityId) { this.activityId = activityId; } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } } Index: lams_common/src/java/org/lamsfoundation/lams/logevent/LogEventType.java =================================================================== diff -u --- lams_common/src/java/org/lamsfoundation/lams/logevent/LogEventType.java (revision 0) +++ lams_common/src/java/org/lamsfoundation/lams/logevent/LogEventType.java (revision 5f82321c5864250c612773630ff209a45e71a3f1) @@ -0,0 +1,63 @@ +/**************************************************************** + * Copyright (C) 2005 LAMS Foundation (http://lamsfoundation.org) + * ============================================================= + * License Information: http://lamsfoundation.org/licensing/lams/2.0/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2.0 + * as published by the Free Software Foundation. + * + * This program 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 * USA + * + * http://www.gnu.org/licenses/gpl.txt + * **************************************************************** + */ + + +package org.lamsfoundation.lams.logevent; + +import java.io.Serializable; + +public class LogEventType implements Serializable { + + private static final long serialVersionUID = 5275008411348257866L; + + private Integer id; + private String description; + private String area; + + public Integer getId() { + return id; + } + public void setId(Integer id) { + this.id = id; + } + public String getDescription() { + return description; + } + public void setDescription(String description) { + this.description = description; + } + public String getArea() { + return area; + } + public void setArea(String area) { + this.area = area; + } + + public String getDescriptionI18NKey() { + return "label."+description.toLowerCase().replace("_", "."); + } + + public String getAreaI18NKey() { + return "label."+area.toLowerCase().replace("_", "."); + } + +} Index: lams_common/src/java/org/lamsfoundation/lams/logevent/dao/ILogEventDAO.java =================================================================== diff -u -r51fb2a37254f24bb2a805d4ffd54482c779f43fa -r5f82321c5864250c612773630ff209a45e71a3f1 --- lams_common/src/java/org/lamsfoundation/lams/logevent/dao/ILogEventDAO.java (.../ILogEventDAO.java) (revision 51fb2a37254f24bb2a805d4ffd54482c779f43fa) +++ lams_common/src/java/org/lamsfoundation/lams/logevent/dao/ILogEventDAO.java (.../ILogEventDAO.java) (revision 5f82321c5864250c612773630ff209a45e71a3f1) @@ -27,6 +27,7 @@ import java.util.List; import org.lamsfoundation.lams.logevent.LogEvent; +import org.lamsfoundation.lams.logevent.LogEventType; /** * DAO interface for LogEvent. @@ -68,4 +69,16 @@ */ List getEventsOccurredBetween(Date startDate, Date finishDate); + /** Get the generic event types */ + List getEventTypes(); + + /** Get the date of the oldest log event */ + Date getOldestEventDate(); + + /** Used for displaying paged lists of events */ + List getEventsForTablesorter(int page, int size, int sorting, String searchString, Date startDate, + Date endDate, String area, Integer typeId); + + int countEventsWithRestrictions(String searchString, Date startDate, Date endDate, String area, Integer typeId); + } Index: lams_common/src/java/org/lamsfoundation/lams/logevent/dao/hibernate/LogEventDAO.java =================================================================== diff -u -r51fb2a37254f24bb2a805d4ffd54482c779f43fa -r5f82321c5864250c612773630ff209a45e71a3f1 --- lams_common/src/java/org/lamsfoundation/lams/logevent/dao/hibernate/LogEventDAO.java (.../LogEventDAO.java) (revision 51fb2a37254f24bb2a805d4ffd54482c779f43fa) +++ lams_common/src/java/org/lamsfoundation/lams/logevent/dao/hibernate/LogEventDAO.java (.../LogEventDAO.java) (revision 5f82321c5864250c612773630ff209a45e71a3f1) @@ -26,9 +26,12 @@ import java.util.Date; import java.util.List; +import org.hibernate.SQLQuery; import org.lamsfoundation.lams.dao.hibernate.LAMSBaseDAO; import org.lamsfoundation.lams.logevent.LogEvent; +import org.lamsfoundation.lams.logevent.LogEventType; import org.lamsfoundation.lams.logevent.dao.ILogEventDAO; +import org.lamsfoundation.lams.logevent.service.ILogEventService; import org.springframework.stereotype.Repository; /** @@ -48,11 +51,16 @@ private static final String GET_LOG_EVENTS_OCCURED_BETWEEN_DATES = "from " + LogEvent.class.getName() + " where occurred_date_time > ? and occurred_date_time <= ? order by occurred_date_time asc"; + private static final String GET_OLDEST_LOG_EVENT_DATE = "select min(occurredDateTime) from " + LogEvent.class.getName(); + + private static final String GET_LOG_EVENT_TYPES = "from " + LogEventType.class.getName(); + @Override public void save(LogEvent logEvent) { super.insert(logEvent); } + @SuppressWarnings("rawtypes") @Override public LogEvent getById(Long logEventId) { List list = doFind(GET_LOG_EVENT_BY_ID, logEventId); @@ -75,4 +83,124 @@ return (List) doFind(GET_LOG_EVENTS_OCCURED_BETWEEN_DATES, startDate, finishDate); } + /** Get the generic event types */ + @SuppressWarnings("unchecked") + public List getEventTypes() { + return (List) doFind(GET_LOG_EVENT_TYPES); + } + + /** Get the date of the oldest log event (and not the time) */ + @SuppressWarnings("rawtypes") + public Date getOldestEventDate() { + List list = doFind(GET_OLDEST_LOG_EVENT_DATE); + if ( list.size() > 0 ) + return (Date) list.get(0); + return null; + } + + @Override + @SuppressWarnings("unchecked") + /** + * Will return List<[ForumUser, String], [ForumUser, String], ... , [ForumUser, String]> + * where the String is the notebook entry. No notebook entries needed? Will return "null" in their place. + */ + public List getEventsForTablesorter(int page, int size, int sorting, String searchString, Date startDate, + Date endDate, String area, Integer typeId) { + String sortingOrder; + switch (sorting) { + case ILogEventService.SORT_BY_DATE_ASC: + sortingOrder = "occurred_date_time ASC"; + break; + case ILogEventService.SORT_BY_DATE_DESC: + sortingOrder = "occurred_date_time DESC"; + break; + default: + sortingOrder = "occurred_date_time ASC"; + } + + // Basic select for the user records + StringBuilder queryText = new StringBuilder(); + + queryText.append("SELECT * FROM lams_log_event e "); + addWhereClause(startDate, endDate, area, typeId, queryText); +// // If filtering by name add a name based where clause (LDEV-3779: must come before the Notebook JOIN statement) +// buildNameSearch(queryText, searchString); +// + // Now specify the sort based on the switch statement above. + queryText.append(" ORDER BY " + sortingOrder); + + SQLQuery query = getSession().createSQLQuery(queryText.toString()); + query.addEntity("event", LogEvent.class); + addParameters(startDate, endDate, area, typeId, query); + query.setFirstResult(page * size).setMaxResults(size); + return query.list(); + + } + + private void addWhereClause(Date startDate, Date endDate, String area, Integer typeId, StringBuilder queryText) { + boolean needAnd = false; + if ((startDate != null && endDate != null) || area != null || typeId != null) { + queryText.append(" WHERE "); + if (startDate != null && endDate != null) { + queryText.append("( occurred_date_time > :startDate AND occurred_date_time <= :endDate )"); + needAnd = true; + } + if (typeId != null) { + if (needAnd) + queryText.append(" AND "); + queryText.append(" log_event_type_id = :typeId "); + } else if (area != null) { + if (needAnd) + queryText.append(" AND "); + queryText.append( + " log_event_type_id in (SELECT log_event_type_id FROM lams_log_event_type WHERE area = :area) "); + } + } + } + + private void addParameters(Date startDate, Date endDate, String area, Integer typeId, SQLQuery query) { + if (startDate != null && endDate != null) { + query.setDate("startDate", startDate); + query.setDate("endDate", endDate); + } + if (typeId != null) { + query.setInteger("typeId", typeId); + } else if (area != null) { + query.setString("area", area); + } + } + +// private void buildNameSearch(StringBuilder queryText, String searchString) { +// if (!StringUtils.isBlank(searchString)) { +// String[] tokens = searchString.trim().split("\\s+"); +// for (String token : tokens) { +// String escToken = StringEscapeUtils.escapeSql(token); +// queryText.append(" AND (user.first_name LIKE '%").append(escToken) +// .append("%' OR user.last_name LIKE '%").append(escToken).append("%' OR user.login_name LIKE '%") +// .append(escToken).append("%')"); +// } +// } +// } + + @Override + @SuppressWarnings("rawtypes") + public int countEventsWithRestrictions(String searchString, Date startDate, Date endDate, String area, + Integer typeId) { + + // Basic select for the user records + StringBuilder queryText = new StringBuilder(); + + queryText.append("SELECT count(*) FROM lams_log_event e "); + addWhereClause(startDate, endDate, area, typeId, queryText); + + SQLQuery query = getSession().createSQLQuery(queryText.toString()); + addParameters(startDate, endDate, area, typeId, query); + + List list = query.list(); + if (list == null || list.size() == 0) { + return 0; + } + return ((Number) list.get(0)).intValue(); + } + } Index: lams_common/src/java/org/lamsfoundation/lams/logevent/dto/LogEventTypeDTO.java =================================================================== diff -u --- lams_common/src/java/org/lamsfoundation/lams/logevent/dto/LogEventTypeDTO.java (revision 0) +++ lams_common/src/java/org/lamsfoundation/lams/logevent/dto/LogEventTypeDTO.java (revision 5f82321c5864250c612773630ff209a45e71a3f1) @@ -0,0 +1,68 @@ +/*************************************************************************** + * Copyright (C) 2005 LAMS Foundation (http://lamsfoundation.org) + * ============================================================= + * License Information: http://lamsfoundation.org/licensing/lams/2.0/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2.0 + * as published by the Free Software Foundation. + * + * This program 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + * + * http://www.gnu.org/licenses/gpl.txt + * ***********************************************************************/ + +package org.lamsfoundation.lams.logevent.dto; + +import org.lamsfoundation.lams.logevent.LogEventType; + +/** + * Contains the user text descriptions as well as the db fields + */ +public class LogEventTypeDTO { + private Integer id; + private String description; + private String areaCode; + private String areaDescription; + + public LogEventTypeDTO(LogEventType dbObject, String i18NTypeDescription, String i18NAreaDescription) { + id = dbObject.getId(); + description = i18NTypeDescription; + areaCode = dbObject.getArea(); + areaDescription = i18NAreaDescription; + } + public Integer getId() { + return id; + } + public void setId(Integer id) { + this.id = id; + } + public String getAreaCode() { + return areaCode; + } + public void setAreaCode(String areaCode) { + this.areaCode = areaCode; + } + public String getDescription() { + return description; + } + public void setDescription(String description) { + this.description = description; + } + public String getAreaDescription() { + return areaDescription; + } + public void setAreaDescription(String areaDescription) { + this.areaDescription = areaDescription; + } + + +} Index: lams_common/src/java/org/lamsfoundation/lams/logevent/service/ILogEventService.java =================================================================== diff -u -r51fb2a37254f24bb2a805d4ffd54482c779f43fa -r5f82321c5864250c612773630ff209a45e71a3f1 --- lams_common/src/java/org/lamsfoundation/lams/logevent/service/ILogEventService.java (.../ILogEventService.java) (revision 51fb2a37254f24bb2a805d4ffd54482c779f43fa) +++ lams_common/src/java/org/lamsfoundation/lams/logevent/service/ILogEventService.java (.../ILogEventService.java) (revision 5f82321c5864250c612773630ff209a45e71a3f1) @@ -27,13 +27,18 @@ import java.util.List; import org.lamsfoundation.lams.logevent.LogEvent; +import org.lamsfoundation.lams.logevent.LogEventType; /** * Manages LogEvents. * * @author Andrey Balan */ public interface ILogEventService { + + /** Constants used for sorting */ + static final int SORT_BY_DATE_ASC = 0; + static final int SORT_BY_DATE_DESC = 1; /** * Records event of specified type in database. @@ -44,6 +49,14 @@ void logEvent(Integer logEventTypeId, Integer userId, Long learningDesignId, Long lessonId, Long activityId); /** + * Records event of specified type in database. + * + * @param logEventTypeId + * @param userId + */ + void logEvent(Integer logEventTypeId, Integer userId, Long learningDesignId, Long lessonId, Long activityId, String description); + + /** * Returns event by the given id. * * @return @@ -69,4 +82,16 @@ */ List getEventsOccurredBetween(Date startDate, Date finishDate); + /** Get the Log Event Types in a structured form */ + List getEventTypes(); + + /** Get the date of the oldest event log entry. Handy for letting a user select a date range */ + Date getOldestEventDate(); + + /** Used for displaying paged lists of events */ + List getEventsForTablesorter(int page, int size, int sorting, String searchString, Date startDate, + Date endDate, String area, Integer typeId); + + int countEventsWithRestrictions(String searchString, Date startDate, Date endDate, String area, Integer typeId); + } Index: lams_common/src/java/org/lamsfoundation/lams/logevent/service/LogEventService.java =================================================================== diff -u -r51fb2a37254f24bb2a805d4ffd54482c779f43fa -r5f82321c5864250c612773630ff209a45e71a3f1 --- lams_common/src/java/org/lamsfoundation/lams/logevent/service/LogEventService.java (.../LogEventService.java) (revision 51fb2a37254f24bb2a805d4ffd54482c779f43fa) +++ lams_common/src/java/org/lamsfoundation/lams/logevent/service/LogEventService.java (.../LogEventService.java) (revision 5f82321c5864250c612773630ff209a45e71a3f1) @@ -28,6 +28,7 @@ import org.apache.log4j.Logger; import org.lamsfoundation.lams.logevent.LogEvent; +import org.lamsfoundation.lams.logevent.LogEventType; import org.lamsfoundation.lams.logevent.dao.ILogEventDAO; import org.lamsfoundation.lams.usermanagement.User; import org.lamsfoundation.lams.usermanagement.service.IUserManagementService; @@ -70,18 +71,24 @@ } @Override - public void logEvent(Integer logEventTypeId, Integer userId, Long learningDesignId, Long lessonId, + public void logEvent(Integer logEventTypeId, Integer userId, Long targetUserId, Long lessonId, Long activityId) { + logEvent(logEventTypeId, userId, targetUserId, lessonId, activityId, null); + } + @Override + public void logEvent(Integer logEventTypeId, Integer userId, Long targetUserId, Long lessonId, + Long activityId, String description) { User user = (userId != null) ? (User) userManagementService.findById(User.class, userId) : null; if (user == null) { throw new RuntimeException("User can't be null"); } LogEvent logEvent = new LogEvent(); logEvent.setLogEventTypeId(logEventTypeId); logEvent.setUser(user); - logEvent.setLearningDesignId(learningDesignId); + logEvent.setTargetId(targetUserId); logEvent.setLessonId(lessonId); logEvent.setActivityId(activityId); + logEvent.setDescription(description); logEventDAO.save(logEvent); } @@ -100,6 +107,27 @@ return logEventDAO.getEventsOccurredBetween(startDate, finishDate); } + @Override + public List getEventTypes() { + return logEventDAO.getEventTypes(); + } + + @Override + public Date getOldestEventDate() { + return logEventDAO.getOldestEventDate(); + } + + @Override + public List getEventsForTablesorter(int page, int size, int sorting, String searchString, Date startDate, + Date endDate, String area, Integer typeId) { + return logEventDAO.getEventsForTablesorter(page, size, sorting, searchString, startDate, endDate, area, typeId); + } + + @Override + public int countEventsWithRestrictions(String searchString, Date startDate, Date endDate, String area, Integer typeId) { + return logEventDAO.countEventsWithRestrictions(searchString, startDate, endDate, area, typeId); + } + /** * * @param logEventDAO Index: lams_common/src/java/org/lamsfoundation/lams/util/audit/AuditService.java =================================================================== diff -u -r2abc3485dc2d24ea02044a64271f3ee0d3b8c11b -r5f82321c5864250c612773630ff209a45e71a3f1 --- lams_common/src/java/org/lamsfoundation/lams/util/audit/AuditService.java (.../AuditService.java) (revision 2abc3485dc2d24ea02044a64271f3ee0d3b8c11b) +++ lams_common/src/java/org/lamsfoundation/lams/util/audit/AuditService.java (.../AuditService.java) (revision 5f82321c5864250c612773630ff209a45e71a3f1) @@ -24,11 +24,15 @@ package org.lamsfoundation.lams.util.audit; +import java.util.Set; + import javax.servlet.http.HttpSession; -import org.apache.log4j.Logger; import org.lamsfoundation.lams.learningdesign.ToolActivity; import org.lamsfoundation.lams.learningdesign.dao.IActivityDAO; +import org.lamsfoundation.lams.lesson.Lesson; +import org.lamsfoundation.lams.logevent.LogEvent; +import org.lamsfoundation.lams.logevent.service.ILogEventService; import org.lamsfoundation.lams.usermanagement.dto.UserDTO; import org.lamsfoundation.lams.util.MessageService; import org.lamsfoundation.lams.web.session.SessionManager; @@ -38,7 +42,7 @@ * Write out audit entries to a log4j based log file. Gets the user details from the shared session. */ /* - * Relies on the followig two entries in the log4j configuration file: + * Relies on the following two entries in the log4j configuration file: * * @@ -56,7 +60,8 @@ */ public class AuditService implements IAuditService { - static Logger logger = Logger.getLogger(AuditService.class.getName()); +// static Logger logger = Logger.getLogger(AuditService.class.getName()); + ILogEventService logEventService; private final String AUDIT_CHANGE_I18N_KEY = "audit.change.entry"; private final String AUDIT_MARK_CHANGE_I18N_KEY = "audit.change.mark"; @@ -69,6 +74,18 @@ protected MessageService messageService; protected IActivityDAO activityDao; + private Integer getUserID() { + HttpSession ss = SessionManager.getSession(); + if (ss != null) { + UserDTO user = (UserDTO) ss.getAttribute(AttributeNames.USER); + if (user != null) { + return user.getUserID(); + } + } + return null; + } + + private String getUserString() { HttpSession ss = SessionManager.getSession(); if (ss != null) { @@ -86,14 +103,35 @@ @Override public void log(String moduleName, String message) { - logger.info(getUserString() + moduleName + ": " + message); + logEventService.logEvent(LogEvent.UNKNOWN, getUserID(), null, null, null, getUserString() + moduleName + ": " + message); } @Override public void log(UserDTO userDTO, String moduleName, String message) { - logger.info(getUserString(userDTO) + moduleName + ": " + message); + logEventService.logEvent(LogEvent.UNKNOWN, getUserID(), null, null, null, getUserString(userDTO) + moduleName + ": " + message); } + + @SuppressWarnings("unchecked") + private void logEvent(Integer logEventTypeId, Long targetUserId, Long toolContentId, String description) { + Integer userId = getUserID(); + Long lessonId = null; + Long activityId = null; + if ( toolContentId != null ) { + ToolActivity toolActivity = activityDao.getToolActivityByToolContentId(toolContentId); + if ( toolActivity != null ) { + activityId = toolActivity.getActivityId(); + Set lessons = (Set) toolActivity.getLearningDesign().getLessons(); + // DB allows the same learning design to be used for multiple lessons but in practice it is 1-1. + if ( lessons.size() > 0) { + lessonId = lessons.iterator().next().getLessonId(); + } + } + // lookup lessonId from activityId + } + logEventService.logEvent(logEventTypeId, userId, targetUserId, lessonId, activityId, description); + } + @Override public void logChange(String moduleName, Long originalUserId, String originalUserLogin, String originalText, String newText) { @@ -102,7 +140,7 @@ args[1] = originalText; args[2] = newText; String message = messageService.getMessage(AUDIT_CHANGE_I18N_KEY, args); - log(moduleName, message); + logEvent(LogEvent.LEARNER_CONTENT_UPDATED, originalUserId, null, message.toString()); } @Override @@ -112,17 +150,17 @@ args[0] = originalUserLogin + "(" + originalUserId + ")"; args[1] = originalMark; args[2] = newMark; - String message = messageService.getMessage(AUDIT_MARK_CHANGE_I18N_KEY, args); - log(moduleName, message); + StringBuilder message = new StringBuilder(moduleName).append(messageService.getMessage(AUDIT_MARK_CHANGE_I18N_KEY, args)); + logEvent(LogEvent.MARK_UPDATED, originalUserId, null, message.toString()); } - + @Override public void logHideEntry(String moduleName, Long originalUserId, String originalUserLogin, String hiddenItem) { String[] args = new String[3]; args[0] = originalUserLogin + "(" + originalUserId + ")"; args[1] = hiddenItem; String message = messageService.getMessage(AUDIT_HIDE_I18N_KEY, args); - log(moduleName, message); + logEvent(LogEvent.LEARNER_CONTENT_SHOW_HIDE, originalUserId, null, message.toString()); } @Override @@ -131,8 +169,8 @@ args[0] = originalUserLogin + "(" + originalUserId + ")"; args[1] = hiddenItem; String message = messageService.getMessage(AUDIT_SHOW_I18N_KEY, args); - log(moduleName, message); - } + logEvent(LogEvent.LEARNER_CONTENT_SHOW_HIDE, originalUserId, null, message.toString()); + } @Override public void logStartEditingActivityInMonitor(Long toolContentId) { @@ -158,7 +196,7 @@ String[] args = new String[] { user.getLogin() + "(" + user.getUserID() + ")", "(activityId:" + toolActivity.getActivityId() + ")" }; String message = messageService.getMessage(messageKey, args); - log(toolSignature, message); + logEvent(LogEvent.TYPE_ACTIVITY_EDIT, null, null, message.toString()); } /* *** Spring Injection Methods ************ */ @@ -179,4 +217,12 @@ this.activityDao = activityDao; } + public ILogEventService getLogEventService() { + return logEventService; + } + + public void setLogEventService(ILogEventService logEventService) { + this.logEventService = logEventService; + } + }