package aceboot::security

import aceboot::web.*

/** 路由授权策略:HTTP 方法(* 通配)+ 路径前缀 → 要求拥有任一角色。 */
public struct RolePolicy {
    public let method: String
    public let pathPrefix: String
    public let roles: Array<String>

    public init(method: String, pathPrefix: String, roles: Array<String>) {
        this.method = method
        this.pathPrefix = pathPrefix
        this.roles = roles
    }
}

/**
 * 路由授权中间件(经 @Middleware 注册插入):对命中策略的请求要求角色,无权限 -> 403。
 * 依赖认证中间件已写入 Principal(jwtAuth);命中的多条策略全部要求(AND)。
 * 这是「路由级鉴权」的第三方实现——核心框架不内置安全逻辑。
 */
public func authorize(policies: Array<RolePolicy>): Middleware {
    return {
        ctx, next =>
        for (p in policies) {
            if ((p.method == "*" || p.method == ctx.method) && ctx.path.startsWith(p.pathPrefix)) {
                enforcePolicy(ctx, p.roles)
            }
        }
        next()
    }
}

func enforcePolicy(ctx: Context, required: Array<String>): Unit {
    let have = match (currentPrincipal(ctx)) {
        case Some(pp) => pp.roles
        case None => throw HttpError(401, "authentication required")
    }
    for (need in required) {
        for (h in have) {
            if (h == need) {
                return
            }
        }
    }
    throw HttpError(403, "insufficient permissions")
}