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