001    /**
002     * Copyright (c) 2000-present Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portal.security.permission;
016    
017    import com.liferay.exportimport.kernel.lar.ExportImportThreadLocal;
018    import com.liferay.portal.kernel.cache.MultiVMPoolUtil;
019    import com.liferay.portal.kernel.cache.PortalCache;
020    import com.liferay.portal.kernel.cache.index.IndexEncoder;
021    import com.liferay.portal.kernel.cache.index.PortalCacheIndexer;
022    import com.liferay.portal.kernel.model.ResourceConstants;
023    import com.liferay.portal.kernel.model.Role;
024    import com.liferay.portal.kernel.security.permission.PermissionThreadLocal;
025    import com.liferay.portal.kernel.security.permission.ResourceBlockIdsBag;
026    import com.liferay.portal.kernel.security.permission.UserBag;
027    import com.liferay.portal.kernel.util.HashUtil;
028    import com.liferay.portal.kernel.util.StringBundler;
029    import com.liferay.portal.kernel.util.StringPool;
030    import com.liferay.portal.util.PropsValues;
031    
032    import java.io.Serializable;
033    
034    import java.util.Arrays;
035    import java.util.Objects;
036    
037    /**
038     * @author Charles May
039     * @author Michael Young
040     * @author Shuyang Zhou
041     * @author Connor McKay
042     * @author L??szl?? Csontos
043     */
044    public class PermissionCacheUtil {
045    
046            public static final String PERMISSION_CACHE_NAME =
047                    PermissionCacheUtil.class.getName() + "_PERMISSION";
048    
049            public static final String PERMISSION_CHECKER_BAG_CACHE_NAME =
050                    PermissionCacheUtil.class.getName() + "_PERMISSION_CHECKER_BAG";
051    
052            public static final String RESOURCE_BLOCK_IDS_BAG_CACHE_NAME =
053                    PermissionCacheUtil.class.getName() + "_RESOURCE_BLOCK_IDS_BAG";
054    
055            public static final String USER_BAG_CACHE_NAME =
056                    PermissionCacheUtil.class.getName() + "_USER_BAG";
057    
058            public static final String USER_PRIMARY_KEY_ROLE_CACHE_NAME =
059                    PermissionCacheUtil.class.getName() + "_USER_PRIMARY_KEY_ROLE";
060    
061            public static final String USER_ROLE_CACHE_NAME =
062                    PermissionCacheUtil.class.getName() + "_USER_ROLE";
063    
064            public static void clearCache() {
065                    if (ExportImportThreadLocal.isImportInProcess()) {
066                            return;
067                    }
068    
069                    _userRolePortalCache.removeAll();
070                    _userGroupRoleIdsPortalCache.removeAll();
071                    _permissionPortalCache.removeAll();
072                    _resourceBlockIdsBagCache.removeAll();
073                    _userBagPortalCache.removeAll();
074                    _userPrimaryKeyRolePortalCache.removeAll();
075            }
076    
077            public static void clearCache(long... userIds) {
078                    if (ExportImportThreadLocal.isImportInProcess()) {
079                            return;
080                    }
081    
082                    for (long userId : userIds) {
083                            _userBagPortalCache.remove(userId);
084    
085                            _userGroupRoleIdsPortalCacheIndexer.removeKeys(userId);
086                            _userPrimaryKeyRolePortalCacheUserIdIndexer.removeKeys(userId);
087                            _userRolePortalCacheIndexer.removeKeys(userId);
088                    }
089    
090                    _permissionPortalCache.removeAll();
091                    _resourceBlockIdsBagCache.removeAll();
092            }
093    
094            public static void clearResourceBlockCache(
095                    long companyId, long groupId, String name) {
096    
097                    if (ExportImportThreadLocal.isImportInProcess() ||
098                            !PermissionThreadLocal.isFlushResourceBlockEnabled(
099                                    companyId, groupId, name)) {
100    
101                            return;
102                    }
103    
104                    _resourceBlockIdsBagCacheIndexer.removeKeys(
105                            ResourceBlockIdsBagKeyIndexEncoder.encode(
106                                    companyId, groupId, name));
107            }
108    
109            public static void clearResourceCache() {
110                    if (!ExportImportThreadLocal.isImportInProcess()) {
111                            _resourceBlockIdsBagCache.removeAll();
112                            _permissionPortalCache.removeAll();
113                    }
114            }
115    
116            public static void clearResourcePermissionCache(
117                    int scope, String name, String primKey) {
118    
119                    if (ExportImportThreadLocal.isImportInProcess() ||
120                            !PermissionThreadLocal.isFlushResourcePermissionEnabled(
121                                    name, primKey)) {
122    
123                            return;
124                    }
125    
126                    if (scope == ResourceConstants.SCOPE_INDIVIDUAL) {
127                            _permissionPortalCacheNamePrimKeyIndexer.removeKeys(
128                                    PermissionKeyNamePrimKeyIndexEncoder.encode(name, primKey));
129                    }
130                    else if (scope == ResourceConstants.SCOPE_GROUP) {
131                            _permissionPortalCacheGroupIdIndexer.removeKeys(
132                                    Long.valueOf(primKey));
133                    }
134                    else {
135                            _permissionPortalCache.removeAll();
136                    }
137            }
138    
139            public static Boolean getPermission(
140                    long groupId, String name, String primKey, long[] roleIds,
141                    String actionId) {
142    
143                    PermissionKey permissionKey = new PermissionKey(
144                            groupId, name, primKey, roleIds, actionId);
145    
146                    return _permissionPortalCache.get(permissionKey);
147            }
148    
149            public static ResourceBlockIdsBag getResourceBlockIdsBag(
150                    long companyId, long groupId, long userId, String name) {
151    
152                    ResourceBlockIdsBagKey resourceBlockIdsBagKey =
153                            new ResourceBlockIdsBagKey(companyId, groupId, userId, name);
154    
155                    return _resourceBlockIdsBagCache.get(resourceBlockIdsBagKey);
156            }
157    
158            public static UserBag getUserBag(long userId) {
159                    return _userBagPortalCache.get(userId);
160            }
161    
162            public static long[] getUserGroupRoleIds(long userId, long groupId) {
163                    UserGroupRoleIdsKey userGroupRoleIdsKey = new UserGroupRoleIdsKey(
164                            userId, groupId);
165    
166                    return _userGroupRoleIdsPortalCache.get(userGroupRoleIdsKey);
167            }
168    
169            public static Boolean getUserPrimaryKeyRole(
170                    long userId, long primaryKey, String roleName) {
171    
172                    UserPrimaryKeyRoleKey userPrimaryKeyRoleKey = new UserPrimaryKeyRoleKey(
173                            userId, primaryKey, roleName);
174    
175                    return _userPrimaryKeyRolePortalCache.get(userPrimaryKeyRoleKey);
176            }
177    
178            public static Boolean getUserRole(long userId, Role role) {
179                    UserRoleKey userRoleKey = new UserRoleKey(userId, role.getRoleId());
180    
181                    Boolean userRole = _userRolePortalCache.get(userRoleKey);
182    
183                    if (userRole != null) {
184                            return userRole;
185                    }
186    
187                    UserBag userBag = getUserBag(userId);
188    
189                    if (userBag == null) {
190                            return null;
191                    }
192    
193                    userRole = userBag.hasRole(role);
194    
195                    _userRolePortalCache.put(userRoleKey, userRole);
196    
197                    return userRole;
198            }
199    
200            public static void putPermission(
201                    long groupId, String name, String primKey, long[] roleIds,
202                    String actionId, Boolean value) {
203    
204                    PermissionKey permissionKey = new PermissionKey(
205                            groupId, name, primKey, roleIds, actionId);
206    
207                    _permissionPortalCache.put(permissionKey, value);
208            }
209    
210            public static void putResourceBlockIdsBag(
211                    long companyId, long groupId, long userId, String name,
212                    ResourceBlockIdsBag resourceBlockIdsBag) {
213    
214                    if (resourceBlockIdsBag == null) {
215                            return;
216                    }
217    
218                    ResourceBlockIdsBagKey resourceBlockIdsBagKey =
219                            new ResourceBlockIdsBagKey(companyId, groupId, userId, name);
220    
221                    _resourceBlockIdsBagCache.put(
222                            resourceBlockIdsBagKey, resourceBlockIdsBag);
223            }
224    
225            public static void putUserBag(long userId, UserBag userBag) {
226                    _userBagPortalCache.put(userId, userBag);
227            }
228    
229            public static void putUserGroupRoleIds(
230                    long userId, long groupId, long[] roleIds) {
231    
232                    if (roleIds == null) {
233                            return;
234                    }
235    
236                    UserGroupRoleIdsKey userGroupRoleIdsKey = new UserGroupRoleIdsKey(
237                            userId, groupId);
238    
239                    _userGroupRoleIdsPortalCache.put(userGroupRoleIdsKey, roleIds);
240            }
241    
242            public static void putUserPrimaryKeyRole(
243                    long userId, long primaryKey, String roleName, Boolean value) {
244    
245                    if (value == null) {
246                            return;
247                    }
248    
249                    UserPrimaryKeyRoleKey userPrimaryKeyRoleKey = new UserPrimaryKeyRoleKey(
250                            userId, primaryKey, roleName);
251    
252                    _userPrimaryKeyRolePortalCache.put(userPrimaryKeyRoleKey, value);
253            }
254    
255            public static void putUserRole(long userId, Role role, Boolean value) {
256                    if (value == null) {
257                            return;
258                    }
259    
260                    UserRoleKey userRoleKey = new UserRoleKey(userId, role.getRoleId());
261    
262                    _userRolePortalCache.put(userRoleKey, value);
263            }
264    
265            public static void removePermission(
266                    long groupId, String name, String primKey, long[] roleIds,
267                    String actionId) {
268    
269                    PermissionKey permissionKey = new PermissionKey(
270                            groupId, name, primKey, roleIds, actionId);
271    
272                    _permissionPortalCache.remove(permissionKey);
273            }
274    
275            public static void removeResourceBlockIdsBag(
276                    long companyId, long groupId, long userId, String name) {
277    
278                    ResourceBlockIdsBagKey resourceBlockIdsBagKey =
279                            new ResourceBlockIdsBagKey(companyId, groupId, userId, name);
280    
281                    _resourceBlockIdsBagCache.remove(resourceBlockIdsBagKey);
282            }
283    
284            public static void removeUserBag(long userId) {
285                    _userBagPortalCache.remove(userId);
286            }
287    
288            public static void removeUserGroupRoleIds(long userId, long groupId) {
289                    UserGroupRoleIdsKey userGroupRoleIdsKey = new UserGroupRoleIdsKey(
290                            userId, groupId);
291    
292                    _userGroupRoleIdsPortalCache.remove(userGroupRoleIdsKey);
293            }
294    
295            public static void removeUserPrimaryKeyRole(
296                    long userId, long primaryKey, String roleName) {
297    
298                    UserPrimaryKeyRoleKey userPrimaryKeyRoleKey = new UserPrimaryKeyRoleKey(
299                            userId, primaryKey, roleName);
300    
301                    _userPrimaryKeyRolePortalCache.remove(userPrimaryKeyRoleKey);
302            }
303    
304            private static final PortalCache<PermissionKey, Boolean>
305                    _permissionPortalCache = MultiVMPoolUtil.getPortalCache(
306                            PERMISSION_CACHE_NAME,
307                            PropsValues.PERMISSIONS_OBJECT_BLOCKING_CACHE);
308            private static final PortalCacheIndexer<Long, PermissionKey, Boolean>
309                    _permissionPortalCacheGroupIdIndexer = new PortalCacheIndexer<>(
310                            new PermissionKeyGroupIdIndexEncoder(), _permissionPortalCache);
311            private static final PortalCacheIndexer<String, PermissionKey, Boolean>
312                    _permissionPortalCacheNamePrimKeyIndexer = new PortalCacheIndexer<>(
313                            new PermissionKeyNamePrimKeyIndexEncoder(), _permissionPortalCache);
314            private static final
315                    PortalCache<ResourceBlockIdsBagKey, ResourceBlockIdsBag>
316                            _resourceBlockIdsBagCache = MultiVMPoolUtil.getPortalCache(
317                                    RESOURCE_BLOCK_IDS_BAG_CACHE_NAME,
318                                    PropsValues.PERMISSIONS_OBJECT_BLOCKING_CACHE);
319            private static final PortalCacheIndexer
320                    <String, ResourceBlockIdsBagKey, ResourceBlockIdsBag>
321                            _resourceBlockIdsBagCacheIndexer = new PortalCacheIndexer<>(
322                                    new ResourceBlockIdsBagKeyIndexEncoder(),
323                                    _resourceBlockIdsBagCache);
324            private static final PortalCache<Long, UserBag> _userBagPortalCache =
325                    MultiVMPoolUtil.getPortalCache(
326                            USER_BAG_CACHE_NAME, PropsValues.PERMISSIONS_OBJECT_BLOCKING_CACHE);
327            private static final PortalCache<UserGroupRoleIdsKey, long[]>
328                    _userGroupRoleIdsPortalCache = MultiVMPoolUtil.getPortalCache(
329                            PERMISSION_CHECKER_BAG_CACHE_NAME,
330                            PropsValues.PERMISSIONS_OBJECT_BLOCKING_CACHE);
331            private static final PortalCacheIndexer<Long, UserGroupRoleIdsKey, long[]>
332                    _userGroupRoleIdsPortalCacheIndexer = new PortalCacheIndexer<>(
333                            new UserGroupRoleIdsKeyIndexEncoder(),
334                            _userGroupRoleIdsPortalCache);
335            private static final PortalCache<UserPrimaryKeyRoleKey, Boolean>
336                    _userPrimaryKeyRolePortalCache = MultiVMPoolUtil.getPortalCache(
337                            USER_PRIMARY_KEY_ROLE_CACHE_NAME,
338                            PropsValues.PERMISSIONS_OBJECT_BLOCKING_CACHE);
339            private static final PortalCacheIndexer
340                    <Long, UserPrimaryKeyRoleKey, Boolean>
341                            _userPrimaryKeyRolePortalCacheUserIdIndexer =
342                                    new PortalCacheIndexer<>(
343                                            new UserGroupRoleKeyUserIdEncoder(),
344                                            _userPrimaryKeyRolePortalCache);
345            private static final PortalCache<UserRoleKey, Boolean>
346                    _userRolePortalCache = MultiVMPoolUtil.getPortalCache(
347                            USER_ROLE_CACHE_NAME,
348                            PropsValues.PERMISSIONS_OBJECT_BLOCKING_CACHE);
349            private static final PortalCacheIndexer<Long, UserRoleKey, Boolean>
350                    _userRolePortalCacheIndexer = new PortalCacheIndexer<>(
351                            new UserRoleKeyIndexEncoder(), _userRolePortalCache);
352    
353            private static class PermissionKey implements Serializable {
354    
355                    @Override
356                    public boolean equals(Object obj) {
357                            PermissionKey permissionKey = (PermissionKey)obj;
358    
359                            if ((permissionKey._groupId == _groupId) &&
360                                    Objects.equals(permissionKey._name, _name) &&
361                                    Objects.equals(permissionKey._primKey, _primKey) &&
362                                    Arrays.equals(permissionKey._roleIds, _roleIds) &&
363                                    Objects.equals(permissionKey._actionId, _actionId)) {
364    
365                                    return true;
366                            }
367    
368                            return false;
369                    }
370    
371                    @Override
372                    public int hashCode() {
373                            int hashCode = HashUtil.hash(0, _groupId);
374    
375                            hashCode = HashUtil.hash(hashCode, _name);
376                            hashCode = HashUtil.hash(hashCode, _primKey);
377                            hashCode = HashUtil.hash(hashCode, _roleIds.length);
378    
379                            for (long roleId : _roleIds) {
380                                    hashCode = HashUtil.hash(hashCode, roleId);
381                            }
382    
383                            hashCode = HashUtil.hash(hashCode, _actionId);
384    
385                            return hashCode;
386                    }
387    
388                    private PermissionKey(
389                            long groupId, String name, String primKey, long[] roleIds,
390                            String actionId) {
391    
392                            _groupId = groupId;
393                            _name = name;
394                            _primKey = primKey;
395                            _roleIds = roleIds;
396                            _actionId = actionId;
397                    }
398    
399                    private static final long serialVersionUID = 1L;
400    
401                    private final String _actionId;
402                    private final long _groupId;
403                    private final String _name;
404                    private final String _primKey;
405                    private final long[] _roleIds;
406    
407            }
408    
409            private static class PermissionKeyGroupIdIndexEncoder
410                    implements IndexEncoder<Long, PermissionKey> {
411    
412                    @Override
413                    public Long encode(PermissionKey permissionKey) {
414                            return permissionKey._groupId;
415                    }
416    
417            }
418    
419            private static class PermissionKeyNamePrimKeyIndexEncoder
420                    implements IndexEncoder<String, PermissionKey> {
421    
422                    public static String encode(String name, String primKey) {
423                            return name.concat(StringPool.UNDERLINE).concat(primKey);
424                    }
425    
426                    @Override
427                    public String encode(PermissionKey permissionKey) {
428                            return encode(permissionKey._name, permissionKey._primKey);
429                    }
430    
431            }
432    
433            private static class ResourceBlockIdsBagKey implements Serializable {
434    
435                    @Override
436                    public boolean equals(Object obj) {
437                            ResourceBlockIdsBagKey resourceBlockIdsKey =
438                                    (ResourceBlockIdsBagKey)obj;
439    
440                            if ((resourceBlockIdsKey._companyId == _companyId) &&
441                                    (resourceBlockIdsKey._groupId == _groupId) &&
442                                    (resourceBlockIdsKey._userId == _userId) &&
443                                    Objects.equals(resourceBlockIdsKey._name, _name)) {
444    
445                                    return true;
446                            }
447    
448                            return false;
449                    }
450    
451                    @Override
452                    public int hashCode() {
453                            int hashCode = HashUtil.hash(0, _companyId);
454    
455                            hashCode = HashUtil.hash(hashCode, _groupId);
456                            hashCode = HashUtil.hash(hashCode, _userId);
457                            hashCode = HashUtil.hash(hashCode, _name);
458    
459                            return hashCode;
460                    }
461    
462                    private ResourceBlockIdsBagKey(
463                            long companyId, long groupId, long userId, String name) {
464    
465                            _companyId = companyId;
466                            _groupId = groupId;
467                            _userId = userId;
468                            _name = name;
469                    }
470    
471                    private static final long serialVersionUID = 1L;
472    
473                    private final long _companyId;
474                    private final long _groupId;
475                    private final String _name;
476                    private final long _userId;
477    
478            }
479    
480            private static class ResourceBlockIdsBagKeyIndexEncoder
481                    implements IndexEncoder<String, ResourceBlockIdsBagKey> {
482    
483                    public static String encode(long companyId, long groupId, String name) {
484                            StringBundler sb = new StringBundler(5);
485    
486                            sb.append(companyId);
487                            sb.append(StringPool.UNDERLINE);
488                            sb.append(groupId);
489                            sb.append(StringPool.UNDERLINE);
490                            sb.append(name);
491    
492                            return sb.toString();
493                    }
494    
495                    @Override
496                    public String encode(ResourceBlockIdsBagKey resourceBlockIdsBagKey) {
497                            return encode(
498                                    resourceBlockIdsBagKey._companyId,
499                                    resourceBlockIdsBagKey._groupId, resourceBlockIdsBagKey._name);
500                    }
501    
502            }
503    
504            private static class UserGroupRoleIdsKey implements Serializable {
505    
506                    @Override
507                    public boolean equals(Object obj) {
508                            UserGroupRoleIdsKey userGroupRoleIdsKey = (UserGroupRoleIdsKey)obj;
509    
510                            if ((userGroupRoleIdsKey._userId == _userId) &&
511                                    (userGroupRoleIdsKey._groupId == _groupId)) {
512    
513                                    return true;
514                            }
515    
516                            return false;
517                    }
518    
519                    @Override
520                    public int hashCode() {
521                            int hashCode = HashUtil.hash(0, _userId);
522    
523                            return HashUtil.hash(hashCode, _groupId);
524                    }
525    
526                    private UserGroupRoleIdsKey(long userId, long groupId) {
527                            _userId = userId;
528                            _groupId = groupId;
529                    }
530    
531                    private static final long serialVersionUID = 1L;
532    
533                    private final long _groupId;
534                    private final long _userId;
535    
536            }
537    
538            private static class UserGroupRoleIdsKeyIndexEncoder
539                    implements IndexEncoder<Long, UserGroupRoleIdsKey> {
540    
541                    @Override
542                    public Long encode(UserGroupRoleIdsKey userGroupRoleIdsKey) {
543                            return userGroupRoleIdsKey._userId;
544                    }
545    
546            }
547    
548            private static class UserGroupRoleKeyUserIdEncoder
549                    implements IndexEncoder<Long, UserPrimaryKeyRoleKey> {
550    
551                    @Override
552                    public Long encode(UserPrimaryKeyRoleKey key) {
553                            return key._userId;
554                    }
555    
556            }
557    
558            private static class UserPrimaryKeyRoleKey implements Serializable {
559    
560                    @Override
561                    public boolean equals(Object obj) {
562                            UserPrimaryKeyRoleKey userPrimaryKeyRoleKey =
563                                    (UserPrimaryKeyRoleKey)obj;
564    
565                            if ((userPrimaryKeyRoleKey._userId == _userId) &&
566                                    (userPrimaryKeyRoleKey._primaryKey == _primaryKey) &&
567                                    Objects.equals(userPrimaryKeyRoleKey._name, _name)) {
568    
569                                    return true;
570                            }
571    
572                            return false;
573                    }
574    
575                    @Override
576                    public int hashCode() {
577                            int hashCode = HashUtil.hash(0, _userId);
578    
579                            hashCode = HashUtil.hash(hashCode, _primaryKey);
580                            hashCode = HashUtil.hash(hashCode, _name);
581    
582                            return hashCode;
583                    }
584    
585                    private UserPrimaryKeyRoleKey(
586                            long userId, long primaryKey, String name) {
587    
588                            _userId = userId;
589                            _primaryKey = primaryKey;
590                            _name = name;
591                    }
592    
593                    private static final long serialVersionUID = 1L;
594    
595                    private final String _name;
596                    private final long _primaryKey;
597                    private final long _userId;
598    
599            }
600    
601            private static class UserRoleKey implements Serializable {
602    
603                    @Override
604                    public boolean equals(Object obj) {
605                            UserRoleKey userRoleKey = (UserRoleKey)obj;
606    
607                            if ((userRoleKey._userId == _userId) &&
608                                    (userRoleKey._roleId == _roleId)) {
609    
610                                    return true;
611                            }
612    
613                            return false;
614                    }
615    
616                    @Override
617                    public int hashCode() {
618                            int hashCode = HashUtil.hash(0, _userId);
619    
620                            return HashUtil.hash(hashCode, _roleId);
621                    }
622    
623                    private UserRoleKey(long userId, long roleId) {
624                            _userId = userId;
625                            _roleId = roleId;
626                    }
627    
628                    private static final long serialVersionUID = 1L;
629    
630                    private final long _roleId;
631                    private final long _userId;
632    
633            }
634    
635            private static class UserRoleKeyIndexEncoder
636                    implements IndexEncoder<Long, UserRoleKey> {
637    
638                    @Override
639                    public Long encode(UserRoleKey userRoleKey) {
640                            return userRoleKey._userId;
641                    }
642    
643            }
644    
645    }