1/*
2 *    Copyright (C) 2014-2017 Christian Muehlhaeuser
3 *
4 *    This program is free software: you can redistribute it and/or modify
5 *    it under the terms of the GNU Affero General Public License as published
6 *    by the Free Software Foundation, either version 3 of the License, or
7 *    (at your option) any later version.
8 *
9 *    This program is distributed in the hope that it will be useful,
10 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
11 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 *    GNU Affero General Public License for more details.
13 *
14 *    You should have received a copy of the GNU Affero General Public License
15 *    along with this program.  If not, see <http://www.gnu.org/licenses/>.
16 *
17 *    Authors:
18 *      Christian Muehlhaeuser <muesli@gmail.com>
19 */
20
21// Package bees is Beehive's central module system.
22package bees
23
24import log "github.com/sirupsen/logrus"
25
26// ChainElement is an element in a Chain
27type ChainElement struct {
28	Action Action
29	Filter Filter
30}
31
32// Chain is a user defined chain
33type Chain struct {
34	Name        string
35	Description string
36	Event       *Event
37	Filters     []string
38	Actions     []string
39	Elements    []ChainElement `json:"Elements,omitempty"`
40}
41
42var (
43	chains []Chain
44)
45
46// GetChains returns all chains
47func GetChains() []Chain {
48	return chains
49}
50
51// GetChain returns a chain with a specific id
52func GetChain(id string) *Chain {
53	for _, c := range chains {
54		if c.Name == id {
55			return &c
56		}
57	}
58
59	return nil
60}
61
62// SetChains sets the currently configured chains
63func SetChains(cs []Chain) {
64	newcs := []Chain{}
65	// migrate old chain style
66	for _, c := range cs {
67		for _, el := range c.Elements {
68			if el.Action.Name != "" {
69				el.Action.ID = UUID()
70				c.Actions = append(c.Actions, el.Action.ID)
71				actions = append(actions, el.Action)
72			}
73			if el.Filter.Name != "" {
74				//FIXME: migrate old style filters
75				c.Filters = append(c.Filters, el.Filter.Options.Value.(string))
76			}
77		}
78		c.Elements = []ChainElement{}
79
80		newcs = append(newcs, c)
81	}
82
83	chains = newcs
84}
85
86// execChains executes chains for an event we received
87func execChains(event *Event) {
88	for _, c := range chains {
89		if c.Event.Name != event.Name || c.Event.Bee != event.Bee {
90			continue
91		}
92
93		m := make(map[string]interface{})
94		for _, opt := range event.Options {
95			m[opt.Name] = opt.Value
96		}
97		ctx.FillMap(m)
98
99		failed := false
100		log.Debugln("Executing chain:", c.Name, "-", c.Description)
101		for _, el := range c.Filters {
102			if execFilter(el, m) {
103				log.Debugln("\t\tPassed filter!")
104			} else {
105				log.Debugln("\t\tDid not pass filter!")
106				failed = true
107				break
108			}
109		}
110		if failed {
111			continue
112		}
113
114		for _, el := range c.Actions {
115			action := GetAction(el)
116			if action == nil {
117				log.Println("\t\tERROR: Unknown action referenced!")
118				continue
119			}
120			execAction(*action, m)
121		}
122	}
123}
124