mirror of
https://github.com/Buriburizaem0n/nezha_domains.git
synced 2026-09-19 17:50:12 +00:00
87 lines
3.4 KiB
Go
87 lines
3.4 KiB
Go
//go:build agentcompat
|
|
|
|
package controller
|
|
|
|
import (
|
|
"github.com/gin-gonic/gin"
|
|
|
|
"github.com/nezhahq/nezha/model"
|
|
"github.com/nezhahq/nezha/service/rpc"
|
|
"github.com/nezhahq/nezha/service/singleton"
|
|
)
|
|
|
|
type agentcompatCapabilityIdentity struct {
|
|
purpose rpc.AgentCompatCapabilityPurpose
|
|
serverID uint64
|
|
resourceID uint64
|
|
}
|
|
|
|
type agentcompatCapabilityProof struct {
|
|
owner rpc.AgentCompatCapabilityOwner
|
|
identity agentcompatCapabilityIdentity
|
|
}
|
|
|
|
func currentAgentcompatCapabilityProof(context *gin.Context, identity agentcompatCapabilityIdentity) (agentcompatCapabilityProof, error) {
|
|
if err := validateAgentcompatCapabilityIdentity(identity.purpose, identity.serverID, identity.resourceID); err != nil {
|
|
return agentcompatCapabilityProof{}, err
|
|
}
|
|
token := APITokenFromContext(context)
|
|
authorized, present := context.Get(model.CtxKeyAuthorizedUser)
|
|
user, validUser := authorized.(*model.User)
|
|
if token == nil || token.ID == 0 || !present || !validUser || user == nil || user.ID == 0 {
|
|
return agentcompatCapabilityProof{}, errAgentcompatCapabilityUnavailable
|
|
}
|
|
if singleton.ServerShared == nil {
|
|
return agentcompatCapabilityProof{}, errAgentcompatCapabilityUnavailable
|
|
}
|
|
server, exists := singleton.ServerShared.Get(identity.serverID)
|
|
if !exists || server == nil || !server.HasPermission(context) || !patAllowsServer(context, identity.serverID) {
|
|
return agentcompatCapabilityProof{}, errAgentcompatCapabilityUnavailable
|
|
}
|
|
if identity.purpose == rpc.AgentCompatCapabilityNAT && !currentAgentcompatNATPermission(context, identity) {
|
|
return agentcompatCapabilityProof{}, errAgentcompatCapabilityUnavailable
|
|
}
|
|
return agentcompatCapabilityProof{
|
|
owner: rpc.AgentCompatCapabilityOwner{PATID: token.ID, UserID: user.ID, IsAdmin: user.Role.IsAdmin()},
|
|
identity: identity,
|
|
}, nil
|
|
}
|
|
|
|
func currentAgentcompatNATPermission(context *gin.Context, identity agentcompatCapabilityIdentity) bool {
|
|
if singleton.NATShared == nil {
|
|
return false
|
|
}
|
|
domain := singleton.NATShared.GetDomain(identity.resourceID)
|
|
if domain == "" {
|
|
return false
|
|
}
|
|
profile := singleton.NATShared.GetNATConfigByDomain(domain)
|
|
return profile != nil && profile.ID == identity.resourceID && profile.ServerID == identity.serverID && profile.HasPermission(context)
|
|
}
|
|
|
|
func (proof agentcompatCapabilityProof) registration() rpc.AgentCompatCapabilityRegistration {
|
|
return rpc.AgentCompatCapabilityRegistration{
|
|
Owner: proof.owner, Purpose: proof.identity.purpose, TargetServerID: proof.identity.serverID,
|
|
ResourceID: proof.identity.resourceID, ServerAccessAllowed: true,
|
|
}
|
|
}
|
|
|
|
func (proof agentcompatCapabilityProof) access(capability rpc.AgentCompatIOStreamCapability) rpc.AgentCompatCapabilityAccess {
|
|
return rpc.AgentCompatCapabilityAccess{
|
|
Capability: capability, Owner: proof.owner, Purpose: proof.identity.purpose,
|
|
TargetServerID: proof.identity.serverID, ResourceID: proof.identity.resourceID, ServerAccessAllowed: true,
|
|
}
|
|
}
|
|
|
|
func agentcompatCapabilityIdentityFromWire(purpose string, serverID, resourceID uint64) (agentcompatCapabilityIdentity, error) {
|
|
parsedPurpose, err := parseAgentcompatCapabilityPurpose(purpose)
|
|
if err != nil {
|
|
return agentcompatCapabilityIdentity{}, err
|
|
}
|
|
identity := agentcompatCapabilityIdentity{purpose: parsedPurpose, serverID: serverID, resourceID: resourceID}
|
|
if err := validateAgentcompatCapabilityIdentity(identity.purpose, identity.serverID, identity.resourceID); err != nil {
|
|
return agentcompatCapabilityIdentity{}, err
|
|
}
|
|
return identity, nil
|
|
}
|