Class Utils
-
Field Summary
FieldsModifier and TypeFieldDescriptionstatic final Stringstatic final Stringstatic final org.exoplatform.social.metadata.model.MetadataKeystatic final Stringstatic final org.exoplatform.social.metadata.model.MetadataTypestatic final Stringstatic final Stringstatic final Stringstatic final Stringstatic final Stringstatic final Stringstatic final Stringstatic final Stringstatic final Stringstatic final String -
Method Summary
Modifier and TypeMethodDescriptionstatic voidaddUserSpacesIdentities(org.exoplatform.social.core.space.spi.SpaceService spaceService, org.exoplatform.social.core.manager.IdentityManager identityManager, String username, List<Long> identityIds) static voidbroadcastEvent(org.exoplatform.services.listener.ListenerService listenerService, String eventName, Object source, Object data) static StringbuildGuestResponseConfirmationPage(org.exoplatform.agenda.constant.EventAttendeeResponse response, Locale locale) Builds the minimal HTML page acknowledging an answer given through a tokenised invitation link, naming the answer that was recorded.static StringbuildInvitationExpiredPage(Locale locale, String eventUrl) Builds the page shown to somebody who follows an invitation link whose meeting is over.static booleancanAccessCalendar(org.exoplatform.social.core.manager.IdentityManager identityManager, org.exoplatform.social.core.space.spi.SpaceService spaceService, long ownerId, long userIdentityId) static booleancanCreateEvent(org.exoplatform.social.core.manager.IdentityManager identityManager, org.exoplatform.social.core.space.spi.SpaceService spaceService, long ownerId, long userIdentityId) static booleancanEditCalendar(org.exoplatform.social.core.manager.IdentityManager identityManager, org.exoplatform.social.core.space.spi.SpaceService spaceService, long ownerId, long userIdentityId) static booleancanInviteeEdit(org.exoplatform.social.core.manager.IdentityManager identityManager, org.exoplatform.social.core.space.spi.SpaceService spaceService, long ownerId) static booleancanPublishCalendar(org.exoplatform.social.core.manager.IdentityManager identityManager, org.exoplatform.social.core.space.spi.SpaceService spaceService, long ownerId, long userIdentityId) Whether a user may publish a calendar as a private link, and so read, create, reset or delete that link (EXO-90252).static voidcheckAclByCalendarOwner(org.exoplatform.social.core.manager.IdentityManager identityManager, org.exoplatform.social.core.space.spi.SpaceService spaceService, long ownerId, String username) static voiddetectEventModifiedFields(org.exoplatform.agenda.model.Event newEvent, org.exoplatform.agenda.model.Event oldEvent, org.exoplatform.agenda.model.AgendaEventModification eventModification) static StringescapeEmoticons(String text) Replaces every non-ASCII character by its HTML numeric entity, so an emoji survives a mail body that is not read as UTF-8.static byte[]generateIcsFile(String eventId, String ownerId, String eventSummary, String eventDescription, String startDateRFC3339, String endDateRFC3339, String eventConference, String eventModifierId, String eventCreatorFullName, String location, String eventUrl, org.exoplatform.agenda.constant.EventAvailability availability, Locale userLocale, ZoneId timeZone) Builds the iCalendar document eXo attaches to the mail that announces an event.getCalendarOwnersOfUser(org.exoplatform.social.core.space.spi.SpaceService spaceService, org.exoplatform.social.core.manager.IdentityManager identityManager, org.exoplatform.social.core.identity.model.Identity userIdentity) static net.fortuna.ical4j.model.RecurgetICalendarRecur(org.exoplatform.agenda.model.EventRecurrence recurrence, ZoneId zoneId) static net.fortuna.ical4j.model.TimeZonegetICalTimeZone(ZoneId zoneId) static org.exoplatform.social.core.identity.model.IdentitygetIdentityById(org.exoplatform.social.core.manager.IdentityManager identityManager, long identityId) static org.exoplatform.social.core.identity.model.IdentitygetIdentityById(org.exoplatform.social.core.manager.IdentityManager identityManager, String identityId) static longgetIdentityIdByUsername(org.exoplatform.social.core.manager.IdentityManager identityManager, String username) static ZonedDateTimegetOccurrenceId(boolean allDay, ZonedDateTime eventStartDate, ZoneId eventStartDateTimeZone) static ZonedDateTimegetOccurrenceId(boolean allDay, net.fortuna.ical4j.model.DateTime eventStartDate, ZoneId eventStartDateTimeZone) static List<org.exoplatform.agenda.model.Event> getOccurrences(org.exoplatform.agenda.model.Event event, LocalDate from, LocalDate to, int limit) static StringgetResourceBundleLabel(Locale locale, String label) getSpaceMembersBySpaceName(String spaceName, org.exoplatform.social.core.space.spi.SpaceService spaceService) static StringgetUserLanguage(String userId) Gets platform language of user.static longinvitationTokenExpiry(org.exoplatform.agenda.model.Event event) The instant past which a tokenised invitation link for this event stops being honoured.static booleanisEventAttendee(org.exoplatform.social.core.manager.IdentityManager identityManager, org.exoplatform.social.core.space.spi.SpaceService spaceService, long identityId, List<org.exoplatform.agenda.model.EventAttendee> eventAttendees) static booleanisEventAttendee(org.exoplatform.social.core.manager.IdentityManager identityManager, org.exoplatform.social.core.space.spi.SpaceService spaceService, long identityId, org.exoplatform.agenda.model.EventAttendeeList eventAttendeeList) static booleanisExternal(String userId) static org.exoplatform.agenda.model.EventmaskForAccess(org.exoplatform.agenda.model.Event event, org.exoplatform.agenda.constant.EventAccess access) Renders an event for the access its reader has (EXO-90357): the access is stamped on the event, and aEventVisibility.PRIVATEevent read through a view share alone becomes busy time — summary, description, location and parameters cleared, markedmaskedso that every render path leaves out what it would otherwise read again by identifier (attendees, conferences, reminders, date options).static ZonedDateTimetoDateTime(String dateTimeString, ZoneId userTimeZone)
-
Field Details
-
EVENT_METADATA_NAME
- See Also:
-
EVENT_METADATA_TYPE
public static final org.exoplatform.social.metadata.model.MetadataType EVENT_METADATA_TYPE -
EVENT_METADATA_KEY
public static final org.exoplatform.social.metadata.model.MetadataKey EVENT_METADATA_KEY -
EVENT_ID
- See Also:
-
CONTENT_ID
- See Also:
-
POST_CREATE_AGENDA_EVENT_EVENT
- See Also:
-
POST_UPDATE_AGENDA_EVENT_EVENT
- See Also:
-
POST_DELETE_AGENDA_EVENT_EVENT
- See Also:
-
POST_MOVE_AGENDA_EVENT_EVENT
- See Also:
-
POST_EVENT_RESPONSE_SENT
- See Also:
-
POST_EVENT_RESPONSE_SAVED
- See Also:
-
POST_CREATE_AGENDA_EVENT_POLL
- See Also:
-
POST_VOTES_AGENDA_EVENT_POLL
- See Also:
-
POST_VOTE_AGENDA_EVENT_POLL
- See Also:
-
POST_DISMISS_AGENDA_EVENT_POLL
- See Also:
-
-
Method Details
-
getCalendarOwnersOfUser
-
addUserSpacesIdentities
public static void addUserSpacesIdentities(org.exoplatform.social.core.space.spi.SpaceService spaceService, org.exoplatform.social.core.manager.IdentityManager identityManager, String username, List<Long> identityIds) throws Exception - Throws:
Exception
-
getOccurrences
-
getOccurrenceId
public static ZonedDateTime getOccurrenceId(boolean allDay, net.fortuna.ical4j.model.DateTime eventStartDate, ZoneId eventStartDateTimeZone) -
getOccurrenceId
public static ZonedDateTime getOccurrenceId(boolean allDay, ZonedDateTime eventStartDate, ZoneId eventStartDateTimeZone) -
getICalendarRecur
public static net.fortuna.ical4j.model.Recur getICalendarRecur(org.exoplatform.agenda.model.EventRecurrence recurrence, ZoneId zoneId) -
checkAclByCalendarOwner
public static void checkAclByCalendarOwner(org.exoplatform.social.core.manager.IdentityManager identityManager, org.exoplatform.social.core.space.spi.SpaceService spaceService, long ownerId, String username) throws IllegalAccessException - Parameters:
identityManager-IdentityManagerservice instancespaceService-SpaceServiceservice instanceownerId- calendar ownerIdentitytechnical identifierusername- name of user accessing calendar data- Throws:
IllegalAccessException- when the user ACL fails
-
canCreateEvent
public static boolean canCreateEvent(org.exoplatform.social.core.manager.IdentityManager identityManager, org.exoplatform.social.core.space.spi.SpaceService spaceService, long ownerId, long userIdentityId) - Parameters:
identityManager-IdentityManagerservice instancespaceService-SpaceServiceservice instanceownerId- calendar ownerIdentitytechnical identifieruserIdentityId-Identityidentifier of user accessing calendar data- Returns:
- true if user can create event in a calendar, else return false
-
canInviteeEdit
public static boolean canInviteeEdit(org.exoplatform.social.core.manager.IdentityManager identityManager, org.exoplatform.social.core.space.spi.SpaceService spaceService, long ownerId) - Parameters:
identityManager-IdentityManagerservice instancespaceService-SpaceServiceservice instanceownerId- calendar ownerIdentitytechnical identifier- Returns:
- true if owner is a space and has at least one redactor, else return false
-
canEditCalendar
public static boolean canEditCalendar(org.exoplatform.social.core.manager.IdentityManager identityManager, org.exoplatform.social.core.space.spi.SpaceService spaceService, long ownerId, long userIdentityId) - Parameters:
identityManager-IdentityManagerservice instancespaceService-SpaceServiceservice instanceownerId- calendar ownerIdentitytechnical identifieruserIdentityId-Identityidentifier of user accessing calendar data- Returns:
- true if user can modify calendar or its events, else return false
-
canPublishCalendar
public static boolean canPublishCalendar(org.exoplatform.social.core.manager.IdentityManager identityManager, org.exoplatform.social.core.space.spi.SpaceService spaceService, long ownerId, long userIdentityId) Whether a user may publish a calendar as a private link, and so read, create, reset or delete that link (EXO-90252).A personal calendar: its owner. A space calendar: a real manager of the space — a member holding the manager role, social's
isMember(space, user) && isManager(space, user). Deliberately notcanEditCalendar(org.exoplatform.social.core.manager.IdentityManager, org.exoplatform.social.core.space.spi.SpaceService, long, long), whoseSpaceService.canManageSpacealso admits super-managers (platform administrators, holders of the space template's admin permission) who are not managers of that space: a link anyone can read from outside eXo is published by the people who run the space, and only while they do.- Parameters:
identityManager-IdentityManagerservice instancespaceService-SpaceServiceservice instanceownerId- calendar ownerIdentitytechnical identifieruserIdentityId-Identityidentifier of the user- Returns:
- true when the user may publish the calendar
-
canAccessCalendar
public static boolean canAccessCalendar(org.exoplatform.social.core.manager.IdentityManager identityManager, org.exoplatform.social.core.space.spi.SpaceService spaceService, long ownerId, long userIdentityId) - Parameters:
identityManager-IdentityManagerservice instancespaceService-SpaceServiceservice instanceownerId- calendar ownerIdentitytechnical identifieruserIdentityId-Identityidentifier of user accessing calendar data- Returns:
- true if user can access calendar or its events, else return false
-
broadcastEvent
-
getIdentityById
public static org.exoplatform.social.core.identity.model.Identity getIdentityById(org.exoplatform.social.core.manager.IdentityManager identityManager, long identityId) -
getIdentityById
public static org.exoplatform.social.core.identity.model.Identity getIdentityById(org.exoplatform.social.core.manager.IdentityManager identityManager, String identityId) -
getIdentityIdByUsername
public static long getIdentityIdByUsername(org.exoplatform.social.core.manager.IdentityManager identityManager, String username) -
getSpaceMembersBySpaceName
-
isEventAttendee
public static boolean isEventAttendee(org.exoplatform.social.core.manager.IdentityManager identityManager, org.exoplatform.social.core.space.spi.SpaceService spaceService, long identityId, org.exoplatform.agenda.model.EventAttendeeList eventAttendeeList) -
isEventAttendee
public static boolean isEventAttendee(org.exoplatform.social.core.manager.IdentityManager identityManager, org.exoplatform.social.core.space.spi.SpaceService spaceService, long identityId, List<org.exoplatform.agenda.model.EventAttendee> eventAttendees) -
getICalTimeZone
-
toDateTime
-
detectEventModifiedFields
public static void detectEventModifiedFields(org.exoplatform.agenda.model.Event newEvent, org.exoplatform.agenda.model.Event oldEvent, org.exoplatform.agenda.model.AgendaEventModification eventModification) -
getResourceBundleLabel
-
buildGuestResponseConfirmationPage
public static String buildGuestResponseConfirmationPage(org.exoplatform.agenda.constant.EventAttendeeResponse response, Locale locale) Builds the minimal HTML page acknowledging an answer given through a tokenised invitation link, naming the answer that was recorded.It was introduced for an external attendee - a guest invited by mail address, having no account on the platform - who cannot be redirected to the event page of the portal, which would only display a login form to them (EXO-89705). Since EXO-89753 it serves a second reader with the same problem for a different reason: somebody answering from the description of their calendar copy, on a client which renders no RSVP control of its own. That reader gets no feedback whatsoever from the client they clicked in, so the page has to say what was recorded, not merely that something was - which is why the answer is named in the sentence rather than implied by the page having loaded at all.
-
buildInvitationExpiredPage
Builds the page shown to somebody who follows an invitation link whose meeting is over.The alternative was to let the refusal fall through as a bare 401, which tells its reader nothing at all: they clicked an Accept button in an invitation and got a blank error, with no way to tell whether they had answered, whether the link was broken, or whether they were looking at a fault of their own. This is the same self contained surface the confirmation above uses, saying instead that the invitation can no longer be answered here - and carrying a way into eXo, where the meeting can still be looked at and, if it has not happened yet, still be answered.
The link is offered rather than followed. Redirecting a guest, who has no account, would land them on a login form - the exact outcome EXO-89705 built this page to avoid.
- Parameters:
locale-Localeused to translate the labels of the page, the defaultLocaleof the server is used when nulleventUrl- absolute address of the event inside eXo, blank when the portal cannot be asked for one, in which case the page simply carries no link- Returns:
- the HTML content of the expired invitation page
-
invitationTokenExpiry
public static long invitationTokenExpiry(org.exoplatform.agenda.model.Event event) The instant past which a tokenised invitation link for this event stops being honoured.The bound is the meeting itself. A link exists to answer an invitation, and once the meeting is over there is no answer left to give, so nothing legitimate is lost by refusing it - while a link that outlives its meeting stays a usable "answer as this person" credential for anyone the mail was ever forwarded to (EXO-89752).
Which end. For a recurring event
Event.getEnd()is the end of the first occurrence, not of the series - the two are stored in different rows and swapped apart inEntityMapper.fromEntity(org.exoplatform.agenda.entity.EventEntity)- so bounding a series by it would kill the link after its first meeting, while an answer legitimately applies to every occurrence still to come. The series end,EventRecurrence.getOverallEnd(), is used instead.A series that never ends is already answered, and not here.
EntityMapperstoresoverallStart.plusYears(10)as the end of an endless recurrence, and reads it back intogetOverallEnd(). That is a persisted property of the event rather than a horizon invented in this method, so an endless standup gets ten years of answerable link and this code gains no second opinion about what "no end" means.Why there is a grace period at all. Expiring at the exact end would kill the link in the hand of somebody answering during the meeting's last minute, and would kill it outright for an invitation whose meeting was lengthened after the mail went out. A day covers both, plus any clock skew between the node that minted the token and the node that reads it, and is short enough that a leaked link is not a lasting credential.
It is a pure function of the event, and must stay one. The same value has to come out on every render, because the calendar copy writes these links into its DESCRIPTION and the mirror rewrites any copy whose description changed (EXO-89753, EXO-89716). Deriving the bound from "now" - a sliding window from the moment of minting - would make every sweep mint a different token and put every copy into permanent churn. Nothing in this method may read the clock.
- Parameters:
event- theEventthe invitation answers, null tolerated- Returns:
- the expiry as a number of seconds since the epoch, or 0 when the event carries no date to bound it by - which the caller must treat as "cannot be answered" rather than as "never expires"
-
getUserLanguage
Gets platform language of user. In case of any errors return null.- Parameters:
userId- user Id- Returns:
- the platform language
-
isExternal
-
generateIcsFile
public static byte[] generateIcsFile(String eventId, String ownerId, String eventSummary, String eventDescription, String startDateRFC3339, String endDateRFC3339, String eventConference, String eventModifierId, String eventCreatorFullName, String location, String eventUrl, org.exoplatform.agenda.constant.EventAvailability availability, Locale userLocale, ZoneId timeZone) Builds the iCalendar document eXo attaches to the mail that announces an event.The document is a
PUBLISHone, not aREQUEST: answering an invitation is handled by the tokenised links carried in the mail body, not by iMIP.Method.PUBLISHis written into the body so it says the same thing as themethod=PUBLISHparameter the MIME part already declares, as RFC 6047 asks.- Parameters:
eventId- identifier of the event, used to derive a UID that is stable across every mail describing this meeting (EXO-89680)ownerId- identifier of the identity owning the event's calendar, used to name the space the invitation comes fromeventSummary- event title, written asSUMMARYeventDescription- event description, HTML as the editor stored itstartDateRFC3339- event start, RFC 3339endDateRFC3339- event end, RFC 3339eventConference- conference URL, blank when the event has noneeventModifierId- identifier of the identity to write asORGANIZEReventCreatorFullName- display name of whoever sent the invitationlocation- event location, blank when the event has noneeventUrl- link back to the event in eXo, written asURLand named in the description. Blank for a recipient with no eXo account: the link resolves to a login screen for a guest, so the caller — which is the only party that knows who the mail is going to — leaves it out for one (EXO-89751)availability- whether the event takes the recipient's time, written asTRANSP.FREEis transparent, everything else — includingDEFAULTand a null — is opaque, the same readingCalendarFeedIcsWriterand the CalDAV writer use. It must be written rather than left out: RFC 5545 §3.8.2.7 makes an absentTRANSPdefault toOPAQUE, so saying nothing is saying "busy" (EXO-90327)userLocale- locale of the recipient, the one the labels are read intimeZone- time zone the dates are written in- Returns:
- the iCalendar document, UTF-8 encoded
-
escapeEmoticons
Replaces every non-ASCII character by its HTML numeric entity, so an emoji survives a mail body that is not read as UTF-8.- Parameters:
text- text to escape- Returns:
- the text with every codepoint above 127 written as an entity
-
maskForAccess
public static org.exoplatform.agenda.model.Event maskForAccess(org.exoplatform.agenda.model.Event event, org.exoplatform.agenda.constant.EventAccess access) Renders an event for the access its reader has (EXO-90357): the access is stamped on the event, and aEventVisibility.PRIVATEevent read through a view share alone becomes busy time — summary, description, location and parameters cleared, markedmaskedso that every render path leaves out what it would otherwise read again by identifier (attendees, conferences, reminders, date options). Everything else is returned as it is. The one helper every read path goes through, the service for the event it reads and the REST builder for the series it renders from an occurrence.- Parameters:
event- the event, a copy of the cached one; may be nullaccess- how the reader may read it; null leaves the event as it is- Returns:
- the same event, masked when it must be
-