1 | /* |
2 | * Copyright 2004-2014 H2 Group. Multiple-Licensed under the MPL 2.0, |
3 | * and the EPL 1.0 (http://h2database.com/html/license.html). |
4 | * Initial Developer: H2 Group |
5 | */ |
6 | package org.h2.command.ddl; |
7 | |
8 | import java.util.ArrayList; |
9 | |
10 | import org.h2.api.ErrorCode; |
11 | import org.h2.command.CommandInterface; |
12 | import org.h2.engine.Database; |
13 | import org.h2.engine.Right; |
14 | import org.h2.engine.RightOwner; |
15 | import org.h2.engine.Role; |
16 | import org.h2.engine.Session; |
17 | import org.h2.message.DbException; |
18 | import org.h2.table.Table; |
19 | import org.h2.util.New; |
20 | |
21 | /** |
22 | * This class represents the statements |
23 | * GRANT RIGHT, |
24 | * GRANT ROLE, |
25 | * REVOKE RIGHT, |
26 | * REVOKE ROLE |
27 | */ |
28 | public class GrantRevoke extends DefineCommand { |
29 | |
30 | private ArrayList<String> roleNames; |
31 | private int operationType; |
32 | private int rightMask; |
33 | private final ArrayList<Table> tables = New.arrayList(); |
34 | private RightOwner grantee; |
35 | |
36 | public GrantRevoke(Session session) { |
37 | super(session); |
38 | } |
39 | |
40 | public void setOperationType(int operationType) { |
41 | this.operationType = operationType; |
42 | } |
43 | |
44 | /** |
45 | * Add the specified right bit to the rights bitmap. |
46 | * |
47 | * @param right the right bit |
48 | */ |
49 | public void addRight(int right) { |
50 | this.rightMask |= right; |
51 | } |
52 | |
53 | /** |
54 | * Add the specified role to the list of roles. |
55 | * |
56 | * @param roleName the role |
57 | */ |
58 | public void addRoleName(String roleName) { |
59 | if (roleNames == null) { |
60 | roleNames = New.arrayList(); |
61 | } |
62 | roleNames.add(roleName); |
63 | } |
64 | |
65 | public void setGranteeName(String granteeName) { |
66 | Database db = session.getDatabase(); |
67 | grantee = db.findUser(granteeName); |
68 | if (grantee == null) { |
69 | grantee = db.findRole(granteeName); |
70 | if (grantee == null) { |
71 | throw DbException.get(ErrorCode.USER_OR_ROLE_NOT_FOUND_1, granteeName); |
72 | } |
73 | } |
74 | } |
75 | |
76 | @Override |
77 | public int update() { |
78 | session.getUser().checkAdmin(); |
79 | session.commit(true); |
80 | Database db = session.getDatabase(); |
81 | if (roleNames != null) { |
82 | for (String name : roleNames) { |
83 | Role grantedRole = db.findRole(name); |
84 | if (grantedRole == null) { |
85 | throw DbException.get(ErrorCode.ROLE_NOT_FOUND_1, name); |
86 | } |
87 | if (operationType == CommandInterface.GRANT) { |
88 | grantRole(grantedRole); |
89 | } else if (operationType == CommandInterface.REVOKE) { |
90 | revokeRole(grantedRole); |
91 | } else { |
92 | DbException.throwInternalError("type=" + operationType); |
93 | } |
94 | } |
95 | } else { |
96 | if (operationType == CommandInterface.GRANT) { |
97 | grantRight(); |
98 | } else if (operationType == CommandInterface.REVOKE) { |
99 | revokeRight(); |
100 | } else { |
101 | DbException.throwInternalError("type=" + operationType); |
102 | } |
103 | } |
104 | return 0; |
105 | } |
106 | |
107 | private void grantRight() { |
108 | Database db = session.getDatabase(); |
109 | for (Table table : tables) { |
110 | Right right = grantee.getRightForTable(table); |
111 | if (right == null) { |
112 | int id = getObjectId(); |
113 | right = new Right(db, id, grantee, rightMask, table); |
114 | grantee.grantRight(table, right); |
115 | db.addDatabaseObject(session, right); |
116 | } else { |
117 | right.setRightMask(right.getRightMask() | rightMask); |
118 | db.updateMeta(session, right); |
119 | } |
120 | } |
121 | } |
122 | |
123 | private void grantRole(Role grantedRole) { |
124 | if (grantedRole != grantee && grantee.isRoleGranted(grantedRole)) { |
125 | return; |
126 | } |
127 | if (grantee instanceof Role) { |
128 | Role granteeRole = (Role) grantee; |
129 | if (grantedRole.isRoleGranted(granteeRole)) { |
130 | // cyclic role grants are not allowed |
131 | throw DbException.get(ErrorCode.ROLE_ALREADY_GRANTED_1, grantedRole.getSQL()); |
132 | } |
133 | } |
134 | Database db = session.getDatabase(); |
135 | int id = getObjectId(); |
136 | Right right = new Right(db, id, grantee, grantedRole); |
137 | db.addDatabaseObject(session, right); |
138 | grantee.grantRole(grantedRole, right); |
139 | } |
140 | |
141 | private void revokeRight() { |
142 | for (Table table : tables) { |
143 | Right right = grantee.getRightForTable(table); |
144 | if (right == null) { |
145 | continue; |
146 | } |
147 | int mask = right.getRightMask(); |
148 | int newRight = mask & ~rightMask; |
149 | Database db = session.getDatabase(); |
150 | if (newRight == 0) { |
151 | db.removeDatabaseObject(session, right); |
152 | } else { |
153 | right.setRightMask(newRight); |
154 | db.updateMeta(session, right); |
155 | } |
156 | } |
157 | } |
158 | |
159 | private void revokeRole(Role grantedRole) { |
160 | Right right = grantee.getRightForRole(grantedRole); |
161 | if (right == null) { |
162 | return; |
163 | } |
164 | Database db = session.getDatabase(); |
165 | db.removeDatabaseObject(session, right); |
166 | } |
167 | |
168 | @Override |
169 | public boolean isTransactional() { |
170 | return false; |
171 | } |
172 | |
173 | /** |
174 | * Add the specified table to the list of tables. |
175 | * |
176 | * @param table the table |
177 | */ |
178 | public void addTable(Table table) { |
179 | tables.add(table); |
180 | } |
181 | |
182 | @Override |
183 | public int getType() { |
184 | return operationType; |
185 | } |
186 | |
187 | /** |
188 | * @return true if this command is using Roles |
189 | */ |
190 | public boolean isRoleMode() { |
191 | return roleNames != null; |
192 | } |
193 | |
194 | /** |
195 | * @return true if this command is using Rights |
196 | */ |
197 | public boolean isRightMode() { |
198 | return rightMask != 0; |
199 | } |
200 | } |