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