Skip to content

Commit

Permalink
feat: 支持目录权限配置 #1579 (#1612)
Browse files Browse the repository at this point in the history
* feat: 拉取一级目录时,结合权限校验 #1585

* feat: 权限相关接口允许项目管理员访问 #1579

* feat: 支持目录权限配置 #1579

* feat: 支持目录权限配置 #1579

* feat: 支持目录权限配置 #1579

* feat: 支持目录权限配置 #1579

* feat: 支持目录权限配置 #1579

* feat: 支持目录权限配置 #1579
  • Loading branch information
owenlxu authored Jan 3, 2024
1 parent dd9b15f commit 9dd3c4c
Show file tree
Hide file tree
Showing 6 changed files with 80 additions and 28 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@
package com.tencent.bkrepo.auth.pojo.permission

import io.swagger.annotations.ApiModel

@ApiModel("校验权限请求")
data class ListPathResult(
// when true, need to compare
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,12 @@ class ServicePermissionController @Autowired constructor(
private val permissionService: PermissionService
) : ServicePermissionClient, OpenResource(permissionService) {


/**
* 本接口不做权限校验,返回空列表时可能表示所有路径均有权限,也可能为无项目仓库权限,因此需要单独做仓库权限校验
*/
override fun listPermissionPath(userId: String, projectId: String, repoName: String): Response<ListPathResult> {
val permissionPath = permissionService.listPermissionPath(userId, projectId, repoName)
val permissionPath = permissionService.listNoPermissionPath(userId, projectId, repoName)
val status = permissionPath.isNotEmpty()
val result = ListPathResult(status = status, path = mapOf(ListPathOperationType.NIN to permissionPath))
return ResponseBuilder.success(result)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ interface PermissionService {
/**
* 获取有权限路径列表
*/
fun listPermissionPath(userId: String, projectId: String, repoName: String): List<String>
fun listNoPermissionPath(userId: String, projectId: String, repoName: String): List<String>

fun createPermission(request: CreatePermissionRequest): Boolean

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,13 @@ import com.tencent.bkrepo.auth.constant.CUSTOM
import com.tencent.bkrepo.auth.constant.LOG
import com.tencent.bkrepo.auth.constant.PIPELINE
import com.tencent.bkrepo.auth.constant.REPORT
import com.tencent.bkrepo.auth.pojo.enums.PermissionAction
import com.tencent.bkrepo.auth.pojo.enums.ResourceType
import com.tencent.bkrepo.auth.pojo.enums.PermissionAction.MANAGE
import com.tencent.bkrepo.auth.pojo.enums.PermissionAction.READ
import com.tencent.bkrepo.auth.pojo.enums.PermissionAction.WRITE
import com.tencent.bkrepo.auth.pojo.enums.PermissionAction.VIEW
import com.tencent.bkrepo.auth.pojo.enums.ResourceType.NODE
import com.tencent.bkrepo.auth.pojo.enums.ResourceType.REPO
import com.tencent.bkrepo.auth.pojo.enums.ResourceType.PROJECT
import com.tencent.bkrepo.auth.pojo.permission.CheckPermissionRequest
import com.tencent.bkrepo.auth.repository.AccountRepository
import com.tencent.bkrepo.auth.repository.PermissionRepository
Expand Down Expand Up @@ -83,7 +88,7 @@ class DevopsPermissionServiceImpl constructor(
}

// devops 体系
if (checkDevopsProjectPermission(userId, projectId, PermissionAction.READ.name)) {
if (checkDevopsProjectPermission(userId, projectId, READ.name)) {
return getAllRepoByProjectId(projectId)
}
return super.listPermissionRepo(projectId, userId, appId)
Expand Down Expand Up @@ -113,11 +118,11 @@ class DevopsPermissionServiceImpl constructor(
return allProjectList.distinct()
}

override fun listPermissionPath(userId: String, projectId: String, repoName: String): List<String> {
if (checkDevopsProjectPermission(userId, projectId, PermissionAction.MANAGE.name)) {
override fun listNoPermissionPath(userId: String, projectId: String, repoName: String): List<String> {
if (checkDevopsProjectPermission(userId, projectId, MANAGE.name)) {
return emptyList()
}
return super.listPermissionPath(userId, projectId, repoName)
return super.listNoPermissionPath(userId, projectId, repoName)
}

private fun parsePipelineId(path: String): String? {
Expand All @@ -138,9 +143,9 @@ class DevopsPermissionServiceImpl constructor(
return true
}
// project权限
if (resourceType == ResourceType.PROJECT.name) {
if (resourceType == PROJECT.name) {
return checkDevopsProjectPermission(uid, projectId!!, action)
|| super.checkBkIamV3ProjectPermission(projectId!!, uid, action)
|| super.checkBkIamV3ProjectPermission(projectId!!, uid, action)
}

// repo或者node权限
Expand All @@ -155,7 +160,7 @@ class DevopsPermissionServiceImpl constructor(
checkDevopsReportPermission(action)
}
else -> {
super.checkPermission(request) || checkDevopsProjectPermission(uid, projectId!!, action)
checkRepoNotInDevops(request)
}
}

Expand All @@ -168,6 +173,16 @@ class DevopsPermissionServiceImpl constructor(
}
}

private fun checkRepoNotInDevops(request: CheckPermissionRequest): Boolean {
with(request) {
if (resourceType == NODE.name && super.isNodeNeedLocalCheck(projectId!!, repoName!!)) {
return checkDevopsProjectPermission(uid, projectId!!, action) && super.checkPermission(request)
} else {
return super.checkPermission(request) || checkDevopsProjectPermission(uid, projectId!!, action)
}
}
}

private fun checkDevopsPipelineOrProjectPermission(request: CheckPermissionRequest): Boolean {
with(request) {
var projectPass = false
Expand All @@ -182,9 +197,7 @@ class DevopsPermissionServiceImpl constructor(
}

private fun checkDevopsReportPermission(action: String): Boolean {
return action == PermissionAction.READ.name ||
action == PermissionAction.WRITE.name ||
action == PermissionAction.VIEW.name
return action == READ.name || action == WRITE.name || action == VIEW.name
}

private fun checkDevopsPipelinePermission(
Expand All @@ -195,8 +208,8 @@ class DevopsPermissionServiceImpl constructor(
action: String
): Boolean {
return when (resourceType) {
ResourceType.REPO.name -> checkDevopsProjectPermission(uid, projectId, action)
ResourceType.NODE.name -> {
REPO.name -> checkDevopsProjectPermission(uid, projectId, action)
NODE.name -> {
val pipelineId = parsePipelineId(path ?: return false) ?: return false
pipelinePermission(uid, projectId, pipelineId, action)
}
Expand All @@ -207,7 +220,7 @@ class DevopsPermissionServiceImpl constructor(
private fun checkDevopsProjectPermission(userId: String, projectId: String, action: String): Boolean {
logger.debug("checkDevopsProjectPermission: [$userId,$projectId,$action]")
return when (action) {
PermissionAction.MANAGE.name -> devopsProjectService.isProjectManager(userId, projectId)
MANAGE.name -> devopsProjectService.isProjectManager(userId, projectId)
else -> devopsProjectService.isProjectMember(userId, projectId, action)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,19 +95,20 @@ open class PermissionServiceImpl constructor(
resourceType?.let {
repoName?.let {
return permissionRepository.findByResourceTypeAndProjectIdAndRepos(
resourceType, projectId, repoName)
resourceType, projectId, repoName
)
.map { PermRequestUtil.convToPermission(it) }
}
return permissionRepository.findByResourceTypeAndProjectId(
resourceType, projectId)
resourceType, projectId
)
.map { PermRequestUtil.convToPermission(it) }
}
repoName?.let {
return permissionRepository.findByResourceTypeAndProjectIdAndRepos(
ResourceType.REPO.name, projectId, repoName)
return permissionRepository.findByResourceTypeAndProjectIdAndRepos(REPO.name, projectId, repoName)
.map { PermRequestUtil.convToPermission(it) }
}
return permissionRepository.findByResourceTypeAndProjectId(ResourceType.PROJECT.name, projectId)
return permissionRepository.findByResourceTypeAndProjectId(PROJECT.name, projectId)
.map { PermRequestUtil.convToPermission(it) }
}

Expand Down Expand Up @@ -255,15 +256,31 @@ open class PermissionServiceImpl constructor(
projectId, repoName, uid, resourceType, roles
)
val result = mongoTemplate.find(query, TPermission::class.java)
if (result.isEmpty() || path == null) return false

result.forEach {
if (checkIncludePatternAction(it.includePattern, path!!, it.actions, action)) return true

if (checkExcludePatternAction(it.excludePattern, path!!, it.actions, action)) return false
}

val noPermissionQuery = PermissionQueryHelper.buildNoPermissionCheck(
projectId, repoName, uid, resourceType, roles
)
val noPermissionResult = mongoTemplate.find(noPermissionQuery, TPermission::class.java)
noPermissionResult.forEach {
if (checkIncludePatternAction(it.includePattern, path!!, it.actions, action)) return false
}
}
return false
return true
}

fun isNodeNeedLocalCheck(projectId: String, repoName: String): Boolean {
val projectPermission = permissionRepository.findByResourceTypeAndProjectIdAndRepos(
NODE.name,
projectId,
repoName,
)
return projectPermission.isNotEmpty()
}

private fun checkIncludePatternAction(
Expand Down Expand Up @@ -385,7 +402,7 @@ open class PermissionServiceImpl constructor(
return repoList.distinct()
}

override fun listPermissionPath(userId: String, projectId: String, repoName: String): List<String> {
override fun listNoPermissionPath(userId: String, projectId: String, repoName: String): List<String> {
val projectPermission = permissionRepository.findByResourceTypeAndProjectIdAndRepos(
NODE.name,
projectId,
Expand Down Expand Up @@ -562,8 +579,8 @@ open class PermissionServiceImpl constructor(
override fun updatePermissionDeployInRepo(request: UpdatePermissionDeployInRepoRequest): Boolean {
checkPermissionExist(request.permissionId)
return updatePermissionById(request.permissionId, TPermission::includePattern.name, request.path)
&& updatePermissionById(request.permissionId, TPermission::users.name, request.users)
&& updatePermissionById(request.permissionId, TPermission::permName.name, request.name)
&& updatePermissionById(request.permissionId, TPermission::users.name, request.users)
&& updatePermissionById(request.permissionId, TPermission::permName.name, request.name)
}

companion object {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,26 @@ object PermissionQueryHelper {
}
return Query(celeriac)
}

fun buildNoPermissionCheck(
projectId: String?,
repoName: String?,
uid: String,
resourceType: String,
roles: List<String>
): Query {
val criteria = Criteria()
var celeriac = criteria.andOperator(
Criteria.where(TPermission::users.name).`ne`(uid),
Criteria.where(TPermission::roles.name).`nin`(roles)
).and(TPermission::resourceType.name).`is`(resourceType)
projectId?.let {
celeriac = celeriac.and(TPermission::projectId.name).`is`(projectId)
}
repoName?.let {
celeriac = celeriac.and(TPermission::repos.name).`is`(repoName)
}
return Query(celeriac)
}

}

0 comments on commit 9dd3c4c

Please sign in to comment.