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