diff --git a/schema.json b/schema.json index 3307dd6..071d634 100644 --- a/schema.json +++ b/schema.json @@ -30,6 +30,9 @@ "additionalProperties": { "type": "string" } + }, + "templateRuleKey": { + "type": "string" } } } diff --git a/src/main/kotlin/br/com/felipezorzo/zpa/cli/Main.kt b/src/main/kotlin/br/com/felipezorzo/zpa/cli/Main.kt index f0e2b66..a51b316 100644 --- a/src/main/kotlin/br/com/felipezorzo/zpa/cli/Main.kt +++ b/src/main/kotlin/br/com/felipezorzo/zpa/cli/Main.kt @@ -7,6 +7,7 @@ import br.com.felipezorzo.zpa.cli.config.RuleLevel import br.com.felipezorzo.zpa.cli.exporters.ConsoleExporter import br.com.felipezorzo.zpa.cli.exporters.GenericIssueFormatExporter import br.com.felipezorzo.zpa.cli.plugin.PluginManager +import br.com.felipezorzo.zpa.cli.rules.CliActiveRules import com.beust.jcommander.JCommander import com.beust.jcommander.ParameterException import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper @@ -15,7 +16,6 @@ import com.felipebz.zpa.api.PlSqlFile import com.felipebz.zpa.api.ZpaRulesDefinition import com.felipebz.zpa.api.checks.PlSqlVisitor import com.felipebz.zpa.metadata.FormsMetadata -import com.felipebz.zpa.rules.ActiveRules import com.felipebz.zpa.rules.Repository import com.felipebz.zpa.rules.RuleMetadataLoader import com.felipebz.zpa.rules.ZpaChecks @@ -159,8 +159,7 @@ class Main(private val args: Arguments) { pluginManager.unloadPlugins() } - private fun getActiveRules(): ActiveRules { - val activeRules = ActiveRules() + private fun getActiveRules(): CliActiveRules { val config = if (args.configFile.isNotEmpty()) { val configFile = File(args.configFile) mapper.readValue(configFile, ConfigFile::class.java) @@ -168,6 +167,8 @@ class Main(private val args: Arguments) { ConfigFile() } + val activeRules = CliActiveRules(config) + if (config.rules.isNotEmpty()) { activeRules.addRuleConfigurer { repo, rule, configuration -> var ruleConfig = config.rules["${repo.key}:${rule.key}"] ?: config.rules[rule.key] diff --git a/src/main/kotlin/br/com/felipezorzo/zpa/cli/config/ConfigFile.kt b/src/main/kotlin/br/com/felipezorzo/zpa/cli/config/ConfigFile.kt index 8cf9826..949f279 100644 --- a/src/main/kotlin/br/com/felipezorzo/zpa/cli/config/ConfigFile.kt +++ b/src/main/kotlin/br/com/felipezorzo/zpa/cli/config/ConfigFile.kt @@ -48,6 +48,7 @@ enum class RuleLevel { class RuleOptions { var level: RuleLevel = RuleLevel.ON var parameters: Map = emptyMap() + var templateRuleKey: String? = null } class RuleCategoryDeserializer : JsonDeserializer() { diff --git a/src/main/kotlin/br/com/felipezorzo/zpa/cli/rules/CliActiveRule.kt b/src/main/kotlin/br/com/felipezorzo/zpa/cli/rules/CliActiveRule.kt new file mode 100644 index 0000000..8c4a9bd --- /dev/null +++ b/src/main/kotlin/br/com/felipezorzo/zpa/cli/rules/CliActiveRule.kt @@ -0,0 +1,33 @@ +/** + * Z PL/SQL Analyzer + * Copyright (C) 2015-2025 Felipe Zorzo + * mailto:felipe AT felipezorzo DOT com DOT br + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package br.com.felipezorzo.zpa.cli.rules + +import com.felipebz.zpa.rules.* + +class CliActiveRule( + private val activeRule : ActiveRule, + private val rule: ZpaRule +) : ZpaActiveRule by activeRule { + + constructor(repository : ZpaRepository, rule: ZpaRule, configuration: ActiveRuleConfiguration?) : this(ActiveRule(repository, rule, configuration), rule) + + override val templateRuleKey: String? + get() = (rule as? CliCustomRule)?.templateRuleKey +} diff --git a/src/main/kotlin/br/com/felipezorzo/zpa/cli/rules/CliActiveRules.kt b/src/main/kotlin/br/com/felipezorzo/zpa/cli/rules/CliActiveRules.kt new file mode 100644 index 0000000..10bf6ef --- /dev/null +++ b/src/main/kotlin/br/com/felipezorzo/zpa/cli/rules/CliActiveRules.kt @@ -0,0 +1,91 @@ +/** + * Z PL/SQL Analyzer + * Copyright (C) 2015-2026 Felipe Zorzo + * mailto:felipe AT felipezorzo DOT com DOT br + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package br.com.felipezorzo.zpa.cli.rules + +import br.com.felipezorzo.zpa.cli.config.ConfigFile +import com.felipebz.zpa.rules.* + +class CliActiveRules(val config: ConfigFile?) : ZpaActiveRules { + + private val repositories = mutableListOf() + private val activeRuleConfigurers = mutableListOf() + + fun addRepository(repository: Repository): CliActiveRules = apply { + repositories.add(repository) + } + + fun addRuleConfigurer(filter: ActiveRuleConfigurer): CliActiveRules = apply { + activeRuleConfigurers.add(filter) + } + + override fun findByRepository(repository: String): Collection { + val repo = this.repositories.first { it.key == repository } + val repoAvailableRules = repo.availableRules + val customRules = addCustomRulesByConfig(config, repo) + + return (repoAvailableRules + customRules) + .mapNotNull { rule -> + val activeRuleConfiguration = ActiveRuleConfiguration(repo.key, rule.key) + if (activeRuleConfigurers.all { it.apply(repo, rule, activeRuleConfiguration) }) { + CliActiveRule(repo, rule, activeRuleConfiguration) + } else { + null + } + } + } + + fun addCustomRulesByConfig(config: ConfigFile?, repo: Repository): List { + if (config == null) return emptyList() + + return config.rules.entries + .mapNotNull { (key, ruleConfig) -> + val templateRuleKey = ruleConfig.options.templateRuleKey?.let { RuleKeyParser.parse(it) } ?: return@mapNotNull null + if (templateRuleKey.repository.isNotEmpty() && templateRuleKey.repository != repo.key) return@mapNotNull null + val templateRule = repo.rule(templateRuleKey.rule) ?: return@mapNotNull null + + createCustomRuleFromTemplateRule(key, templateRule) + } + } + + private fun createCustomRuleFromTemplateRule(key: String, templateRule: ZpaRule): CliCustomRule { + + val rule = Rule(key).apply { + name = templateRule.name + remediationConstant = templateRule.remediationConstant + scope = templateRule.scope + severity = templateRule.severity + status = templateRule.status + tags = templateRule.tags + htmlDescription = templateRule.htmlDescription + isActivatedByDefault = templateRule.isActivatedByDefault + templateRule.params.forEach { param -> + createParam(param.key).apply { + description = param.description + defaultValue = param.defaultValue + } + } + } + + return CliCustomRule(rule).apply { + templateRuleKey = templateRule.key + } + } + +} diff --git a/src/main/kotlin/br/com/felipezorzo/zpa/cli/rules/CliCustomRule.kt b/src/main/kotlin/br/com/felipezorzo/zpa/cli/rules/CliCustomRule.kt new file mode 100644 index 0000000..23efe24 --- /dev/null +++ b/src/main/kotlin/br/com/felipezorzo/zpa/cli/rules/CliCustomRule.kt @@ -0,0 +1,28 @@ +/** + * Z PL/SQL Analyzer + * Copyright (C) 2015-2026 Felipe Zorzo + * mailto:felipe AT felipezorzo DOT com DOT br + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package br.com.felipezorzo.zpa.cli.rules + +import com.felipebz.zpa.rules.ZpaRule + +class CliCustomRule( + rule: ZpaRule +) : ZpaRule by rule { + var templateRuleKey : String? = null +} diff --git a/src/main/kotlin/br/com/felipezorzo/zpa/cli/rules/RuleKeyParser.kt b/src/main/kotlin/br/com/felipezorzo/zpa/cli/rules/RuleKeyParser.kt new file mode 100644 index 0000000..0b2a128 --- /dev/null +++ b/src/main/kotlin/br/com/felipezorzo/zpa/cli/rules/RuleKeyParser.kt @@ -0,0 +1,33 @@ +/** + * Z PL/SQL Analyzer + * Copyright (C) 2015-2026 Felipe Zorzo + * mailto:felipe AT felipezorzo DOT com DOT br + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package br.com.felipezorzo.zpa.cli.rules + +import com.felipebz.zpa.rules.RuleKey + +object RuleKeyParser { + fun parse(key: String): RuleKey { + val parts = key.split(":", limit = 2) + return if (parts.size == 2) { + RuleKey(parts[0], parts[1]) + } else { + RuleKey("", parts[0]) + } + } +}