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.security.server.logic;
018
019import com.echothree.control.user.security.common.spec.SecurityRoleUniversalSpec;
020import com.echothree.model.control.core.common.ComponentVendors;
021import com.echothree.model.control.core.common.EntityTypes;
022import com.echothree.model.control.core.common.exception.InvalidParameterCountException;
023import com.echothree.model.control.core.server.logic.EntityInstanceLogic;
024import com.echothree.model.control.security.common.exception.MissingRequiredSecurityRoleGroupNameException;
025import com.echothree.model.control.security.common.exception.UnknownDefaultSecurityRoleException;
026import com.echothree.model.control.security.common.exception.UnknownSecurityRoleNameException;
027import com.echothree.model.control.security.server.control.SecurityControl;
028import com.echothree.model.control.selector.server.control.SelectorControl;
029import com.echothree.model.data.party.server.entity.Party;
030import com.echothree.model.data.security.server.entity.SecurityRole;
031import com.echothree.model.data.security.server.entity.SecurityRoleGroup;
032import com.echothree.util.common.exception.BaseException;
033import com.echothree.util.common.message.ExecutionErrors;
034import com.echothree.util.server.control.BaseLogic;
035import com.echothree.util.server.message.ExecutionErrorAccumulator;
036import com.echothree.util.server.persistence.EntityPermission;
037import com.echothree.util.server.validation.ParameterUtils;
038import javax.enterprise.context.ApplicationScoped;
039import javax.enterprise.inject.spi.CDI;
040import javax.inject.Inject;
041
042@ApplicationScoped
043public class SecurityRoleLogic
044        extends BaseLogic {
045
046    @Inject
047    protected SecurityControl securityControl;
048
049    @Inject
050    SelectorControl selectorControl;
051
052    @Inject
053    EntityInstanceLogic entityInstanceLogic;
054
055    @Inject
056    protected SecurityRoleGroupLogic securityRoleGroupLogic;
057
058    protected SecurityRoleLogic() {
059        super();
060    }
061
062    public static SecurityRoleLogic getInstance() {
063        return CDI.current().select(SecurityRoleLogic.class).get();
064    }
065
066    public SecurityRole getSecurityRoleByName(final Class<? extends BaseException> unknownSecurityRoleGroupException, final ExecutionErrors unknownSecurityRoleGroupExecutionError,
067            final Class<? extends BaseException>  unknownSecurityRoleException, final ExecutionErrors unknownSecurityRoleExecutionError,
068            final ExecutionErrorAccumulator eea, final String securityRoleGroupName, final String securityRoleName) {
069        var securityRoleGroup = securityRoleGroupLogic.getSecurityRoleGroupByName(unknownSecurityRoleGroupException, unknownSecurityRoleGroupExecutionError,
070                eea, securityRoleGroupName, EntityPermission.READ_ONLY);
071        SecurityRole securityRole = null;
072
073        if(eea == null || !eea.hasExecutionErrors()) {
074            securityRole = getSecurityRoleByName(unknownSecurityRoleException, unknownSecurityRoleExecutionError, eea,
075                    securityRoleGroup, securityRoleName);
076        }
077
078        return securityRole;
079    }
080
081    public SecurityRole getSecurityRoleByName(final Class<? extends BaseException> unknownException, final ExecutionErrors unknownExecutionError,
082            final ExecutionErrorAccumulator eea, final SecurityRoleGroup securityRoleGroup, final String securityRoleName, EntityPermission entityPermission) {
083        var securityRole = securityControl.getSecurityRoleByName(securityRoleGroup, securityRoleName, entityPermission);
084
085        if(securityRole == null) {
086            handleExecutionError(unknownException, eea, unknownExecutionError.name(), securityRoleGroup.getLastDetail().getSecurityRoleGroupName(),
087                    securityRoleName);
088        }
089
090        return securityRole;
091    }
092
093    public SecurityRole getSecurityRoleByName(final Class<? extends BaseException> unknownException, final ExecutionErrors unknownExecutionError,
094            final ExecutionErrorAccumulator eea, final SecurityRoleGroup securityRoleGroup, final String securityRoleName) {
095        return getSecurityRoleByName(unknownException, unknownExecutionError, eea, securityRoleGroup, securityRoleName, EntityPermission.READ_ONLY);
096    }
097
098    public SecurityRole getSecurityRoleByNameForUpdate(final Class<? extends BaseException> unknownException, final ExecutionErrors unknownExecutionError,
099            final ExecutionErrorAccumulator eea, final SecurityRoleGroup securityRoleGroup, final String securityRoleName) {
100        return getSecurityRoleByName(unknownException, unknownExecutionError, eea, securityRoleGroup, securityRoleName, EntityPermission.READ_WRITE);
101    }
102
103    public SecurityRole getSecurityRoleByName(final ExecutionErrorAccumulator eea, final SecurityRoleGroup securityRoleGroup, final String securityRoleName,
104            final EntityPermission entityPermission) {
105        return getSecurityRoleByName(UnknownSecurityRoleNameException.class, ExecutionErrors.UnknownSecurityRoleName,
106                eea, securityRoleGroup, securityRoleName, entityPermission);
107    }
108
109    public SecurityRole getSecurityRoleByName(final ExecutionErrorAccumulator eea, final SecurityRoleGroup securityRoleGroup, final String securityRoleName) {
110        return getSecurityRoleByName(UnknownSecurityRoleNameException.class, ExecutionErrors.UnknownSecurityRoleName,
111                eea, securityRoleGroup, securityRoleName);
112    }
113
114    public SecurityRole getSecurityRoleByNameForUpdate(final ExecutionErrorAccumulator eea, final SecurityRoleGroup securityRoleGroup, final String securityRoleName) {
115        return getSecurityRoleByNameForUpdate(UnknownSecurityRoleNameException.class, ExecutionErrors.UnknownSecurityRoleName,
116                eea, securityRoleGroup, securityRoleName);
117    }
118
119    public SecurityRole getSecurityRoleByName(final ExecutionErrorAccumulator eea, final String securityRoleGroupName, final String securityRoleName,
120            final EntityPermission entityPermission) {
121        var securityRoleGroup = securityRoleGroupLogic.getSecurityRoleGroupByName(eea, securityRoleGroupName);
122        SecurityRole securityRole = null;
123
124        if(eea == null || !eea.hasExecutionErrors()) {
125            securityRole = getSecurityRoleByName(UnknownSecurityRoleNameException.class, ExecutionErrors.UnknownSecurityRoleName,
126                    eea, securityRoleGroup, securityRoleName, entityPermission);
127        }
128
129        return securityRole;
130    }
131
132    public SecurityRole getSecurityRoleByName(final ExecutionErrorAccumulator eea, final String securityRoleGroupName, final String securityRoleName) {
133        return getSecurityRoleByName(eea, securityRoleGroupName, securityRoleName, EntityPermission.READ_ONLY);
134    }
135
136    public SecurityRole getSecurityRoleByNameForUpdate(final ExecutionErrorAccumulator eea, final String securityRoleGroupName, final String securityRoleName) {
137        return getSecurityRoleByName(eea, securityRoleGroupName, securityRoleName, EntityPermission.READ_WRITE);
138    }
139
140    public SecurityRole getSecurityRoleByUniversalSpec(final ExecutionErrorAccumulator eea, final SecurityRoleUniversalSpec universalSpec,
141            final boolean allowDefault, final EntityPermission entityPermission) {
142        var securityRoleGroupName = universalSpec.getSecurityRoleGroupName();
143        var securityRoleName = universalSpec.getSecurityRoleName();
144        var nameParameterCount= ParameterUtils.getInstance().countNonNullParameters(securityRoleGroupName, securityRoleName);
145        var possibleEntitySpecs= entityInstanceLogic.countPossibleEntitySpecs(universalSpec);
146        SecurityRole securityRole = null;
147
148        if(nameParameterCount < 3 && possibleEntitySpecs == 0) {
149            SecurityRoleGroup securityRoleGroup = null;
150
151            if(securityRoleGroupName != null) {
152                securityRoleGroup = securityRoleGroupLogic.getSecurityRoleGroupByName(eea, securityRoleGroupName);
153            } else {
154                handleExecutionError(MissingRequiredSecurityRoleGroupNameException.class, eea, ExecutionErrors.MissingRequiredSecurityRoleGroupName.name());
155            }
156
157            if(eea == null || !eea.hasExecutionErrors()) {
158                if(securityRoleName == null) {
159                    if(allowDefault) {
160                        securityRole = securityControl.getDefaultSecurityRole(securityRoleGroup, entityPermission);
161
162                        if(securityRole == null) {
163                            handleExecutionError(UnknownDefaultSecurityRoleException.class, eea, ExecutionErrors.UnknownDefaultSecurityRole.name());
164                        }
165                    } else {
166                        handleExecutionError(InvalidParameterCountException.class, eea, ExecutionErrors.InvalidParameterCount.name());
167                    }
168                } else {
169                    securityRole = getSecurityRoleByName(eea, securityRoleGroup, securityRoleName, entityPermission);
170                }
171            }
172        } else if(nameParameterCount == 0 && possibleEntitySpecs == 1) {
173            var entityInstance = entityInstanceLogic.getEntityInstance(eea, universalSpec,
174                    ComponentVendors.ECHO_THREE.name(), EntityTypes.SecurityRole.name());
175
176            if(eea == null || !eea.hasExecutionErrors()) {
177                securityRole = securityControl.getSecurityRoleByEntityInstance(entityInstance, entityPermission);
178            }
179        } else {
180            handleExecutionError(InvalidParameterCountException.class, eea, ExecutionErrors.InvalidParameterCount.name());
181        }
182
183        return securityRole;
184    }
185
186    public SecurityRole getSecurityRoleByUniversalSpec(final ExecutionErrorAccumulator eea, final SecurityRoleUniversalSpec universalSpec,
187            boolean allowDefault) {
188        return getSecurityRoleByUniversalSpec(eea, universalSpec, allowDefault, EntityPermission.READ_ONLY);
189    }
190
191    public SecurityRole getSecurityRoleByUniversalSpecForUpdate(final ExecutionErrorAccumulator eea, final SecurityRoleUniversalSpec universalSpec,
192            boolean allowDefault) {
193        return getSecurityRoleByUniversalSpec(eea, universalSpec, allowDefault, EntityPermission.READ_WRITE);
194    }
195    
196    public boolean hasSecurityRole(final Party party, final SecurityRole securityRole) {
197        var result = false;
198
199        if(party != null) {
200            var partySecurityRole = securityControl.getPartySecurityRole(party, securityRole);
201
202            if(partySecurityRole != null) {
203                var securityRolePartyType = securityControl.getSecurityRolePartyType(securityRole, party.getLastDetail().getPartyType());
204
205                if(securityRolePartyType == null) {
206                    result = true;
207                } else {
208                    var partySelector = securityRolePartyType.getPartySelector();
209
210                    if(partySelector != null) {
211                        if(selectorControl.getSelectorParty(partySelector, party) != null) {
212                            result = true;
213                        }
214                    }
215                }
216            }
217        }
218        
219        return result;
220    }
221
222    public boolean hasSecurityRoleUsingNames(final ExecutionErrorAccumulator eea, final Party party, final String securityRoleGroupName,
223            final String securityRoleName) {
224        var securityRole = getSecurityRoleByName(eea, securityRoleGroupName, securityRoleName);
225        var result = false;
226        
227        if(!hasExecutionErrors(eea)) {
228            result = hasSecurityRole(party, securityRole);
229        }
230        
231        return result;
232    }
233    
234}