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