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.enterprise.inject.spi.CDI; 031import javax.inject.Inject; 032 033@ApplicationScoped 034public class UserVisitLogic 035 extends BaseLogic { 036 037 @Inject 038 UserVisitFactory userVisitFactory; 039 040 @Inject 041 OrderControl orderControl; 042 043 @Inject 044 SearchControl searchControl; 045 046 @Inject 047 UserControl userControl; 048 049 @Inject 050 UserSessionLogic userSessionLogic; 051 052 @Inject 053 WorkRequirementLogic workRequirementLogic; 054 055 protected UserVisitLogic() { 056 super(); 057 } 058 059 public static UserVisitLogic getInstance() { 060 return CDI.current().select(UserVisitLogic.class).get(); 061 } 062 063 private void cleanupUserVisitDependencies(final UserVisit userVisit, final Long endTime, final PartyPK cleanedUpBy) { 064 orderControl.deleteOrderUserVisitsByUserVisit(userVisit); 065 066 // Clear any searches since they may contain results that should not be accessible by another user. 067 searchControl.removeUserVisitSearchesByUserVisit(userVisit); 068 069 workRequirementLogic.endWorkTimesByUserVisit(userVisit, endTime, cleanedUpBy); 070 } 071 072 public void invalidateUserVisit(UserVisit userVisit, PartyPK invalidatedBy) { 073 if(userVisit != null) { 074 var userSession = userSessionLogic.deleteUserSessionByUserVisit(userVisit); 075 076 cleanupUserVisitDependencies(userVisit, null, invalidatedBy); 077 078 if(userVisit.getRetainUntilTime() == null) { 079 if(userSession != null) { 080 userControl.removeUserSession(userSession); 081 } 082 083 userControl.removeUserVisit(userVisit); 084 } else { 085 userControl.deleteUserVisit(userVisit); 086 } 087 } 088 } 089 090 public void invalidateUserVisit(UserVisitPK userVisitPK, PartyPK invalidatedBy) { 091 invalidateUserVisit(userControl.getUserVisitByPKForUpdate(userVisitPK), invalidatedBy); 092 } 093 094 public void invalidateAbandonedUserVisits(Long abandonedTime, PartyPK invalidatedBy) { 095 for(var userVisit: userControl.getAbandonedUserVisits(abandonedTime)) { 096 userVisit = userVisitFactory.getEntityFromPK(EntityPermission.READ_WRITE, userVisit.getPrimaryKey()); 097 098 invalidateUserVisit(userVisit, invalidatedBy); 099 } 100 } 101 102 public void removeInvalidatedUserVisits() { 103 for(var userVisit: userControl.getInvalidatedUserVisits()) { 104 userVisit = userVisitFactory.getEntityFromPK(EntityPermission.READ_WRITE, userVisit.getPrimaryKey()); 105 106 userControl.removeUserVisit(userVisit); 107 } 108 } 109 110 /** Disassociate any Party from the specified UserVisit by deleting the UserSession, keep all the Preferred* properties. 111 */ 112 public void disassociatePartyFromUserVisit(final UserVisit userVisit, final Long endTime, final PartyPK disassociatedBy) { 113 var userSession = userControl.getUserSessionByUserVisitForUpdate(userVisit); 114 115 if(userSession != null) { 116 // If there wasn't a specific UserSession and Party assocaited with the UserVisit, 117 // then we shouldn't need to perform this step. 118 cleanupUserVisitDependencies(userVisit, endTime, disassociatedBy); 119 120 userControl.deleteUserSession(userSession); 121 } 122 } 123 124 /** Remove any Party's specific connection to the UserVisit and its UserKey. Clearing the connection in the UserKey is one step beyond 125 * what's provided by disassociatePartyFromUserVisit(...). 126 */ 127 public void logout(final UserVisitPK userVisitPK, final Long endTime, final PartyPK loggedOutBy) { 128 var userVisit = userControl.getUserVisitByPK(userVisitPK); 129 var userKey = userVisit.getUserKey(); 130 var userKeyDetailValue = userControl.getUserKeyDetailValueByPKForUpdate(userKey.getLastDetail().getPrimaryKey()); 131 132 if(userKeyDetailValue.getPartyPK() != null || userKeyDetailValue.getPartyRelationshipPK() != null) { 133 userKeyDetailValue.setPartyPK(null); 134 userKeyDetailValue.setPartyRelationshipPK(null); 135 userControl.updateUserKeyFromValue(userKeyDetailValue); 136 } 137 138 disassociatePartyFromUserVisit(userVisit, endTime, loggedOutBy); 139 140 // TODO: Create audit trail 141 } 142 143}