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 Set<Long> roleIds = new HashSet<Long>();
306
307 for (long groupId : groupIds) {
308 for (long roleId : getRoleIds(groupId)) {
309 roleIds.add(roleId);
310 }
311 }
312
313 return ArrayUtil.toLongArray(roleIds);
314 }
315
316 protected String getRoleIdsOrOwnerIdSQL(
317 PermissionChecker permissionChecker, long[] groupIds,
318 String userIdField) {
319
320 StringBundler sb = new StringBundler();
321
322 sb.append(StringPool.OPEN_PARENTHESIS);
323
324 sb.append("ResourcePermission.roleId IN (");
325
326 long[] roleIds = getRoleIds(groupIds);
327
328 if (roleIds.length == 0) {
329 roleIds = _NO_ROLE_IDS;
330 }
331
332 sb.append(StringUtil.merge(roleIds));
333
334 sb.append(StringPool.CLOSE_PARENTHESIS);
335
336 if (permissionChecker.isSignedIn()) {
337 sb.append(" OR ");
338
339 long userId = permissionChecker.getUserId();
340
341 if (Validator.isNotNull(userIdField)) {
342 sb.append(StringPool.OPEN_PARENTHESIS);
343 sb.append(userIdField);
344 sb.append(" = ");
345 sb.append(userId);
346 sb.append(StringPool.CLOSE_PARENTHESIS);
347 }
348 else {
349 sb.append("(ResourcePermission.ownerId = ");
350 sb.append(userId);
351 sb.append(StringPool.CLOSE_PARENTHESIS);
352 }
353 }
354
355 sb.append(StringPool.CLOSE_PARENTHESIS);
356
357 return sb.toString();
358 }
359
360 protected long getUserId() {
361 long userId = 0;
362
363 PermissionChecker permissionChecker =
364 PermissionThreadLocal.getPermissionChecker();
365
366 if (permissionChecker != null) {
367 userId = permissionChecker.getUserId();
368 }
369
370 return userId;
371 }
372
373 protected String getUserResourceBlockIdsSQL(
374 PermissionChecker permissionChecker, long checkGroupId, long[] roleIds,
375 String className, Set<Long> userResourceBlockIds) {
376
377 if (userResourceBlockIds.size() <
378 PropsValues.
379 PERMISSIONS_INLINE_SQL_RESOURCE_BLOCK_QUERY_THRESHHOLD) {
380
381 return StringUtil.merge(userResourceBlockIds);
382 }
383
384 return StringUtil.replace(
385 CustomSQLUtil.get(FIND_BY_RESOURCE_BLOCK_ID),
386 new String[] {
387 "[$COMPANY_ID$]", "[$GROUP_ID$]", "[$RESOURCE_BLOCK_NAME$]",
388 "[$ROLE_ID$]"
389 },
390 new String[] {
391 String.valueOf(permissionChecker.getCompanyId()),
392 String.valueOf(checkGroupId), className,
393 StringUtil.merge(roleIds)
394 });
395 }
396
397 protected String replacePermissionCheckBlocks(
398 String sql, String className, String classPKField, String userIdField,
399 long[] groupIds, String bridgeJoin) {
400
401 PermissionChecker permissionChecker =
402 PermissionThreadLocal.getPermissionChecker();
403
404 long checkGroupId = 0;
405
406 if (groupIds.length == 1) {
407 checkGroupId = groupIds[0];
408 }
409
410 long[] roleIds = permissionChecker.getRoleIds(
411 getUserId(), checkGroupId);
412
413 try {
414 for (long roleId : roleIds) {
415 if (ResourceTypePermissionLocalServiceUtil.
416 hasCompanyScopePermission(
417 permissionChecker.getCompanyId(), className, roleId,
418 ActionKeys.VIEW)) {
419
420 return sql;
421 }
422 }
423 }
424 catch (Exception e) {
425 }
426
427 Set<Long> userResourceBlockIds = getResourceBlockIds(
428 permissionChecker.getCompanyId(), groupIds, className);
429
430 String permissionWhere = StringPool.BLANK;
431
432 if (Validator.isNotNull(bridgeJoin)) {
433 permissionWhere = bridgeJoin;
434 }
435
436 Set<Long> ownerResourceBlockIds = getOwnerResourceBlockIds(
437 permissionChecker.getCompanyId(), groupIds, className);
438
439
440
441
442 ownerResourceBlockIds.removeAll(userResourceBlockIds);
443
444
445
446
447 if (ownerResourceBlockIds.isEmpty()) {
448 ownerResourceBlockIds.add(_NO_RESOURCE_BLOCKS_ID);
449 }
450
451 if (userResourceBlockIds.isEmpty()) {
452 userResourceBlockIds.add(_NO_RESOURCE_BLOCKS_ID);
453 }
454
455 if (Validator.isNotNull(userIdField)) {
456 permissionWhere = permissionWhere.concat(
457 CustomSQLUtil.get(FILTER_BY_RESOURCE_BLOCK_ID_OWNER));
458
459 permissionWhere = StringUtil.replace(
460 permissionWhere,
461 new String[] {
462 "[$OWNER_RESOURCE_BLOCK_ID$]", "[$USER_ID$]",
463 "[$USER_ID_FIELD$]", "[$USER_RESOURCE_BLOCK_ID$]"
464 },
465 new String[] {
466 getOwnerResourceBlockIdsSQL(
467 permissionChecker, checkGroupId, className,
468 ownerResourceBlockIds),
469 String.valueOf(permissionChecker.getUserId()), userIdField,
470 getUserResourceBlockIdsSQL(
471 permissionChecker, checkGroupId, roleIds, className,
472 userResourceBlockIds)
473 });
474 }
475 else {
476 permissionWhere = permissionWhere.concat(
477 CustomSQLUtil.get(FILTER_BY_RESOURCE_BLOCK_ID));
478
479 permissionWhere = StringUtil.replace(
480 permissionWhere, "[$USER_RESOURCE_BLOCK_ID$]",
481 getUserResourceBlockIdsSQL(
482 permissionChecker, checkGroupId, roleIds, className,
483 userResourceBlockIds));
484 }
485
486 int pos = sql.indexOf(_WHERE_CLAUSE);
487
488 if (pos != -1) {
489 StringBundler sb = new StringBundler(4);
490
491 sb.append(sql.substring(0, pos));
492 sb.append(permissionWhere);
493 sb.append(" AND ");
494 sb.append(sql.substring(pos + 7));
495
496 return sb.toString();
497 }
498
499 pos = sql.indexOf(_GROUP_BY_CLAUSE);
500
501 if (pos != -1) {
502 return sql.substring(0, pos + 1).concat(permissionWhere).concat(
503 sql.substring(pos + 1));
504 }
505
506 pos = sql.indexOf(_ORDER_BY_CLAUSE);
507
508 if (pos != -1) {
509 return sql.substring(0, pos + 1).concat(permissionWhere).concat(
510 sql.substring(pos + 1));
511 }
512
513 return sql.concat(StringPool.SPACE).concat(permissionWhere);
514 }
515
516 protected String replacePermissionCheckJoin(
517 String sql, String className, String classPKField, String userIdField,
518 String groupIdField, long[] groupIds, String bridgeJoin) {
519
520 if (Validator.isNull(classPKField)) {
521 throw new IllegalArgumentException("classPKField is null");
522 }
523
524 PermissionChecker permissionChecker =
525 PermissionThreadLocal.getPermissionChecker();
526
527 long checkGroupId = 0;
528
529 if (groupIds.length == 1) {
530 checkGroupId = groupIds[0];
531 }
532
533 if (permissionChecker.hasPermission(
534 checkGroupId, className, 0, ActionKeys.VIEW)) {
535
536 return sql;
537 }
538
539 String permissionJoin = StringPool.BLANK;
540
541 if (Validator.isNotNull(bridgeJoin)) {
542 permissionJoin = bridgeJoin;
543 }
544
545 permissionJoin += CustomSQLUtil.get(JOIN_RESOURCE_PERMISSION);
546
547 StringBundler sb = new StringBundler();
548
549 sb.append("(((ResourcePermission.primKey = CAST_TEXT(");
550 sb.append(classPKField);
551 sb.append(")) AND ((");
552
553 boolean hasPreviousViewableGroup = false;
554
555 List<Long> viewableGroupIds = new ArrayList<Long>();
556
557 for (int j = 0; j < groupIds.length; j++) {
558 long groupId = groupIds[j];
559
560 if (!permissionChecker.hasPermission(
561 groupId, className, 0, ActionKeys.VIEW)) {
562
563 if ((j > 0) && hasPreviousViewableGroup) {
564 sb.append(" OR ");
565 }
566
567 hasPreviousViewableGroup = true;
568
569 sb.append(StringPool.OPEN_PARENTHESIS);
570
571 if (Validator.isNull(groupIdField)) {
572 sb.append(
573 classPKField.substring(
574 0, classPKField.lastIndexOf(CharPool.PERIOD)));
575 sb.append(".groupId = ");
576 }
577 else {
578 sb.append(groupIdField);
579 sb.append(" = ");
580 }
581
582 sb.append(groupId);
583 sb.append(StringPool.CLOSE_PARENTHESIS);
584 }
585 else {
586 viewableGroupIds.add(groupId);
587 }
588 }
589
590 sb.append(StringPool.CLOSE_PARENTHESIS);
591
592 if (!viewableGroupIds.isEmpty()) {
593 for (Long viewableGroupId : viewableGroupIds) {
594 sb.append(" OR (");
595
596 if (Validator.isNull(groupIdField)) {
597 sb.append(
598 classPKField.substring(
599 0, classPKField.lastIndexOf(CharPool.PERIOD)));
600 sb.append(".groupId = ");
601 }
602 else {
603 sb.append(groupIdField);
604 sb.append(" = ");
605 }
606
607 sb.append(viewableGroupId);
608 sb.append(StringPool.CLOSE_PARENTHESIS);
609 }
610 }
611
612 sb.append(")))");
613
614 String roleIdsOrOwnerIdSQL = getRoleIdsOrOwnerIdSQL(
615 permissionChecker, groupIds, userIdField);
616
617 int scope = ResourceConstants.SCOPE_INDIVIDUAL;
618
619 permissionJoin = StringUtil.replace(
620 permissionJoin,
621 new String[] {
622 "[$CLASS_NAME$]", "[$COMPANY_ID$]", "[$PRIM_KEYS$]",
623 "[$RESOURCE_SCOPE_INDIVIDUAL$]", "[$ROLE_IDS_OR_OWNER_ID$]"
624 },
625 new String[] {
626 className, String.valueOf(permissionChecker.getCompanyId()),
627 sb.toString(), String.valueOf(scope), roleIdsOrOwnerIdSQL
628 });
629
630 int pos = sql.indexOf(_WHERE_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(_GROUP_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 pos = sql.indexOf(_ORDER_BY_CLAUSE);
645
646 if (pos != -1) {
647 return sql.substring(0, pos + 1).concat(permissionJoin).concat(
648 sql.substring(pos + 1));
649 }
650
651 return sql.concat(StringPool.SPACE).concat(permissionJoin);
652 }
653
654 private static final String _GROUP_BY_CLAUSE = " GROUP BY ";
655
656 private static final long _NO_RESOURCE_BLOCKS_ID = -1;
657
658 private static final long[] _NO_ROLE_IDS = {0};
659
660 private static final String _ORDER_BY_CLAUSE = " ORDER BY ";
661
662 private static final String _WHERE_CLAUSE = " WHERE ";
663
664 }