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