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