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