]> granicus.if.org Git - icinga2/blob - lib/icinga/usergroup.cpp
Refactor logging code
[icinga2] / lib / icinga / usergroup.cpp
1 /******************************************************************************
2  * Icinga 2                                                                   *
3  * Copyright (C) 2012-2014 Icinga Development Team (http://www.icinga.org)    *
4  *                                                                            *
5  * This program is free software; you can redistribute it and/or              *
6  * modify it under the terms of the GNU General Public License                *
7  * as published by the Free Software Foundation; either version 2             *
8  * of the License, or (at your option) any later version.                     *
9  *                                                                            *
10  * This program is distributed in the hope that it will be useful,            *
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of             *
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the              *
13  * GNU General Public License for more details.                               *
14  *                                                                            *
15  * You should have received a copy of the GNU General Public License          *
16  * along with this program; if not, write to the Free Software Foundation     *
17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.             *
18  ******************************************************************************/
19
20 #include "icinga/usergroup.hpp"
21 #include "config/objectrule.hpp"
22 #include "base/dynamictype.hpp"
23 #include "base/objectlock.hpp"
24 #include "base/logger.hpp"
25 #include "base/context.hpp"
26 #include "base/workqueue.hpp"
27 #include <boost/foreach.hpp>
28
29 using namespace icinga;
30
31 REGISTER_TYPE(UserGroup);
32
33 INITIALIZE_ONCE(&UserGroup::RegisterObjectRuleHandler);
34
35 void UserGroup::RegisterObjectRuleHandler(void)
36 {
37         ObjectRule::RegisterType("UserGroup", &UserGroup::EvaluateObjectRules);
38 }
39
40 bool UserGroup::EvaluateObjectRuleOne(const User::Ptr& user, const ObjectRule& rule)
41 {
42         DebugInfo di = rule.GetDebugInfo();
43
44         std::ostringstream msgbuf;
45         msgbuf << "Evaluating 'object' rule (" << di << ")";
46         CONTEXT(msgbuf.str());
47
48         Dictionary::Ptr locals = make_shared<Dictionary>();
49         locals->Set("user", user);
50
51         if (!rule.EvaluateFilter(locals))
52                 return false;
53
54         Log(LogDebug, "UserGroup")
55             << "Assigning membership for group '" << rule.GetName() << "' to user '" << user->GetName() << "' for rule " << di;
56
57         String group_name = rule.GetName();
58         UserGroup::Ptr group = UserGroup::GetByName(group_name);
59
60         if (!group) {
61                 Log(LogCritical, "UserGroup")
62                     << "Invalid membership assignment. Group '" << group_name << "' does not exist.";
63                 return false;
64         }
65
66         /* assign user group membership */
67         group->ResolveGroupMembership(user, true);
68
69         /* update groups attribute for apply */
70         user->AddGroup(group_name);
71
72         return true;
73 }
74
75 void UserGroup::EvaluateObjectRule(const ObjectRule& rule)
76 {
77         BOOST_FOREACH(const User::Ptr& user, DynamicType::GetObjectsByType<User>()) {
78                 CONTEXT("Evaluating group membership in '" + rule.GetName() + "' for user '" + user->GetName() + "'");
79
80                 EvaluateObjectRuleOne(user, rule);
81         }
82 }
83
84 void UserGroup::EvaluateObjectRules(const std::vector<ObjectRule>& rules)
85 {
86         ParallelWorkQueue upq;
87
88         BOOST_FOREACH(const ObjectRule& rule, rules) {
89                 upq.Enqueue(boost::bind(UserGroup::EvaluateObjectRule, boost::cref(rule)));
90         }
91
92         upq.Join();
93 }
94
95 std::set<User::Ptr> UserGroup::GetMembers(void) const
96 {
97         boost::mutex::scoped_lock lock(m_UserGroupMutex);
98         return m_Members;
99 }
100
101 void UserGroup::AddMember(const User::Ptr& user)
102 {
103         boost::mutex::scoped_lock lock(m_UserGroupMutex);
104         m_Members.insert(user);
105 }
106
107 void UserGroup::RemoveMember(const User::Ptr& user)
108 {
109         boost::mutex::scoped_lock lock(m_UserGroupMutex);
110         m_Members.erase(user);
111 }
112
113 bool UserGroup::ResolveGroupMembership(User::Ptr const& user, bool add, int rstack) {
114
115         if (add && rstack > 20) {
116                 Log(LogWarning, "UserGroup")
117                     << "Too many nested groups for group '" << GetName() << "': User '"
118                     << user->GetName() << "' membership assignment failed.";
119
120                 return false;
121         }
122
123         Array::Ptr groups = GetGroups();
124
125         if (groups && groups->GetLength() > 0) {
126                 ObjectLock olock(groups);
127
128                 BOOST_FOREACH(const String& name, groups) {
129                         UserGroup::Ptr group = UserGroup::GetByName(name);
130
131                         if (group && !group->ResolveGroupMembership(user, add, rstack + 1))
132                                 return false;
133                 }
134         }
135
136         if (add)
137                 AddMember(user);
138         else
139                 RemoveMember(user);
140
141         return true;
142 }
143