use of com.zimbra.cs.account.Group in project zm-mailbox by Zimbra.
the class GetDistributionListMembers method processDLMembers.
protected Element processDLMembers(ZimbraSoapContext zsc, String dlName, Account account, int limit, int offset, DLMembers dlMembers) throws ServiceException {
if (!GalSearchControl.canExpandGalGroup(dlName, dlMembers.getDLZimbraId(), account)) {
ZimbraLog.misc.warn("dlName: %s, dlMembers(%s) size %d, id %s", dlName, dlMembers.getClass(), dlMembers.getTotal(), dlMembers.getDLZimbraId());
Group dl = Provisioning.getInstance().getGroup(DistributionListBy.name, dlName);
if (dl == null) {
throw ServiceException.NOT_FOUND(dlName + " does not exist");
} else {
throw ServiceException.PERM_DENIED("can not access dl members: " + dlName);
}
}
Element response = zsc.createElement(AccountConstants.GET_DISTRIBUTION_LIST_MEMBERS_RESPONSE);
if (dlMembers != null) {
int numMembers = dlMembers.getTotal();
if (offset > 0 && offset >= numMembers) {
throw ServiceException.INVALID_REQUEST("offset " + offset + " greater than size " + numMembers, null);
}
int endIndex = offset + limit;
if (limit == 0) {
endIndex = numMembers;
}
if (endIndex > numMembers) {
endIndex = numMembers;
}
dlMembers.encodeMembers(offset, endIndex, response);
response.addAttribute(AccountConstants.A_MORE, endIndex < numMembers);
response.addAttribute(AccountConstants.A_TOTAL, numMembers);
}
return response;
}
use of com.zimbra.cs.account.Group in project zm-mailbox by Zimbra.
the class GetDistributionListMembers method handle.
@Override
public Element handle(Element request, Map<String, Object> context) throws ServiceException {
ZimbraSoapContext zsc = getZimbraSoapContext(context);
Account account = getRequestedAccount(zsc);
if (!canAccessAccount(zsc, account)) {
throw ServiceException.PERM_DENIED("can not access account");
}
Element eDL = request.getElement(AdminConstants.E_DL);
String dlName = eDL.getText();
int offset = getOffset(request);
int limit = getLimit(request);
// null offset/limit and set _offset/_limit before calling searchGal().
request.addAttribute(MailConstants.A_QUERY_OFFSET, (String) null);
request.addAttribute(MailConstants.A_LIMIT, (String) null);
request.addAttribute(AccountConstants.A_OFFSET_INTERNAL, offset);
request.addAttribute(AccountConstants.A_LIMIT_INTERNAL, limit);
boolean proxiedToHomeOfInternalGroup = request.getAttributeBool(A_PROXIED_TO_HOME_OF_GROUP, false);
DLMembersResult dlMembersResult = null;
/*
* see if the group is an internal group
*/
Provisioning prov = Provisioning.getInstance();
Group group = prov.getGroupBasic(DistributionListBy.name, dlName);
if (group != null) {
/*
* Is an internal group, get members from LDAP instead of GAL
* for group owners and members.
*
* This makes updates on internal groups reflected in the UI
* sooner than the next GSA delta sync cycle for group owners and members.
* (bug 72482 and bug 73460).
*/
dlMembersResult = getMembersFromLdap(context, request, account, group, proxiedToHomeOfInternalGroup);
}
if (dlMembersResult == null) {
/*
* - this is not an internal group, or
* - this is an internal group but the requesting account is not an owner
* or member of the group, or
* - this is an internal hideInGal group and the requesting account is not
* an owner of the group.
*
* Do GAL search if this is not a hideInGal group. This check is a small
* optimization and is not necessary, because if the group is hideInGal, it
* won't be found in GAL anyway, so just save the GAL search.
*
* If proxiedToHomeOfInternalGroup is true, we were proxied here from inside the
* getMembersFromLdap() path in the previous hop. We must have gone into the above
* getMembersFromLdap() in this hop, and it returned null (or in a nearly
* impossible case the group cannot be found in this server and we did not
* even go into the above getMembersFromLdap). In this case, do not do
* a GAL search, because the GAL search could once again proxy the request
* to the GAL sync account's home server. We will just leave dlMembersResult
* null and let the NO_SUCH_DISTRIBUTION_LIST be thrown. When the
* NO_SUCH_DISTRIBUTION_LIST got back to the previous hop, in
* getMembersFromLdap, it will return null and control will reach here again
* (in the "previous" hop). Now, since the proxiedToHomeOfInternalGroup
* flag is not on, we will proceed to do the GAL search if the group is not hideInGal.
*/
boolean hideInGal = (group != null && group.hideInGal());
if (!hideInGal && !proxiedToHomeOfInternalGroup) {
dlMembersResult = GalGroupMembers.searchGal(zsc, account, dlName, request);
}
}
if (dlMembersResult == null) {
throw AccountServiceException.NO_SUCH_DISTRIBUTION_LIST(dlName);
}
if (dlMembersResult instanceof ProxiedDLMembers) {
return ((ProxiedDLMembers) dlMembersResult).getResponse();
} else if (dlMembersResult instanceof DLMembers) {
return processDLMembers(zsc, dlName, account, limit, offset, (DLMembers) dlMembersResult);
} else {
throw ServiceException.FAILURE("unsopported DLMembersResult class: " + dlMembersResult.getClass().getCanonicalName(), null);
}
}
use of com.zimbra.cs.account.Group in project zm-mailbox by Zimbra.
the class DiscoverRights method discoverRights.
public static void discoverRights(Account account, Set<Right> rights, Element eParent, boolean onMaster) throws ServiceException {
AccessManager accessMgr = AccessManager.getInstance();
Map<Right, Set<Entry>> discoveredRights = accessMgr.discoverUserRights(account, rights, onMaster);
Locale locale = account.getLocale();
for (Map.Entry<Right, Set<Entry>> targetsForRight : discoveredRights.entrySet()) {
Right right = targetsForRight.getKey();
Set<Entry> targets = targetsForRight.getValue();
List<Entry> sortedTargets = Entry.sortByDisplayName(targets, locale);
boolean isDelegatedSendRight = isDelegatedSendRight(right);
Element eTargets = eParent.addElement(AccountConstants.E_TARGETS);
eTargets.addAttribute(AccountConstants.A_RIGHT, right.getName());
for (Entry target : sortedTargets) {
TargetType targetType = TargetType.getTargetType(target);
Element eTarget = eTargets.addElement(AccountConstants.E_TARGET);
eTarget.addAttribute(AccountConstants.A_TYPE, targetType.getCode());
if (isDelegatedSendRight) {
if (target instanceof Account || target instanceof Group) {
String[] addrs = AccountUtil.getAllowedSendAddresses((NamedEntry) target);
NamedEntry entry = (NamedEntry) target;
for (String addr : addrs) {
Element eEmail = eTarget.addElement(AccountConstants.E_EMAIL);
eEmail.addAttribute(AccountConstants.A_ADDR, addr);
}
if (target instanceof Account) {
eTarget.addAttribute(AccountConstants.A_DISPLAY, ((Account) entry).getDisplayName());
} else if (target instanceof Group) {
eTarget.addAttribute(AccountConstants.A_DISPLAY, ((Group) entry).getDisplayName());
}
} else {
throw ServiceException.FAILURE("internal error, target for " + " delegated send rights must be account or group", null);
}
} else {
if (target instanceof NamedEntry) {
NamedEntry entry = (NamedEntry) target;
eTarget.addAttribute(AccountConstants.A_ID, entry.getId());
eTarget.addAttribute(AccountConstants.A_NAME, entry.getName());
if (target instanceof Account) {
eTarget.addAttribute(AccountConstants.A_DISPLAY, ((Account) entry).getDisplayName());
} else if (target instanceof Group) {
eTarget.addAttribute(AccountConstants.A_DISPLAY, ((Group) entry).getDisplayName());
}
} else {
eTarget.addAttribute(AccountConstants.A_NAME, target.getLabel());
}
}
}
}
}
use of com.zimbra.cs.account.Group in project zm-mailbox by Zimbra.
the class FolderAction method handleFolder.
private String handleFolder(Map<String, Object> context, Element request, String operation, Element result) throws ServiceException {
Element action = request.getElement(MailConstants.E_ACTION);
ZimbraSoapContext zsc = getZimbraSoapContext(context);
Mailbox mbox = getRequestedMailbox(zsc);
OperationContext octxt = getOperationContext(zsc, context);
ItemIdFormatter ifmt = new ItemIdFormatter(zsc);
ItemId iid = new ItemId(action.getAttribute(MailConstants.A_ID), zsc);
if (operation.equals(OP_EMPTY)) {
boolean subfolders = action.getAttributeBool(MailConstants.A_RECURSIVE, true);
mbox.emptyFolder(octxt, iid.getId(), subfolders);
// empty trash means also to purge all IMAP \Deleted messages
if (iid.getId() == Mailbox.ID_FOLDER_TRASH)
mbox.purgeImapDeleted(octxt);
} else if (operation.equals(OP_REFRESH)) {
mbox.synchronizeFolder(octxt, iid.getId());
} else if (operation.equals(OP_IMPORT)) {
String url = action.getAttribute(MailConstants.A_URL);
mbox.importFeed(octxt, iid.getId(), url, false);
} else if (operation.equals(OP_FREEBUSY)) {
boolean fb = action.getAttributeBool(MailConstants.A_EXCLUDE_FREEBUSY, false);
mbox.alterTag(octxt, iid.getId(), MailItem.Type.FOLDER, Flag.FlagInfo.EXCLUDE_FREEBUSY, fb, null);
FreeBusyProvider.mailboxChanged(zsc.getRequestedAccountId());
} else if (operation.equals(OP_CHECK) || operation.equals(OP_UNCHECK)) {
mbox.alterTag(octxt, iid.getId(), MailItem.Type.FOLDER, Flag.FlagInfo.CHECKED, operation.equals(OP_CHECK), null);
} else if (operation.equals(OP_SET_URL)) {
String url = action.getAttribute(MailConstants.A_URL, "");
mbox.setFolderUrl(octxt, iid.getId(), url);
if (!url.equals("")) {
mbox.synchronizeFolder(octxt, iid.getId());
}
if (action.getAttribute(MailConstants.A_EXCLUDE_FREEBUSY, null) != null) {
boolean fb = action.getAttributeBool(MailConstants.A_EXCLUDE_FREEBUSY, false);
mbox.alterTag(octxt, iid.getId(), MailItem.Type.FOLDER, Flag.FlagInfo.EXCLUDE_FREEBUSY, fb, null);
}
} else if (operation.equals(OP_REVOKE)) {
String zid = action.getAttribute(MailConstants.A_ZIMBRA_ID);
mbox.revokeAccess(octxt, iid.getId(), zid);
} else if (operation.equals(OP_GRANT)) {
Element grant = action.getElement(MailConstants.E_GRANT);
short rights = ACL.stringToRights(grant.getAttribute(MailConstants.A_RIGHTS));
byte gtype = ACL.stringToType(grant.getAttribute(MailConstants.A_GRANT_TYPE));
String zid = grant.getAttribute(MailConstants.A_ZIMBRA_ID, null);
long expiry = grant.getAttributeLong(MailConstants.A_EXPIRY, 0);
String secret = null;
NamedEntry nentry = null;
if (gtype == ACL.GRANTEE_AUTHUSER) {
zid = GuestAccount.GUID_AUTHUSER;
} else if (gtype == ACL.GRANTEE_PUBLIC) {
zid = GuestAccount.GUID_PUBLIC;
expiry = validateGrantExpiry(grant.getAttribute(MailConstants.A_EXPIRY, null), AccountUtil.getMaxPublicShareLifetime(mbox.getAccount(), mbox.getFolderById(octxt, iid.getId()).getDefaultView()));
} else if (gtype == ACL.GRANTEE_GUEST) {
zid = grant.getAttribute(MailConstants.A_DISPLAY);
if (zid == null || zid.indexOf('@') < 0)
throw ServiceException.INVALID_REQUEST("invalid guest id or password", null);
// first make sure they didn't accidentally specify "guest" instead of "usr"
boolean guestGrantee = true;
try {
nentry = lookupGranteeByName(zid, ACL.GRANTEE_USER, zsc);
if (nentry instanceof MailTarget) {
Domain domain = Provisioning.getInstance().getDomain(mbox.getAccount());
String granteeDomainName = ((MailTarget) nentry).getDomainName();
if (domain.isInternalSharingCrossDomainEnabled() || domain.getName().equals(granteeDomainName) || Sets.newHashSet(domain.getInternalSharingDomain()).contains(granteeDomainName)) {
guestGrantee = false;
zid = nentry.getId();
gtype = nentry instanceof Group ? ACL.GRANTEE_GROUP : ACL.GRANTEE_USER;
}
}
} catch (ServiceException e) {
// this is the normal path, where lookupGranteeByName throws account.NO_SUCH_USER
}
if (guestGrantee) {
secret = grant.getAttribute(MailConstants.A_ARGS, null);
// password is no longer required for external sharing
if (secret == null) {
secret = grant.getAttribute(MailConstants.A_PASSWORD, null);
}
}
} else if (gtype == ACL.GRANTEE_KEY) {
zid = grant.getAttribute(MailConstants.A_DISPLAY);
// unlike guest, we do not require the display name to be an email address
// unlike guest, we do not fixup grantee type for key grantees if they specify an internal user
// get the optional accesskey
secret = grant.getAttribute(MailConstants.A_ACCESSKEY, null);
} else if (zid != null) {
nentry = lookupGranteeByZimbraId(zid, gtype);
} else {
try {
nentry = lookupGranteeByName(grant.getAttribute(MailConstants.A_DISPLAY), gtype, zsc);
zid = nentry.getId();
// make sure they didn't accidentally specify "usr" instead of "grp"
if (gtype == ACL.GRANTEE_USER && nentry instanceof Group) {
gtype = ACL.GRANTEE_GROUP;
}
} catch (ServiceException e) {
if (AccountServiceException.NO_SUCH_ACCOUNT.equals(e.getCode())) {
// looks like the case of an internal user not provisioned yet
// we'll treat it as external sharing
gtype = ACL.GRANTEE_GUEST;
zid = grant.getAttribute(MailConstants.A_DISPLAY);
} else {
throw e;
}
}
}
ACL.Grant g = mbox.grantAccess(octxt, iid.getId(), zid, gtype, rights, secret, expiry);
// kinda hacky -- return the zimbra id and name of the grantee in the response
result.addAttribute(MailConstants.A_ZIMBRA_ID, zid);
if (nentry != null)
result.addAttribute(MailConstants.A_DISPLAY, nentry.getName());
else if (gtype == ACL.GRANTEE_GUEST || gtype == ACL.GRANTEE_KEY)
result.addAttribute(MailConstants.A_DISPLAY, zid);
if (gtype == ACL.GRANTEE_KEY)
result.addAttribute(MailConstants.A_ACCESSKEY, g.getPassword());
} else if (operation.equals(OP_REVOKEORPHANGRANTS)) {
String zid = action.getAttribute(MailConstants.A_ZIMBRA_ID);
byte gtype = ACL.stringToType(action.getAttribute(MailConstants.A_GRANT_TYPE));
revokeOrphanGrants(octxt, mbox, iid, zid, gtype);
} else if (operation.equals(OP_UPDATE)) {
// duplicating code from ItemAction.java for now...
String newName = action.getAttribute(MailConstants.A_NAME, null);
String folderId = action.getAttribute(MailConstants.A_FOLDER, null);
ItemId iidFolder = new ItemId(folderId == null ? "-1" : folderId, zsc);
if (!iidFolder.belongsTo(mbox)) {
throw ServiceException.INVALID_REQUEST("cannot move folder between mailboxes", null);
} else if (folderId != null && iidFolder.getId() <= 0) {
throw MailServiceException.NO_SUCH_FOLDER(iidFolder.getId());
}
String flags = action.getAttribute(MailConstants.A_FLAGS, null);
byte color = (byte) action.getAttributeLong(MailConstants.A_COLOR, -1);
String view = action.getAttribute(MailConstants.A_DEFAULT_VIEW, null);
Element eAcl = action.getOptionalElement(MailConstants.E_ACL);
ACL acl = null;
if (eAcl != null) {
acl = parseACL(eAcl, view == null ? mbox.getFolderById(octxt, iid.getId()).getDefaultView() : MailItem.Type.of(view), mbox.getAccount());
}
if (color >= 0) {
mbox.setColor(octxt, iid.getId(), MailItem.Type.FOLDER, color);
}
if (acl != null) {
mbox.setPermissions(octxt, iid.getId(), acl);
}
if (flags != null) {
mbox.setTags(octxt, iid.getId(), MailItem.Type.FOLDER, Flag.toBitmask(flags), null, null);
}
if (view != null) {
mbox.setFolderDefaultView(octxt, iid.getId(), MailItem.Type.of(view));
}
if (newName != null) {
mbox.rename(octxt, iid.getId(), MailItem.Type.FOLDER, newName, iidFolder.getId());
} else if (iidFolder.getId() > 0) {
mbox.move(octxt, iid.getId(), MailItem.Type.FOLDER, iidFolder.getId(), null);
}
} else if (operation.equals(OP_SYNCON) || operation.equals(OP_SYNCOFF)) {
mbox.alterTag(octxt, iid.getId(), MailItem.Type.FOLDER, Flag.FlagInfo.SYNC, operation.equals(OP_SYNCON), null);
} else if (operation.equals(OP_RETENTIONPOLICY)) {
mbox.setRetentionPolicy(octxt, iid.getId(), MailItem.Type.FOLDER, new RetentionPolicy(action.getElement(MailConstants.E_RETENTION_POLICY)));
} else if (operation.equals(OP_DISABLE_ACTIVESYNC) || operation.equals(OP_ENABLE_ACTIVESYNC)) {
mbox.setActiveSyncDisabled(octxt, iid.getId(), operation.equals(OP_DISABLE_ACTIVESYNC));
} else if (operation.equals(OP_WEBOFFLINESYNCDAYS)) {
mbox.setFolderWebOfflineSyncDays(octxt, iid.getId(), action.getAttributeInt(MailConstants.A_NUM_DAYS));
} else {
throw ServiceException.INVALID_REQUEST("unknown operation: " + operation, null);
}
return ifmt.formatItemId(iid);
}
use of com.zimbra.cs.account.Group in project zm-mailbox by Zimbra.
the class SendShareNotification method validateRequest.
private Collection<ShareInfoData> validateRequest(ZimbraSoapContext zsc, Map<String, Object> context, OperationContext octxt, Mailbox mbox, Element request) throws ServiceException {
Element eShare = request.getOptionalElement(MailConstants.E_SHARE);
if (eShare != null) {
return Arrays.asList(validateShareRecipient(zsc, context, octxt, mbox, eShare));
}
String action = request.getAttribute(MailConstants.A_ACTION, null);
ArrayList<ShareInfoData> shareInfos = new ArrayList<ShareInfoData>();
SendShareNotificationRequest req = JaxbUtil.elementToJaxb(request);
ItemId iid = new ItemId(req.getItem().getId(), zsc);
MailItem item = mbox.getItemById(octxt, iid.getId(), MailItem.Type.UNKNOWN);
Provisioning prov = Provisioning.getInstance();
Account account = getRequestedAccount(zsc);
if (item instanceof Mountpoint) {
Mountpoint mp = (Mountpoint) item;
account = prov.get(AccountBy.id, mp.getOwnerId());
}
for (EmailAddrInfo email : req.getEmailAddresses()) {
// add the non-existing grantee as type GRANTEE_GUEST for share notification.
// for revoke notifications return the non-existing grantees only
Pair<NamedEntry, String> grantee;
boolean guestGrantee = false;
byte granteeType = ACL.GRANTEE_USER;
String granteeId = null;
String granteeEmail = email.getAddress();
String granteeDisplayName = null;
try {
grantee = getGrantee(zsc, granteeType, granteeId, granteeEmail);
NamedEntry entry = grantee.getFirst();
if (entry instanceof MailTarget) {
Domain domain = prov.getDomain(account);
String granteeDomainName = ((MailTarget) entry).getDomainName();
if (domain.isInternalSharingCrossDomainEnabled() || domain.getName().equals(granteeDomainName) || Sets.newHashSet(domain.getInternalSharingDomain()).contains(granteeDomainName)) {
if (entry instanceof Group) {
granteeType = ACL.GRANTEE_GROUP;
}
granteeId = entry.getId();
granteeDisplayName = grantee.getSecond();
} else {
guestGrantee = true;
}
}
} catch (ServiceException e) {
if (!e.getCode().equals(MailServiceException.NO_SUCH_GRANTEE)) {
throw e;
}
guestGrantee = true;
}
if (guestGrantee) {
granteeType = ACL.GRANTEE_GUEST;
// if guest, granteeId is the same as granteeEmail
granteeId = granteeEmail;
}
shareInfos.add(getShareInfoData(zsc, context, account, octxt, granteeType, granteeEmail, granteeId, granteeDisplayName, item, REVOKE.equals(action)));
}
return shareInfos;
}
Aggregations