content: /*******************************************************************************
   * Copyright (C) 2021, 1C-Soft LLC and others.
   *
   * This program and the accompanying materials are made
   * available under the terms of the Eclipse Public License 2.0
   * which is available at https://www.eclipse.org/legal/epl-2.0/
   *
   * SPDX-License-Identifier: EPL-2.0
   *
   * Contributors:
   *     1C-Soft LLC - initial API and implementation
   *******************************************************************************/
  package com.e1c.v8codestyle.right.check;
  
  import static com._1c.g5.v8.dt.rights.model.RightsPackage.Literals.RLS;
  import static com._1c.g5.v8.dt.rights.model.RightsPackage.Literals.RLS__CONDITION;
  import static com._1c.g5.v8.dt.rights.model.RightsPackage.Literals.ROLE_DESCRIPTION;
  
  import java.text.MessageFormat;
  
  import org.eclipse.core.runtime.Assert;
  import org.eclipse.core.runtime.IProgressMonitor;
  import org.eclipse.xtext.EcoreUtil2;
  
  import com._1c.g5.v8.bm.integration.IBmModel;
  import com._1c.g5.v8.dt.core.platform.IBmModelManager;
  import com._1c.g5.v8.dt.core.platform.IV8Project;
  import com._1c.g5.v8.dt.core.platform.IV8ProjectManager;
  import com._1c.g5.v8.dt.md.MdUtil;
  import com._1c.g5.v8.dt.metadata.mdclass.MdObject;
  import com._1c.g5.v8.dt.metadata.mdclass.Role;
  import com._1c.g5.v8.dt.metadata.mdclass.ScriptVariant;
  import com._1c.g5.v8.dt.rights.model.ObjectRight;
  import com._1c.g5.v8.dt.rights.model.ObjectRights;
  import com._1c.g5.v8.dt.rights.model.Rls;
  import com._1c.g5.v8.dt.rights.model.RoleDescription;
  import com._1c.g5.v8.dt.rights.model.util.RightsModelUtil;
  import com.e1c.g5.v8.dt.check.CheckComplexity;
  import com.e1c.g5.v8.dt.check.ICheckParameters;
  import com.e1c.g5.v8.dt.check.components.BasicCheck;
  import com.e1c.g5.v8.dt.check.settings.IssueSeverity;
  import com.e1c.g5.v8.dt.check.settings.IssueType;
  import com.e1c.v8codestyle.check.StandardCheckExtension;
  import com.e1c.v8codestyle.internal.right.CorePlugin;
  import com.google.inject.Inject;
  
  /**
   * Checks that role has right restriction (RLS) for roles with full-access level.
   *
   * @author Dmitriy Marmyshev
   */
  public class RoleRightHasRls
      extends BasicCheck
  {
  
      private static final String CHECK_ID = "role-right-has-rls"; //$NON-NLS-1$
  
      private static final String ROLE_NAME_PATTERN_PARAMETER_NAME = "roleNamePattern"; //$NON-NLS-1$
  
      private static final String ROLE_NAME_PATTERN_PARAMETER_DEFAULT =
          "ПолныеПрава|АдминистраторСистемы|FullAccess|SystemAdministrator"; //$NON-NLS-1$
  
      public static final String EXCLUDE_OBJECT_NAME_PATTERN_PARAMETER_NAME = "excludeObjectNamePattern"; //$NON-NLS-1$
  
      private final IV8ProjectManager v8ProjectManager;
  
      private final IBmModelManager bmModelManager;
  
      /**
       * Creates new instance of check that find RLS set common roles.
       *
       * @param v8ProjectManager the V8 project manager, cannot be {@code null}.
       * @param bmModelManager  the BM model manager, cannot be {@code null}.
       */
      @Inject
      public RoleRightHasRls(IV8ProjectManager v8ProjectManager, IBmModelManager bmModelManager)
      {
          this.v8ProjectManager = v8ProjectManager;
          this.bmModelManager = bmModelManager;
      }
  
      @Override
      public String getCheckId()
      {
          return CHECK_ID;
      }
  
      @Override
      protected void check(Object object, ResultAcceptor resultAceptor, ICheckParameters parameters,
          IProgressMonitor monitor)
      {
          Rls rls = (Rls)object;
  
          if (rls.getCondition() != null && !rls.getCondition().isBlank())
          {
              String roleNamePattern = parameters.getString(ROLE_NAME_PATTERN_PARAMETER_NAME);
              if (roleNamePattern != null && !roleNamePattern.isBlank())
              {
                  IBmModel model = bmModelManager.getModel(rls);
                  RoleDescription description = EcoreUtil2.getContainerOfType(rls, RoleDescription.class);
                  Role role = RightsModelUtil.getOwner(description, model);
                  if (role == null || !role.getName().matches(roleNamePattern))
                  {
                      return;
                  }
              }
  
              ObjectRight right = EcoreUtil2.getContainerOfType(rls, ObjectRight.class);
              ObjectRights rights = EcoreUtil2.getContainerOfType(right, ObjectRights.class);
              MdObject mdObject = rights.getObject() instanceof MdObject ? (MdObject)rights.getObject() : null;
  
              String excludeObjectNamePattern = parameters.getString(EXCLUDE_OBJECT_NAME_PATTERN_PARAMETER_NAME);
              if (excludeObjectNamePattern != null && !excludeObjectNamePattern.isBlank() && mdObject != null
                  && mdObject.getName().matches(excludeObjectNamePattern))
              {
                  return;
              }
              IV8Project project = v8ProjectManager.getProject(rls);
  
              String rightName = getRightName(right, project);
              String mdName = getMdObjectName(mdObject, project);
  
              String message =
                  MessageFormat.format(Messages.RoleRightHasRls_Role_Right__0__for__1__has_RLS, rightName, mdName);
              resultAceptor.addIssue(message, RLS__CONDITION);
          }
  
      }
  
      @Override
      protected void configureCheck(CheckConfigurer builder)
      {
          builder.title(Messages.RoleRightHasRls_title)
              .description(Messages.RoleRightHasRls_description)
              .complexity(CheckComplexity.NORMAL)
              .severity(IssueSeverity.MAJOR)
              .issueType(IssueType.WARNING)
              .extension(new StandardCheckExtension(488, getCheckId(), CorePlugin.PLUGIN_ID))
              .topObject(ROLE_DESCRIPTION)
              .containment(RLS)
              .features(RLS__CONDITION)
              .parameter(ROLE_NAME_PATTERN_PARAMETER_NAME, String.class, ROLE_NAME_PATTERN_PARAMETER_DEFAULT,
                  Messages.RoleRightHasRls_Role_name_pattern)
              .parameter(EXCLUDE_OBJECT_NAME_PATTERN_PARAMETER_NAME, String.class, "", //$NON-NLS-1$
                  Messages.RoleRightHasRls_Exclude_Right_Object_name_pattern);
      }
  
      private String getRightName(ObjectRight right, IV8Project project)
      {
          Assert.isNotNull(project);
          if (project.getScriptVariant() == ScriptVariant.RUSSIAN)
          {
              return right.getRight().getNameRu();
          }
          return right.getRight().getName();
      }
  
      private String getMdObjectName(MdObject mdObject, IV8Project project)
      {
          Assert.isNotNull(project);
          if (mdObject == null)
          {
              return "Unknown"; //$NON-NLS-1$
          }
  
          if (project.getScriptVariant() == ScriptVariant.RUSSIAN)
          {
              return MdUtil.getFullyQualifiedNameRu(mdObject).toString();
          }
          return MdUtil.getFullyQualifiedName(mdObject).toString();
      }
  
  }
  