125 lines
4.0 KiB
Groovy
125 lines
4.0 KiB
Groovy
/**
|
||
* Permission Scheme Housekeeping (Cloud) – Report + optional Delete
|
||
* ----------------------------------------------------------------
|
||
* Delete rule:
|
||
* - Scheme darf nur gelöscht werden, wenn:
|
||
* 1) es in keinem PROTECTED_PROJECT verwendet wird
|
||
* 2) es nicht über PROTECTED_SCHEME_IDS geschützt ist
|
||
* 3) es nicht über PROTECTED_NAME_PATTERNS geschützt ist
|
||
*/
|
||
|
||
def PROTECTED_PROJECT_KEYS = ["NIN","NICS","NINPDS","NINPDSARC","CS","CRON"]
|
||
|
||
// Zusätzliche Sicherung:
|
||
def PROTECTED_SCHEME_IDS = [
|
||
// "10000", // <- optional: hier IDs eintragen, die NIE gelöscht werden dürfen
|
||
]
|
||
def PROTECTED_NAME_PATTERNS = [
|
||
"default",
|
||
"system"
|
||
]
|
||
|
||
def DRY_RUN = true // erst auf false, wenn der Report passt
|
||
|
||
logger.info("=== Permission Scheme Housekeeping ===")
|
||
logger.info("Protected projects: ${PROTECTED_PROJECT_KEYS}")
|
||
logger.info("Protected scheme IDs: ${PROTECTED_SCHEME_IDS}")
|
||
logger.info("Protected name patterns: ${PROTECTED_NAME_PATTERNS}")
|
||
logger.info("DRY_RUN: ${DRY_RUN}")
|
||
|
||
// Helper: Name-Schutz (case-insensitive)
|
||
def isNameProtected = { String name ->
|
||
def n = (name ?: "").toLowerCase()
|
||
return PROTECTED_NAME_PATTERNS.any { p -> n.contains((p ?: "").toLowerCase()) }
|
||
}
|
||
|
||
// Helper: ID-Schutz
|
||
def isIdProtected = { String id ->
|
||
return PROTECTED_SCHEME_IDS.any { it?.toString() == id?.toString() }
|
||
}
|
||
|
||
// 1) Project -> PermissionSchemeId (nur 6 Calls)
|
||
def projectToSchemeId = [:]
|
||
|
||
PROTECTED_PROJECT_KEYS.each { key ->
|
||
def resp = get("/rest/api/3/project/${key}/permissionscheme")
|
||
.asObject(Map)
|
||
|
||
if (resp.status == 200) {
|
||
// Jira liefert hier i.d.R. {id, name, ...}
|
||
projectToSchemeId[key] = resp.body?.id?.toString()
|
||
} else {
|
||
projectToSchemeId[key] = null
|
||
logger.warn("WARN|PROJECT_LOOKUP_FAILED|${key}|status=${resp.status}")
|
||
}
|
||
}
|
||
|
||
logger.info("INFO|PROJECT_SCHEME_MAP|${projectToSchemeId}")
|
||
|
||
// 2) Alle Permission Schemes holen
|
||
def schemesResp = get("/rest/api/3/permissionscheme")
|
||
.asObject(Map)
|
||
|
||
assert schemesResp.status == 200
|
||
|
||
// Je nach API-Response ist das typischerweise body.permissionSchemes
|
||
def schemes = schemesResp.body?.permissionSchemes ?: []
|
||
logger.info("INFO|TOTAL_SCHEMES|${schemes.size()}")
|
||
|
||
def candidates = [] // [id, name, reason]
|
||
def keptByUsage = 0
|
||
def keptByRule = 0
|
||
|
||
schemes.each { scheme ->
|
||
def schemeId = scheme.id?.toString()
|
||
def schemeName = scheme.name?.toString()
|
||
|
||
def usedBy = projectToSchemeId.findAll { k, v -> v == schemeId }*.key
|
||
def nameProtected = isNameProtected(schemeName)
|
||
def idProtected = isIdProtected(schemeId)
|
||
|
||
// Schutz greift immer (egal ob benutzt oder nicht)
|
||
if (idProtected || nameProtected) {
|
||
keptByRule++
|
||
def why = []
|
||
if (idProtected) why << "ID_PROTECTED"
|
||
if (nameProtected) why << "NAME_PROTECTED"
|
||
logger.info("KEEP|schemeId=${schemeId}|name=${schemeName}|usedBy=${usedBy}|reason=${why}")
|
||
return
|
||
}
|
||
|
||
// Projekt-Usage entscheidet
|
||
if (usedBy && !usedBy.isEmpty()) {
|
||
keptByUsage++
|
||
logger.info("KEEP|schemeId=${schemeId}|name=${schemeName}|usedBy=${usedBy}|reason=USED_BY_PROTECTED_PROJECT")
|
||
return
|
||
}
|
||
|
||
// Kandidat
|
||
logger.info("DEL?|schemeId=${schemeId}|name=${schemeName}|usedBy=[]|reason=UNUSED")
|
||
candidates << [schemeId, schemeName, "UNUSED"]
|
||
|
||
if (!DRY_RUN) {
|
||
def delResp = delete("/rest/api/3/permissionscheme/${schemeId}")
|
||
.asString()
|
||
|
||
if (delResp.status == 204) {
|
||
logger.info("DEL|OK|schemeId=${schemeId}|name=${schemeName}")
|
||
} else {
|
||
logger.error("DEL|FAIL|schemeId=${schemeId}|name=${schemeName}|status=${delResp.status}|body=${delResp.body}")
|
||
}
|
||
}
|
||
}
|
||
|
||
logger.info("=== SUMMARY ===")
|
||
logger.info("Total schemes: ${schemes.size()}")
|
||
logger.info("Kept (used by protected projects): ${keptByUsage}")
|
||
logger.info("Kept (protected by rules): ${keptByRule}")
|
||
logger.info("Delete candidates: ${candidates.size()}")
|
||
|
||
candidates.each { c ->
|
||
logger.info("CANDIDATE|schemeId=${c[0]}|name=${c[1]}|reason=${c[2]}")
|
||
}
|
||
|
||
logger.info("=== DONE ===")
|