Search in sources :

Example 1 with FolderACL

use of com.zimbra.cs.mailbox.acl.FolderACL in project zm-mailbox by Zimbra.

the class InviteFallback method doCheckRight.

//
// allow the invite right if the authed user has admin folder right on the default calendar folder
// (calendar folder in which the appointment is to be updated when the owner of the calendar receives 
// an invite)
//
protected Boolean doCheckRight(Account authedAcct, Entry target, boolean asAdmin) throws ServiceException {
    // Don't do anything unless running inside the server
    if (!Zimbra.started())
        return null;
    if (!(target instanceof Account))
        return null;
    Account targetAcct = (Account) target;
    OperationContext octxt = new OperationContext(authedAcct, asAdmin);
    int defaultCalendarfolderId = Mailbox.ID_FOLDER_CALENDAR;
    FolderACL folderACL = new FolderACL(octxt, targetAcct, defaultCalendarfolderId, Boolean.FALSE);
    // bug 42146
    //     admin rights (granted by UI): rwidxa 
    //     manager rights (granted by UI): rwidx 
    //
    // don't need the action right - it's for accepting/denying invites on behave of the invitee
    // don't need the admin right - it's for granting/revoking rights on the owner's folder
    // 
    // don't worry about the private right: we are checking if the authed user can invite(public/private)
    // the target user, the authed user is composing the invite and he sees what's in his invite anyway.
    //
    short rightsNeeded = ACL.RIGHT_READ | ACL.RIGHT_WRITE | ACL.RIGHT_INSERT | ACL.RIGHT_DELETE;
    boolean hasRights = folderACL.canAccess(rightsNeeded);
    if (hasRights)
        return Boolean.TRUE;
    else
        return null;
}
Also used : OperationContext(com.zimbra.cs.mailbox.OperationContext) Account(com.zimbra.cs.account.Account) FolderACL(com.zimbra.cs.mailbox.acl.FolderACL)

Example 2 with FolderACL

use of com.zimbra.cs.mailbox.acl.FolderACL in project zm-mailbox by Zimbra.

the class TestFolderACLCache method doTest.

/*
     * To test remote: hardcode FolderACL.ShareTarget.onLocalServer() to return false.
     *                 make sure you change it back after testing
     */
private void doTest(Account authedAcct, String ownerAcctId, int targetFolderId, short expectedEffectivePermissions, short needRightsForCanAccessTest, boolean expectedCanAccess) throws ServiceException {
    OperationContext octxt;
    if (authedAcct == null)
        octxt = null;
    else
        octxt = new OperationContext(authedAcct);
    FolderACL folderAcl = new FolderACL(octxt, ownerAcctId, targetFolderId);
    short effectivePermissions = folderAcl.getEffectivePermissions();
    boolean canAccess = folderAcl.canAccess(needRightsForCanAccessTest);
    boolean good = false;
    // mask out the create folder right, it is an internal right, which is returned
    // by getEffectivePermissions if owner is on local server but not returned if
    // the owner is remote.
    //
    // The diff is not a real bug and can be ignored
    short actual = effectivePermissions;
    short expected = expectedEffectivePermissions;
    if (actual == -1)
        actual = ACL.stringToRights(ACL.rightsToString(actual));
    if (expected == -1)
        expected = ACL.stringToRights(ACL.rightsToString(expected));
    Assert.assertEquals(expected, actual);
    Assert.assertEquals(expectedCanAccess, canAccess);
    good = true;
    ZimbraLog.test.debug("Test %s:authedAcct='%s' targetFolderId='%s' %s\n effectivePermissions: %s  (expected: %s)\n" + "    canAccess:            %s (expected: %s)", testName, authedAcct, targetFolderId, (!good ? "***FAILED***" : ""), formatRights(effectivePermissions), formatRights(expectedEffectivePermissions), canAccess, expectedCanAccess);
}
Also used : OperationContext(com.zimbra.cs.mailbox.OperationContext) FolderACL(com.zimbra.cs.mailbox.acl.FolderACL)

Example 3 with FolderACL

use of com.zimbra.cs.mailbox.acl.FolderACL in project zm-mailbox by Zimbra.

the class CalSummaryCache method getCalendarSummary.

