001// -------------------------------------------------------------------------------- 002// Copyright 2002-2026 Echo Three, LLC 003// 004// Licensed under the Apache License, Version 2.0 (the "License"); 005// you may not use this file except in compliance with the License. 006// You may obtain a copy of the License at 007// 008// http://www.apache.org/licenses/LICENSE-2.0 009// 010// Unless required by applicable law or agreed to in writing, software 011// distributed under the License is distributed on an "AS IS" BASIS, 012// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013// See the License for the specific language governing permissions and 014// limitations under the License. 015// -------------------------------------------------------------------------------- 016 017package com.echothree.model.control.user.server.logic; 018 019import com.echothree.model.control.order.server.control.OrderControl; 020import com.echothree.model.control.search.server.control.SearchControl; 021import com.echothree.model.control.user.server.control.UserControl; 022import com.echothree.model.control.workrequirement.server.logic.WorkRequirementLogic; 023import com.echothree.model.data.party.common.pk.PartyPK; 024import com.echothree.model.data.user.common.pk.UserVisitPK; 025import com.echothree.model.data.user.server.entity.UserVisit; 026import com.echothree.model.data.user.server.factory.UserVisitFactory; 027import com.echothree.util.server.control.BaseLogic; 028import com.echothree.util.server.persistence.EntityPermission; 029import javax.enterprise.context.ApplicationScoped; 030import javax.inject.Inject; 031 032@ApplicationScoped 033public class UserVisitLogic 034 extends BaseLogic { 035 036 @Inject 037 UserVisitFactory userVisitFactory; 038 039 @Inject 040 OrderControl orderControl; 041 042 @Inject 043 SearchControl searchControl; 044 045 @Inject 046 UserControl userControl; 047 048 @Inject 049 UserSessionLogic userSessionLogic; 050 051 @Inject 052 WorkRequirementLogic workRequirementLogic; 053 054 protected UserVisitLogic() { 055 super(); 056 } 057 058 private void cleanupUserVisitDependencies(final UserVisit userVisit, final Long endTime, final PartyPK cleanedUpBy) { 059 orderControl.deleteOrderUserVisitsByUserVisit(userVisit); 060 061 // Clear any searches since they may contain results that should not be accessible by another user. 062 searchControl.removeUserVisitSearchesByUserVisit(userVisit); 063 064 workRequirementLogic.endWorkTimesByUserVisit(userVisit, endTime, cleanedUpBy); 065 } 066 067 public void invalidateUserVisit(UserVisit userVisit, PartyPK invalidatedBy) { 068 if(userVisit != null) { 069 var userSession = userSessionLogic.deleteUserSessionByUserVisit(userVisit); 070 071 cleanupUserVisitDependencies(userVisit, null, invalidatedBy); 072 073 if(userVisit.getRetainUntilTime() == null) { 074 if(userSession != null) { 075 userControl.removeUserSession(userSession); 076 } 077 078 userControl.removeUserVisit(userVisit); 079 } else { 080 userControl.deleteUserVisit(userVisit); 081 } 082 } 083 } 084 085 public void invalidateUserVisit(UserVisitPK userVisitPK, PartyPK invalidatedBy) { 086 invalidateUserVisit(userControl.getUserVisitByPKForUpdate(userVisitPK), invalidatedBy); 087 } 088 089 public void invalidateAbandonedUserVisits(Long abandonedTime, PartyPK invalidatedBy) { 090 for(var userVisit: userControl.getAbandonedUserVisits(abandonedTime)) { 091 userVisit = userVisitFactory.getEntityFromPK(EntityPermission.READ_WRITE, userVisit.getPrimaryKey()); 092 093 invalidateUserVisit(userVisit, invalidatedBy); 094 } 095 } 096 097 public void removeInvalidatedUserVisits() { 098 for(var userVisit: userControl.getInvalidatedUserVisits()) { 099 userVisit = userVisitFactory.getEntityFromPK(EntityPermission.READ_WRITE, userVisit.getPrimaryKey()); 100 101 userControl.removeUserVisit(userVisit); 102 } 103 } 104 105 /** Disassociate any Party from the specified UserVisit by deleting the UserSession, keep all the Preferred* properties. 106 */ 107 public void disassociatePartyFromUserVisit(final UserVisit userVisit, final Long endTime, final PartyPK disassociatedBy) { 108 var userSession = userControl.getUserSessionByUserVisitForUpdate(userVisit); 109 110 if(userSession != null) { 111 // If there wasn't a specific UserSession and Party assocaited with the UserVisit, 112 // then we shouldn't need to perform this step. 113 cleanupUserVisitDependencies(userVisit, endTime, disassociatedBy); 114 115 userControl.deleteUserSession(userSession); 116 } 117 } 118 119 /** Remove any Party's specific connection to the UserVisit and its UserKey. Clearing the connection in the UserKey is one step beyond 120 * what's provided by disassociatePartyFromUserVisit(...). 121 */ 122 public void logout(final UserVisitPK userVisitPK, final Long endTime, final PartyPK loggedOutBy) { 123 var userVisit = userControl.getUserVisitByPK(userVisitPK); 124 var userKey = userVisit.getUserKey(); 125 var userKeyDetailValue = userControl.getUserKeyDetailValueByPKForUpdate(userKey.getLastDetail().getPrimaryKey()); 126 127 if(userKeyDetailValue.getPartyPK() != null || userKeyDetailValue.getPartyRelationshipPK() != null) { 128 userKeyDetailValue.setPartyPK(null); 129 userKeyDetailValue.setPartyRelationshipPK(null); 130 userControl.updateUserKeyFromValue(userKeyDetailValue); 131 } 132 133 disassociatePartyFromUserVisit(userVisit, endTime, loggedOutBy); 134 135 // TODO: Create audit trail 136 } 137 138}