001
014
015 package com.liferay.portal.security.permission;
016
017 import com.liferay.portal.kernel.util.ArrayUtil;
018 import com.liferay.portal.kernel.util.CharPool;
019 import com.liferay.portal.kernel.util.StringBundler;
020 import com.liferay.portal.kernel.util.StringPool;
021 import com.liferay.portal.kernel.util.StringUtil;
022 import com.liferay.portal.kernel.util.Validator;
023 import com.liferay.portal.model.ResourceConstants;
024 import com.liferay.portal.service.ResourceBlockLocalServiceUtil;
025 import com.liferay.portal.service.ResourceTypePermissionLocalServiceUtil;
026 import com.liferay.portal.util.PropsValues;
027 import com.liferay.util.dao.orm.CustomSQLUtil;
028
029 import java.util.HashSet;
030 import java.util.Set;
031
032
036 public class InlineSQLHelperImpl implements InlineSQLHelper {
037
038 public static final String FILTER_BY_RESOURCE_BLOCK_ID =
039 InlineSQLHelper.class.getName() + ".filterByResourceBlockId";
040
041 public static final String FILTER_BY_RESOURCE_BLOCK_ID_OWNER =
042 InlineSQLHelper.class.getName() + ".filterByResourceBlockIdOwner";
043
044 public static final String JOIN_RESOURCE_PERMISSION =
045 InlineSQLHelper.class.getName() + ".joinResourcePermission";
046
047 public boolean isEnabled() {
048 return isEnabled(0);
049 }
050
051 public boolean isEnabled(long groupId) {
052 if (PropsValues.PERMISSIONS_USER_CHECK_ALGORITHM != 6) {
053 return false;
054 }
055
056 if (!PropsValues.PERMISSIONS_INLINE_SQL_CHECK_ENABLED) {
057 return false;
058 }
059
060 PermissionChecker permissionChecker =
061 PermissionThreadLocal.getPermissionChecker();
062
063 if (permissionChecker == null) {
064 return false;
065 }
066
067 if (groupId > 0) {
068 if (permissionChecker.isGroupAdmin(groupId) ||
069 permissionChecker.isGroupOwner(groupId)) {
070
071 return false;
072 }
073 }
074 else {
075 if (permissionChecker.isCompanyAdmin()) {
076 return false;
077 }
078 }
079
080 return true;
081 }
082
083 public boolean isEnabled(long[] groupIds) {
084 if (PropsValues.PERMISSIONS_USER_CHECK_ALGORITHM != 6) {
085 return false;
086 }
087
088 if (!PropsValues.PERMISSIONS_INLINE_SQL_CHECK_ENABLED) {
089 return false;
090 }
091
092 for (long groupId : groupIds) {
093 if (isEnabled(groupId)) {
094 return true;
095 }
096 }
097
098 return false;
099 }
100
101 public String replacePermissionCheck(
102 String sql, String className, String classPKField) {
103
104 return replacePermissionCheck(
105 sql, className, classPKField, null, new long[] {0}, null);
106 }
107
108 public String replacePermissionCheck(
109 String sql, String className, String classPKField, long groupId) {
110
111 return replacePermissionCheck(
112 sql, className, classPKField, null, new long[] {groupId}, null);
113 }
114
115 public String replacePermissionCheck(
116 String sql, String className, String classPKField, long groupId,
117 String bridgeJoin) {
118
119 return replacePermissionCheck(
120 sql, className, classPKField, null, new long[] {groupId},
121 bridgeJoin);
122 }
123
124 public String replacePermissionCheck(
125 String sql, String className, String classPKField, long[] groupIds) {
126
127 return replacePermissionCheck(
128 sql, className, classPKField, null, groupIds, null);
129 }
130
131 public String replacePermissionCheck(
132 String sql, String className, String classPKField, long[] groupIds,
133 String bridgeJoin) {
134
135 return replacePermissionCheck(
136 sql, className, classPKField, null, groupIds, bridgeJoin);
137 }
138
139 public String replacePermissionCheck(
140 String sql, String className, String classPKField, String userIdField) {
141
142 return replacePermissionCheck(
143 sql, className, classPKField, userIdField, new long[] {0}, null);
144 }
145
146 public String replacePermissionCheck(
147 String sql, String className, String classPKField, String userIdField,
148 long groupId) {
149
150 return replacePermissionCheck(
151 sql, className, classPKField, userIdField, new long[] {groupId},
152 null);
153 }
154
155 public String replacePermissionCheck(
156 String sql, String className, String classPKField, String userIdField,
157 long groupId, String bridgeJoin) {
158
159 return replacePermissionCheck(
160 sql, className, classPKField, userIdField, new long[] {groupId},
161 bridgeJoin);
162 }
163
164 public String replacePermissionCheck(
165 String sql, String className, String classPKField, String userIdField,
166 long[] groupIds) {
167
168 return replacePermissionCheck(
169 sql, className, classPKField, userIdField, groupIds, null);
170 }
171
172 public String replacePermissionCheck(
173 String sql, String className, String classPKField, String userIdField,
174 long[] groupIds, String bridgeJoin) {
175
176 if (!isEnabled(groupIds)) {
177 return sql;
178 }
179
180 if (Validator.isNull(className)) {
181 throw new IllegalArgumentException("className is null");
182 }
183
184 if (Validator.isNull(sql)) {
185 return sql;
186 }
187
188 if (ResourceBlockLocalServiceUtil.isSupported(className)) {
189 return replacePermissionCheckBlocks(
190 sql, className, classPKField, userIdField, groupIds,
191 bridgeJoin);
192 }
193 else {
194 return replacePermissionCheckJoin(
195 sql, className, classPKField, userIdField, groupIds,
196 bridgeJoin);
197 }
198 }
199
200 public String replacePermissionCheck(
201 String sql, String className, String classPKField, String userIdField,
202 String bridgeJoin) {
203
204 return replacePermissionCheck(
205 sql, className, classPKField, userIdField, 0, bridgeJoin);
206 }
207
208 protected Set<Long> getOwnerResourceBlockIds(
209 long companyId, long[] groupIds, String className) {
210
211 Set<Long> resourceBlockIds = new HashSet<Long>();
212
213 PermissionChecker permissionChecker =
214 PermissionThreadLocal.getPermissionChecker();
215
216 for (long groupId : groupIds) {
217 resourceBlockIds.addAll(
218 permissionChecker.getOwnerResourceBlockIds(
219 companyId, groupId, className, ActionKeys.VIEW));
220 }
221
222 return resourceBlockIds;
223 }
224
225 protected Set<Long> getResourceBlockIds(
226 long companyId, long[] groupIds, String className) {
227
228 Set<Long> resourceBlockIds = new HashSet<Long>();
229
230 PermissionChecker permissionChecker =
231 PermissionThreadLocal.getPermissionChecker();
232
233 for (long groupId : groupIds) {
234 resourceBlockIds.addAll(
235 permissionChecker.getResourceBlockIds(
236 companyId, groupId, permissionChecker.getUserId(), className,
237 ActionKeys.VIEW));
238 }
239
240 return resourceBlockIds;
241 }
242
243 protected long[] getRoleIds(long groupId) {
244 long[] roleIds = PermissionChecker.DEFAULT_ROLE_IDS;
245
246 PermissionChecker permissionChecker =
247 PermissionThreadLocal.getPermissionChecker();
248
249 if (permissionChecker != null) {
250 roleIds = permissionChecker.getRoleIds(
251 permissionChecker.getUserId(), groupId);
252 }
253
254 return roleIds;
255 }
256
257 protected long[] getRoleIds(long[] groupIds) {
258 long[] roleIds = PermissionChecker.DEFAULT_ROLE_IDS;
259
260 for (long groupId : groupIds) {
261 for (long roleId : getRoleIds(groupId)) {
262 if (!ArrayUtil.contains(roleIds, roleId)) {
263 roleIds = ArrayUtil.append(roleIds, roleId);
264 }
265 }
266 }
267
268 return roleIds;
269 }
270
271 protected long getUserId() {
272 long userId = 0;
273
274 PermissionChecker permissionChecker =
275 PermissionThreadLocal.getPermissionChecker();
276
277 if (permissionChecker != null) {
278 userId = permissionChecker.getUserId();
279 }
280
281 return userId;
282 }
283
284 protected String replacePermissionCheckBlocks(
285 String sql, String className, String classPKField, String userIdField,
286 long[] groupIds, String bridgeJoin) {
287
288 PermissionChecker permissionChecker =
289 PermissionThreadLocal.getPermissionChecker();
290
291 long checkGroupId = 0;
292
293 if (groupIds.length == 1) {
294 checkGroupId = groupIds[0];
295 }
296
297 long companyId = permissionChecker.getCompanyId();
298
299 long[] roleIds = permissionChecker.getRoleIds(
300 getUserId(), checkGroupId);
301
302 try {
303 for (long roleId : roleIds) {
304 if (ResourceTypePermissionLocalServiceUtil.
305 hasCompanyScopePermission(
306 companyId, className, roleId, ActionKeys.VIEW)) {
307
308 return sql;
309 }
310 }
311 }
312 catch (Exception e) {
313 }
314
315 Set<Long> userResourceBlockIds = getResourceBlockIds(
316 companyId, groupIds, className);
317
318 String permissionWhere = StringPool.BLANK;
319
320 if (Validator.isNotNull(bridgeJoin)) {
321 permissionWhere = bridgeJoin;
322 }
323
324 Set<Long> ownerResourceBlockIds = getOwnerResourceBlockIds(
325 companyId, groupIds, className);
326
327
328
329
330 ownerResourceBlockIds.removeAll(userResourceBlockIds);
331
332
333
334
335 if (userResourceBlockIds.size() == 0) {
336 userResourceBlockIds.add(_NO_RESOURCE_BLOCKS_ID);
337 }
338
339 if (Validator.isNotNull(userIdField) &&
340 ownerResourceBlockIds.size() > 0) {
341
342 permissionWhere = permissionWhere.concat(
343 CustomSQLUtil.get(FILTER_BY_RESOURCE_BLOCK_ID_OWNER));
344
345 permissionWhere = StringUtil.replace(
346 permissionWhere,
347 new String[] {
348 "[$OWNER_RESOURCE_BLOCK_IDS$]",
349 "[$USER_ID$]",
350 "[$USER_ID_FIELD$]",
351 "[$USER_RESOURCE_BLOCK_IDS$]"
352 },
353 new String[] {
354 StringUtil.merge(ownerResourceBlockIds),
355 String.valueOf(permissionChecker.getUserId()),
356 userIdField,
357 StringUtil.merge(userResourceBlockIds)
358 });
359 }
360 else {
361 permissionWhere = permissionWhere.concat(
362 CustomSQLUtil.get(FILTER_BY_RESOURCE_BLOCK_ID));
363
364 permissionWhere = StringUtil.replace(
365 permissionWhere, "[$USER_RESOURCE_BLOCK_IDS$]",
366 StringUtil.merge(userResourceBlockIds));
367 }
368
369 int pos = sql.indexOf(_WHERE_CLAUSE);
370
371 if (pos != -1) {
372 StringBundler sb = new StringBundler(4);
373
374 sb.append(sql.substring(0, pos));
375 sb.append(permissionWhere);
376 sb.append(" AND ");
377 sb.append(sql.substring(pos + 7));
378
379 return sb.toString();
380 }
381
382 pos = sql.indexOf(_GROUP_BY_CLAUSE);
383
384 if (pos != -1) {
385 return sql.substring(0, pos + 1).concat(permissionWhere).concat(
386 sql.substring(pos + 1));
387 }
388
389 pos = sql.indexOf(_ORDER_BY_CLAUSE);
390
391 if (pos != -1) {
392 return sql.substring(0, pos + 1).concat(permissionWhere).concat(
393 sql.substring(pos + 1));
394 }
395
396 return sql.concat(StringPool.SPACE).concat(permissionWhere);
397 }
398
399 protected String replacePermissionCheckJoin(
400 String sql, String className, String classPKField, String userIdField,
401 long[] groupIds, String bridgeJoin) {
402
403 if (Validator.isNull(classPKField)) {
404 throw new IllegalArgumentException("classPKField is null");
405 }
406
407 PermissionChecker permissionChecker =
408 PermissionThreadLocal.getPermissionChecker();
409
410 long checkGroupId = 0;
411
412 if (groupIds.length == 1) {
413 checkGroupId = groupIds[0];
414 }
415
416 if (permissionChecker.hasPermission(
417 checkGroupId, className, 0, ActionKeys.VIEW)) {
418
419 return sql;
420 }
421
422 String permissionJoin = StringPool.BLANK;
423
424 if (Validator.isNotNull(bridgeJoin)) {
425 permissionJoin = bridgeJoin;
426 }
427
428 permissionJoin += CustomSQLUtil.get(JOIN_RESOURCE_PERMISSION);
429
430 StringBundler sb = new StringBundler();
431
432 sb.append("(InlineSQLResourcePermission.scope = ");
433 sb.append(ResourceConstants.SCOPE_INDIVIDUAL);
434 sb.append(" AND ");
435 sb.append("InlineSQLResourcePermission.primKey = CAST_TEXT(");
436 sb.append(classPKField);
437 sb.append(") AND (");
438
439 long userId = getUserId();
440
441 boolean hasPreviousViewableGroup = false;
442
443 for (int j = 0; j < groupIds.length; j++) {
444 long groupId = groupIds[j];
445
446 if (!permissionChecker.hasPermission(
447 groupId, className, 0, ActionKeys.VIEW)) {
448
449 if ((j > 0) && hasPreviousViewableGroup) {
450 sb.append(" OR ");
451 }
452
453 hasPreviousViewableGroup = true;
454
455 sb.append("(");
456 sb.append(
457 classPKField.substring(
458 0, classPKField.lastIndexOf(CharPool.PERIOD)));
459 sb.append(".groupId = ");
460 sb.append(groupId);
461 sb.append(")");
462
463 long[] roleIds = getRoleIds(groupId);
464
465 if (roleIds.length == 0) {
466 roleIds = _NO_ROLE_IDS;
467 }
468
469 sb.append(" AND (");
470
471 for (int i = 0; i < roleIds.length; i++) {
472 if (i > 0) {
473 sb.append(" OR ");
474 }
475
476 sb.append("InlineSQLResourcePermission.roleId = ");
477 sb.append(roleIds[i]);
478 }
479
480 if (permissionChecker.isSignedIn()) {
481 sb.append(" OR ");
482
483 if (Validator.isNotNull(userIdField)) {
484 sb.append("(");
485 sb.append(userIdField);
486 sb.append(" = ");
487 sb.append(userId);
488 sb.append(")");
489 }
490 else {
491 sb.append("(InlineSQLResourcePermission.ownerId = ");
492 sb.append(userId);
493 sb.append(")");
494 }
495 }
496
497 sb.append(")");
498 }
499 }
500
501 sb.append("))");
502
503 permissionJoin = StringUtil.replace(
504 permissionJoin,
505 new String[] {
506 "[$CLASS_NAME$]",
507 "[$COMPANY_ID$]",
508 "[$PRIM_KEYS$]"
509 },
510 new String[] {
511 className,
512 String.valueOf(permissionChecker.getCompanyId()),
513 sb.toString()
514 });
515
516 int pos = sql.indexOf(_WHERE_CLAUSE);
517
518 if (pos != -1) {
519 return sql.substring(0, pos + 1).concat(permissionJoin).concat(
520 sql.substring(pos + 1));
521 }
522
523 pos = sql.indexOf(_GROUP_BY_CLAUSE);
524
525 if (pos != -1) {
526 return sql.substring(0, pos + 1).concat(permissionJoin).concat(
527 sql.substring(pos + 1));
528 }
529
530 pos = sql.indexOf(_ORDER_BY_CLAUSE);
531
532 if (pos != -1) {
533 return sql.substring(0, pos + 1).concat(permissionJoin).concat(
534 sql.substring(pos + 1));
535 }
536
537 return sql.concat(StringPool.SPACE).concat(permissionJoin);
538 }
539
540 private static final String _GROUP_BY_CLAUSE = " GROUP BY ";
541
542 private static final long _NO_RESOURCE_BLOCKS_ID = -1;
543
544 private static final long[] _NO_ROLE_IDS = {0};
545
546 private static final String _ORDER_BY_CLAUSE = " ORDER BY ";
547
548 private static final String _WHERE_CLAUSE = " WHERE ";
549
550 }