diff --git a/microsoft-integration/api/src/java/org/sakaiproject/microsoft/api/MicrosoftCommonService.java b/microsoft-integration/api/src/java/org/sakaiproject/microsoft/api/MicrosoftCommonService.java index 4b917ba6e06..59a8f5f52f8 100644 --- a/microsoft-integration/api/src/java/org/sakaiproject/microsoft/api/MicrosoftCommonService.java +++ b/microsoft-integration/api/src/java/org/sakaiproject/microsoft/api/MicrosoftCommonService.java @@ -122,7 +122,7 @@ public static enum PermissionRoles { READ, WRITE } boolean addMemberToTeam(String userId, String teamId) throws MicrosoftCredentialsException; boolean addOwnerToTeam(String userId, String teamId) throws MicrosoftCredentialsException; - SynchronizationStatus addUsersToTeamOrGroup(String teamId, List members, SynchronizationStatus status, LinkedList roles) throws MicrosoftCredentialsException; + SynchronizationStatus addUsersToTeamOrGroup(SiteSynchronization ss, List members, SynchronizationStatus status, LinkedList roles) throws MicrosoftCredentialsException; boolean removeUserFromGroup(String userId, String groupId) throws MicrosoftCredentialsException; boolean removeMemberFromTeam(String memberId, String teamId) throws MicrosoftCredentialsException; diff --git a/microsoft-integration/api/src/java/org/sakaiproject/microsoft/api/MicrosoftLoggingService.java b/microsoft-integration/api/src/java/org/sakaiproject/microsoft/api/MicrosoftLoggingService.java index 8ccfd47f58b..79d5606c656 100644 --- a/microsoft-integration/api/src/java/org/sakaiproject/microsoft/api/MicrosoftLoggingService.java +++ b/microsoft-integration/api/src/java/org/sakaiproject/microsoft/api/MicrosoftLoggingService.java @@ -32,7 +32,14 @@ import org.sakaiproject.microsoft.api.model.MicrosoftLog; +import java.time.ZonedDateTime; +import java.util.List; + public interface MicrosoftLoggingService { void saveLog(MicrosoftLog log); + + List findAll(); + + List findFromZonedDateTime(ZonedDateTime zonedDateTime); } \ No newline at end of file diff --git a/microsoft-integration/api/src/java/org/sakaiproject/microsoft/api/model/MicrosoftLog.java b/microsoft-integration/api/src/java/org/sakaiproject/microsoft/api/model/MicrosoftLog.java index 6a455e60b56..3b810d2e340 100644 --- a/microsoft-integration/api/src/java/org/sakaiproject/microsoft/api/model/MicrosoftLog.java +++ b/microsoft-integration/api/src/java/org/sakaiproject/microsoft/api/model/MicrosoftLog.java @@ -102,7 +102,9 @@ public class MicrosoftLog { public static final String EVENT_TOO_MANY_REQUESTS = "event.too_many_requests"; public static final String EVENT_USER_NOT_FOUND_ON_TEAM = "event.user_not_found_on_team"; + public static final String EVENT_JOB_RESULT = "event.job_result"; + public static final String[] MICROSOFT_ERRORS = {EVENT_TOO_MANY_REQUESTS}; public enum Status { KO, OK diff --git a/microsoft-integration/api/src/java/org/sakaiproject/microsoft/api/persistence/MicrosoftLoggingRepository.java b/microsoft-integration/api/src/java/org/sakaiproject/microsoft/api/persistence/MicrosoftLoggingRepository.java index aef0a6dc8d5..5bad88acf22 100644 --- a/microsoft-integration/api/src/java/org/sakaiproject/microsoft/api/persistence/MicrosoftLoggingRepository.java +++ b/microsoft-integration/api/src/java/org/sakaiproject/microsoft/api/persistence/MicrosoftLoggingRepository.java @@ -18,6 +18,10 @@ import org.sakaiproject.microsoft.api.model.MicrosoftLog; import org.sakaiproject.serialization.SerializableRepository; +import java.time.ZonedDateTime; +import java.util.List; + public interface MicrosoftLoggingRepository extends SerializableRepository { + List getLogsFromZonedDateTime(ZonedDateTime zonedDateTime); } \ No newline at end of file diff --git a/microsoft-integration/impl/src/main/java/org/sakaiproject/microsoft/impl/MicrosoftCommonServiceImpl.java b/microsoft-integration/impl/src/main/java/org/sakaiproject/microsoft/impl/MicrosoftCommonServiceImpl.java index a6afb880cb4..6148f870322 100644 --- a/microsoft-integration/impl/src/main/java/org/sakaiproject/microsoft/impl/MicrosoftCommonServiceImpl.java +++ b/microsoft-integration/impl/src/main/java/org/sakaiproject/microsoft/impl/MicrosoftCommonServiceImpl.java @@ -1202,8 +1202,9 @@ public boolean addOwnerToTeam(String userId, String teamId) throws MicrosoftCred } @Override - public SynchronizationStatus addUsersToTeamOrGroup(String teamId, List members, SynchronizationStatus status, LinkedList roles) throws MicrosoftCredentialsException { + public SynchronizationStatus addUsersToTeamOrGroup(SiteSynchronization ss, List members, SynchronizationStatus status, LinkedList roles) throws MicrosoftCredentialsException { boolean res = false; + String teamId = ss.getTeamId(); String dataKey = roles.contains(MicrosoftUser.OWNER) ? "ownerId" : "memberId"; boolean generalError = false; @@ -1269,6 +1270,7 @@ public SynchronizationStatus addUsersToTeamOrGroup(String teamId, List findAll() { + return (List) microsoftLoggingRepository.findAll(); + } + + @Override + public List findFromZonedDateTime(ZonedDateTime zonedDateTime) { + return (List) microsoftLoggingRepository.getLogsFromZonedDateTime(zonedDateTime); + } } diff --git a/microsoft-integration/impl/src/main/java/org/sakaiproject/microsoft/impl/MicrosoftSynchronizationServiceImpl.java b/microsoft-integration/impl/src/main/java/org/sakaiproject/microsoft/impl/MicrosoftSynchronizationServiceImpl.java index 84b403828b7..f2b4b8a465b 100644 --- a/microsoft-integration/impl/src/main/java/org/sakaiproject/microsoft/impl/MicrosoftSynchronizationServiceImpl.java +++ b/microsoft-integration/impl/src/main/java/org/sakaiproject/microsoft/impl/MicrosoftSynchronizationServiceImpl.java @@ -704,7 +704,7 @@ public SynchronizationStatus runSiteSynchronization(SiteSynchronization ss) thro } } //add members to team - ret = microsoftCommonService.addUsersToTeamOrGroup(ss.getTeamId(), filteredMembersFound, ret, new LinkedList<>()); + ret = microsoftCommonService.addUsersToTeamOrGroup(ss, filteredMembersFound, ret, new LinkedList<>()); List filteredOwnersFound = microsoftCommonService.getUsers(filteredSiteMembers.getOwners().keySet(), mappedMicrosoftUserId); List filteredOwnersNotFound = filteredSiteMembers.getOwners().keySet().stream().filter(id -> filteredOwnersFound.stream().noneMatch(mu -> mu != null && mu.getEmail().equalsIgnoreCase(id))).collect(Collectors.toList()); @@ -741,7 +741,7 @@ public SynchronizationStatus runSiteSynchronization(SiteSynchronization ss) thro } } - ret = microsoftCommonService.addUsersToTeamOrGroup(ss.getTeamId(), filteredOwnersFound, ret, new LinkedList<>(Collections.singletonList(MicrosoftUser.OWNER))); + ret = microsoftCommonService.addUsersToTeamOrGroup(ss, filteredOwnersFound, ret, new LinkedList<>(Collections.singletonList(MicrosoftUser.OWNER))); //process all group synchronizations related if (ss.getGroupSynchronizationsList() != null && ss.getGroupSynchronizationsList().size() > 0) { @@ -1141,7 +1141,7 @@ private void siteCreated(String siteId) throws MicrosoftGenericException { if (site != null) { //check filters if (!siteFilter.match(site)) { - break; + return; } teamId = microsoftCommonService.createTeam(site.getTitle(), credentials.getEmail()); diff --git a/microsoft-integration/impl/src/main/java/org/sakaiproject/microsoft/impl/jobs/RunSynchronizationsJob.java b/microsoft-integration/impl/src/main/java/org/sakaiproject/microsoft/impl/jobs/RunSynchronizationsJob.java index 77bf0fdc260..2f7fa552a47 100644 --- a/microsoft-integration/impl/src/main/java/org/sakaiproject/microsoft/impl/jobs/RunSynchronizationsJob.java +++ b/microsoft-integration/impl/src/main/java/org/sakaiproject/microsoft/impl/jobs/RunSynchronizationsJob.java @@ -15,18 +15,26 @@ */ package org.sakaiproject.microsoft.impl.jobs; +import java.time.ZonedDateTime; +import java.util.Arrays; +import java.util.HashMap; import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; import org.quartz.Job; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; import org.sakaiproject.authz.api.SecurityService; import org.sakaiproject.microsoft.api.MicrosoftConfigurationService; +import org.sakaiproject.microsoft.api.MicrosoftLoggingService; import org.sakaiproject.microsoft.api.MicrosoftSynchronizationService; import org.sakaiproject.microsoft.api.data.MicrosoftLogInvokers; import org.sakaiproject.microsoft.api.data.SakaiSiteFilter; import org.sakaiproject.microsoft.api.data.SynchronizationStatus; import org.sakaiproject.microsoft.api.exceptions.MicrosoftGenericException; +import org.sakaiproject.microsoft.api.model.MicrosoftLog; import org.sakaiproject.microsoft.api.model.SiteSynchronization; import org.sakaiproject.tool.api.Session; import org.sakaiproject.tool.api.SessionManager; @@ -45,6 +53,9 @@ public class RunSynchronizationsJob implements Job { @Setter private MicrosoftSynchronizationService microsoftSynchronizationService; + + @Setter + private MicrosoftLoggingService microsoftLoggingService; @Setter MicrosoftConfigurationService microsoftConfigurationService; @@ -57,6 +68,8 @@ public void init() { public void execute(JobExecutionContext context) throws JobExecutionException { log.info("RunSynchronizationsJob started."); Session session = sessionManager.getCurrentSession(); + ZonedDateTime startTime = ZonedDateTime.now(); + try { session.setUserEid("admin"); session.setUserId("admin"); @@ -88,6 +101,19 @@ public void execute(JobExecutionContext context) throws JobExecutionException { finally { session.clear(); } + + List logs = microsoftLoggingService.findFromZonedDateTime(startTime); + //if log is not from job invoker and is an error, remove it + logs = logs.stream().filter(l -> Arrays.stream(MicrosoftLog.MICROSOFT_ERRORS).noneMatch(e -> e.equals(l.getEvent())) && l.getContext().containsKey("origin") && l.getContext().get("origin").equals(MicrosoftLogInvokers.JOB.getCode())).collect(Collectors.toList()); + Set sites = logs.stream().filter(l -> l.getEvent().equals(MicrosoftLog.EVENT_ADD_MEMBER) || l.getEvent().equals(MicrosoftLog.EVENT_ADD_OWNER) || l.getEvent().equals(MicrosoftLog.EVENT_USER_ADDED_TO_CHANNEL)).collect(Collectors.toList()).stream().map(l -> l.getContext().get("siteId")).collect(Collectors.toSet()); + Map data = new HashMap<>(); + data.put("log_amount", String.valueOf(logs.size())); + data.put("start_time", startTime.toLocalDateTime().toString()); + data.put("sites_modified_amount", String.valueOf(sites.size())); + data.put("sites_modified", String.join(",", sites)); + data.putAll(logs.stream().collect(Collectors.groupingBy(MicrosoftLog::getEvent, Collectors.counting())).entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, e -> String.valueOf(e.getValue())))); + + microsoftLoggingService.saveLog(MicrosoftLog.builder().event(MicrosoftLog.EVENT_JOB_RESULT).context(data).build()); log.info("RunSynchronizationsJob completed."); } diff --git a/microsoft-integration/impl/src/main/java/org/sakaiproject/microsoft/impl/persistence/MicrosoftLoggingRepositoryImpl.java b/microsoft-integration/impl/src/main/java/org/sakaiproject/microsoft/impl/persistence/MicrosoftLoggingRepositoryImpl.java index a6e8ff318c9..05b37432626 100644 --- a/microsoft-integration/impl/src/main/java/org/sakaiproject/microsoft/impl/persistence/MicrosoftLoggingRepositoryImpl.java +++ b/microsoft-integration/impl/src/main/java/org/sakaiproject/microsoft/impl/persistence/MicrosoftLoggingRepositoryImpl.java @@ -19,6 +19,19 @@ import org.sakaiproject.microsoft.api.persistence.MicrosoftLoggingRepository; import org.sakaiproject.serialization.BasicSerializableRepository; +import java.time.ZonedDateTime; +import java.util.List; +import java.util.stream.Collectors; + public class MicrosoftLoggingRepositoryImpl extends BasicSerializableRepository implements MicrosoftLoggingRepository { + @Override + public List getLogsFromZonedDateTime(ZonedDateTime zonedDateTime) { + String query = "SELECT ml FROM MicrosoftLog ml WHERE ml.eventDate >= :zonedDateTime"; + query += " ORDER BY ml.id DESC, ml.eventDate DESC"; + return sessionFactory.getCurrentSession().createQuery(query, MicrosoftLog.class) + .setParameter("zonedDateTime", zonedDateTime) + .stream() + .collect(Collectors.toList()); + } } diff --git a/microsoft-integration/impl/src/webapp/WEB-INF/components.xml b/microsoft-integration/impl/src/webapp/WEB-INF/components.xml index 6c123bc3084..ecece5b7cd9 100644 --- a/microsoft-integration/impl/src/webapp/WEB-INF/components.xml +++ b/microsoft-integration/impl/src/webapp/WEB-INF/components.xml @@ -114,6 +114,7 @@ +