支持单位授权与客户端限制

This commit is contained in:
Codex
2026-06-01 11:58:14 +08:00
parent 28adc8143a
commit c136cc2cc8
36 changed files with 861 additions and 49 deletions

View File

@@ -0,0 +1,55 @@
package com.xspaceagi.system.domain.service.impl;
import com.xspaceagi.system.infra.dao.entity.SysGroup;
import com.xspaceagi.system.spec.enums.StatusEnum;
import java.util.Date;
/**
* Centralized department authorization rule for login and client registration.
*/
public final class GroupAuthorizationPolicy {
private GroupAuthorizationPolicy() {
}
public static Result evaluate(SysGroup group, long currentClientCount, Date now) {
if (group == null) {
return Result.deny(Reason.NO_GROUP);
}
if (!StatusEnum.isEnabled(group.getStatus())) {
return Result.deny(Reason.GROUP_DISABLED);
}
if (!Integer.valueOf(1).equals(group.getAuthEnabled())) {
return Result.deny(Reason.AUTH_DISABLED);
}
Date expireTime = group.getExpireTime();
if (expireTime != null && !expireTime.after(now)) {
return Result.deny(Reason.EXPIRED);
}
Integer maxClientCount = group.getMaxClientCount();
if (maxClientCount != null && maxClientCount > -1 && currentClientCount >= maxClientCount) {
return Result.deny(Reason.CLIENT_QUOTA_REACHED);
}
return Result.allow();
}
public enum Reason {
ALLOWED,
NO_GROUP,
GROUP_DISABLED,
AUTH_DISABLED,
EXPIRED,
CLIENT_QUOTA_REACHED
}
public record Result(boolean allowed, Reason reason) {
private static Result allow() {
return new Result(true, Reason.ALLOWED);
}
private static Result deny(Reason reason) {
return new Result(false, reason);
}
}
}

View File

@@ -0,0 +1,90 @@
package com.xspaceagi.system.domain.service.impl;
import com.xspaceagi.system.infra.dao.entity.SysGroup;
import com.xspaceagi.system.spec.enums.StatusEnum;
import org.junit.jupiter.api.Test;
import java.util.Calendar;
import java.util.Date;
import static org.assertj.core.api.Assertions.assertThat;
class GroupAuthorizationPolicyTest {
@Test
void allowsEnabledAuthorizedGroupBeforeExpirationWhenClientQuotaAvailable() {
SysGroup group = group(StatusEnum.ENABLED.getCode(), 1, future(), 2);
GroupAuthorizationPolicy.Result result = GroupAuthorizationPolicy.evaluate(group, 1, now());
assertThat(result.allowed()).isTrue();
assertThat(result.reason()).isEqualTo(GroupAuthorizationPolicy.Reason.ALLOWED);
}
@Test
void deniesDisabledGroup() {
SysGroup group = group(StatusEnum.DISABLED.getCode(), 1, future(), 2);
GroupAuthorizationPolicy.Result result = GroupAuthorizationPolicy.evaluate(group, 0, now());
assertThat(result.allowed()).isFalse();
assertThat(result.reason()).isEqualTo(GroupAuthorizationPolicy.Reason.GROUP_DISABLED);
}
@Test
void deniesGroupWithoutAuthorization() {
SysGroup group = group(StatusEnum.ENABLED.getCode(), 0, future(), 2);
GroupAuthorizationPolicy.Result result = GroupAuthorizationPolicy.evaluate(group, 0, now());
assertThat(result.allowed()).isFalse();
assertThat(result.reason()).isEqualTo(GroupAuthorizationPolicy.Reason.AUTH_DISABLED);
}
@Test
void deniesExpiredGroup() {
SysGroup group = group(StatusEnum.ENABLED.getCode(), 1, past(), 2);
GroupAuthorizationPolicy.Result result = GroupAuthorizationPolicy.evaluate(group, 0, now());
assertThat(result.allowed()).isFalse();
assertThat(result.reason()).isEqualTo(GroupAuthorizationPolicy.Reason.EXPIRED);
}
@Test
void deniesWhenClientQuotaReached() {
SysGroup group = group(StatusEnum.ENABLED.getCode(), 1, future(), 2);
GroupAuthorizationPolicy.Result result = GroupAuthorizationPolicy.evaluate(group, 2, now());
assertThat(result.allowed()).isFalse();
assertThat(result.reason()).isEqualTo(GroupAuthorizationPolicy.Reason.CLIENT_QUOTA_REACHED);
}
private SysGroup group(Integer status, Integer authEnabled, Date expireTime, Integer maxClientCount) {
SysGroup group = new SysGroup();
group.setStatus(status);
group.setAuthEnabled(authEnabled);
group.setExpireTime(expireTime);
group.setMaxClientCount(maxClientCount);
return group;
}
private Date now() {
return new Date(1_700_000_000_000L);
}
private Date future() {
Calendar calendar = Calendar.getInstance();
calendar.setTime(now());
calendar.add(Calendar.DATE, 1);
return calendar.getTime();
}
private Date past() {
Calendar calendar = Calendar.getInstance();
calendar.setTime(now());
calendar.add(Calendar.DATE, -1);
return calendar.getTime();
}
}