Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat:提供项目管理相关openapi接口 #11231 #11272

Merged
merged 19 commits into from
Dec 10, 2024
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
a71c3a5
feat:提供项目管理相关openapi接口 #11231
fcfang123 Nov 20, 2024
85ba6cc
feat:提供项目管理相关openapi接口 #11231
fcfang123 Nov 20, 2024
1f3f2c4
feat:提供项目管理相关openapi接口 #11231
fcfang123 Nov 20, 2024
d146930
feat:提供项目管理相关openapi接口 #11231
fcfang123 Nov 22, 2024
910803c
feat:提供项目管理相关openapi接口 #11231
fcfang123 Nov 22, 2024
30233a0
feat:提供项目管理相关openapi接口 #11231
fcfang123 Nov 22, 2024
607c327
feat:提供项目管理相关openapi接口 #11231
fcfang123 Dec 2, 2024
5825d98
feat:提供项目管理相关openapi接口 #11231
fcfang123 Dec 2, 2024
04c1f09
feat:提供项目管理相关openapi接口 #11231
fcfang123 Dec 3, 2024
b3bc23c
feat:提供项目管理相关openapi接口 #11231
fcfang123 Dec 3, 2024
ac1a918
feat:提供项目管理相关openapi接口 #11231
fcfang123 Dec 3, 2024
24ea875
feat:提供项目管理相关openapi接口 #11231
fcfang123 Dec 3, 2024
ef29f51
feat:提供项目管理相关openapi接口 #11231
fcfang123 Dec 3, 2024
3048784
feat:提供项目管理相关openapi接口 #11231
fcfang123 Dec 3, 2024
91e4512
feat:提供项目管理相关openapi接口 #11231
fcfang123 Dec 3, 2024
01b3749
feat:提供项目管理相关openapi接口 #11231
fcfang123 Dec 3, 2024
cc8f5d6
feat:提供项目管理相关openapi接口 #11231
fcfang123 Dec 3, 2024
c57d366
feat:提供项目管理相关openapi接口 #11231
fcfang123 Dec 3, 2024
7731a41
feat:提供项目管理相关openapi接口 #11231
fcfang123 Dec 9, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,10 @@ object ArtifactoryMessageCode {
const val GET_FILE_FAIL = "2102046" // 构建分发获取文件失败
const val JOB_EXECUTE_FAIL = "2102047" // JOB执行失败,msg{0}

const val HANDOVER_TO_PROJECT_DOWNLOAD_PERMISSION_FORBIDDEN = "2102048" // 流水线代持人{0}没有项目{1}下载权限
// 流水线代持人{0}在项目{1}下没有流水线{2}下载构件权限
const val HANDOVER_TO_PIPELINE_DOWNLOAD_PERMISSION_FORBIDDEN = "2102049"

const val BK_BLUE_SHIELD_SHARE_FILES_WITH_YOU = "bkBlueShieldShareFilesWithYou" // 【蓝盾版本仓库通知】{0}与你共享{1}文件
// 【蓝盾版本仓库通知】{0}与你共享{1}等{2}个文件
const val BK_BLUE_SHIELD_SHARE_AND_OTHER_FILES_WITH_YOU = "bkBlueShieldShareAndOtherFilesWithYou"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ interface ServiceProjectAuthResource {

@GET
@Path("/{projectCode}/users/{userId}/isProjectUsers")
@Operation(summary = "判断是否某个项目中某个组角色的成员")
@Operation(summary = "校验用户是否有访问项目权限")
fun isProjectUser(
@HeaderParam(AUTH_HEADER_DEVOPS_BK_TOKEN)
@Parameter(description = "认证token", required = true)
Expand All @@ -134,6 +134,18 @@ interface ServiceProjectAuthResource {
group: BkAuthGroup? = null
): Result<Boolean>

@GET
@Path("/{projectCode}/users/{userId}/isProjectMember")
@Operation(summary = "校验用户是否是项目成员")
fun isProjectMember(
@PathParam("userId")
@Parameter(description = "用户Id", required = true)
userId: String,
@PathParam("projectCode")
@Parameter(description = "项目Code", required = true)
projectCode: String
): Result<Boolean>

@GET
@Path("/{projectCode}/users/{userId}/checkUserInProjectLevelGroup")
@Operation(summary = "是否该用户在项目级别的组中")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,9 +71,9 @@ class AuthCronSyncGroupAndMember(
}

/**
* 1小时同步一次用户过期时间
* 10分钟同步一次用户过期时间
* */
@Scheduled(initialDelay = 1000, fixedRate = 3600000)
@Scheduled(initialDelay = 1000, fixedRate = 600000)
fun syncGroupMemberExpiredTimeRegularly() {
if (!enable) {
return
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
package com.tencent.devops.auth.dao

import com.tencent.devops.auth.pojo.vo.AuthItsmCallbackInfo
import com.tencent.devops.common.db.utils.skipCheck
import com.tencent.devops.model.auth.tables.TAuthItsmCallback
import com.tencent.devops.model.auth.tables.records.TAuthItsmCallbackRecord
import org.jooq.DSLContext
Expand Down Expand Up @@ -95,6 +96,7 @@ class AuthItsmCallbackDao {
return dslContext.selectFrom(this)
.where(ENGLISH_NAME.eq(projectCode))
.orderBy(CREATE_TIME.desc())
.skipCheck()
.fetchAny()
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@ import com.tencent.bk.sdk.iam.constants.ManagerScopesEnum
import com.tencent.devops.auth.pojo.AuthResourceGroupMember
import com.tencent.devops.auth.pojo.ResourceMemberInfo
import com.tencent.devops.auth.pojo.dto.ProjectMembersQueryConditionDTO
import com.tencent.devops.auth.pojo.enum.MemberType
import com.tencent.devops.common.auth.api.pojo.BkAuthGroup
import com.tencent.devops.common.db.utils.skipCheck
import com.tencent.devops.model.auth.tables.TAuthResourceAuthorization
import com.tencent.devops.model.auth.tables.TAuthResourceGroupMember
import com.tencent.devops.model.auth.tables.records.TAuthResourceGroupMemberRecord
Expand Down Expand Up @@ -269,6 +271,29 @@ class AuthResourceGroupMemberDao {
}
}

fun isMemberInProject(
dslContext: DSLContext,
projectCode: String,
userId: String,
iamTemplateIds: List<String>,
memberDeptInfos: List<String>?
): Boolean {
return with(TAuthResourceGroupMember.T_AUTH_RESOURCE_GROUP_MEMBER) {
dslContext.selectCount()
.from(this)
.where(
buildMemberGroupCondition(
projectCode = projectCode,
memberId = userId,
iamTemplateIds = iamTemplateIds,
memberDeptInfos = memberDeptInfos,
minExpiredAt = LocalDateTime.now()
)
)
.fetchOne(0, Int::class.java)!! > 0
}
}

fun handoverGroupMembers(
dslContext: DSLContext,
projectCode: String,
Expand Down Expand Up @@ -368,6 +393,7 @@ class AuthResourceGroupMemberDao {
)
.orderBy(field(MEMBER_ID))
.offset(offset).limit(limit)
.skipCheck()
.fetch().map {
ResourceMemberInfo(id = it.value1(), name = it.value2(), type = it.value3())
}
Expand Down Expand Up @@ -455,6 +481,7 @@ class AuthResourceGroupMemberDao {
countDistinct(field(MEMBER_ID, Long::class.java))
).from(resourceMemberUnionAuthorizationMember)
.groupBy(field(MEMBER_TYPE, Long::class.java))
.skipCheck()
.fetch().map { Pair(it.value1(), it.value2()) }.toMap()
}

Expand All @@ -479,6 +506,7 @@ class AuthResourceGroupMemberDao {
deptName = deptName
)
)
.skipCheck()
.fetchOne(0, Long::class.java) ?: 0L
}

Expand Down Expand Up @@ -622,32 +650,42 @@ class AuthResourceGroupMemberDao {
iamTemplateIds: List<String>,
resourceType: String? = null,
iamGroupIds: List<Int>? = null,
excludeIamGroupIds: List<Int>? = null,
minExpiredAt: LocalDateTime? = null,
maxExpiredAt: LocalDateTime? = null
maxExpiredAt: LocalDateTime? = null,
memberDeptInfos: List<String>? = null
): MutableList<Condition> {
val conditions = mutableListOf<Condition>()
with(TAuthResourceGroupMember.T_AUTH_RESOURCE_GROUP_MEMBER) {
conditions.add(PROJECT_CODE.eq(projectCode))
conditions.add(
// 获取直接加入
(MEMBER_ID.eq(memberId).and(
MEMBER_TYPE.`in`(
listOf(
ManagerScopesEnum.getType(ManagerScopesEnum.USER),
ManagerScopesEnum.getType(ManagerScopesEnum.DEPARTMENT)
)
)
))
.or(
MEMBER_ID.`in`(iamTemplateIds)
.and(MEMBER_TYPE.eq(ManagerScopesEnum.getType(ManagerScopesEnum.TEMPLATE)))
)
)
MEMBER_TYPE.`in`(listOf(MemberType.USER.type, MemberType.DEPARTMENT.type))
)).let {
// 获取模板加入
if (iamTemplateIds.isNotEmpty()) {
it.or(MEMBER_ID.`in`(iamTemplateIds).and(MEMBER_TYPE.eq(MemberType.TEMPLATE.type)))
} else {
it
}
}.let {
// 获取组织加入
if (!memberDeptInfos.isNullOrEmpty()) {
it.or(MEMBER_ID.`in`(memberDeptInfos).and(MEMBER_TYPE.eq(MemberType.DEPARTMENT.type)))
} else {
it
}
})
resourceType?.let { conditions.add(RESOURCE_TYPE.eq(resourceType)) }
minExpiredAt?.let { conditions.add(EXPIRED_TIME.ge(minExpiredAt)) }
maxExpiredAt?.let { conditions.add(EXPIRED_TIME.le(maxExpiredAt)) }
if (!iamGroupIds.isNullOrEmpty()) {
conditions.add(IAM_GROUP_ID.`in`(iamGroupIds))
}
if (!excludeIamGroupIds.isNullOrEmpty()) {
conditions.add(IAM_GROUP_ID.notIn(excludeIamGroupIds))
}
}
return conditions
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,8 @@ class RbacAuthConfiguration {
dslContext = dslContext,
deptService = deptService,
permissionAuthorizationService = permissionAuthorizationService,
syncIamGroupMemberService = syncIamGroupMemberService
syncIamGroupMemberService = syncIamGroupMemberService,
rbacCacheService = rbacCacheService
)

@Bean
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -149,13 +149,28 @@ class RbacPermissionProjectService(
}
}

override fun isProjectMember(
userId: String,
projectCode: String
): Boolean {
return resourceMemberService.isProjectMember(
projectCode = projectCode,
userId = userId
)
}

override fun checkUserInProjectLevelGroup(userId: String, projectCode: String): Boolean {
return resourceGroupMemberService.getResourceGroupMembers(
// todo 下个迭代改回
// return resourceGroupMemberService.getResourceGroupMembers(
// projectCode = projectCode,
// resourceType = AuthResourceType.PROJECT.value,
// resourceCode = projectCode,
// group = null
// ).contains(userId)
return resourceMemberService.isProjectMember(
projectCode = projectCode,
resourceType = AuthResourceType.PROJECT.value,
resourceCode = projectCode,
group = null
).contains(userId)
userId = userId
)
}

override fun checkProjectManager(userId: String, projectCode: String): Boolean {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ import org.slf4j.LoggerFactory
import org.slf4j.MDC
import org.springframework.beans.factory.annotation.Autowired
import java.time.LocalDateTime
import java.util.concurrent.Callable
import java.util.concurrent.CompletableFuture
import java.util.concurrent.CompletionException
import java.util.concurrent.Executors
Expand Down Expand Up @@ -119,8 +120,8 @@ class RbacPermissionResourceGroupSyncService @Autowired constructor(
limit = limit,
offset = offset
).data?.map { it.englishName } ?: break
projectCodes.forEach { projectCode ->
syncMemberExpiredExecutorService.submit {
val futures = projectCodes.map { projectCode ->
syncMemberExpiredExecutorService.submit(Callable {
logger.info("start to sync project group member expired time|$projectCode")
val projectMembersOfExpired = authResourceGroupMemberDao.listResourceGroupMember(
dslContext = dslContext,
Expand All @@ -136,15 +137,19 @@ class RbacPermissionResourceGroupSyncService @Autowired constructor(
verifyResults.forEach { (groupId, verifyResult) ->
if (verifyResult.belong == true && verifyResult.expiredAt > LocalDateTime.now().timestamp()) {
logger.info("The member of group needs to have been renewed:$projectCode|$groupId|$memberId")
syncIamGroupMember(
authResourceGroupMemberDao.update(
dslContext = dslContext,
projectCode = projectCode,
iamGroupId = groupId
iamGroupId = groupId,
expiredTime = DateTimeUtil.convertTimestampToLocalDateTime(verifyResult.expiredAt),
memberId = memberId
)
}
}
}
}
})
}
futures.forEach { it.get() }
offset += limit
} while (projectCodes.size == limit)
}
Expand Down Expand Up @@ -218,62 +223,58 @@ class RbacPermissionResourceGroupSyncService @Autowired constructor(
}

override fun syncIamGroupMembersOfApply() {
val traceId = MDC.get(TraceTag.BIZID)
syncExecutorService.submit {
MDC.put(TraceTag.BIZID, traceId)
val limit = 100
var offset = 0
val startEpoch = System.currentTimeMillis()
val finalRecordsOfPending = mutableListOf<TAuthResourceGroupApplyRecord>()
val finalRecordsOfSuccess = mutableListOf<TAuthResourceGroupApplyRecord>()
do {
logger.info("sync members of apply | start")
// 获取7天内未审批单据
val records = authResourceGroupApplyDao.list(
dslContext = dslContext,
day = 7,
limit = limit,
offset = offset
)
val (recordsOfSuccess, recordsOfPending) = records.partition {
try {
val isMemberJoinedToGroup = iamV2ManagerService.verifyGroupValidMember(
it.memberId,
it.iamGroupId.toString()
)[it.iamGroupId]?.belong == true
isMemberJoinedToGroup
} catch (ignore: Exception) {
logger.warn("verify group valid member failed,${it.memberId}|${it.iamGroupId}", ignore)
authResourceGroupApplyDao.delete(dslContext, it.id)
false
}
val limit = 100
var offset = 0
val startEpoch = System.currentTimeMillis()
val finalRecordsOfPending = mutableListOf<TAuthResourceGroupApplyRecord>()
val finalRecordsOfSuccess = mutableListOf<TAuthResourceGroupApplyRecord>()
do {
logger.info("sync members of apply | start")
// 获取7天内未审批单据
val records = authResourceGroupApplyDao.list(
dslContext = dslContext,
day = 7,
limit = limit,
offset = offset
)
val (recordsOfSuccess, recordsOfPending) = records.partition {
try {
val isMemberJoinedToGroup = iamV2ManagerService.verifyGroupValidMember(
it.memberId,
it.iamGroupId.toString()
)[it.iamGroupId]?.belong == true
isMemberJoinedToGroup
} catch (ignore: Exception) {
logger.warn("verify group valid member failed,${it.memberId}|${it.iamGroupId}", ignore)
authResourceGroupApplyDao.delete(dslContext, it.id)
false
}
finalRecordsOfPending.addAll(recordsOfPending)
finalRecordsOfSuccess.addAll(recordsOfSuccess)
offset += limit
} while (records.size == limit)
if (finalRecordsOfPending.isNotEmpty()) {
authResourceGroupApplyDao.batchUpdate(
dslContext = dslContext,
ids = finalRecordsOfPending.map { it.id },
applyToGroupStatus = ApplyToGroupStatus.PENDING
)
}
if (finalRecordsOfSuccess.isNotEmpty()) {
finalRecordsOfSuccess.forEach {
syncIamGroupMember(
projectCode = it.projectCode,
iamGroupId = it.iamGroupId
)
}
authResourceGroupApplyDao.batchUpdate(
dslContext = dslContext,
ids = finalRecordsOfSuccess.map { it.id },
applyToGroupStatus = ApplyToGroupStatus.SUCCEED
finalRecordsOfPending.addAll(recordsOfPending)
finalRecordsOfSuccess.addAll(recordsOfSuccess)
offset += limit
} while (records.size == limit)
if (finalRecordsOfPending.isNotEmpty()) {
authResourceGroupApplyDao.batchUpdate(
dslContext = dslContext,
ids = finalRecordsOfPending.map { it.id },
applyToGroupStatus = ApplyToGroupStatus.PENDING
)
}
if (finalRecordsOfSuccess.isNotEmpty()) {
finalRecordsOfSuccess.forEach {
syncIamGroupMember(
projectCode = it.projectCode,
iamGroupId = it.iamGroupId
)
}
logger.info("It take(${System.currentTimeMillis() - startEpoch})ms to sync members of apply")
authResourceGroupApplyDao.batchUpdate(
dslContext = dslContext,
ids = finalRecordsOfSuccess.map { it.id },
applyToGroupStatus = ApplyToGroupStatus.SUCCEED
)
}
logger.info("It take(${System.currentTimeMillis() - startEpoch})ms to sync members of apply")
}

override fun syncGroupAndMember(projectCode: String) {
Expand Down
Loading