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