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