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