use of org.bedework.calfacade.BwEventProxy in project bw-calendar-engine by Bedework.
the class BwSysIntfImpl method addEvent.
/* ====================================================================
* Events
* ==================================================================== */
/* (non-Javadoc)
* @see org.bedework.caldav.server.SysIntf#addEvent(org.bedework.caldav.server.CalDAVEvent, boolean, boolean)
*/
@Override
public Collection<CalDAVEvent> addEvent(final CalDAVEvent ev, final boolean noInvites, final boolean rollbackOnError) throws WebdavException {
try {
/* Is the event a scheduling object? */
final EventInfo ei = getEvinfo(ev);
final Collection<BwEventProxy> bwevs = getSvci().getEventsHandler().add(ei, noInvites, // scheduling - inbox
false, // autocreate
false, rollbackOnError).failedOverrides;
if (bwevs == null) {
return null;
}
final Collection<CalDAVEvent> evs = new ArrayList<CalDAVEvent>();
for (final BwEvent bwev : bwevs) {
evs.add(new BwCalDAVEvent(this, new EventInfo(bwev)));
}
return evs;
} catch (final CalFacadeAccessException cfae) {
throw new WebdavForbidden();
} catch (final CalFacadeException cfe) {
if (CalFacadeException.schedulingTooManyAttendees.equals(cfe.getDetailMessage())) {
throw new WebdavForbidden(CaldavTags.maxAttendeesPerInstance, ev.getParentPath() + "/" + cfe.getExtra());
}
if (CalFacadeException.invalidOverride.equals(cfe.getDetailMessage())) {
throw new WebdavForbidden(CaldavTags.validCalendarData, ev.getParentPath() + "/" + cfe.getExtra());
}
if (CalFacadeException.duplicateGuid.equals(cfe.getDetailMessage())) {
throw new WebdavForbidden(CaldavTags.noUidConflict, ev.getParentPath() + "/" + cfe.getExtra());
}
if (CalFacadeException.duplicateName.equals(cfe.getDetailMessage())) {
throw new WebdavForbidden(CaldavTags.noUidConflict, ev.getParentPath() + "/" + ev.getName());
}
throw new WebdavException(cfe);
} catch (Throwable t) {
throw new WebdavException(t);
}
}
use of org.bedework.calfacade.BwEventProxy in project bw-calendar-engine by Bedework.
the class CalintfHelper method postGetEvent.
/* Post processing of event access has been checked
*/
protected CoreEventInfo postGetEvent(final BwEvent ev, final Filters f, final Acl.CurrentAccess ca) throws CalFacadeException {
/* XXX-ALARM
if (currentMode == userMode) {
ev.setAlarms(getAlarms(ev, user));
}
*/
BwEvent event;
if (ev instanceof BwEventAnnotation) {
event = new BwEventProxy((BwEventAnnotation) ev);
if ((f != null) && !f.postFilter(ev, currentPrincipal())) {
return null;
}
} else {
event = ev;
}
CoreEventInfo cei = new CoreEventInfo(event, ca);
return cei;
}
use of org.bedework.calfacade.BwEventProxy in project bw-calendar-engine by Bedework.
the class BwIndexEsImpl method getSearchResult.
@Override
public List<SearchResultEntry> getSearchResult(final SearchResult sres, final int offset, final int num, final int desiredAccess) throws CalFacadeException {
if (debug) {
debug("offset: " + offset + ", num: " + num);
}
final EsSearchResult res = (EsSearchResult) sres;
res.pageStart = offset;
final SearchRequestBuilder srb = getClient().prepareSearch(searchIndexes);
if (res.curQuery != null) {
srb.setQuery(res.curQuery);
}
srb.setSearchType(SearchType.QUERY_THEN_FETCH).setPostFilter(res.curFilter).setFrom(res.pageStart);
final int size;
if (num < 0) {
size = (int) sres.getFound();
} else {
size = num;
}
// TODO - need a configurable absolute max size for fetches
srb.setSize(size);
final List<SearchResultEntry> entities = new ArrayList<>(size);
if (!Util.isEmpty(res.curSort)) {
SortOrder so;
for (final SortTerm st : res.curSort) {
if (st.isAscending()) {
so = SortOrder.ASC;
} else {
so = SortOrder.DESC;
}
srb.addSort(new FieldSortBuilder(ESQueryFilter.makePropertyRef(st.getProperties())).order(so));
}
}
if (res.requiresSecondaryFetch) {
// Limit to href then fetch those
srb.addField(ESQueryFilter.hrefJname);
}
final SearchResponse resp = srb.execute().actionGet();
if (resp.status() != RestStatus.OK) {
if (debug) {
debug("Search returned status " + resp.status());
}
}
final SearchHits hitsResp = resp.getHits();
if ((hitsResp.getHits() == null) || (hitsResp.getHits().length == 0)) {
return entities;
}
// Break condition: No hits are returned
if (hitsResp.hits().length == 0) {
return entities;
}
final List<SearchHit> hits;
if (res.requiresSecondaryFetch) {
hits = multiFetch(hitsResp, res.recurRetrieval);
if (hits == null) {
return entities;
}
} else {
hits = Arrays.asList(hitsResp.getHits());
}
final Map<String, Collection<BwEventAnnotation>> overrides = new HashMap<>();
final Collection<EventInfo> masters = new TreeSet<>();
EntityBuilder.checkFlushCache(currentChangeToken());
/* If we are retrieving events with a time range query and we are asking for the
* master + overrides then we need to check that the master really has an
* instance in the given time range */
final boolean checkTimeRange = (res.recurRetrieval.mode == Rmode.overrides) && ((res.latestStart != null) || (res.earliestEnd != null));
final Set<String> excluded = new TreeSet<>();
for (final SearchHit hit : hits) {
res.pageStart++;
final String dtype = hit.getType();
if (dtype == null) {
throw new CalFacadeException("org.bedework.index.noitemtype");
}
final String kval = hit.getId();
if (kval == null) {
throw new CalFacadeException("org.bedework.index.noitemkey");
}
final EntityBuilder eb = getEntityBuilder(hit.sourceAsMap());
Object entity = null;
switch(dtype) {
case docTypeCollection:
entity = eb.makeCollection();
break;
case docTypeCategory:
entity = eb.makeCat();
break;
case docTypeContact:
entity = eb.makeContact();
break;
case docTypeLocation:
entity = eb.makeLocation();
break;
case docTypeEvent:
case docTypePoll:
entity = eb.makeEvent(kval, res.recurRetrieval.mode == Rmode.expanded);
final EventInfo ei = (EventInfo) entity;
final BwEvent ev = ei.getEvent();
final Response evrestResp = new Response();
restoreEvProps(evrestResp, ei);
if (evrestResp.getStatus() != ok) {
warn("Failed restore of ev props: " + evrestResp);
}
final Acl.CurrentAccess ca = res.accessCheck.checkAccess(ev, desiredAccess, true);
if ((ca == null) || !ca.getAccessAllowed()) {
continue;
}
ei.setCurrentAccess(ca);
if (ev instanceof BwEventAnnotation) {
if (excluded.contains(ev.getUid())) {
continue;
}
// Treat as override
final Collection<BwEventAnnotation> ov = overrides.computeIfAbsent(ev.getHref(), k -> new TreeSet<>());
ov.add((BwEventAnnotation) ev);
continue;
}
if (checkTimeRange && dtype.equals(docTypeEvent) && ev.getRecurring()) {
if (Util.isEmpty(RecurUtil.getPeriods(ev, 99, 1, res.latestStart, res.earliestEnd).instances)) {
excluded.add(ev.getUid());
continue;
}
}
masters.add(ei);
break;
}
entities.add(new SearchResultEntry(entity, dtype, hit.getScore()));
}
for (final EventInfo ei : masters) {
final BwEvent ev = ei.getEvent();
if (ev.getRecurring()) {
final Collection<BwEventAnnotation> ov = overrides.get(ev.getHref());
if (ov != null) {
for (final BwEventAnnotation ann : ov) {
final BwEvent proxy = new BwEventProxy(ann);
ann.setTarget(ev);
ann.setMaster(ev);
final EventInfo oei = new EventInfo(proxy);
ei.addOverride(oei);
}
}
}
}
return entities;
}
use of org.bedework.calfacade.BwEventProxy in project bw-calendar-engine by Bedework.
the class CoreEvents method makeInstanceProxy.
/**
* The master has been checked for access and we now build and
* return an event proxy for an instance which has no override.
*
* @param inst the instance
* @param ca Checked access from master
* @return CoreEventInfo
* @throws CalFacadeException on error
*/
private CoreEventInfo makeInstanceProxy(final BwRecurrenceInstance inst, final CurrentAccess ca) throws CalFacadeException {
final BwEvent mstr = inst.getMaster();
/*
if (recurRetrieval.mode == Rmode.masterOnly) {
// Master only and we've just seen it for the first time
// Note we will not do this for freebusy. We need all recurrences.
/* XXX I think this was wrong. Why make an override?
* /
// make a fake one pointing at the owners override
override = new BwEventAnnotation();
override.setTarget(mstr);
override.setMaster(mstr);
BwDateTime start = mstr.getDtstart();
BwDateTime end = mstr.getDtend();
override.setDtstart(start);
override.setDtend(end);
override.setDuration(BwDateTime.makeDuration(start, end).toString());
override.setCreatorHref(mstr.getCreatorHref());
override.setOwnerHref(getUser().getPrincipalRef());
return new CoreEventInfo(new BwEventProxy(override), ca);
}
*/
/* success so now we build a proxy with the event and any override.
*/
final BwEventAnnotation override = new BwEventAnnotation();
override.setTarget(mstr);
override.setMaster(mstr);
final BwDateTime start = inst.getDtstart();
final BwDateTime end = inst.getDtend();
override.setRecurrenceId(inst.getRecurrenceId());
override.setDtstart(start);
override.setDtend(end);
override.setDuration(BwDateTime.makeDuration(start, end).toString());
override.setCreatorHref(mstr.getCreatorHref());
override.setOwnerHref(mstr.getOwnerHref());
override.setOverride(true);
override.setName(mstr.getName());
override.setUid(mstr.getUid());
/* At this point we have an event with possible overrides. If this is free
* busy we need to replace it all with a skeleton event holding only date/time
* information.
*
* We can't do this before I think because we need to allow the user to
* override the transparency on a particular instance,
*/
final BwEvent proxy = new BwEventProxy(override);
return new CoreEventInfo(proxy, ca);
}
use of org.bedework.calfacade.BwEventProxy in project bw-calendar-engine by Bedework.
the class CoreEvents method updateEvent.
@Override
public UpdateEventResult updateEvent(final EventInfo ei) throws CalFacadeException {
final BwEvent val = ei.getEvent();
final Collection<BwEventProxy> overrides = ei.getOverrideProxies();
final Collection<BwEventProxy> deletedOverrides = ei.getDeletedOverrideProxies(cb.getPrincipalInfo().getPrincipal().getPrincipalRef());
final UpdateEventResult ue = new UpdateEventResult();
if (!ac.checkAccess(val, privWrite, true).getAccessAllowed()) {
// XXX Is this correct?
try {
ac.checkAccess(val, privWriteContent, false);
} catch (final CalFacadeException cfe) {
throwException(cfe);
}
}
BwEventProxy proxy = null;
if (val instanceof BwEventProxy) {
proxy = (BwEventProxy) val;
}
final BwCalendar col = getCollection(val.getColPath());
final boolean shared = col.getPublick() || col.getShared();
if ((proxy != null) && (proxy.getRef().getOverride())) {
final BwEventAnnotation ann = proxy.getRef();
final BwEvent mstr = ann.getMaster();
if (!proxy.getUid().equals(mstr.getUid())) {
throwException("org.bedework.cannot.overrideuid");
}
if (!proxy.getName().equals(mstr.getName())) {
throwException("org.bedework.cannot.overridename");
}
} else {
/* The guid must not exist in the same calendar. We assign a guid if
* one wasn't assigned already. However, the event may have come with a guid
* (caldav, import, etc) so we need to check here.
*
* It also ensures our guid allocation is working OK
*/
final CollectionInfo collInf = col.getCollectionInfo();
if (collInf.uniqueKey) {
String name = calendarGuidExists(val, false, false);
if (name == null) {
name = calendarGuidExists(val, true, false);
}
if (name != null) {
throwException(CalFacadeException.duplicateGuid, name);
}
}
/* Similarly for event names which must be unique within a collection
*/
if (calendarNameExists(val, false, false) || calendarNameExists(val, true, false)) {
throwException(new CalFacadeDupNameException(val.getName()));
}
}
if (!(val instanceof BwEventProxy)) {
dao.update(val);
final Collection<BwDbentity<?>> deleted = val.getDeletedEntities();
if (deleted != null) {
for (final BwDbentity ent : deleted) {
dao.delete(ent);
}
deleted.clear();
}
if (val.testRecurring()) {
if (!Util.isEmpty(overrides)) {
for (final BwEventProxy pxy : overrides) {
final BwEventAnnotation ann = pxy.getRef();
boolean updated = false;
if ((ann.getRecurring() != null) && ann.getRecurring()) {
// be safe
ann.setRecurring(false);
updated = true;
}
if (ann.getTombstoned() == null) {
// be safe
ann.setTombstoned(false);
updated = true;
}
if (ann.unsaved()) {
dao.save(ann);
} else if (updated) {
updateProxy(new BwEventProxy(ann));
}
}
}
updateRecurrences(ei, ue, overrides, shared);
}
if (!val.testRecurring() || (Util.isEmpty(overrides) && Util.isEmpty(deletedOverrides))) {
notify(SysEvent.SysCode.ENTITY_UPDATED, val, shared);
indexEntity(ei);
return ue;
}
if (!Util.isEmpty(overrides)) {
updateOverrides: for (final BwEventProxy pxy : overrides) {
final BwEventAnnotation ann = pxy.getRef();
if (ue.deleted != null) {
for (final BwRecurrenceInstance ri : ue.deleted) {
if (ri.getRecurrenceId().equals(ann.getRecurrenceId())) {
continue updateOverrides;
}
}
}
if (ue.added != null) {
for (final BwRecurrenceInstance ri : ue.added) {
if (ri.getRecurrenceId().equals(ann.getRecurrenceId())) {
continue updateOverrides;
}
}
}
// be safe
ann.setRecurring(false);
if (ann.getTombstoned() == null) {
// be safe
ann.setTombstoned(false);
}
if (!ann.unsaved()) {
updateProxy(new BwEventProxy(ann));
} else {
dao.save(ann);
/* See if there is an instance for this override
*/
BwRecurrenceInstance ri = dao.getInstance(val, ann.getRecurrenceId());
if (ri == null) {
final BwDateTime rid = BwDateTime.fromUTC(ann.getRecurrenceId().length() == 8, ann.getRecurrenceId());
final Dur dur = new Dur(val.getDuration());
final BwDateTime end = rid.addDur(dur);
ri = new BwRecurrenceInstance();
ri.setDtstart(rid);
ri.setDtend(end);
ri.setRecurrenceId(rid.getDate());
ri.setMaster(val);
ri.setOverride(ann);
dao.save(ri);
} else {
ri.setOverride(ann);
dao.update(ri);
}
}
notifyInstanceChange(SysEvent.SysCode.ENTITY_UPDATED, val, shared, ann.getRecurrenceId());
}
}
if (!Util.isEmpty(deletedOverrides)) {
final Collection<String> rids = new ArrayList<>();
for (final BwEventProxy pxy : deletedOverrides) {
rids.add(pxy.getRecurrenceId());
}
removeInstances(val, rids, ue, deletedOverrides, shared);
}
} else {
if (proxy.getChangeFlag()) {
updateProxy(proxy);
}
}
notify(SysEvent.SysCode.ENTITY_UPDATED, val, shared);
if (proxy != null) {
if (ei.getRetrievedEvent() == null) {
warn("No retrieved event for indexer");
} else {
final EventInfo rei = ei.getRetrievedEvent();
rei.addOverride(ei);
indexEntity(rei);
}
} else {
indexEntity(ei);
}
return ue;
}
Aggregations