1 /*
2    Drawpile - a collaborative drawing program.
3 
4    Copyright (C) 2015-2018 Calle Laakkonen
5 
6    Drawpile is free software: you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation, either version 3 of the License, or
9    (at your option) any later version.
10 
11    Drawpile is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15 
16    You should have received a copy of the GNU General Public License
17    along with Drawpile.  If not, see <http://www.gnu.org/licenses/>.
18 */
19 
20 #ifndef ACLFILTER_H
21 #define ACLFILTER_H
22 
23 #include "features.h"
24 
25 #include <QObject>
26 #include <QHash>
27 #include <QSet>
28 #include <bitset>
29 
30 namespace protocol {
31 	class Message;
32 	class SessionOwner;
33 	class TrustedUsers;
34 }
35 
36 namespace canvas {
37 
38 class UserSet {
39 public:
40 	UserSet() = default;
41 
contains(uint8_t id)42 	bool contains(uint8_t id) const { return m_users[id]; }
set(uint8_t id)43 	void set(uint8_t id) { m_users[id] = true; }
unset(uint8_t id)44 	bool unset(uint8_t id) { bool wasSet = m_users[id]; m_users[id] = false; return wasSet; }
reset()45 	void reset() { m_users.reset(); }
46 
setFromList(const QList<uint8_t> ids)47 	void setFromList(const QList<uint8_t> ids) {
48 		m_users.reset();
49 		for(int i=0;i<ids.size();++i)
50 			m_users[ids[i]] = true;
51 	}
52 
toList()53 	QList<uint8_t> toList() const {
54 		QList<uint8_t> lst;
55 		for(int i=0;i<256;++i)
56 			if(m_users[i])
57 				lst << i;
58 		return lst;
59 	}
60 
61 private:
62 	std::bitset<256> m_users;
63 };
64 
65 class AclFilter : public QObject
66 {
67 	Q_OBJECT
68 public:
69 	struct LayerAcl {
70 		bool locked;              // layer is locked for all users
71 		Tier tier;                // layer access tier (if not exclusive)
72 		QList<uint8_t> exclusive; // if not empty, only these users can draw on this layer
73 	};
74 
75 	explicit AclFilter(QObject *parent=nullptr);
76 	AclFilter *clone(QObject *newParent=nullptr) const;
77 
78 	//! Reset all access controls
79 	void reset(uint8_t myId, bool localMode);
80 
81 	//! Go online mode: refresh status bits
82 	void setOnlineMode(uint8_t myId);
83 
84 	/**
85 	 * @brief Filter a message
86 	 *
87 	 * This will also update the filter state.
88 	 *
89 	 * @param msg the message
90 	 * @return false if message must be dropped
91 	 */
92 	bool filterMessage(const protocol::Message &msg);
93 
94 	//! Does the local user have operator privileges?
isLocalUserOperator()95 	bool isLocalUserOperator() const { return m_isOperator; }
96 
97 	//! Has the local user been tagged as trusted?
isLocalUserTrusted()98 	bool isLocalUserTrusted() const { return m_isTrusted; }
99 
100 	//! Is there a general session lock in place?
isSessionLocked()101 	bool isSessionLocked() const { return m_sessionLocked; }
102 
103 	//! Has the local user been locked individually?
isLocalUserLocked()104 	bool isLocalUserLocked() const { return m_localUserLocked; }
105 
106 	//! Is the local user locked for any reason?
isLocked()107 	bool isLocked() const { return m_sessionLocked | m_localUserLocked; }
108 
109 	//! Check if the local user can draw on the given layer
isLayerLocked(int layerId)110 	bool isLayerLocked(int layerId) const {
111 		return isLocked() || isLayerLockedFor(layerId, m_myId, userTier(m_myId));
112 	}
113 
114 	//! Can the local user use this feature?
canUseFeature(Feature f)115 	bool canUseFeature(Feature f) const { return localUserTier() <= featureTier(f); }
116 
117 	//! Get the local user's feature access tier
localUserTier()118 	Tier localUserTier() const { return userTier(m_myId); }
119 
120 	//! Get the given feature's access tier
featureTier(Feature f)121 	Tier featureTier(Feature f) const { Q_ASSERT(int(f)>=0 && int(f) < FeatureCount); return m_featureTiers[int(f)]; }
122 
123 	/**
124 	 * @brief Get the access controls for an individual layer
125 	 * If the layer has not been configured, an unlocked set will be returned.
126 	 */
127 	LayerAcl layerAcl(int id) const;
128 
129 	//! Get the list of locked users
lockedUsers()130 	QList<uint8_t> lockedUsers() const { return m_userlocks.toList(); }
131 
132 signals:
133 	void localOpChanged(bool op);
134 	void localLockChanged(bool lock);
135 	void layerAclChanged(int id);
136 
137 	void userLocksChanged(const QList<uint8_t> lockedUsers);
138 	void operatorListChanged(const QList<uint8_t> opUsers);
139 	void trustedUserListChanged(const QList<uint8_t> trustedUsers);
140 
141 	//! The local user's access to a feature just changed
142 	void featureAccessChanged(Feature feature, bool canUse);
143 
144 	//! A feature's access tier was changed
145 	void featureTierChanged(Feature feature, Tier tier);
146 
147 private:
148 	void setOperator(bool op);
149 	void setTrusted(bool trusted);
150 	void setSessionLock(bool lock);
151 	void setUserLock(bool lock);
152 	void setLockByDefault(bool lock);
153 	void setFeature(Feature feature, Tier tier);
154 
155 	void updateSessionOwnership(const protocol::SessionOwner &msg);
156 	void updateTrustedUserList(const protocol::TrustedUsers &msg);
157 
158 	bool isLayerLockedFor(int layerId, uint8_t userId, Tier userTier) const;
159 
userTier(int id)160 	Tier userTier(int id) const {
161 		if(id == 0) // only the server can use ID 0
162 			return Tier::Op;
163 		if(m_ops.contains(id))
164 			return Tier::Op;
165 		if(m_trusted.contains(id))
166 			return Tier::Trusted;
167 		if(m_auth.contains(id))
168 			return Tier::Auth;
169 		return Tier::Guest;
170 	}
171 
172 	int m_myId = 1;                 // the ID of the local user
173 
174 	bool m_isOperator = false;      // is the local user an operator?
175 	bool m_isTrusted = false;       // does the local user have trusted status?
176 	bool m_sessionLocked = false;   // is the session locked?
177 	bool m_localUserLocked = false; // is the local user locked individually?
178 
179 	QHash<int,LayerAcl> m_layers;          // layer access controls
180 	UserSet m_ops;                         // list of operators
181 	UserSet m_trusted;                     // list of trusted users
182 	UserSet m_auth;                        // list of registered users
183 	UserSet m_userlocks;                   // list of individually locked users
184 	QSet<uint16_t> m_protectedAnnotations; // list of protected annotations
185 	Tier m_featureTiers[FeatureCount] = {Tier::Guest}; // feature access tiers
186 };
187 
188 }
189 
190 #endif // ACLFILTER_H
191