diff --git a/controllers/peer.go b/controllers/peer.go index 0b3ad28..2a3402d 100644 --- a/controllers/peer.go +++ b/controllers/peer.go @@ -35,7 +35,8 @@ func (o *PeerController) Search() { 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.PEER), user, peerID, groups, nil).Search(nil, search, isDraft == "true", int64(offset), int64(limit)) + o.Data["json"] = oclib.NewRequest(oclib.LibDataEnum(oclib.PEER), user, peerID, groups, nil).Search( + nil, search, isDraft == "true", int64(offset), int64(limit)) o.ServeJSON() } @@ -58,7 +59,6 @@ func (o *PeerController) SearchExtended() { fmt.Println(res, oclib.FiltersFromFlatMap(res, &peer.Peer{})) data := oclib.NewRequest(oclib.LibDataEnum(oclib.PEER), user, peerID, groups, nil).Search( oclib.FiltersFromFlatMap(res, &peer.Peer{}), "", isDraft == "true", int64(offset), int64(limit)) - fmt.Println(data.Data[0].GetName()) o.Data["json"] = data o.ServeJSON() } @@ -137,6 +137,24 @@ func (o *PeerController) Valid() { o.Data["json"] = data o.ServeJSON() return + } else if l.Data != nil && l.ToPeer().Verify && (l.ToPeer().Relation == peer.MASTER || l.ToPeer().Relation == peer.PENDING_MASTER) { + data := req.UpdateOne(map[string]interface{}{ + "verify": false, + "relation": peer.MASTER, + }, l.ToPeer().GetID()) + fmt.Println(l.Data, data.Data) + data.Data.(*peer.Peer).Relation = peer.NANO // dest is a nano + 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, @@ -155,10 +173,13 @@ func (o *PeerController) Add() { user, _, _ := oclib.ExtractTokenInfo(*o.Ctx.Request) id := o.Ctx.Input.Param(":id") infrastructure.SearchMu.Lock() + defer infrastructure.SearchMu.Unlock() + fmt.Println("qdqqds", infrastructure.SearchStreamAction) if infrastructure.SearchStreamAction[user] != nil { for _, p := range infrastructure.SearchStreamAction[user] { if p.GetID() == id { req := oclib.NewRequestAdmin(oclib.LibDataEnum(oclib.PEER), nil) + p.NotInCatalog = false o.Data["json"] = req.StoreOne(p.Serialize(p)) o.ServeJSON() return @@ -215,6 +236,10 @@ func (o *PeerController) Blacklist() { // used from : peer ask, or response, only from peer origin is authorized to change... func (o *PeerController) changeRelation(id string, dest *peer.Peer, user string, groups []string, relation peer.PeerRelation, request *oclib.Request) { + if dest.IsNano { + fmt.Println("can't change relation on nano") + return + } infrastructure.SearchMu.Lock() if dest == nil && infrastructure.SearchStreamAction[user] != nil { // add auto in base if not existing req := oclib.NewRequestAdmin(oclib.LibDataEnum(oclib.PEER), nil) @@ -243,6 +268,8 @@ func (o *PeerController) changeRelation(id string, dest *peer.Peer, user string, switch relation { case peer.PARTNER: relation = peer.PENDING_PARTNER + case peer.NANO: + relation = peer.PENDING_NANO case peer.BLACKLIST: relation = peer.NONE } @@ -250,7 +277,9 @@ func (o *PeerController) changeRelation(id string, dest *peer.Peer, user string, if dest.Verify && relation == peer.PENDING_PARTNER { relation = peer.PARTNER } - fmt.Println("CHANGE REL", dest.GetID()) + if dest.Verify && relation == peer.PENDING_NANO { + relation = peer.NANO + } data := request.UpdateOne(map[string]interface{}{ "relation": relation, }, dest.GetID()) @@ -304,7 +333,7 @@ func (o *PeerController) Delete() { o.ServeJSON() } -func Websocket(ctx ctx.Context, user string, conn *websocket.Conn) { +func Websocket(c ctx.Context, user string, conn *websocket.Conn) { defer conn.Close() done := make(chan struct{}) @@ -323,9 +352,9 @@ func Websocket(ctx ctx.Context, user string, conn *websocket.Conn) { infrastructure.SearchMu.Lock() delete(infrastructure.SearchStream, user) delete(infrastructure.SearchStreamAction, user) + fmt.Println("DEFER") infrastructure.SearchMu.Unlock() } - fmt.Println("CLOSE !") infrastructure.EmitNATS(user, nil, tools.PropalgationMessage{ Action: tools.PB_CLOSE_SEARCH, DataType: tools.PEER.EnumIndex(), @@ -337,16 +366,20 @@ func Websocket(ctx ctx.Context, user string, conn *websocket.Conn) { if !ok { continue } - infrastructure.SearchMu.Lock() - infrastructure.SearchStreamAction[user] = append(infrastructure.SearchStreamAction[user], msg) - infrastructure.SearchMu.Unlock() - + // Only accumulate peers in the action list (not online-change events). + if msg.Peer != nil { + fmt.Println("AAADDD") + infrastructure.SearchMu.Lock() + infrastructure.SearchStreamAction[user] = append(infrastructure.SearchStreamAction[user], msg.Peer) + infrastructure.SearchMu.Unlock() + fmt.Println("AAADDD", infrastructure.SearchStreamAction[user]) + } if conn.WriteJSON(msg) != nil { continue } case <-done: return - case <-ctx.Done(): + case <-c.Done(): return } } diff --git a/env.env b/env.env index c0d18f1..d60dd97 100644 --- a/env.env +++ b/env.env @@ -1,4 +1,4 @@ -KUBERNETES_SERVICE_HOST=192.168.47.20 -KUBE_CA="LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJkekNDQVIyZ0F3SUJBZ0lCQURBS0JnZ3Foa2pPUFFRREFqQWpNU0V3SHdZRFZRUUREQmhyTTNNdGMyVnkKZG1WeUxXTmhRREUzTWpNeE1USXdNell3SGhjTk1qUXdPREE0TVRBeE16VTJXaGNOTXpRd09EQTJNVEF4TXpVMgpXakFqTVNFd0h3WURWUVFEREJock0zTXRjMlZ5ZG1WeUxXTmhRREUzTWpNeE1USXdNell3V1RBVEJnY3Foa2pPClBRSUJCZ2dxaGtqT1BRTUJCd05DQUFTVlk3ZHZhNEdYTVdkMy9jMlhLN3JLYjlnWXgyNSthaEE0NmkyNVBkSFAKRktQL2UxSVMyWVF0dzNYZW1TTUQxaStZdzJSaVppNUQrSVZUamNtNHdhcnFvMEl3UURBT0JnTlZIUThCQWY4RQpCQU1DQXFRd0R3WURWUjBUQVFIL0JBVXdBd0VCL3pBZEJnTlZIUTRFRmdRVWtlUVJpNFJiODduME5yRnZaWjZHClc2SU55NnN3Q2dZSUtvWkl6ajBFQXdJRFNBQXdSUUlnRXA5ck04WmdNclRZSHYxZjNzOW5DZXZZeWVVa3lZUk4KWjUzazdoaytJS1FDSVFDbk05TnVGKzlTakIzNDFacGZ5ays2NEpWdkpSM3BhcmVaejdMd2lhNm9kdz09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K" -KUBE_CERT="LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJrVENDQVRlZ0F3SUJBZ0lJWUxWNkFPQkdrU1F3Q2dZSUtvWkl6ajBFQXdJd0l6RWhNQjhHQTFVRUF3d1kKYXpOekxXTnNhV1Z1ZEMxallVQXhOekl6TVRFeU1ETTJNQjRYRFRJME1EZ3dPREV3TVRNMU5sb1hEVEkxTURndwpPREV3TVRNMU5sb3dNREVYTUJVR0ExVUVDaE1PYzNsemRHVnRPbTFoYzNSbGNuTXhGVEFUQmdOVkJBTVRESE41CmMzUmxiVHBoWkcxcGJqQlpNQk1HQnlxR1NNNDlBZ0VHQ0NxR1NNNDlBd0VIQTBJQUJGQ2Q1MFdPeWdlQ2syQzcKV2FrOWY4MVAvSkJieVRIajRWOXBsTEo0ck5HeHFtSjJOb2xROFYxdUx5RjBtOTQ2Nkc0RmRDQ2dqaXFVSk92Swp3NVRPNnd5alNEQkdNQTRHQTFVZER3RUIvd1FFQXdJRm9EQVRCZ05WSFNVRUREQUtCZ2dyQmdFRkJRY0RBakFmCkJnTlZIU01FR0RBV2dCVFJkOFI5cXVWK2pjeUVmL0ovT1hQSzMyS09XekFLQmdncWhrak9QUVFEQWdOSUFEQkYKQWlFQTArbThqTDBJVldvUTZ0dnB4cFo4NVlMalF1SmpwdXM0aDdnSXRxS3NmUVVDSUI2M2ZNdzFBMm5OVWU1TgpIUGZOcEQwSEtwcVN0Wnk4djIyVzliYlJUNklZCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0KLS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJlRENDQVIyZ0F3SUJBZ0lCQURBS0JnZ3Foa2pPUFFRREFqQWpNU0V3SHdZRFZRUUREQmhyTTNNdFkyeHAKWlc1MExXTmhRREUzTWpNeE1USXdNell3SGhjTk1qUXdPREE0TVRBeE16VTJXaGNOTXpRd09EQTJNVEF4TXpVMgpXakFqTVNFd0h3WURWUVFEREJock0zTXRZMnhwWlc1MExXTmhRREUzTWpNeE1USXdNell3V1RBVEJnY3Foa2pPClBRSUJCZ2dxaGtqT1BRTUJCd05DQUFRc3hXWk9pbnIrcVp4TmFEQjVGMGsvTDF5cE01VHAxOFRaeU92ektJazQKRTFsZWVqUm9STW0zNmhPeVljbnN3d3JoNnhSUnBpMW5RdGhyMzg0S0Z6MlBvMEl3UURBT0JnTlZIUThCQWY4RQpCQU1DQXFRd0R3WURWUjBUQVFIL0JBVXdBd0VCL3pBZEJnTlZIUTRFRmdRVTBYZkVmYXJsZm8zTWhIL3lmemx6Cnl0OWlqbHN3Q2dZSUtvWkl6ajBFQXdJRFNRQXdSZ0loQUxJL2dNYnNMT3MvUUpJa3U2WHVpRVMwTEE2cEJHMXgKcnBlTnpGdlZOekZsQWlFQW1wdjBubjZqN3M0MVI0QzFNMEpSL0djNE53MHdldlFmZWdEVGF1R2p3cFk9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K" -KUBE_DATA="LS0tLS1CRUdJTiBFQyBQUklWQVRFIEtFWS0tLS0tCk1IY0NBUUVFSU5ZS1BFb1dhd1NKUzJlRW5oWmlYMk5VZlY1ZlhKV2krSVNnV09TNFE5VTlvQW9HQ0NxR1NNNDkKQXdFSG9VUURRZ0FFVUozblJZN0tCNEtUWUx0WnFUMS96VS84a0Z2Sk1lUGhYMm1Vc25pczBiR3FZblkyaVZEeApYVzR2SVhTYjNqcm9iZ1YwSUtDT0twUWs2OHJEbE03ckRBPT0KLS0tLS1FTkQgRUMgUFJJVkFURSBLRVktLS0tLQo=" +KUBERNETES_SERVICE_HOST=192.168.1.169 +KUBE_CA="LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJkekNDQVIyZ0F3SUJBZ0lCQURBS0JnZ3Foa2pPUFFRREFqQWpNU0V3SHdZRFZRUUREQmhyTTNNdGMyVnkKZG1WeUxXTmhRREUzTnpReU56STVNVEF3SGhjTk1qWXdNekl6TVRNek5URXdXaGNOTXpZd016SXdNVE16TlRFdwpXakFqTVNFd0h3WURWUVFEREJock0zTXRjMlZ5ZG1WeUxXTmhRREUzTnpReU56STVNVEF3V1RBVEJnY3Foa2pPClBRSUJCZ2dxaGtqT1BRTUJCd05DQUFSSGpYRDVpbnRIYWZWSk5VaDFlRnIxcXBKdFlkUmc5NStKVENEa0tadTIKYjUxRXlKaG1zanRIY3BDUndGL1VGMzlvdzY4TFBUcjBxaUorUHlhQTBLZUtvMEl3UURBT0JnTlZIUThCQWY4RQpCQU1DQXFRd0R3WURWUjBUQVFIL0JBVXdBd0VCL3pBZEJnTlZIUTRFRmdRVTdWQkNzZVN3ajJ2cmczMFE5UG8vCnV6ZzAvMjR3Q2dZSUtvWkl6ajBFQXdJRFNBQXdSUUloQUlEOVY2aFlUSS83ZW1hRzU0dDdDWVU3TXFSdDdESUkKNlgvSUwrQ0RLbzlNQWlCdlFEMGJmT0tVWDc4UmRGdUplcEhEdWFUMUExaGkxcWdIUGduM1dZdDBxUT09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K" +KUBE_CERT="LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJrVENDQVRlZ0F3SUJBZ0lJUU5KbFNJQUJPMDR3Q2dZSUtvWkl6ajBFQXdJd0l6RWhNQjhHQTFVRUF3d1kKYXpOekxXTnNhV1Z1ZEMxallVQXhOemMwTWpjeU9URXdNQjRYRFRJMk1ETXlNekV6TXpVeE1Gb1hEVEkzTURNeQpNekV6TXpVeE1Gb3dNREVYTUJVR0ExVUVDaE1PYzNsemRHVnRPbTFoYzNSbGNuTXhGVEFUQmdOVkJBTVRESE41CmMzUmxiVHBoWkcxcGJqQlpNQk1HQnlxR1NNNDlBZ0VHQ0NxR1NNNDlBd0VIQTBJQUJMY3Uwb2pUbVg4RFhTQkYKSHZwZDZNVEoyTHdXc1lRTmdZVURXRDhTVERIUWlCczlMZ0x5ZTdOMEFvZk85RkNZVW1HamhiaVd3WFVHR3dGTgpUdlRMU2lXalNEQkdNQTRHQTFVZER3RUIvd1FFQXdJRm9EQVRCZ05WSFNVRUREQUtCZ2dyQmdFRkJRY0RBakFmCkJnTlZIU01FR0RBV2dCUlJhRW9wQzc5NGJyTHlnR0g5SVhvbDZTSmlFREFLQmdncWhrak9QUVFEQWdOSUFEQkYKQWlFQWhaRUlrSWV3Y1loL1NmTFVCVjE5MW1CYTNRK0J5S2J5eTVlQmpwL3kzeWtDSUIxWTJicTVOZTNLUUU4RAprNnNzeFJrbjJmN0VoWWVRQU1pUlJ2MjIweDNLCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0KLS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJkekNDQVIyZ0F3SUJBZ0lCQURBS0JnZ3Foa2pPUFFRREFqQWpNU0V3SHdZRFZRUUREQmhyTTNNdFkyeHAKWlc1MExXTmhRREUzTnpReU56STVNVEF3SGhjTk1qWXdNekl6TVRNek5URXdXaGNOTXpZd016SXdNVE16TlRFdwpXakFqTVNFd0h3WURWUVFEREJock0zTXRZMnhwWlc1MExXTmhRREUzTnpReU56STVNVEF3V1RBVEJnY3Foa2pPClBRSUJCZ2dxaGtqT1BRTUJCd05DQUFTcTdVTC85MEc1ZmVTaE95NjI3eGFZWlM5dHhFdWFoWFQ3Vk5wZkpQSnMKaEdXd2UxOXdtbXZzdlp6dlNPUWFRSzJaMmttN0hSb1IrNlA1YjIyamczbHVvMEl3UURBT0JnTlZIUThCQWY4RQpCQU1DQXFRd0R3WURWUjBUQVFIL0JBVXdBd0VCL3pBZEJnTlZIUTRFRmdRVVVXaEtLUXUvZUc2eThvQmgvU0Y2Ckpla2lZaEF3Q2dZSUtvWkl6ajBFQXdJRFNBQXdSUUloQUk3cGxHczFtV20ySDErbjRobDBNTk13RmZzd0o5ZXIKTzRGVkM0QzhwRG44QWlCN3NZMVFwd2M5VkRUeGNZaGxuZzZNUzRXai85K0lHWjJxcy94UStrMjdTQT09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K" +KUBE_DATA="LS0tLS1CRUdJTiBFQyBQUklWQVRFIEtFWS0tLS0tCk1IY0NBUUVFSUROZDRnWXd6aVRhK1hwNnFtNVc3SHFzc1JJNkREaUJTbUV2ZHoxZzk3VGxvQW9HQ0NxR1NNNDkKQXdFSG9VUURRZ0FFdHk3U2lOT1pmd05kSUVVZStsM294TW5ZdkJheGhBMkJoUU5ZUHhKTU1kQ0lHejB1QXZKNwpzM1FDaDg3MFVKaFNZYU9GdUpiQmRRWWJBVTFPOU10S0pRPT0KLS0tLS1FTkQgRUMgUFJJVkFURSBLRVktLS0tLQo=" diff --git a/go.mod b/go.mod index 782e743..dedcff0 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-20260407090927-6fe91eda875d + cloud.o-forge.io/core/oc-lib v0.0.0-20260429050913-47d487ea8011 github.com/beego/beego/v2 v2.3.8 github.com/smartystreets/goconvey v1.7.2 ) diff --git a/go.sum b/go.sum index c9b6229..cdc6ed7 100644 --- a/go.sum +++ b/go.sum @@ -44,6 +44,18 @@ cloud.o-forge.io/core/oc-lib v0.0.0-20260407075448-b7ee6d8e7f13 h1:mygo9rIB3uJ/G cloud.o-forge.io/core/oc-lib v0.0.0-20260407075448-b7ee6d8e7f13/go.mod h1:+ENuvBfZdESSvecoqGY/wSvRlT3vinEolxKgwbOhUpA= cloud.o-forge.io/core/oc-lib v0.0.0-20260407090927-6fe91eda875d h1:54Vl14gurwAkmZEaWZKUM5eDZfB7MF/fzWjibWLQljE= cloud.o-forge.io/core/oc-lib v0.0.0-20260407090927-6fe91eda875d/go.mod h1:+ENuvBfZdESSvecoqGY/wSvRlT3vinEolxKgwbOhUpA= +cloud.o-forge.io/core/oc-lib v0.0.0-20260417074500-5cc04ee49015 h1:Q6sYlSfW9PIK9XyhDmGPPxDNmMAR9CPbgNedhNpYpYw= +cloud.o-forge.io/core/oc-lib v0.0.0-20260417074500-5cc04ee49015/go.mod h1:JynnOb3eMr9VZW1mHq+Vsl3tzx6gPhPsGKpQD/dtEBc= +cloud.o-forge.io/core/oc-lib v0.0.0-20260423074839-e70e89b630b7 h1:WdExXiecLnST8a7gAh6Z9Xd1Q+0/EjTy1P+b9ABoga8= +cloud.o-forge.io/core/oc-lib v0.0.0-20260423074839-e70e89b630b7/go.mod h1:JynnOb3eMr9VZW1mHq+Vsl3tzx6gPhPsGKpQD/dtEBc= +cloud.o-forge.io/core/oc-lib v0.0.0-20260423080412-b9ad5d5ea744 h1:o+mtitSp2xoKB/24l2hDQB0nXpVaMKKf9lpw9OTFrRI= +cloud.o-forge.io/core/oc-lib v0.0.0-20260423080412-b9ad5d5ea744/go.mod h1:JynnOb3eMr9VZW1mHq+Vsl3tzx6gPhPsGKpQD/dtEBc= +cloud.o-forge.io/core/oc-lib v0.0.0-20260423083351-560c997bf135 h1:HJtecjH0vnwruCTZ8Adueh4FfZHPT00HuV9JTf5D5g4= +cloud.o-forge.io/core/oc-lib v0.0.0-20260423083351-560c997bf135/go.mod h1:JynnOb3eMr9VZW1mHq+Vsl3tzx6gPhPsGKpQD/dtEBc= +cloud.o-forge.io/core/oc-lib v0.0.0-20260423090802-25880077d195 h1:3zgPhZMFcyfeSInyWPxxwUejSEOAUCUl1tS6f9+BNF0= +cloud.o-forge.io/core/oc-lib v0.0.0-20260423090802-25880077d195/go.mod h1:JynnOb3eMr9VZW1mHq+Vsl3tzx6gPhPsGKpQD/dtEBc= +cloud.o-forge.io/core/oc-lib v0.0.0-20260429050913-47d487ea8011 h1:owV5pQ+mS5xDCKEcGTO+BgsyYrKjkISL8LDsmjEb/3s= +cloud.o-forge.io/core/oc-lib v0.0.0-20260429050913-47d487ea8011/go.mod h1:JynnOb3eMr9VZW1mHq+Vsl3tzx6gPhPsGKpQD/dtEBc= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/Knetic/govaluate v3.0.0+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= diff --git a/infrastructure/nats.go b/infrastructure/nats.go index 39b72ea..8cfaac3 100644 --- a/infrastructure/nats.go +++ b/infrastructure/nats.go @@ -5,6 +5,7 @@ import ( "fmt" "slices" "sync" + "time" oclib "cloud.o-forge.io/core/oc-lib" "cloud.o-forge.io/core/oc-lib/config" @@ -19,14 +20,15 @@ var ressourceCols = []oclib.LibDataEnum{ var SearchMu sync.RWMutex var SearchStreamAction = map[string][]*peer.Peer{} -var SearchStream = map[string]chan *peer.Peer{} +var SearchStream = map[string]chan WSMessage{} func EmitNATS(user string, groups []string, message tools.PropalgationMessage) { b, _ := json.Marshal(message) if message.Action == tools.PB_SEARCH { SearchMu.Lock() - SearchStream[user] = make(chan *peer.Peer, 128) + SearchStream[user] = make(chan WSMessage, 128) SearchStreamAction[user] = []*peer.Peer{} + fmt.Println("NEW PB") SearchMu.Unlock() } tools.NewNATSCaller().SetNATSPub(tools.PROPALGATION_EVENT, tools.NATSResponse{ @@ -39,24 +41,6 @@ func EmitNATS(user string, groups []string, message tools.PropalgationMessage) { }) } -// un ressource quand on l'ajoute à notre catalogue elle nous est étrangère. -// pour se la réaffecté à soit, on peut alors changer le créator ID. -// pour protéger une ressource l'idée serait de la signée. -// si on la stocke en base, elle va se dépréciée plus encore si le user n'est pas un partenaire. -// elle ne sera pas maintenue à jour. Si c'est une ressource publique et qu'elle change -// l'offre peut disparaitre mais subsisté chez nous. -// alors si on en dispose et qu'on souhaite l'exploité. On doit en vérifier la validité... ou... -// la mettre à jour. Le problème de la mise à jour c'est qu'on peut facilement -// overflow.... de stream pour avoir à jour sa ressource. -// donc l'idée est que la vérification soit manuelle... ou lors d'une vérification de dernière instance. - -// si une ressource est exploitée dans un workflow ou un shared workspace. -// elle doit être vérifié par les pairs engagés. -// si la donnée est déclaré comme donnée de l'emmetteur alors on vérifie que la signature est bien émise, par -// l'emmetteur. Sinon... on doit interrogé le pair qui a émit la donnée. Est ce que la donnée est à jour. -// lui va vérifier la signature de la ressource qu'il possède correspondante si elle existe, si non. AIE, -// on met à jour mais on pète une erreur. - var self *peer.Peer func ListenNATS() { @@ -65,15 +49,15 @@ func ListenNATS() { if resp.FromApp == config.GetAppName() || !slices.Contains(ressourceCols, oclib.LibDataEnum(resp.Datatype)) { return } + self, _ := oclib.GetMySelf() + if self != nil && self.IsNano { + return + } p := &peer.Peer{} if err := json.Unmarshal(resp.Payload, &p); err == nil { - /*if err := verify(resp.Payload); err != nil { - return // don't trust anyone... only friends and foes are privilege - }*/ - fmt.Println("CREATE_RESOURCE", p.GetID()) - if ok, _ := oclib.IsMySelf(p.GetID()); ok { + if self.GetID() == p.GetID() { fmt.Println("it's ourselve !") return } @@ -99,11 +83,24 @@ func ListenNATS() { "relation": p.Relation, }, p.GetID()) } + } else if p.Relation == peer.PENDING_NANO || p.Relation == peer.NANO { + if data.ToPeer().Verify { + access.UpdateOne(map[string]interface{}{ + "verify": false, + "relation": peer.MASTER, + }, p.GetID()) + } else { + access.UpdateOne(map[string]interface{}{ + "verify": true, + "relation": peer.PENDING_MASTER, + }, p.GetID()) + } } else if p.Relation != peer.SELF && p.Relation != peer.BLACKLIST { if p.Relation == peer.PARTNER || p.Relation == peer.PENDING_PARTNER { p.Verify = true p.Relation = peer.PENDING_PARTNER } + p.IsNano = config.GetConfig().IsNano access.StoreOne(p.Serialize(p)) } } @@ -113,23 +110,54 @@ func ListenNATS() { return } p := &peer.Peer{} - err := json.Unmarshal(resp.Payload, p) - if err == nil { - access := oclib.NewRequestAdmin(oclib.LibDataEnum(oclib.PEER), nil) - fmt.Println("ADD in SEARCH STREAM", p.GetID()) - if s := access.Search(&dbs.Filters{ - And: map[string][]dbs.Filter{ - "peer_id": {{Operator: dbs.EQUAL.String(), Value: p.PeerID}}, - }, - }, "", false, 0, 1); len(s.Data) > 0 { - p.Relation = s.Data[0].(*peer.Peer).Relation - } else { - p.NotInCatalog = true - } - SearchMu.Lock() - SearchStream[resp.User] <- p // TODO when do we update it in our catalog ? - SearchMu.Unlock() + if err := json.Unmarshal(resp.Payload, p); err != nil { + return } + access := oclib.NewRequestAdmin(oclib.LibDataEnum(oclib.PEER), nil) + fmt.Println("ADD in SEARCH STREAM", p.GetID()) + if s := access.Search(&dbs.Filters{ + And: map[string][]dbs.Filter{ + "peer_id": {{Operator: dbs.EQUAL.String(), Value: p.PeerID}}, + }, + }, "", false, 0, 1); len(s.Data) > 0 { + p.Relation = s.Data[0].(*peer.Peer).Relation + } else { + p.NotInCatalog = true + } + + // Stamp volatile online state from cache. + p.Online = IsOnline(p.PeerID) + now := time.Now() + if p.Online { + p.LastHeartbeat = &now + } + + SearchMu.RLock() + if ch, ok := SearchStream[resp.User]; ok { + select { + case ch <- WSMessage{Type: "peer", Peer: p}: + default: + } + } + SearchMu.RUnlock() + }, + + // PEER_OBSERVE_RESPONSE_EVENT is emitted by oc-discovery when it + // receives a heartbeat from an observed remote peer. + tools.PEER_OBSERVE_RESPONSE_EVENT: func(resp tools.NATSResponse) { + var batch struct { + PeerIDs []string `json:"peer_ids"` + Metrics map[string]*PeerConnectivityMetrics `json:"metrics"` + } + + if err := json.Unmarshal(resp.Payload, &batch); err != nil { + return + } + if len(batch.PeerIDs) == 0 { + return + } + fmt.Println("METRICS", batch.Metrics) + HandleHeartbeatBatch(batch.PeerIDs, batch.Metrics) }, }) } diff --git a/infrastructure/observe.go b/infrastructure/observe.go new file mode 100644 index 0000000..f380c8d --- /dev/null +++ b/infrastructure/observe.go @@ -0,0 +1,326 @@ +package infrastructure + +import ( + "encoding/json" + "fmt" + "sync" + "time" + + "cloud.o-forge.io/core/oc-lib/models/peer" + "cloud.o-forge.io/core/oc-lib/tools" +) + +const observeTimeout = 60 * time.Second +const offlineRetryInterval = 60 * time.Second + +// PeerConnectivityMetrics is the quality snapshot received from oc-discovery +// via PEER_OBSERVE_RESPONSE_EVENT and forwarded to the frontend via WebSocket. +type PeerConnectivityMetrics struct { + LatencyMs float64 `json:"latency_ms"` + Speed string `json:"speed"` // "fast" | "slow" + Reliability string `json:"reliability"` // "reliable" | "watch" + TrustScore float64 `json:"trust_score"` + LastSeenAt time.Time `json:"last_seen_at"` + MissRate float64 `json:"miss_rate"` +} + +// WSMessage is sent on every WebSocket endpoint (search and observe). +// +// Type == "peer" → Peer field is set +// Type == "connectivity" → PeerID + Online + Metrics are set +type WSMessage struct { + Type string `json:"type"` + Peer *peer.Peer `json:"peer,omitempty"` + PeerID string `json:"peer_id,omitempty"` + Online bool `json:"online,omitempty"` + Metrics *PeerConnectivityMetrics `json:"metrics,omitempty"` +} + +// ShallowPeer is the minimal peer representation the frontend sends when +// requesting observation. oc-discovery uses Address/StreamAddress to reach it. +type ShallowPeer struct { + ID string `json:"id"` + PeerID string `json:"peer_id"` + Address string `json:"address"` + StreamAddress string `json:"stream_address"` +} + +// peerObserveCmd is the NATS payload sent to oc-discovery. +// +// Observe → User + Peers populated +// Close → User + PeerIDs + Close=true +// CloseAll → User + CloseAll=true +type peerObserveCmd struct { + User string `json:"user"` + Peers []ShallowPeer `json:"peers,omitempty"` + PeerIDs []string `json:"peer_ids,omitempty"` + Close bool `json:"close,omitempty"` + CloseAll bool `json:"close_all,omitempty"` +} + +// ── online cache ───────────────────────────────────────────────────────────── + +type onlineState struct { + online bool + timer *time.Timer + metrics *PeerConnectivityMetrics +} + +var ( + onlineMu sync.Mutex + onlineCache = map[string]*onlineState{} + + offlineMu sync.Mutex + offlineCache = map[string]struct{}{} +) + +// IsOnline returns whether peerID is currently considered online. +func IsOnline(peerID string) bool { + onlineMu.Lock() + defer onlineMu.Unlock() + if s, ok := onlineCache[peerID]; ok { + return s.online + } + return false +} + +// HandleHeartbeatBatch processes a batch of peer heartbeats with optional metrics. +// Called from the PEER_OBSERVE_RESPONSE_EVENT NATS listener. +func HandleHeartbeatBatch(peerIDs []string, metricsMap map[string]*PeerConnectivityMetrics) { + for _, id := range peerIDs { + var m *PeerConnectivityMetrics + if metricsMap != nil { + m = metricsMap[id] + } + setOnline(id, m) + } +} + +func setOnline(peerID string, metrics *PeerConnectivityMetrics) { + fmt.Println("SET ONLINE ", peerID, metrics) + onlineMu.Lock() + s, exists := onlineCache[peerID] + if !exists { + s = &onlineState{} + onlineCache[peerID] = s + } + s.online = true + s.metrics = metrics + if s.timer != nil { + s.timer.Stop() + } + s.timer = time.AfterFunc(observeTimeout, func() { setOffline(peerID) }) + onlineMu.Unlock() + + offlineMu.Lock() + delete(offlineCache, peerID) + offlineMu.Unlock() + + broadcastConnectivity(peerID, true, metrics) +} + +func setOffline(peerID string) { + onlineMu.Lock() + s, ok := onlineCache[peerID] + if !ok || !s.online { + onlineMu.Unlock() + return + } + s.online = false + s.timer = nil + onlineMu.Unlock() + + offlineMu.Lock() + offlineCache[peerID] = struct{}{} + offlineMu.Unlock() + + broadcastConnectivity(peerID, false, nil) +} + +// broadcastConnectivity fans out a connectivity change to all observe sessions +// watching peerID. +func broadcastConnectivity(peerID string, online bool, metrics *PeerConnectivityMetrics) { + fmt.Println("BORADCAST METRICS", metrics) + msg := WSMessage{Type: "connectivity", PeerID: peerID, Online: online, Metrics: metrics} + + sessionsMu.RLock() + for _, s := range sessions { + for _, p := range s.peers { + if p.PeerID == peerID { + select { + case s.ch <- msg: + default: + } + break + } + } + } + sessionsMu.RUnlock() +} + +// ── observe sessions ────────────────────────────────────────────────────────── + +// observeSession holds per-WS-connection state (user, watched peers, output channel). +type observeSession struct { + user string + peers []ShallowPeer + ch chan WSMessage +} + +var ( + sessionsMu sync.RWMutex + sessions = map[string]*observeSession{} +) + +// RegisterObserveSession creates an empty session for connID / user. +func RegisterObserveSession(connID, user string, ch chan WSMessage) { + sessionsMu.Lock() + sessions[connID] = &observeSession{user: user, ch: ch} + sessionsMu.Unlock() +} + +// AddObservedPeers merges new peers into the session, emits a NATS observe +// command (user-scoped), and returns the current online state for each peer. +func AddObservedPeers(connID string, peers []ShallowPeer) []WSMessage { + fmt.Println("AddObservedPeers Concrete") + sessionsMu.Lock() + s, ok := sessions[connID] + if !ok { + sessionsMu.Unlock() + fmt.Println("sessions IS NOT") + return nil + } + existing := make(map[string]struct{}, len(s.peers)) + for _, p := range s.peers { + existing[p.PeerID] = struct{}{} + } + var newPeers []ShallowPeer + for _, p := range peers { + if _, dup := existing[p.PeerID]; !dup { + s.peers = append(s.peers, p) + newPeers = append(newPeers, p) + } + } + user := s.user + sessionsMu.Unlock() + + fmt.Println("newPeers", newPeers) + + if len(newPeers) > 0 { + EmitObserve(user, newPeers) + } + return GetCurrentStates(peerIDsFrom(peers)) +} + +// CloseObserveSession emits NATS close for all peers in the session, then +// removes it. Call this on WS disconnect (normal or error). +func CloseObserveSession(connID string) { + sessionsMu.Lock() + s, ok := sessions[connID] + if !ok { + sessionsMu.Unlock() + return + } + delete(sessions, connID) + user := s.user + ids := peerIDsFrom(s.peers) + sessionsMu.Unlock() + + if len(ids) > 0 { + EmitClose(user, ids) + } +} + +// GetCurrentStates returns one WSMessage per peer ID from the online cache +// (defaults to offline for unknown peers). +func GetCurrentStates(peerIDs []string) []WSMessage { + onlineMu.Lock() + defer onlineMu.Unlock() + msgs := make([]WSMessage, 0, len(peerIDs)) + for _, id := range peerIDs { + online := false + var metrics *PeerConnectivityMetrics + if s, ok := onlineCache[id]; ok { + online = s.online + metrics = s.metrics + } + msgs = append(msgs, WSMessage{Type: "connectivity", PeerID: id, Online: online, Metrics: metrics}) + } + return msgs +} + +func peerIDsFrom(peers []ShallowPeer) []string { + ids := make([]string, 0, len(peers)) + for _, p := range peers { + ids = append(ids, p.PeerID) + } + return ids +} + +// ── NATS emission ───────────────────────────────────────────────────────────── + +// EmitObserve asks oc-discovery to start observing peers on behalf of user. +func EmitObserve(user string, peers []ShallowPeer) { + emitCmd(peerObserveCmd{User: user, Peers: peers}) +} + +// EmitClose asks oc-discovery to stop observing peerIDs for user. +func EmitClose(user string, peerIDs []string) { + emitCmd(peerObserveCmd{User: user, PeerIDs: peerIDs, Close: true}) +} + +// EmitCloseAll resets all observations for user in oc-discovery. +// Pass an empty user to clear everything (startup reset). +func EmitCloseAll(user string) { + emitCmd(peerObserveCmd{User: user, CloseAll: true}) +} + +func emitCmd(cmd peerObserveCmd) { + b, err := json.Marshal(cmd) + if err != nil { + return + } + tools.NewNATSCaller().SetNATSPub(tools.PEER_OBSERVE_EVENT, tools.NATSResponse{ + FromApp: "oc-peer", + Datatype: tools.PEER, + Method: int(tools.PEER_OBSERVE_EVENT), + Payload: b, + }) +} + +// ── offline retry loop ──────────────────────────────────────────────────────── + +// StartOfflineRetryLoop re-requests observation for offline peers every +// offlineRetryInterval, scoped to each active session's user. +func StartOfflineRetryLoop() { + go func() { + ticker := time.NewTicker(offlineRetryInterval) + defer ticker.Stop() + for range ticker.C { + offlineMu.Lock() + offlineIDs := make(map[string]struct{}, len(offlineCache)) + for id := range offlineCache { + offlineIDs[id] = struct{}{} + } + offlineMu.Unlock() + + if len(offlineIDs) == 0 { + continue + } + + sessionsMu.RLock() + for _, s := range sessions { + var retry []ShallowPeer + for _, p := range s.peers { + if _, off := offlineIDs[p.PeerID]; off { + retry = append(retry, p) + } + } + if len(retry) > 0 { + go EmitObserve(s.user, retry) + } + } + sessionsMu.RUnlock() + } + }() +} diff --git a/main.go b/main.go index 98d599b..a2732ce 100644 --- a/main.go +++ b/main.go @@ -1,23 +1,42 @@ package main import ( - "fmt" + "encoding/json" "oc-peer/infrastructure" _ "oc-peer/routers" oclib "cloud.o-forge.io/core/oc-lib" + "cloud.o-forge.io/core/oc-lib/config" + "cloud.o-forge.io/core/oc-lib/tools" beego "github.com/beego/beego/v2/server/web" ) const appname = "oc-peer" func main() { - for _, info := range beego.BeeApp.Handlers.GetAllControllerInfo() { - fmt.Println(info.GetPattern()) - } oclib.InitAPI(appname, map[string][]string{ "/oc/decentralized/search/:search": {"GET"}, + "/oc/decentralized/observe": {"GET"}, }) go infrastructure.ListenNATS() - beego.Run() + // On startup: reset all ongoing observations in oc-discovery. + // If oc-peer crashed while oc-discovery was still running, oc-discovery may + // hold stale observe streams. Close-all clears them and enters drain mode. + go infrastructure.EmitCloseAll("") + + d := oclib.NewRequestAdmin(oclib.LibDataEnum(oclib.PEER), nil).LoadAll(false, 0, 100000) + for _, dd := range d.Data { + if b, err := json.Marshal(dd); err == nil { + go infrastructure.EmitNATS("root", []string{}, tools.PropalgationMessage{ + DataType: tools.PEER.EnumIndex(), + Action: tools.PB_CREATE, + Payload: b, + }) + } + } + // Retry observe for offline peers every minute. + infrastructure.StartOfflineRetryLoop() + if config.GetConfig().IsApi { + beego.Run() + } } diff --git a/oc-peer b/oc-peer new file mode 100755 index 0000000..ef7faae Binary files /dev/null and b/oc-peer differ diff --git a/routers/router.go b/routers/router.go index 66203a7..3bc2598 100644 --- a/routers/router.go +++ b/routers/router.go @@ -9,10 +9,12 @@ package routers import ( "encoding/json" + "fmt" "net/http" "oc-peer/controllers" "oc-peer/infrastructure" "strings" + "time" oclib "cloud.o-forge.io/core/oc-lib" "cloud.o-forge.io/core/oc-lib/tools" @@ -44,8 +46,7 @@ func init() { ) beego.AddNamespace(ns) - // WebSocket route enregistrée en dehors du pipeline Beego - // beego.Handler bypasse le controller pipeline (pas de WriteHeader parasite) + // WebSocket — peer search (returns found peers + online/offline updates for them) beego.Handler("/oc/decentralized/search/:search", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { conn, err := upgrader.Upgrade(w, r, nil) if err != nil { @@ -55,13 +56,89 @@ func init() { parts := strings.Split(strings.TrimSuffix(r.URL.Path, "/"), "/") search := parts[len(parts)-1] - user, _, groups := oclib.ExtractTokenInfo(*r) + user, _, groups := oclib.ExtractTokenInfoWs(*r) b, _ := json.Marshal(map[string]string{"search": search}) infrastructure.EmitNATS(user, groups, tools.PropalgationMessage{ Action: tools.PB_SEARCH, DataType: tools.PEER.EnumIndex(), Payload: b, }) + fmt.Println("SEARCH", search) controllers.Websocket(r.Context(), user, conn) })) + + // WebSocket — dedicated online/offline feed, user-scoped. + // + // The frontend sends lists of ShallowPeer to watch; oc-peer forwards them + // to oc-discovery via NATS (with user identity). On any disconnect or error + // oc-peer emits NATS close for all peers watched in this session. + beego.Handler("/oc/decentralized/observe", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + conn, err := upgrader.Upgrade(w, r, nil) + if err != nil { + return + } + + user, _, _ := oclib.ExtractTokenInfoWs(*r) + connID := fmt.Sprintf("%p", conn) + ch := make(chan infrastructure.WSMessage, 64) + fmt.Println("SUBSCRIBED TO", connID) + infrastructure.RegisterObserveSession(connID, user, ch) + done := make(chan struct{}) + defer func() { + infrastructure.CloseObserveSession(connID) + close(done) + conn.Close() + }() + + const pongWait = 60 * time.Second + const pingPeriod = 50 * time.Second + const writeWait = 10 * time.Second + + conn.SetReadDeadline(time.Now().Add(pongWait)) + conn.SetPongHandler(func(string) error { + return conn.SetReadDeadline(time.Now().Add(pongWait)) + }) + + // Write loop: forward state-change messages and send keepalive pings. + go func() { + ticker := time.NewTicker(pingPeriod) + defer ticker.Stop() + for { + select { + case msg := <-ch: + fmt.Println("ONLINE", msg) + conn.SetWriteDeadline(time.Now().Add(writeWait)) + if conn.WriteJSON(msg) != nil { + conn.Close() + return + } + case <-ticker.C: + conn.SetWriteDeadline(time.Now().Add(writeWait)) + if conn.WriteMessage(websocket.PingMessage, nil) != nil { + conn.Close() + return + } + case <-done: + return + } + } + }() + + // Read loop: receive peer lists from the frontend. + var req struct { + Peers []infrastructure.ShallowPeer `json:"peers"` + } + for { + if err := conn.ReadJSON(&req); err != nil { + return + } + // AddObservedPeers deduplicates, emits NATS observe, returns snapshot. + for _, msg := range infrastructure.AddObservedPeers(connID, req.Peers) { + select { + case ch <- msg: + default: + } + } + } + })) } diff --git a/swagger/swagger.json b/swagger/swagger.json index e70f833..54bf1d4 100644 --- a/swagger/swagger.json +++ b/swagger/swagger.json @@ -72,21 +72,37 @@ } } }, + "/blacklist/{id}": { + "post": { + "tags": [ + "oc-peer/controllersPeerController" + ], + "description": "add blacklist peer by peerid\n\u003cbr\u003e", + "operationId": "PeerController.Blacklist", + "parameters": [ + { + "in": "path", + "name": "id", + "description": "the peer id you want to blacklist", + "required": true, + "type": "string" + } + ], + "responses": { + "200": { + "description": "{peer} models.peer" + } + } + } + }, "/extended/search": { - "get": { + "post": { "tags": [ "oc-peer/controllersPeerController" ], "description": "search workspace\n\u003cbr\u003e", "operationId": "PeerController.Search", "parameters": [ - { - "in": "path", - "name": "search", - "description": "the word search you want to get", - "required": true, - "type": "string" - }, { "in": "query", "name": "is_draft", @@ -104,6 +120,15 @@ "name": "limit", "description": "false", "type": "string" + }, + { + "in": "body", + "name": "data", + "description": "body for data content (Json format)", + "required": true, + "schema": { + "$ref": "#/definitions/json" + } } ], "responses": { @@ -113,6 +138,52 @@ } } }, + "/known/{id}": { + "post": { + "tags": [ + "oc-peer/controllersPeerController" + ], + "description": "add kwown peer by peerid\n\u003cbr\u003e", + "operationId": "PeerController.known", + "parameters": [ + { + "in": "path", + "name": "id", + "description": "the peer id you want to blacklist", + "required": true, + "type": "string" + } + ], + "responses": { + "200": { + "description": "{peer} models.peer" + } + } + } + }, + "/partner/{id}": { + "post": { + "tags": [ + "oc-peer/controllersPeerController" + ], + "description": "add partner peer by peerid\n\u003cbr\u003e", + "operationId": "PeerController.Partner", + "parameters": [ + { + "in": "path", + "name": "id", + "description": "the peer id you want to blacklist", + "required": true, + "type": "string" + } + ], + "responses": { + "200": { + "description": "{peer} models.peer" + } + } + } + }, "/search/{search}": { "get": { "tags": [ @@ -258,78 +329,13 @@ } } } - }, - "/{id}/blacklist": { - "post": { - "tags": [ - "oc-peer/controllersPeerController" - ], - "description": "add blacklist peer by peerid\n\u003cbr\u003e", - "operationId": "PeerController.Blacklist", - "parameters": [ - { - "in": "path", - "name": "id", - "description": "the peer id you want to blacklist", - "required": true, - "type": "string" - } - ], - "responses": { - "200": { - "description": "{peer} models.peer" - } - } - } - }, - "/{id}/known": { - "post": { - "tags": [ - "oc-peer/controllersPeerController" - ], - "description": "add kwown peer by peerid\n\u003cbr\u003e", - "operationId": "PeerController.known", - "parameters": [ - { - "in": "path", - "name": "id", - "description": "the peer id you want to blacklist", - "required": true, - "type": "string" - } - ], - "responses": { - "200": { - "description": "{peer} models.peer" - } - } - } - }, - "/{id}/partner": { - "post": { - "tags": [ - "oc-peer/controllersPeerController" - ], - "description": "add partner peer by peerid\n\u003cbr\u003e", - "operationId": "PeerController.Partner", - "parameters": [ - { - "in": "path", - "name": "id", - "description": "the peer id you want to blacklist", - "required": true, - "type": "string" - } - ], - "responses": { - "200": { - "description": "{peer} models.peer" - } - } - } } }, "definitions": { + "json": { + "title": "json", + "type": "object" + }, "list": { "title": "list", "type": "object" diff --git a/swagger/swagger.yml b/swagger/swagger.yml index 107c30c..553b65b 100644 --- a/swagger/swagger.yml +++ b/swagger/swagger.yml @@ -69,57 +69,6 @@ paths: responses: "200": description: '{peer} models.peer' - /{id}/blacklist: - post: - tags: - - oc-peer/controllersPeerController - description: |- - add blacklist peer by peerid -
- operationId: PeerController.Blacklist - parameters: - - in: path - name: id - description: the peer id you want to blacklist - required: true - type: string - responses: - "200": - description: '{peer} models.peer' - /{id}/known: - post: - tags: - - oc-peer/controllersPeerController - description: |- - add kwown peer by peerid -
- operationId: PeerController.known - parameters: - - in: path - name: id - description: the peer id you want to blacklist - required: true - type: string - responses: - "200": - description: '{peer} models.peer' - /{id}/partner: - post: - tags: - - oc-peer/controllersPeerController - description: |- - add partner peer by peerid -
- operationId: PeerController.Partner - parameters: - - in: path - name: id - description: the peer id you want to blacklist - required: true - type: string - responses: - "200": - description: '{peer} models.peer' /add/{id}: post: tags: @@ -137,8 +86,25 @@ paths: responses: "200": description: '{peer} models.peer' + /blacklist/{id}: + post: + tags: + - oc-peer/controllersPeerController + description: |- + add blacklist peer by peerid +
+ operationId: PeerController.Blacklist + parameters: + - in: path + name: id + description: the peer id you want to blacklist + required: true + type: string + responses: + "200": + description: '{peer} models.peer' /extended/search: - get: + post: tags: - oc-peer/controllersPeerController description: |- @@ -146,11 +112,6 @@ paths:
operationId: PeerController.Search parameters: - - in: path - name: search - description: the word search you want to get - required: true - type: string - in: query name: is_draft description: "false" @@ -163,9 +124,49 @@ paths: name: limit description: "false" type: string + - in: body + name: data + description: body for data content (Json format) + required: true + schema: + $ref: '#/definitions/json' responses: "200": description: '{workspace} models.workspace' + /known/{id}: + post: + tags: + - oc-peer/controllersPeerController + description: |- + add kwown peer by peerid +
+ operationId: PeerController.known + parameters: + - in: path + name: id + description: the peer id you want to blacklist + required: true + type: string + responses: + "200": + description: '{peer} models.peer' + /partner/{id}: + post: + tags: + - oc-peer/controllersPeerController + description: |- + add partner peer by peerid +
+ operationId: PeerController.Partner + parameters: + - in: path + name: id + description: the peer id you want to blacklist + required: true + type: string + responses: + "200": + description: '{peer} models.peer' /search/{search}: get: tags: @@ -241,6 +242,9 @@ paths: "200": description: "" definitions: + json: + title: json + type: object list: title: list type: object