Skip to content

Commit

Permalink
Merge pull request #10899 from fcfang123/issue-10891
Browse files Browse the repository at this point in the history
feat:活跃用户记录操作和次数 #10891
  • Loading branch information
bkci-bot authored Sep 10, 2024
2 parents 51cd60b + 5a7f840 commit 59ee5a8
Show file tree
Hide file tree
Showing 28 changed files with 457 additions and 66 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ import javax.ws.rs.POST
import javax.ws.rs.Path
import javax.ws.rs.PathParam
import javax.ws.rs.Produces
import javax.ws.rs.QueryParam
import javax.ws.rs.core.MediaType

@Tag(name = "AUTH_MIGRATE", description = "权限-迁移")
Expand Down Expand Up @@ -137,6 +138,9 @@ interface OpAuthMigrateResource {
@Path("/autoRenewal")
@Operation(summary = "自动续期")
fun autoRenewal(
@Parameter(description = "小于该值才会被续期,若传空,则默认用户在用户组中的过期时间小于180天会被自动续期", required = true)
@QueryParam("validExpiredDay")
validExpiredDay: Int?,
@Parameter(description = "按条件迁移项目实体", required = true)
projectConditionDTO: ProjectConditionDTO
): Result<Boolean>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,5 +44,6 @@ data class AuthResourceInfo(
val createUser: String,
val updateUser: String,
val createTime: LocalDateTime,
val updateTime: LocalDateTime
val updateTime: LocalDateTime,
val iamGradeManagerId: String? = null
)
Original file line number Diff line number Diff line change
Expand Up @@ -406,6 +406,7 @@ class AuthResourceDao {
relationId = relationId,
createUser = createUser,
updateUser = updateUser,
iamGradeManagerId = relationId,
createTime = createTime,
updateTime = updateTime
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -178,11 +178,11 @@ class RbacCacheService constructor(
val startEpoch = System.currentTimeMillis()
try {
val actionDTO = ActionDTO()
actionDTO.id = RbacAuthUtils.buildAction(
val action = RbacAuthUtils.buildAction(
authPermission = permission,
authResourceType = AuthResourceType.PROJECT
)

actionDTO.id = action
val resourceNode = V2ResourceNode.builder().system(iamConfiguration.systemId)
.type(AuthResourceType.PROJECT.value)
.id(projectCode)
Expand All @@ -200,7 +200,11 @@ class RbacCacheService constructor(

val result = policyService.verifyPermissions(queryPolicyDTO)
if (result) {
authUserDailyService.save(projectId = projectCode, userId = userId)
authUserDailyService.save(
projectId = projectCode,
userId = userId,
operate = action
)
}
return result
} finally {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -695,7 +695,8 @@ class RbacPermissionResourceMemberService constructor(
override fun autoRenewal(
projectCode: String,
resourceType: String,
resourceCode: String
resourceCode: String,
validExpiredDay: Int
) {
// 1、获取分级管理员或者二级管理员ID
val managerId = authResourceService.get(
Expand All @@ -716,7 +717,7 @@ class RbacPermissionResourceMemberService constructor(
)
val currentTime = TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis())
// 预期的自动过期天数
val expectAutoExpiredAt = currentTime + AUTO_VALID_EXPIRED_AT
val expectAutoExpiredAt = currentTime + TimeUnit.DAYS.toSeconds(validExpiredDay.toLong())
val autoRenewalMembers = mutableSetOf<String>()
resourceGroupInfoList.forEach group@{ resourceGroup ->
val iamGroupId = resourceGroup.relationId.toInt()
Expand All @@ -726,11 +727,14 @@ class RbacPermissionResourceMemberService constructor(
}
val groupMemberInfoList = iamV2ManagerService.getRoleGroupMemberV2(iamGroupId, pageInfoDTO).results
groupMemberInfoList.forEach member@{ member ->
// 已过期或者要半年后才过期的,不自动过期
// 已过期或者小于自动续期范围内的不做续期
if (member.expiredAt < currentTime ||
member.expiredAt > expectAutoExpiredAt
) return@member

) {
val dataTime = DateTimeUtil.convertTimestampToLocalDateTime(member.expiredAt)
logger.info("Group member does not need to be renewed|$iamGroupId|$member|$dataTime")
return@member
}
// 自动续期时间由半年+随机天数,防止同一时间同时过期
val expiredTime = currentTime + AUTO_RENEWAL_EXPIRED_AT +
TimeUnit.DAYS.toSeconds(RandomUtils.nextLong(0, 180))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,11 @@ class RbacPermissionService constructor(

val result = policyService.verifyPermissions(queryPolicyDTO)
if (result) {
authProjectUserMetricsService.save(projectId = projectCode, userId = userId)
authProjectUserMetricsService.save(
projectId = projectCode,
userId = userId,
operate = useAction
)
}
return result
} finally {
Expand Down Expand Up @@ -300,8 +304,12 @@ class RbacPermissionService constructor(
actionList,
listOf(resourceDTO)
)
if (result.values.any { it }) {
authProjectUserMetricsService.save(projectId = projectCode, userId = userId)
result.filter { it.value }.keys.forEach { action ->
authProjectUserMetricsService.save(
projectId = projectCode,
userId = userId,
operate = action
)
}
return result
} finally {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -616,7 +616,10 @@ class RbacPermissionMigrateService constructor(
)
}

override fun autoRenewal(projectConditionDTO: ProjectConditionDTO): Boolean {
override fun autoRenewal(
validExpiredDay: Int,
projectConditionDTO: ProjectConditionDTO
): Boolean {
val traceId = MDC.get(TraceTag.BIZID)
toRbacExecutorService.submit {
MDC.put(TraceTag.BIZID, traceId)
Expand All @@ -634,7 +637,8 @@ class RbacPermissionMigrateService constructor(
migrateProjectsExecutorService.submit {
MDC.put(TraceTag.BIZID, traceId)
autoRenewal(
projectCode = migrateProject.englishName
projectCode = migrateProject.englishName,
validExpiredDay = validExpiredDay
)
}
}
Expand All @@ -644,7 +648,10 @@ class RbacPermissionMigrateService constructor(
return true
}

private fun autoRenewal(projectCode: String) {
private fun autoRenewal(
projectCode: String,
validExpiredDay: Int
) {
var offset = 0
val limit = 100
val startTime = System.currentTimeMillis()
Expand All @@ -666,7 +673,8 @@ class RbacPermissionMigrateService constructor(
permissionResourceMemberService.autoRenewal(
projectCode = projectCode,
resourceType = resourceType,
resourceCode = resourceCode
resourceCode = resourceCode,
validExpiredDay = validExpiredDay
)
} catch (ignored: Throwable) {
logger.error("Failed to auto renewal|$projectCode|$resourceType|$resourceCode")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,10 @@ class SamplePermissionMigrateService(
return true
}

override fun autoRenewal(projectConditionDTO: ProjectConditionDTO): Boolean {
override fun autoRenewal(
validExpiredDay: Int,
projectConditionDTO: ProjectConditionDTO
): Boolean {
return true
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,8 @@ class SamplePermissionResourceMemberService : PermissionResourceMemberService {
override fun autoRenewal(
projectCode: String,
resourceType: String,
resourceCode: String
resourceCode: String,
validExpiredDay: Int
) = Unit

override fun renewalGroupMember(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,11 @@ class OpAuthMigrateResourceImpl @Autowired constructor(
return Result(permissionMigrateService.migrateMonitorResource(projectCodes = projectCodes))
}

override fun autoRenewal(projectConditionDTO: ProjectConditionDTO): Result<Boolean> {
permissionMigrateService.autoRenewal(projectConditionDTO)
override fun autoRenewal(validExpiredDay: Int?, projectConditionDTO: ProjectConditionDTO): Result<Boolean> {
permissionMigrateService.autoRenewal(
validExpiredDay = validExpiredDay ?: 180,
projectConditionDTO = projectConditionDTO
)
return Result(true)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,20 @@ import com.tencent.devops.auth.pojo.vo.BatchOperateGroupMemberCheckVo
import com.tencent.devops.auth.pojo.vo.GroupDetailsInfoVo
import com.tencent.devops.auth.pojo.vo.MemberGroupCountWithPermissionsVo
import com.tencent.devops.auth.service.iam.PermissionResourceMemberService
import com.tencent.devops.auth.service.iam.PermissionService
import com.tencent.devops.common.api.model.SQLPage
import com.tencent.devops.common.api.pojo.Result
import com.tencent.devops.common.auth.api.AuthPermission
import com.tencent.devops.common.auth.api.AuthResourceType
import com.tencent.devops.common.auth.api.BkManagerCheck
import com.tencent.devops.common.auth.rbac.utils.RbacAuthUtils
import com.tencent.devops.common.web.RestResource

@RestResource
class UserAuthResourceMemberResourceImpl(
private val permissionResourceMemberService: PermissionResourceMemberService
private val permissionResourceMemberService: PermissionResourceMemberService,
private val permissionService: PermissionService
) : UserAuthResourceMemberResource {
@BkManagerCheck
override fun listProjectMembers(
userId: String,
projectId: String,
Expand All @@ -33,17 +37,27 @@ class UserAuthResourceMemberResourceImpl(
page: Int,
pageSize: Int
): Result<SQLPage<ResourceMemberInfo>> {
return Result(
permissionResourceMemberService.listProjectMembers(
projectCode = projectId,
memberType = memberType,
userName = userName,
deptName = deptName,
departedFlag = departedFlag ?: false,
page = page,
pageSize = pageSize
)
val hasVisitPermission = permissionService.validateUserResourcePermission(
userId = userId,
resourceType = AuthResourceType.PROJECT.value,
action = RbacAuthUtils.buildAction(AuthPermission.VISIT, AuthResourceType.PROJECT),
projectCode = projectId
)
return if (!hasVisitPermission) {
Result(SQLPage(0, emptyList()))
} else {
Result(
permissionResourceMemberService.listProjectMembers(
projectCode = projectId,
memberType = memberType,
userName = userName,
deptName = deptName,
departedFlag = departedFlag ?: false,
page = page,
pageSize = pageSize
)
)
}
}

@BkManagerCheck
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,51 +33,70 @@ import com.google.common.hash.BloomFilter
import com.google.common.hash.Funnels
import com.tencent.devops.common.event.dispatcher.pipeline.mq.MeasureEventDispatcher
import com.tencent.devops.common.event.pojo.measure.ProjectUserDailyEvent
import com.tencent.devops.common.event.pojo.measure.ProjectUserOperateMetricsData
import com.tencent.devops.common.event.pojo.measure.ProjectUserOperateMetricsEvent
import com.tencent.devops.common.event.pojo.measure.UserOperateCounterData
import org.slf4j.LoggerFactory
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.scheduling.annotation.Scheduled
import org.springframework.stereotype.Service
import java.nio.charset.Charset
import java.time.LocalDate
import java.util.concurrent.Executors
import java.util.concurrent.TimeUnit

@Service
@Suppress("UnstableApiUsage")
class AuthProjectUserMetricsService @Autowired constructor(
private val measureEventDispatcher: MeasureEventDispatcher
) {
private val userOperateCounterData = UserOperateCounterData()

companion object {
private val logger = LoggerFactory.getLogger(AuthProjectUserMetricsService::class.java)

// 期待的用户数10w
private const val EXPECTED_USER_COUNT = 100000

// 错误率0.1%
private const val EXPECTED_FPP = 0.001
private val bloomFilterMap = CacheBuilder.newBuilder()
.maximumSize(2)
.expireAfterWrite(1, TimeUnit.DAYS)
.build<LocalDate, BloomFilter<String>>()

private val executorService = Executors.newFixedThreadPool(5)
}

fun save(
projectId: String,
userId: String
userId: String,
operate: String
) {
val theDate = LocalDate.now()
try {
val bloomKey = "${projectId}_$userId"
val bloomFilter = getBloomFilter(theDate)
if (!bloomFilter.mightContain(bloomKey)) {
measureEventDispatcher.dispatch(
ProjectUserDailyEvent(
projectId = projectId,
userId = userId,
theDate = theDate
executorService.execute {
val theDate = LocalDate.now()
try {
val bloomKey = "${projectId}_$userId"
val bloomFilter = getBloomFilter(theDate)
if (!bloomFilter.mightContain(bloomKey)) {
measureEventDispatcher.dispatch(
ProjectUserDailyEvent(
projectId = projectId,
userId = userId,
theDate = theDate
)
)
bloomFilter.put(bloomKey)
}
saveProjectUserOperateMetrics(
projectId = projectId,
userId = userId,
operate = operate,
theDate = theDate
)
bloomFilter.put(bloomKey)
} catch (ignored: Throwable) {
logger.error("save auth user error", ignored)
}
} catch (ignored: Throwable) {
logger.error("save auth user error", ignored)
}
}

Expand All @@ -93,4 +112,32 @@ class AuthProjectUserMetricsService @Autowired constructor(
}
return bloomFilter!!
}

private fun saveProjectUserOperateMetrics(
projectId: String,
userId: String,
operate: String,
theDate: LocalDate
) {
val projectUserOperateMetricsKey = ProjectUserOperateMetricsData(
projectId = projectId,
userId = userId,
theDate = theDate,
operate = operate
).getProjectUserOperateMetricsKey()
userOperateCounterData.increment(projectUserOperateMetricsKey)
}

@Scheduled(initialDelay = 20000, fixedDelay = 20000)
private fun uploadProjectUserOperateMetrics() {
if (logger.isDebugEnabled) {
logger.debug("upload project user operate metrics :$userOperateCounterData")
}
measureEventDispatcher.dispatch(
ProjectUserOperateMetricsEvent(
userOperateCounterData = userOperateCounterData
)
)
userOperateCounterData.reset()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ interface PermissionMigrateService {
): Boolean

fun autoRenewal(
validExpiredDay: Int,
projectConditionDTO: ProjectConditionDTO
): Boolean

Expand Down
Loading

0 comments on commit 59ee5a8

Please sign in to comment.