package infrastructure import ( "context" "encoding/json" "errors" "time" oclib "cloud.o-forge.io/core/oc-lib" "cloud.o-forge.io/core/oc-lib/dbs" "cloud.o-forge.io/core/oc-lib/models/peer" "cloud.o-forge.io/core/oc-lib/models/resources" "cloud.o-forge.io/core/oc-lib/tools" ) func (ps *PubSubService) searchResponsePublishEvent( ctx context.Context, dt *tools.DataType, user string, peerID string, payload []byte, ) error { return ps.publishEvent(ctx, dt, SEARCH_RESPONSE, user, peerID, payload, true) } func (ps *PubSubService) SearchPublishEvent( ctx context.Context, dt *tools.DataType, typ string, user string, search string, ) error { switch typ { case "partner": ps.searchPartnersPublishEvent( ctx, dt, user, search, ) case "all": b, err := json.Marshal(map[string]string{ "search": search, }) if err != nil { return err } ps.searchPublishEvent( ctx, dt, user, "", b, ) case "known": ps.searchKnownPublishEvent( ctx, dt, user, search, ) default: return errors.New("no type of research found") } return nil } func (ps *PubSubService) searchPartnersPublishEvent( ctx context.Context, dt *tools.DataType, user string, search string, ) error { access := oclib.NewRequestAdmin(oclib.LibDataEnum(oclib.PEER), "", "", []string{}, nil) f := &dbs.Filters{ And: map[string][]dbs.Filter{ // search by name if no filters are provided "state": {{Operator: dbs.EQUAL.String(), Value: peer.ONLINE.EnumIndex()}}, "relation": {{Operator: dbs.EQUAL.String(), Value: peer.PARTNER.EnumIndex()}}, }, } if search != "" { f.Or = map[string][]dbs.Filter{ // filter by like name, short_description, description, owner, url if no filters are provided "abstractintanciatedresource.abstractresource.abstractobject.name": {{Operator: dbs.LIKE.String(), Value: search}}, "abstractintanciatedresource.abstractresource.type": {{Operator: dbs.LIKE.String(), Value: search}}, "abstractintanciatedresource.abstractresource.short_description": {{Operator: dbs.LIKE.String(), Value: search}}, "abstractintanciatedresource.abstractresource.description": {{Operator: dbs.LIKE.String(), Value: search}}, "abstractintanciatedresource.abstractresource.owners.name": {{Operator: dbs.LIKE.String(), Value: search}}, "abstractintanciatedresource.abstractresource.abstractobject.creator_id": {{Operator: dbs.EQUAL.String(), Value: search}}, } } b, err := json.Marshal(map[string]string{ "search": search, }) if err != nil { return err } peersKnown := access.Search(f, "", false) for _, known := range peersKnown.Data { if err := ps.searchPublishEvent(ctx, dt, user, known.GetID(), b); err != nil { return err } } return nil } func (ps *PubSubService) searchKnownPublishEvent( ctx context.Context, dt *tools.DataType, user string, search string, ) error { access := oclib.NewRequestAdmin(oclib.LibDataEnum(oclib.PEER), "", "", []string{}, nil) f := &dbs.Filters{ And: map[string][]dbs.Filter{ // search by name if no filters are provided "state": {{Operator: dbs.EQUAL.String(), Value: peer.ONLINE.EnumIndex()}}, "relation": {{Operator: dbs.NOT.String(), Value: &dbs.Filters{ And: map[string][]dbs.Filter{ "relation": {{Operator: dbs.EQUAL.String(), Value: peer.BLACKLIST.EnumIndex()}}, }, }}}, }, } if search != "" { f.Or = map[string][]dbs.Filter{ // filter by like name, short_description, description, owner, url if no filters are provided "abstractintanciatedresource.abstractresource.abstractobject.name": {{Operator: dbs.LIKE.String(), Value: search}}, "abstractintanciatedresource.abstractresource.type": {{Operator: dbs.LIKE.String(), Value: search}}, "abstractintanciatedresource.abstractresource.short_description": {{Operator: dbs.LIKE.String(), Value: search}}, "abstractintanciatedresource.abstractresource.description": {{Operator: dbs.LIKE.String(), Value: search}}, "abstractintanciatedresource.abstractresource.owners.name": {{Operator: dbs.LIKE.String(), Value: search}}, "abstractintanciatedresource.abstractresource.abstractobject.creator_id": {{Operator: dbs.EQUAL.String(), Value: search}}, } } b, err := json.Marshal(map[string]string{ "search": search, }) if err != nil { return err } peersKnown := access.Search(f, "", false) for _, known := range peersKnown.Data { if err := ps.searchPublishEvent(ctx, dt, user, known.GetID(), b); err != nil { return err } } return nil } func (ps *PubSubService) searchPublishEvent( ctx context.Context, dt *tools.DataType, user string, peerID string, payload []byte, ) error { id, err := oclib.GenerateNodeID() if err != nil { return err } ps.SearchStream[user] = make(chan resources.ResourceInterface, 128) // set up the searchStream if err := ps.subscribeEvents(ctx, dt, SEARCH_RESPONSE, id, 60); err != nil { // TODO Catpure Event ! return err } return ps.publishEvent(ctx, dt, SEARCH, user, peerID, payload, false) } func (ps *PubSubService) CreatePublishEvent( ctx context.Context, dt *tools.DataType, user string, payload []byte, ) error { id, err := oclib.GenerateNodeID() if err != nil { return err } return ps.publishEvent(ctx, dt, CREATE, user, id, payload, false) } func (ps *PubSubService) UpdatePublishEvent( ctx context.Context, dt *tools.DataType, user string, payload []byte, ) error { id, err := oclib.GenerateNodeID() if err != nil { return err } return ps.publishEvent(ctx, dt, UPDATE, user, id, payload, false) } func (ps *PubSubService) DeletePublishEvent( ctx context.Context, dt *tools.DataType, user string, payload []byte, ) error { id, err := oclib.GenerateNodeID() if err != nil { return err } return ps.publishEvent(ctx, dt, DELETE, user, id, payload, false) } func (ps *PubSubService) publishEvent( ctx context.Context, dt *tools.DataType, action PubSubAction, user string, peerID string, payload []byte, chanNamedByDt bool, ) error { name := "oc-catalog." + action.String() + "#" + peerID if chanNamedByDt && dt != nil { // if a datatype is precised then : app.action.datatype#peerID name = "oc-catalog." + action.String() + "." + (*dt).String() + "#" + peerID } from, err := oclib.GenerateNodeID() if err != nil { return err } evt := Event{ Type: name, From: from, User: user, Timestamp: time.Now().Unix(), Payload: payload, } if dt != nil { evt.DataType = int64(dt.EnumIndex()) } else { evt.DataType = -1 } body, _ := json.Marshal(evt) priv, err := LoadKeyFromFile(false) if err != nil { return err } sig, _ := priv.Sign(body) evt.Signature = sig msg, _ := json.Marshal(evt) topic, err := ps.PS.Join(name) if err != nil { return err } return topic.Publish(ctx, msg) } // TODO REVIEW PUBLISHING + ADD SEARCH ON PUBLIC : YES // TODO : Search should verify DataType