// get summary for all appts/tasks in a calendar folder
public CalendarDataResult getCalendarSummary(OperationContext octxt, String targetAcctId, int folderId, MailItem.Type type, long rangeStart, long rangeEnd, boolean computeSubRange) throws ServiceException {
    if (rangeStart > rangeEnd)
        throw ServiceException.INVALID_REQUEST("End time must be after Start time", null);
    Account targetAcct = Provisioning.getInstance().get(AccountBy.id, targetAcctId);
    if (targetAcct == null)
        return null;
    boolean targetAcctOnLocalServer = Provisioning.onLocalServer(targetAcct);
    CalendarDataResult result = new CalendarDataResult();
    if (!LC.calendar_cache_enabled.booleanValue()) {
        ZimbraPerf.COUNTER_CALENDAR_CACHE_HIT.increment(0);
        ZimbraPerf.COUNTER_CALENDAR_CACHE_MEM_HIT.increment(0);
        if (!targetAcctOnLocalServer)
            return null;
        Mailbox mbox = MailboxManager.getInstance().getMailboxByAccount(targetAcct);
        Folder folder = mbox.getFolderById(octxt, folderId);
        Account authAcct = octxt != null ? octxt.getAuthenticatedUser() : null;
        boolean asAdmin = octxt != null ? octxt.isUsingAdminPrivileges() : false;
        result.allowPrivateAccess = CalendarItem.allowPrivateAccess(folder, authAcct, asAdmin);
        result.data = reloadCalendarOverRangeWithFolderScan(octxt, mbox, folderId, type, rangeStart, rangeEnd, null);
        if (ZimbraLog.calendar.isDebugEnabled()) {
            ZimbraLog.calendar.debug("Calendar Summary for %s reloaded (no cache) - %s items private=%s", folder.getName(), result.data.getNumItems(), result.allowPrivateAccess);
        }
        return result;
    }
    // Check if we have read permission.
    short perms;
    try {
        FolderACL facl = new FolderACL(octxt, targetAcctId, folderId);
        perms = facl.getEffectivePermissions();
    } catch (ServiceException se) {
        ZimbraLog.calendar.warn("Problem discovering ACLs for folder %s:%s", targetAcctId, folderId, se);
        throw ServiceException.PERM_DENIED("problem determining whether you have sufficient permissions on folder " + targetAcctId + ":" + folderId + " (" + se.getMessage() + ")");
    }
    if ((short) (perms & ACL.RIGHT_READ) != ACL.RIGHT_READ)
        throw ServiceException.PERM_DENIED("you do not have sufficient permissions on folder " + targetAcctId + ":" + folderId);
    result.allowPrivateAccess = (short) (perms & ACL.RIGHT_PRIVATE) == ACL.RIGHT_PRIVATE;
    // Look up from memcached.
    CalSummaryKey key = new CalSummaryKey(targetAcctId, folderId);
    CalendarData calData = mMemcachedCache.getForRange(key, rangeStart, rangeEnd);
    if (calData != null) {
        ZimbraPerf.COUNTER_CALENDAR_CACHE_HIT.increment(1);
        ZimbraPerf.COUNTER_CALENDAR_CACHE_MEM_HIT.increment(1);
        result.data = calData;
        if (ZimbraLog.calendar.isDebugEnabled()) {
            ZimbraLog.calendar.debug("Calendar Summary for %s:%s reloaded (memcached) - %s items private=%s", targetAcctId, folderId, result.data.getNumItems(), result.allowPrivateAccess);
        }
        return result;
    }
    // If not found in memcached and account is not on local server, we're done.
    if (!targetAcctOnLocalServer) {
        if (ZimbraLog.calendar.isDebugEnabled()) {
            ZimbraLog.calendar.debug("Calendar Summary - ignoring non-local %s:%s", targetAcctId, folderId);
        }
        return null;
    }
    int lruSize = 0;
    CacheLevel dataFrom = CacheLevel.Memory;
    boolean incrementalUpdate = sMaxStaleItems > 0;
    Mailbox mbox = MailboxManager.getInstance().getMailboxByAccountId(targetAcctId);
    // ACL check occurs here.
    Folder folder = mbox.getFolderById(octxt, folderId);
    // All subsequent mailbox access is done as owner to avoid permission errors.
    OperationContext ownerOctxt = new OperationContext(targetAcct);
    int currentModSeq = folder.getImapMODSEQ();
    // Lookup from heap LRU.
    synchronized (mSummaryCache) {
        if (mLRUCapacity > 0) {
            calData = mSummaryCache.get(key);
            lruSize = mSummaryCache.size();
        }
    }
    if (calData != null) {
        // Sanity check: Cached data can't be newer than the backend data.
        if (calData.getModSeq() > currentModSeq) {
            calData = null;
        } else {
            dataFrom = CacheLevel.Memory;
            // Data loaded from heap LRU supports incremental update for stale items.
            incrementalUpdate = sMaxStaleItems > 0;
        }
    }
    if (calData == null) {
        // Load from file.
        try {
            calData = FileStore.loadCalendarData(mbox.getId(), folderId, currentModSeq);
            if (calData != null) {
                // If data is up to date, add to LRU.
                if (calData.getModSeq() == currentModSeq) {
                    if (mLRUCapacity > 0) {
                        synchronized (mSummaryCache) {
                            mSummaryCache.put(key, calData);
                            lruSize = mSummaryCache.size();
                        }
                    }
                } else {
                    // Data loaded from file doesn't have stale items list.  It can't be refreshed incrementally.
                    incrementalUpdate = false;
                }
                dataFrom = CacheLevel.File;
            }
        } catch (ServiceException e) {
            ZimbraLog.calendar.warn("Error loading cached calendar summary", e);
        }
    }
    CalendarData reusableCalData = null;
    Pair<Long, Long> defaultRange = null;
    if (calData != null) {
        if (calData.getModSeq() != currentModSeq || calData.getNumStaleItems() > 0) {
            // current data's range covers the requested range.
            if (rangeStart >= calData.getRangeStart() && rangeEnd <= calData.getRangeEnd())
                reusableCalData = calData;
            // force recompute further down
            calData = null;
        } else if (rangeStart < calData.getRangeStart() || rangeEnd > calData.getRangeEnd()) {
            // Requested range is not within cached range.  Recompute cached range in the hope
            // that the new range will cover the requested range.
            defaultRange = Util.getMonthsRange(System.currentTimeMillis(), sRangeMonthFrom, sRangeNumMonths);
            if (calData.getRangeStart() != defaultRange.getFirst() || calData.getRangeEnd() != defaultRange.getSecond()) {
                calData = null;
            }
        }
    }
    // Recompute data if we must, and add to cache.
    if (calData == null) {
        if (defaultRange == null)
            defaultRange = Util.getMonthsRange(System.currentTimeMillis(), sRangeMonthFrom, sRangeNumMonths);
        calData = reloadCalendarOverRange(ownerOctxt, mbox, folderId, type, defaultRange.getFirst(), defaultRange.getSecond(), reusableCalData, incrementalUpdate);
        synchronized (mSummaryCache) {
            if (mLRUCapacity > 0) {
                mSummaryCache.put(key, calData);
                lruSize = mSummaryCache.size();
            }
        }
        dataFrom = CacheLevel.Miss;
        try {
            // persist it
            FileStore.saveCalendarData(mbox.getId(), calData);
        } catch (ServiceException e) {
            ZimbraLog.calendar.warn("Error persisting calendar summary cache", e);
        }
    }
    assert (calData != null);
    // Put data in memcached if it didn't come from memcached.
    if (!CacheLevel.Memcached.equals(dataFrom))
        mMemcachedCache.put(key, calData);
    if (rangeStart >= calData.getRangeStart() && rangeEnd <= calData.getRangeEnd()) {
        // Requested range is within cached range.
        if (computeSubRange) {
            result.data = calData.getSubRange(rangeStart, rangeEnd);
        } else {
            result.data = calData;
        }
    } else {
        // Requested range is outside the currently cached range.
        dataFrom = CacheLevel.Miss;
        result.data = reloadCalendarOverRange(ownerOctxt, mbox, folderId, type, rangeStart, rangeEnd, reusableCalData, incrementalUpdate);
    }
    // COUNTER_CALENDAR_CACHE_MEM_HIT - A hit is a successful lookup from memory only.
    switch(dataFrom) {
        case Memory:
        case Memcached:
            ZimbraPerf.COUNTER_CALENDAR_CACHE_HIT.increment(1);
            ZimbraPerf.COUNTER_CALENDAR_CACHE_MEM_HIT.increment(1);
            break;
        case File:
            ZimbraPerf.COUNTER_CALENDAR_CACHE_HIT.increment(1);
            ZimbraPerf.COUNTER_CALENDAR_CACHE_MEM_HIT.increment(0);
            break;
        case Miss:
        default:
            ZimbraPerf.COUNTER_CALENDAR_CACHE_HIT.increment(0);
            ZimbraPerf.COUNTER_CALENDAR_CACHE_MEM_HIT.increment(0);
            break;
    }
    ZimbraPerf.COUNTER_CALENDAR_CACHE_LRU_SIZE.increment(lruSize);
    if (ZimbraLog.calendar.isDebugEnabled()) {
        ZimbraLog.calendar.debug("Calendar Summary for %s:%s reloaded (dataFrom=%s) - %s items private=%s", targetAcctId, folderId, dataFrom, (result.data == null) ? 0 : result.data.getNumItems(), result.allowPrivateAccess);
    }
    return result;
}
Also used : OperationContext(com.zimbra.cs.mailbox.OperationContext) Account(com.zimbra.cs.account.Account) Folder(com.zimbra.cs.mailbox.Folder) Mailbox(com.zimbra.cs.mailbox.Mailbox) ServiceException(com.zimbra.common.service.ServiceException) MailServiceException(com.zimbra.cs.mailbox.MailServiceException) FolderACL(com.zimbra.cs.mailbox.acl.FolderACL)

Aggregations

OperationContext (com.zimbra.cs.mailbox.OperationContext)3 FolderACL (com.zimbra.cs.mailbox.acl.FolderACL)3 Account (com.zimbra.cs.account.Account)2 ServiceException (com.zimbra.common.service.ServiceException)1 Folder (com.zimbra.cs.mailbox.Folder)1 MailServiceException (com.zimbra.cs.mailbox.MailServiceException)1 Mailbox (com.zimbra.cs.mailbox.Mailbox)1