peer change
This commit is contained in:
@@ -10,6 +10,7 @@ import (
|
|||||||
oclib "cloud.o-forge.io/core/oc-lib"
|
oclib "cloud.o-forge.io/core/oc-lib"
|
||||||
"cloud.o-forge.io/core/oc-lib/config"
|
"cloud.o-forge.io/core/oc-lib/config"
|
||||||
"cloud.o-forge.io/core/oc-lib/dbs"
|
"cloud.o-forge.io/core/oc-lib/dbs"
|
||||||
|
"cloud.o-forge.io/core/oc-lib/models/organization"
|
||||||
"cloud.o-forge.io/core/oc-lib/models/peer"
|
"cloud.o-forge.io/core/oc-lib/models/peer"
|
||||||
"cloud.o-forge.io/core/oc-lib/tools"
|
"cloud.o-forge.io/core/oc-lib/tools"
|
||||||
beego "github.com/beego/beego/v2/server/web"
|
beego "github.com/beego/beego/v2/server/web"
|
||||||
@@ -214,6 +215,78 @@ func (o *PeerController) Valid() {
|
|||||||
o.ServeJSON()
|
o.ServeJSON()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
} else if l.Data != nil && l.ToPeer().Verify && (l.ToPeer().Relation == peer.ORGANIZATION_MASTER || l.ToPeer().Relation == peer.ORGANIZATION_MASTER_PENDING) {
|
||||||
|
// The remote peer asked us to be their organization master.
|
||||||
|
// We confirm: they become our ORGANIZATION_MEMBER, we become their ORGANIZATION_MASTER.
|
||||||
|
self, serr := oclib.GetMySelf()
|
||||||
|
if serr == nil && self != nil {
|
||||||
|
data := req.UpdateOne(map[string]interface{}{
|
||||||
|
"verify": false,
|
||||||
|
"relation": peer.ORGANIZATION_MEMBER,
|
||||||
|
}, l.ToPeer().GetID())
|
||||||
|
// Stamp our peer ID as their OrganizationMasterID.
|
||||||
|
oclib.NewRequestAdmin(oclib.LibDataEnum(oclib.PEER), nil).UpdateOne(map[string]interface{}{
|
||||||
|
"organization_master_id": self.GetID(),
|
||||||
|
}, l.ToPeer().GetID())
|
||||||
|
if data.Data != nil {
|
||||||
|
b, _ := json.Marshal(data.Data)
|
||||||
|
go infrastructure.EmitNATS(user, groups, tools.PropalgationMessage{
|
||||||
|
DataType: tools.PEER.EnumIndex(),
|
||||||
|
Action: tools.PB_CREATE,
|
||||||
|
Payload: b,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
o.Data["json"] = data
|
||||||
|
o.ServeJSON()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
} else if l.Data != nil && l.ToPeer().Verify && (l.ToPeer().Relation == peer.ORGANIZATION_MEMBER || l.ToPeer().Relation == peer.ORGANIZATION_MEMBER_PENDING) {
|
||||||
|
// The remote peer asked to join our organization as a member.
|
||||||
|
// We confirm: they are our ORGANIZATION_MEMBER, we are their ORGANIZATION_MASTER.
|
||||||
|
self, serr := oclib.GetMySelf()
|
||||||
|
if serr == nil && self != nil {
|
||||||
|
data := req.UpdateOne(map[string]interface{}{
|
||||||
|
"verify": false,
|
||||||
|
"relation": peer.ORGANIZATION_MEMBER,
|
||||||
|
}, l.ToPeer().GetID())
|
||||||
|
// Stamp our ID as the OrganizationMasterID on the new member.
|
||||||
|
oclib.NewRequestAdmin(oclib.LibDataEnum(oclib.PEER), nil).UpdateOne(map[string]interface{}{
|
||||||
|
"organization_master_id": self.GetID(),
|
||||||
|
}, l.ToPeer().GetID())
|
||||||
|
// Set our own OrganizationMasterID on self (we are the master).
|
||||||
|
if self2, _ := oclib.GetMySelf(); self2 != nil && self2.OrganizationMasterID == "" {
|
||||||
|
oclib.NewRequestAdmin(oclib.LibDataEnum(oclib.PEER), nil).UpdateOne(map[string]interface{}{
|
||||||
|
"organization_master_id": self.GetID(),
|
||||||
|
}, self2.GetID())
|
||||||
|
}
|
||||||
|
if data.Data != nil {
|
||||||
|
b, _ := json.Marshal(data.Data)
|
||||||
|
go infrastructure.EmitNATS(user, groups, tools.PropalgationMessage{
|
||||||
|
DataType: tools.PEER.EnumIndex(),
|
||||||
|
Action: tools.PB_CREATE,
|
||||||
|
Payload: b,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
o.Data["json"] = data
|
||||||
|
o.ServeJSON()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
} else if l.Data != nil && l.ToPeer().Verify && l.ToPeer().Relation == peer.ORGANIZATION_PARTNER {
|
||||||
|
data := req.UpdateOne(map[string]interface{}{
|
||||||
|
"verify": false,
|
||||||
|
"relation": peer.ORGANIZATION_PARTNER,
|
||||||
|
}, l.ToPeer().GetID())
|
||||||
|
if data.Data != nil {
|
||||||
|
b, _ := json.Marshal(data.Data)
|
||||||
|
go infrastructure.EmitNATS(user, groups, tools.PropalgationMessage{
|
||||||
|
DataType: tools.PEER.EnumIndex(),
|
||||||
|
Action: tools.PB_CREATE,
|
||||||
|
Payload: b,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
o.Data["json"] = data
|
||||||
|
o.ServeJSON()
|
||||||
|
return
|
||||||
}
|
}
|
||||||
o.Data["json"] = map[string]interface{}{
|
o.Data["json"] = map[string]interface{}{
|
||||||
"data": nil,
|
"data": nil,
|
||||||
@@ -399,6 +472,10 @@ func (o *PeerController) changeRelation(id string, dest *peer.Peer, user string,
|
|||||||
relation = peer.PENDING_NANO
|
relation = peer.PENDING_NANO
|
||||||
case peer.BLACKLIST:
|
case peer.BLACKLIST:
|
||||||
relation = peer.NONE
|
relation = peer.NONE
|
||||||
|
case peer.ORGANIZATION_MASTER:
|
||||||
|
relation = peer.ORGANIZATION_MASTER_PENDING
|
||||||
|
case peer.ORGANIZATION_MEMBER:
|
||||||
|
relation = peer.ORGANIZATION_MEMBER_PENDING
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if dest.Verify && relation == peer.PENDING_PARTNER {
|
if dest.Verify && relation == peer.PENDING_PARTNER {
|
||||||
@@ -407,6 +484,12 @@ func (o *PeerController) changeRelation(id string, dest *peer.Peer, user string,
|
|||||||
if dest.Verify && relation == peer.PENDING_NANO {
|
if dest.Verify && relation == peer.PENDING_NANO {
|
||||||
relation = peer.NANO
|
relation = peer.NANO
|
||||||
}
|
}
|
||||||
|
if dest.Verify && relation == peer.ORGANIZATION_MASTER_PENDING {
|
||||||
|
relation = peer.ORGANIZATION_MASTER
|
||||||
|
}
|
||||||
|
if dest.Verify && relation == peer.ORGANIZATION_MEMBER_PENDING {
|
||||||
|
relation = peer.ORGANIZATION_MEMBER
|
||||||
|
}
|
||||||
wasMaster := dest.Relation == peer.MASTER
|
wasMaster := dest.Relation == peer.MASTER
|
||||||
data := request.UpdateOne(map[string]interface{}{
|
data := request.UpdateOne(map[string]interface{}{
|
||||||
"relation": relation,
|
"relation": relation,
|
||||||
@@ -446,6 +529,128 @@ func (o *PeerController) changeRelation(id string, dest *peer.Peer, user string,
|
|||||||
o.ServeJSON()
|
o.ServeJSON()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// @Title SetOrganization
|
||||||
|
// @Description set organization data on self peer (only allowed when peer has no OrganizationMasterID)
|
||||||
|
// @Param data body json true "organization data"
|
||||||
|
// @Success 200 {peer} models.peer
|
||||||
|
// @router /organization [put]
|
||||||
|
func (o *PeerController) SetOrganization() {
|
||||||
|
self, err := oclib.GetMySelf()
|
||||||
|
if err != nil || self == nil {
|
||||||
|
o.Data["json"] = map[string]interface{}{"data": nil, "code": 404, "error": "self peer not found"}
|
||||||
|
o.ServeJSON()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if self.OrganizationMasterID != "" {
|
||||||
|
o.Data["json"] = map[string]interface{}{"data": nil, "code": 409, "error": "cannot set organization: peer already has an organization master"}
|
||||||
|
o.ServeJSON()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var org organization.Organization
|
||||||
|
if err := json.Unmarshal(o.Ctx.Input.CopyBody(100000), &org); err != nil {
|
||||||
|
o.Data["json"] = map[string]interface{}{"data": nil, "code": 400, "error": "invalid organization payload: " + err.Error()}
|
||||||
|
o.ServeJSON()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
req := oclib.NewRequestAdmin(oclib.LibDataEnum(oclib.PEER), nil)
|
||||||
|
data := req.UpdateOne(map[string]interface{}{"organization": org}, self.GetID())
|
||||||
|
o.Data["json"] = data
|
||||||
|
o.ServeJSON()
|
||||||
|
}
|
||||||
|
|
||||||
|
// @Title OrganizationMasterRequest
|
||||||
|
// @Description request to become the organization master of a peer (send them an ORGANIZATION_MEMBER relation)
|
||||||
|
// @Param id path string true "the peer id to become member of our org"
|
||||||
|
// @Success 200 {peer} models.peer
|
||||||
|
// @router /organization_master/:id [post]
|
||||||
|
func (o *PeerController) OrganizationMasterRequest() {
|
||||||
|
user, _, groups := oclib.ExtractTokenInfo(*o.Ctx.Request)
|
||||||
|
id := o.Ctx.Input.Param(":id")
|
||||||
|
self, err := oclib.GetMySelf()
|
||||||
|
if err != nil || self == nil {
|
||||||
|
o.Data["json"] = map[string]interface{}{"data": nil, "code": 404, "error": "self peer not found"}
|
||||||
|
o.ServeJSON()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
req := oclib.NewRequestAdmin(oclib.LibDataEnum(oclib.PEER), nil)
|
||||||
|
data := req.LoadOne(id)
|
||||||
|
p := data.ToPeer()
|
||||||
|
if p == nil {
|
||||||
|
o.Data["json"] = map[string]interface{}{"data": nil, "code": 404, "error": "peer not found"}
|
||||||
|
o.ServeJSON()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// Send the target peer an ORGANIZATION_MEMBER relation request (they receive us as their master).
|
||||||
|
o.changeRelation(id, p, user, groups, peer.ORGANIZATION_MEMBER, req)
|
||||||
|
}
|
||||||
|
|
||||||
|
// @Title OrganizationMemberRequest
|
||||||
|
// @Description request to join a peer's organization as a member (send them an ORGANIZATION_MASTER relation)
|
||||||
|
// @Param id path string true "the peer id whose org we want to join"
|
||||||
|
// @Success 200 {peer} models.peer
|
||||||
|
// @router /organization_member/:id [post]
|
||||||
|
func (o *PeerController) OrganizationMemberRequest() {
|
||||||
|
user, _, groups := oclib.ExtractTokenInfo(*o.Ctx.Request)
|
||||||
|
id := o.Ctx.Input.Param(":id")
|
||||||
|
self, err := oclib.GetMySelf()
|
||||||
|
if err != nil || self == nil {
|
||||||
|
o.Data["json"] = map[string]interface{}{"data": nil, "code": 404, "error": "self peer not found"}
|
||||||
|
o.ServeJSON()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if self.OrganizationMasterID != "" {
|
||||||
|
o.Data["json"] = map[string]interface{}{"data": nil, "code": 409, "error": "cannot request master: peer already has an organization master"}
|
||||||
|
o.ServeJSON()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
req := oclib.NewRequestAdmin(oclib.LibDataEnum(oclib.PEER), nil)
|
||||||
|
data := req.LoadOne(id)
|
||||||
|
p := data.ToPeer()
|
||||||
|
if p == nil {
|
||||||
|
o.Data["json"] = map[string]interface{}{"data": nil, "code": 404, "error": "peer not found"}
|
||||||
|
o.ServeJSON()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// Send the target peer an ORGANIZATION_MASTER relation request (they receive us as a member candidate).
|
||||||
|
o.changeRelation(id, p, user, groups, peer.ORGANIZATION_MASTER, req)
|
||||||
|
}
|
||||||
|
|
||||||
|
// @Title OrganizationPartner
|
||||||
|
// @Description request organization partner relation with a peer
|
||||||
|
// @Param id path string true "the peer id to set as organization partner"
|
||||||
|
// @Success 200 {peer} models.peer
|
||||||
|
// @router /organization_partner/:id [post]
|
||||||
|
func (o *PeerController) OrganizationPartner() {
|
||||||
|
user, _, groups := oclib.ExtractTokenInfo(*o.Ctx.Request)
|
||||||
|
id := o.Ctx.Input.Param(":id")
|
||||||
|
req := oclib.NewRequestAdmin(oclib.LibDataEnum(oclib.PEER), nil)
|
||||||
|
data := req.LoadOne(id)
|
||||||
|
p := data.ToPeer()
|
||||||
|
if p == nil {
|
||||||
|
o.Data["json"] = map[string]interface{}{"data": nil, "code": 404, "error": "peer not found"}
|
||||||
|
o.ServeJSON()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
o.changeRelation(id, p, user, groups, peer.ORGANIZATION_PARTNER, req)
|
||||||
|
}
|
||||||
|
|
||||||
|
// @Title SetPolicy
|
||||||
|
// @Description assign or clear a policy on a peer
|
||||||
|
// @Param id path string true "the peer id"
|
||||||
|
// @Param data body json true "body with policy_id field"
|
||||||
|
// @Success 200 {peer} models.peer
|
||||||
|
// @router /:id/policy [put]
|
||||||
|
func (o *PeerController) SetPolicy() {
|
||||||
|
user, peerID, groups := oclib.ExtractTokenInfo(*o.Ctx.Request)
|
||||||
|
id := o.Ctx.Input.Param(":id")
|
||||||
|
var body map[string]interface{}
|
||||||
|
json.Unmarshal(o.Ctx.Input.CopyBody(100000), &body)
|
||||||
|
o.Data["json"] = oclib.NewRequest(oclib.LibDataEnum(oclib.PEER), user, peerID, groups, nil).UpdateOne(map[string]interface{}{
|
||||||
|
"policy_id": body["policy_id"],
|
||||||
|
}, id)
|
||||||
|
o.ServeJSON()
|
||||||
|
}
|
||||||
|
|
||||||
// @Title Delete
|
// @Title Delete
|
||||||
// @Description delete peer by peerid
|
// @Description delete peer by peerid
|
||||||
// @Param id path string true "the peer id you want to delete state"
|
// @Param id path string true "the peer id you want to delete state"
|
||||||
|
|||||||
@@ -0,0 +1,81 @@
|
|||||||
|
package controllers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
oclib "cloud.o-forge.io/core/oc-lib"
|
||||||
|
beego "github.com/beego/beego/v2/server/web"
|
||||||
|
)
|
||||||
|
|
||||||
|
type PolicyController struct {
|
||||||
|
beego.Controller
|
||||||
|
}
|
||||||
|
|
||||||
|
// @Title GetAll
|
||||||
|
// @Description get all policies
|
||||||
|
// @Param is_draft query string false
|
||||||
|
// @Param offset query string false
|
||||||
|
// @Param limit query string false
|
||||||
|
// @Success 200 {policy} policy.Policy
|
||||||
|
// @router / [get]
|
||||||
|
func (o *PolicyController) GetAll() {
|
||||||
|
user, peerID, groups := oclib.ExtractTokenInfo(*o.Ctx.Request)
|
||||||
|
isDraft := o.Ctx.Input.Query("is_draft")
|
||||||
|
offset, _ := strconv.Atoi(o.Ctx.Input.Query("offset"))
|
||||||
|
limit, _ := strconv.Atoi(o.Ctx.Input.Query("limit"))
|
||||||
|
o.Data["json"] = oclib.NewRequest(oclib.LibDataEnum(oclib.POLICY), user, peerID, groups, nil).LoadAll(isDraft == "true", int64(offset), int64(limit))
|
||||||
|
o.ServeJSON()
|
||||||
|
}
|
||||||
|
|
||||||
|
// @Title Get
|
||||||
|
// @Description get policy by id
|
||||||
|
// @Param id path string true "the policy id"
|
||||||
|
// @Success 200 {policy} policy.Policy
|
||||||
|
// @router /:id [get]
|
||||||
|
func (o *PolicyController) Get() {
|
||||||
|
user, peerID, groups := oclib.ExtractTokenInfo(*o.Ctx.Request)
|
||||||
|
id := o.Ctx.Input.Param(":id")
|
||||||
|
o.Data["json"] = oclib.NewRequest(oclib.LibDataEnum(oclib.POLICY), user, peerID, groups, nil).LoadOne(id)
|
||||||
|
o.ServeJSON()
|
||||||
|
}
|
||||||
|
|
||||||
|
// @Title Post
|
||||||
|
// @Description create a policy
|
||||||
|
// @Param data body json true "policy body"
|
||||||
|
// @Success 200 {policy} policy.Policy
|
||||||
|
// @router / [post]
|
||||||
|
func (o *PolicyController) Post() {
|
||||||
|
user, peerID, groups := oclib.ExtractTokenInfo(*o.Ctx.Request)
|
||||||
|
var body map[string]interface{}
|
||||||
|
json.Unmarshal(o.Ctx.Input.CopyBody(100000), &body)
|
||||||
|
o.Data["json"] = oclib.NewRequest(oclib.LibDataEnum(oclib.POLICY), user, peerID, groups, nil).StoreOne(body)
|
||||||
|
o.ServeJSON()
|
||||||
|
}
|
||||||
|
|
||||||
|
// @Title Put
|
||||||
|
// @Description update a policy
|
||||||
|
// @Param id path string true "the policy id"
|
||||||
|
// @Param data body json true "policy body"
|
||||||
|
// @Success 200 {policy} policy.Policy
|
||||||
|
// @router /:id [put]
|
||||||
|
func (o *PolicyController) Put() {
|
||||||
|
user, peerID, groups := oclib.ExtractTokenInfo(*o.Ctx.Request)
|
||||||
|
id := o.Ctx.Input.Param(":id")
|
||||||
|
var body map[string]interface{}
|
||||||
|
json.Unmarshal(o.Ctx.Input.CopyBody(100000), &body)
|
||||||
|
o.Data["json"] = oclib.NewRequest(oclib.LibDataEnum(oclib.POLICY), user, peerID, groups, nil).UpdateOne(body, id)
|
||||||
|
o.ServeJSON()
|
||||||
|
}
|
||||||
|
|
||||||
|
// @Title Delete
|
||||||
|
// @Description delete a policy
|
||||||
|
// @Param id path string true "the policy id"
|
||||||
|
// @Success 200 {policy} policy.Policy
|
||||||
|
// @router /:id [delete]
|
||||||
|
func (o *PolicyController) Delete() {
|
||||||
|
user, peerID, groups := oclib.ExtractTokenInfo(*o.Ctx.Request)
|
||||||
|
id := o.Ctx.Input.Param(":id")
|
||||||
|
o.Data["json"] = oclib.NewRequest(oclib.LibDataEnum(oclib.POLICY), user, peerID, groups, nil).DeleteOne(id)
|
||||||
|
o.ServeJSON()
|
||||||
|
}
|
||||||
@@ -3,7 +3,7 @@ module oc-peer
|
|||||||
go 1.25.0
|
go 1.25.0
|
||||||
|
|
||||||
require (
|
require (
|
||||||
cloud.o-forge.io/core/oc-lib v0.0.0-20260528142936-26948da3c1ff
|
cloud.o-forge.io/core/oc-lib v0.0.0-20260605135650-1425a3149455
|
||||||
github.com/beego/beego/v2 v2.3.8
|
github.com/beego/beego/v2 v2.3.8
|
||||||
github.com/smartystreets/goconvey v1.7.2
|
github.com/smartystreets/goconvey v1.7.2
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,5 +1,9 @@
|
|||||||
cloud.o-forge.io/core/oc-lib v0.0.0-20260528142936-26948da3c1ff h1:Pqjt/IBv+AajJkvwqPCUpYunm6ZfXapT1pIXej1iQuc=
|
cloud.o-forge.io/core/oc-lib v0.0.0-20260528142936-26948da3c1ff h1:Pqjt/IBv+AajJkvwqPCUpYunm6ZfXapT1pIXej1iQuc=
|
||||||
cloud.o-forge.io/core/oc-lib v0.0.0-20260528142936-26948da3c1ff/go.mod h1:JynnOb3eMr9VZW1mHq+Vsl3tzx6gPhPsGKpQD/dtEBc=
|
cloud.o-forge.io/core/oc-lib v0.0.0-20260528142936-26948da3c1ff/go.mod h1:JynnOb3eMr9VZW1mHq+Vsl3tzx6gPhPsGKpQD/dtEBc=
|
||||||
|
cloud.o-forge.io/core/oc-lib v0.0.0-20260604070031-d19ff1f8b206 h1:HRbUR9H9CIblNC0Z8obgp2J3jW4d9nO0MLNw/aiZRRs=
|
||||||
|
cloud.o-forge.io/core/oc-lib v0.0.0-20260604070031-d19ff1f8b206/go.mod h1:JynnOb3eMr9VZW1mHq+Vsl3tzx6gPhPsGKpQD/dtEBc=
|
||||||
|
cloud.o-forge.io/core/oc-lib v0.0.0-20260605135650-1425a3149455 h1:hDsqGw1EUY2b4mB+aUFSuQO75t+l+Ow9vZgjHZDK3uw=
|
||||||
|
cloud.o-forge.io/core/oc-lib v0.0.0-20260605135650-1425a3149455/go.mod h1:JynnOb3eMr9VZW1mHq+Vsl3tzx6gPhPsGKpQD/dtEBc=
|
||||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||||
github.com/Masterminds/semver/v3 v3.4.0 h1:Zog+i5UMtVoCU8oKka5P7i9q9HgrJeGzI9SA1Xbatp0=
|
github.com/Masterminds/semver/v3 v3.4.0 h1:Zog+i5UMtVoCU8oKka5P7i9q9HgrJeGzI9SA1Xbatp0=
|
||||||
github.com/Masterminds/semver/v3 v3.4.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM=
|
github.com/Masterminds/semver/v3 v3.4.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM=
|
||||||
|
|||||||
@@ -45,6 +45,70 @@ var self *peer.Peer
|
|||||||
|
|
||||||
func ListenNATS() {
|
func ListenNATS() {
|
||||||
tools.NewNATSCaller().ListenNats(map[tools.NATSMethod]func(tools.NATSResponse){
|
tools.NewNATSCaller().ListenNats(map[tools.NATSMethod]func(tools.NATSResponse){
|
||||||
|
// ORG_PARTNER_EVENT is delivered by our local oc-discovery after receiving a
|
||||||
|
// libp2p stream from the remote. The payload "type" field routes to one of two
|
||||||
|
// sub-flows:
|
||||||
|
// "check" — we are master: validate candidate, emit confirm via PROPALGATION
|
||||||
|
// "confirm" — we are requester: upgrade (or discard) the candidate's relation
|
||||||
|
tools.ORG_PARTNER_EVENT: func(resp tools.NATSResponse) {
|
||||||
|
if resp.FromApp == config.GetAppName() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var msg struct {
|
||||||
|
Type string `json:"type"`
|
||||||
|
RequesterID string `json:"requester_id"`
|
||||||
|
RequesterPeerID string `json:"requester_peer_id"`
|
||||||
|
CandidateID string `json:"candidate_id"`
|
||||||
|
MasterID string `json:"master_id"`
|
||||||
|
Confirmed bool `json:"confirmed"`
|
||||||
|
}
|
||||||
|
if err := json.Unmarshal(resp.Payload, &msg); err != nil || msg.CandidateID == "" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
switch msg.Type {
|
||||||
|
case "check":
|
||||||
|
self, _ := oclib.GetMySelf()
|
||||||
|
if self == nil || self.GetID() != msg.MasterID {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
access := oclib.NewRequestAdmin(oclib.LibDataEnum(oclib.PEER), nil)
|
||||||
|
candidate := access.LoadOne(msg.CandidateID)
|
||||||
|
confirmed := candidate.Data != nil && candidate.ToPeer().Relation == peer.ORGANIZATION_MEMBER
|
||||||
|
|
||||||
|
confirmPayload, _ := json.Marshal(map[string]interface{}{
|
||||||
|
"type": "confirm",
|
||||||
|
"requester_peer_id": msg.RequesterPeerID,
|
||||||
|
"candidate_id": msg.CandidateID,
|
||||||
|
"confirmed": confirmed,
|
||||||
|
})
|
||||||
|
propMsg := tools.PropalgationMessage{
|
||||||
|
Action: tools.PB_ORG_PARTNER,
|
||||||
|
DataType: int(tools.PEER),
|
||||||
|
Payload: confirmPayload,
|
||||||
|
}
|
||||||
|
b, _ := json.Marshal(propMsg)
|
||||||
|
tools.NewNATSCaller().SetNATSPub(tools.PROPALGATION_EVENT, tools.NATSResponse{
|
||||||
|
FromApp: config.GetAppName(),
|
||||||
|
Datatype: tools.PEER,
|
||||||
|
User: resp.User,
|
||||||
|
Groups: resp.Groups,
|
||||||
|
Method: int(tools.PROPALGATION_EVENT),
|
||||||
|
Payload: b,
|
||||||
|
})
|
||||||
|
|
||||||
|
case "confirm":
|
||||||
|
access := oclib.NewRequestAdmin(oclib.LibDataEnum(oclib.PEER), nil)
|
||||||
|
relation := peer.NONE
|
||||||
|
if msg.Confirmed {
|
||||||
|
relation = peer.ORGANIZATION_PARTNER
|
||||||
|
}
|
||||||
|
access.UpdateOne(map[string]interface{}{
|
||||||
|
"relation": relation,
|
||||||
|
"verify": false,
|
||||||
|
}, msg.CandidateID)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
tools.CREATE_RESOURCE: func(resp tools.NATSResponse) {
|
tools.CREATE_RESOURCE: func(resp tools.NATSResponse) {
|
||||||
if resp.FromApp == config.GetAppName() || !slices.Contains(ressourceCols, oclib.LibDataEnum(resp.Datatype)) {
|
if resp.FromApp == config.GetAppName() || !slices.Contains(ressourceCols, oclib.LibDataEnum(resp.Datatype)) {
|
||||||
return
|
return
|
||||||
@@ -101,6 +165,12 @@ func ListenNATS() {
|
|||||||
p.Relation = peer.PENDING_PARTNER
|
p.Relation = peer.PENDING_PARTNER
|
||||||
}
|
}
|
||||||
p.IsNano = config.GetConfig().IsNano
|
p.IsNano = config.GetConfig().IsNano
|
||||||
|
// If the incoming peer shares our OrganizationMasterID, initiate org partner
|
||||||
|
// verification with our master before accepting them as org partner.
|
||||||
|
if self != nil && self.OrganizationMasterID != "" && p.OrganizationMasterID == self.OrganizationMasterID {
|
||||||
|
go requestOrgPartnerVerification(self, p, resp.User, resp.Groups)
|
||||||
|
return
|
||||||
|
}
|
||||||
access.StoreOne(p.Serialize(p))
|
access.StoreOne(p.Serialize(p))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -161,3 +231,37 @@ func ListenNATS() {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// requestOrgPartnerVerification stores the candidate as KNOWN and asks our
|
||||||
|
// OrganizationMaster (via PROPALGATION_EVENT → oc-discovery → libp2p stream)
|
||||||
|
// whether the candidate is really one of its ORGANIZATION_MEMBERs.
|
||||||
|
// The ORG_PARTNER_EVENT "confirm" branch upgrades the relation once the master replies.
|
||||||
|
func requestOrgPartnerVerification(self *peer.Peer, candidate *peer.Peer, user string, groups []string) {
|
||||||
|
// Store candidate as NONE (path "known") — no privilege until master confirms.
|
||||||
|
access := oclib.NewRequestAdmin(oclib.LibDataEnum(oclib.PEER), nil)
|
||||||
|
candidate.Relation = peer.NONE
|
||||||
|
candidate.Verify = false
|
||||||
|
access.StoreOne(candidate.Serialize(candidate))
|
||||||
|
|
||||||
|
checkPayload, _ := json.Marshal(map[string]interface{}{
|
||||||
|
"type": "check",
|
||||||
|
"requester_id": self.GetID(),
|
||||||
|
"requester_peer_id": self.PeerID,
|
||||||
|
"candidate_id": candidate.GetID(),
|
||||||
|
"master_id": self.OrganizationMasterID,
|
||||||
|
})
|
||||||
|
propMsg := tools.PropalgationMessage{
|
||||||
|
Action: tools.PB_ORG_PARTNER,
|
||||||
|
DataType: int(tools.PEER),
|
||||||
|
Payload: checkPayload,
|
||||||
|
}
|
||||||
|
b, _ := json.Marshal(propMsg)
|
||||||
|
tools.NewNATSCaller().SetNATSPub(tools.PROPALGATION_EVENT, tools.NATSResponse{
|
||||||
|
FromApp: config.GetAppName(),
|
||||||
|
Datatype: tools.PEER,
|
||||||
|
User: user,
|
||||||
|
Groups: groups,
|
||||||
|
Method: int(tools.PROPALGATION_EVENT),
|
||||||
|
Payload: b,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|||||||
@@ -25,6 +25,15 @@ func init() {
|
|||||||
Filters: nil,
|
Filters: nil,
|
||||||
Params: nil})
|
Params: nil})
|
||||||
|
|
||||||
|
beego.GlobalControllerRouter["oc-peer/controllers:PeerController"] = append(beego.GlobalControllerRouter["oc-peer/controllers:PeerController"],
|
||||||
|
beego.ControllerComments{
|
||||||
|
Method: "SetPolicy",
|
||||||
|
Router: `/:id/policy`,
|
||||||
|
AllowHTTPMethods: []string{"put"},
|
||||||
|
MethodParams: param.Make(),
|
||||||
|
Filters: nil,
|
||||||
|
Params: nil})
|
||||||
|
|
||||||
beego.GlobalControllerRouter["oc-peer/controllers:PeerController"] = append(beego.GlobalControllerRouter["oc-peer/controllers:PeerController"],
|
beego.GlobalControllerRouter["oc-peer/controllers:PeerController"] = append(beego.GlobalControllerRouter["oc-peer/controllers:PeerController"],
|
||||||
beego.ControllerComments{
|
beego.ControllerComments{
|
||||||
Method: "Delete",
|
Method: "Delete",
|
||||||
@@ -97,6 +106,42 @@ func init() {
|
|||||||
Filters: nil,
|
Filters: nil,
|
||||||
Params: nil})
|
Params: nil})
|
||||||
|
|
||||||
|
beego.GlobalControllerRouter["oc-peer/controllers:PeerController"] = append(beego.GlobalControllerRouter["oc-peer/controllers:PeerController"],
|
||||||
|
beego.ControllerComments{
|
||||||
|
Method: "SetOrganization",
|
||||||
|
Router: `/organization`,
|
||||||
|
AllowHTTPMethods: []string{"put"},
|
||||||
|
MethodParams: param.Make(),
|
||||||
|
Filters: nil,
|
||||||
|
Params: nil})
|
||||||
|
|
||||||
|
beego.GlobalControllerRouter["oc-peer/controllers:PeerController"] = append(beego.GlobalControllerRouter["oc-peer/controllers:PeerController"],
|
||||||
|
beego.ControllerComments{
|
||||||
|
Method: "OrganizationMasterRequest",
|
||||||
|
Router: `/organization_master/:id`,
|
||||||
|
AllowHTTPMethods: []string{"post"},
|
||||||
|
MethodParams: param.Make(),
|
||||||
|
Filters: nil,
|
||||||
|
Params: nil})
|
||||||
|
|
||||||
|
beego.GlobalControllerRouter["oc-peer/controllers:PeerController"] = append(beego.GlobalControllerRouter["oc-peer/controllers:PeerController"],
|
||||||
|
beego.ControllerComments{
|
||||||
|
Method: "OrganizationMemberRequest",
|
||||||
|
Router: `/organization_member/:id`,
|
||||||
|
AllowHTTPMethods: []string{"post"},
|
||||||
|
MethodParams: param.Make(),
|
||||||
|
Filters: nil,
|
||||||
|
Params: nil})
|
||||||
|
|
||||||
|
beego.GlobalControllerRouter["oc-peer/controllers:PeerController"] = append(beego.GlobalControllerRouter["oc-peer/controllers:PeerController"],
|
||||||
|
beego.ControllerComments{
|
||||||
|
Method: "OrganizationPartner",
|
||||||
|
Router: `/organization_partner/:id`,
|
||||||
|
AllowHTTPMethods: []string{"post"},
|
||||||
|
MethodParams: param.Make(),
|
||||||
|
Filters: nil,
|
||||||
|
Params: nil})
|
||||||
|
|
||||||
beego.GlobalControllerRouter["oc-peer/controllers:PeerController"] = append(beego.GlobalControllerRouter["oc-peer/controllers:PeerController"],
|
beego.GlobalControllerRouter["oc-peer/controllers:PeerController"] = append(beego.GlobalControllerRouter["oc-peer/controllers:PeerController"],
|
||||||
beego.ControllerComments{
|
beego.ControllerComments{
|
||||||
Method: "Partner",
|
Method: "Partner",
|
||||||
@@ -115,6 +160,51 @@ func init() {
|
|||||||
Filters: nil,
|
Filters: nil,
|
||||||
Params: nil})
|
Params: nil})
|
||||||
|
|
||||||
|
beego.GlobalControllerRouter["oc-peer/controllers:PolicyController"] = append(beego.GlobalControllerRouter["oc-peer/controllers:PolicyController"],
|
||||||
|
beego.ControllerComments{
|
||||||
|
Method: "GetAll",
|
||||||
|
Router: `/`,
|
||||||
|
AllowHTTPMethods: []string{"get"},
|
||||||
|
MethodParams: param.Make(),
|
||||||
|
Filters: nil,
|
||||||
|
Params: nil})
|
||||||
|
|
||||||
|
beego.GlobalControllerRouter["oc-peer/controllers:PolicyController"] = append(beego.GlobalControllerRouter["oc-peer/controllers:PolicyController"],
|
||||||
|
beego.ControllerComments{
|
||||||
|
Method: "Get",
|
||||||
|
Router: `/:id`,
|
||||||
|
AllowHTTPMethods: []string{"get"},
|
||||||
|
MethodParams: param.Make(),
|
||||||
|
Filters: nil,
|
||||||
|
Params: nil})
|
||||||
|
|
||||||
|
beego.GlobalControllerRouter["oc-peer/controllers:PolicyController"] = append(beego.GlobalControllerRouter["oc-peer/controllers:PolicyController"],
|
||||||
|
beego.ControllerComments{
|
||||||
|
Method: "Post",
|
||||||
|
Router: `/`,
|
||||||
|
AllowHTTPMethods: []string{"post"},
|
||||||
|
MethodParams: param.Make(),
|
||||||
|
Filters: nil,
|
||||||
|
Params: nil})
|
||||||
|
|
||||||
|
beego.GlobalControllerRouter["oc-peer/controllers:PolicyController"] = append(beego.GlobalControllerRouter["oc-peer/controllers:PolicyController"],
|
||||||
|
beego.ControllerComments{
|
||||||
|
Method: "Put",
|
||||||
|
Router: `/:id`,
|
||||||
|
AllowHTTPMethods: []string{"put"},
|
||||||
|
MethodParams: param.Make(),
|
||||||
|
Filters: nil,
|
||||||
|
Params: nil})
|
||||||
|
|
||||||
|
beego.GlobalControllerRouter["oc-peer/controllers:PolicyController"] = append(beego.GlobalControllerRouter["oc-peer/controllers:PolicyController"],
|
||||||
|
beego.ControllerComments{
|
||||||
|
Method: "Delete",
|
||||||
|
Router: `/:id`,
|
||||||
|
AllowHTTPMethods: []string{"delete"},
|
||||||
|
MethodParams: param.Make(),
|
||||||
|
Filters: nil,
|
||||||
|
Params: nil})
|
||||||
|
|
||||||
beego.GlobalControllerRouter["oc-peer/controllers:StatusController"] = append(beego.GlobalControllerRouter["oc-peer/controllers:StatusController"],
|
beego.GlobalControllerRouter["oc-peer/controllers:StatusController"] = append(beego.GlobalControllerRouter["oc-peer/controllers:StatusController"],
|
||||||
beego.ControllerComments{
|
beego.ControllerComments{
|
||||||
Method: "Status",
|
Method: "Status",
|
||||||
|
|||||||
@@ -38,6 +38,11 @@ func init() {
|
|||||||
beego.NSInclude(
|
beego.NSInclude(
|
||||||
&controllers.PeerController{},
|
&controllers.PeerController{},
|
||||||
),
|
),
|
||||||
|
beego.NSNamespace("/policy",
|
||||||
|
beego.NSInclude(
|
||||||
|
&controllers.PolicyController{},
|
||||||
|
),
|
||||||
|
),
|
||||||
beego.NSNamespace("/version",
|
beego.NSNamespace("/version",
|
||||||
beego.NSInclude(
|
beego.NSInclude(
|
||||||
&controllers.VersionController{},
|
&controllers.VersionController{},
|
||||||
|
|||||||
@@ -164,6 +164,100 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/organization": {
|
||||||
|
"put": {
|
||||||
|
"tags": [
|
||||||
|
"oc-peer/controllersPeerController"
|
||||||
|
],
|
||||||
|
"description": "set organization data on self peer (only allowed when peer has no OrganizationMasterID)\n\u003cbr\u003e",
|
||||||
|
"operationId": "PeerController.SetOrganization",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"in": "body",
|
||||||
|
"name": "data",
|
||||||
|
"description": "organization data",
|
||||||
|
"required": true,
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/json"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "{peer} models.peer"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/organization_master/{id}": {
|
||||||
|
"post": {
|
||||||
|
"tags": [
|
||||||
|
"oc-peer/controllersPeerController"
|
||||||
|
],
|
||||||
|
"description": "request to become the organization master of a peer (send them an ORGANIZATION_MEMBER relation)\n\u003cbr\u003e",
|
||||||
|
"operationId": "PeerController.OrganizationMasterRequest",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"in": "path",
|
||||||
|
"name": "id",
|
||||||
|
"description": "the peer id to become member of our org",
|
||||||
|
"required": true,
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "{peer} models.peer"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/organization_member/{id}": {
|
||||||
|
"post": {
|
||||||
|
"tags": [
|
||||||
|
"oc-peer/controllersPeerController"
|
||||||
|
],
|
||||||
|
"description": "request to join a peer's organization as a member (send them an ORGANIZATION_MASTER relation)\n\u003cbr\u003e",
|
||||||
|
"operationId": "PeerController.OrganizationMemberRequest",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"in": "path",
|
||||||
|
"name": "id",
|
||||||
|
"description": "the peer id whose org we want to join",
|
||||||
|
"required": true,
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "{peer} models.peer"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/organization_partner/{id}": {
|
||||||
|
"post": {
|
||||||
|
"tags": [
|
||||||
|
"oc-peer/controllersPeerController"
|
||||||
|
],
|
||||||
|
"description": "request organization partner relation with a peer\n\u003cbr\u003e",
|
||||||
|
"operationId": "PeerController.OrganizationPartner",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"in": "path",
|
||||||
|
"name": "id",
|
||||||
|
"description": "the peer id to set as organization partner",
|
||||||
|
"required": true,
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "{peer} models.peer"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"/partner/{id}": {
|
"/partner/{id}": {
|
||||||
"post": {
|
"post": {
|
||||||
"tags": [
|
"tags": [
|
||||||
|
|||||||
@@ -218,6 +218,75 @@ paths:
|
|||||||
responses:
|
responses:
|
||||||
"200":
|
"200":
|
||||||
description: '{peer} models.peer'
|
description: '{peer} models.peer'
|
||||||
|
/organization:
|
||||||
|
put:
|
||||||
|
tags:
|
||||||
|
- oc-peer/controllersPeerController
|
||||||
|
description: |-
|
||||||
|
set organization data on self peer (only allowed when peer has no OrganizationMasterID)
|
||||||
|
<br>
|
||||||
|
operationId: PeerController.SetOrganization
|
||||||
|
parameters:
|
||||||
|
- in: body
|
||||||
|
name: data
|
||||||
|
description: organization data
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/json'
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: '{peer} models.peer'
|
||||||
|
/organization_master/{id}:
|
||||||
|
post:
|
||||||
|
tags:
|
||||||
|
- oc-peer/controllersPeerController
|
||||||
|
description: |-
|
||||||
|
request to become the organization master of a peer (send them an ORGANIZATION_MEMBER relation)
|
||||||
|
<br>
|
||||||
|
operationId: PeerController.OrganizationMasterRequest
|
||||||
|
parameters:
|
||||||
|
- in: path
|
||||||
|
name: id
|
||||||
|
description: the peer id to become member of our org
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: '{peer} models.peer'
|
||||||
|
/organization_member/{id}:
|
||||||
|
post:
|
||||||
|
tags:
|
||||||
|
- oc-peer/controllersPeerController
|
||||||
|
description: |-
|
||||||
|
request to join a peer's organization as a member (send them an ORGANIZATION_MASTER relation)
|
||||||
|
<br>
|
||||||
|
operationId: PeerController.OrganizationMemberRequest
|
||||||
|
parameters:
|
||||||
|
- in: path
|
||||||
|
name: id
|
||||||
|
description: the peer id whose org we want to join
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: '{peer} models.peer'
|
||||||
|
/organization_partner/{id}:
|
||||||
|
post:
|
||||||
|
tags:
|
||||||
|
- oc-peer/controllersPeerController
|
||||||
|
description: |-
|
||||||
|
request organization partner relation with a peer
|
||||||
|
<br>
|
||||||
|
operationId: PeerController.OrganizationPartner
|
||||||
|
parameters:
|
||||||
|
- in: path
|
||||||
|
name: id
|
||||||
|
description: the peer id to set as organization partner
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: '{peer} models.peer'
|
||||||
/partner/{id}:
|
/partner/{id}:
|
||||||
post:
|
post:
|
||||||
tags:
|
tags:
|
||||||
|
|||||||
Reference in New Issue
Block a user