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