diff --git a/controllers/peer.go b/controllers/peer.go index 65b224c..7a7ffc0 100644 --- a/controllers/peer.go +++ b/controllers/peer.go @@ -10,6 +10,7 @@ import ( oclib "cloud.o-forge.io/core/oc-lib" "cloud.o-forge.io/core/oc-lib/config" "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/tools" beego "github.com/beego/beego/v2/server/web" @@ -214,6 +215,78 @@ func (o *PeerController) Valid() { o.ServeJSON() 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{}{ "data": nil, @@ -399,6 +472,10 @@ func (o *PeerController) changeRelation(id string, dest *peer.Peer, user string, relation = peer.PENDING_NANO case peer.BLACKLIST: 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 { @@ -407,6 +484,12 @@ func (o *PeerController) changeRelation(id string, dest *peer.Peer, user string, if dest.Verify && relation == peer.PENDING_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 data := request.UpdateOne(map[string]interface{}{ "relation": relation, @@ -446,6 +529,128 @@ func (o *PeerController) changeRelation(id string, dest *peer.Peer, user string, 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 // @Description delete peer by peerid // @Param id path string true "the peer id you want to delete state" diff --git a/controllers/policy.go b/controllers/policy.go new file mode 100644 index 0000000..8d52ccd --- /dev/null +++ b/controllers/policy.go @@ -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() +} diff --git a/go.mod b/go.mod index 88465d1..f453af6 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module oc-peer go 1.25.0 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/smartystreets/goconvey v1.7.2 ) diff --git a/go.sum b/go.sum index 8b2f99a..8767000 100644 --- a/go.sum +++ b/go.sum @@ -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/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/Masterminds/semver/v3 v3.4.0 h1:Zog+i5UMtVoCU8oKka5P7i9q9HgrJeGzI9SA1Xbatp0= github.com/Masterminds/semver/v3 v3.4.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM= diff --git a/infrastructure/nats.go b/infrastructure/nats.go index 8cfaac3..5075f26 100644 --- a/infrastructure/nats.go +++ b/infrastructure/nats.go @@ -45,6 +45,70 @@ var self *peer.Peer func ListenNATS() { 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) { if resp.FromApp == config.GetAppName() || !slices.Contains(ressourceCols, oclib.LibDataEnum(resp.Datatype)) { return @@ -101,6 +165,12 @@ func ListenNATS() { p.Relation = peer.PENDING_PARTNER } 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)) } } @@ -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, + }) +} diff --git a/oc-peer b/oc-peer index 88c281f..e72bc81 100755 Binary files a/oc-peer and b/oc-peer differ diff --git a/routers/commentsRouter.go b/routers/commentsRouter.go index 15ed303..c313bfd 100644 --- a/routers/commentsRouter.go +++ b/routers/commentsRouter.go @@ -25,6 +25,15 @@ func init() { Filters: 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.ControllerComments{ Method: "Delete", @@ -97,6 +106,42 @@ func init() { Filters: 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.ControllerComments{ Method: "Partner", @@ -115,6 +160,51 @@ func init() { Filters: 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.ControllerComments{ Method: "Status", diff --git a/routers/router.go b/routers/router.go index bd665c9..3e5c7b1 100644 --- a/routers/router.go +++ b/routers/router.go @@ -38,6 +38,11 @@ func init() { beego.NSInclude( &controllers.PeerController{}, ), + beego.NSNamespace("/policy", + beego.NSInclude( + &controllers.PolicyController{}, + ), + ), beego.NSNamespace("/version", beego.NSInclude( &controllers.VersionController{}, diff --git a/swagger/swagger.json b/swagger/swagger.json index 7dd50b5..ba5dd15 100644 --- a/swagger/swagger.json +++ b/swagger/swagger.json @@ -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}": { "post": { "tags": [ diff --git a/swagger/swagger.yml b/swagger/swagger.yml index d141cdc..b00a393 100644 --- a/swagger/swagger.yml +++ b/swagger/swagger.yml @@ -218,6 +218,75 @@ paths: responses: "200": description: '{peer} models.peer' + /organization: + put: + tags: + - oc-peer/controllersPeerController + description: |- + set organization data on self peer (only allowed when peer has no OrganizationMasterID) +
+ 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) +
+ 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) +
+ 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 +
+ 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}: post: tags: