/// <summary> /// Creates a new reservation. /// </summary> /// <param name="boat">The id of the boat to be reserved.</param> /// <param name="userId">The user creating the reservation.</param> /// <param name="start">The reservation start time.</param> /// <param name="duration">The reservation duration.</param> /// <param name="title">An optional title for the reservation.</param> /// <param name="description">An optional description for the reservation.</param> /// <param name="secondUserId">An optional second user for pairs and doubles.</param> /// <returns>A task containing the data for the created reservation.</returns> public virtual async Task<JToken> CreateReservationAsync( JToken boat, long userId, DateTimeOffset start, TimeSpan duration, string title = null, string description = null, long? secondUserId = null) { using (var client = this.GetHttpClient()) { StringBuilder sb = new StringBuilder(); sb.Append("{"); if (!string.IsNullOrEmpty(title)) { sb.Append($"\"title\": \"{title}\", "); } if (!string.IsNullOrEmpty(title)) { sb.Append($"\"description\": \"{description}\", "); } sb.Append($"\"userId\": {userId}, "); if (secondUserId.HasValue) { sb.Append($"\"participants\": [{secondUserId.Value}], "); } sb.Append($"\"resourceId\": {boat.ResourceId()}, "); sb.Append($"\"startDateTime\": \"{start.ToString("s")}{start.ToString("zzz")}\", "); var end = start + duration; sb.Append($"\"endDateTime\": \"{end.ToString("s")}{end.ToString("zzz")}\""); sb.Append("}"); var requestBody = sb.ToString(); var httpResponse = await client.PostAsync($"Reservations/", new StringContent(requestBody)); await this.CheckResponseAsync(httpResponse); return JToken.Parse(await httpResponse.Content.ReadAsStringAsync()); } }
/// <summary> /// Check to see whether a user has permission to use a boat. By default, we check the /// user in the given UserState. But if a partnerUserId is provided, we check their /// permission instead. /// </summary> /// <param name="userState">The state for the calling user</param> /// <param name="resource">The resource that they want to access</param> /// <param name="partnerUserId">If given, check permission for this user.</param> /// <returns>Task that completes with true if the user has permission for the resource.</returns> public static async Task<bool> HasPermissionForResourceAsync(this UserState userState, JToken resource, long? partnerUserId = null) { var cache = BookedSchedulerCache.Instance[userState.ClubId]; var user = await cache.GetUserAsync(partnerUserId ?? userState.UserId); var resourceId = resource.ResourceId(); // See if the user is granted permission to the resource directly. var okByUser = user .Value<JArray>("permissions") .Any(r => r.Id() == resourceId); if (okByUser) { return true; } // See if any of the user's group memberships grant permission to the resource foreach (var group in user.Value<JArray>("groups")) { var groupNode = await cache.GetGroupAsync(group.Id()); var okByGroup = groupNode .Value<JArray>("permissions") .Any(r => r.Value<string>().EndsWith($"/{resourceId}")); if (okByGroup) { return true; } } return false; }
public static async Task<string> DescribeReservationAsync( this UserState userState, JToken reservation, int index, bool showOwner, bool showDate, bool showIndex, bool useMarkdown) { var startDate = userState.ConvertToLocalTime(reservation.StartDate()); var duration = reservation.Value<string>("duration"); var boatName = await BookedSchedulerCache .Instance[userState.ClubId] .GetResourceNameFromIdAsync(reservation.ResourceId()); string owner = string.Empty; if (showOwner) { owner = $" {reservation.FirstName()} {reservation.LastName()}"; } string partnerName = string.Empty; // // Getting the participant list is messy. When it's empty, it looks like an empty // array. When there are participants, it looks like an object with each key/value // pair consisting of the user id and the full user name. This is probably a bug so // we also try to handle the case that we expected (array of integer user id's). // if (reservation["participants"] is JArray) { var participants = (JArray)reservation["participants"]; if (participants.Count > 0) { var partnerRef = participants[0]; var partnerUser = await BookedSchedulerCache.Instance[userState.ClubId].GetUserAsync(partnerRef.UserId()); partnerName = $" w/ {partnerUser.FullName()}"; } } else if (reservation["participants"] is JObject) { var participants = (JObject)reservation["participants"]; foreach (var kv in participants) { var partnerId = long.Parse(kv.Key); var partnerUser = await BookedSchedulerCache.Instance[userState.ClubId].GetUserAsync(partnerId); partnerName = $" w/ {partnerUser.FullName()}"; break; } } if (useMarkdown) { return string.Format( "{0}**{1} {2}** {3}{4} *({5})*{6}", showIndex ? $"**{index}**: " : string.Empty, showDate ? startDate.ToLocalTime().ToString("d") : string.Empty, startDate.ToLocalTime().ToString("t"), boatName, partnerName, duration, owner); } else { return string.Format( "{0}{1} {2} {3}{4} ({5}) {6}", showIndex ? $"{index}: " : string.Empty, showDate ? startDate.ToLocalTime().ToString("d") : string.Empty, startDate.ToLocalTime().ToString("t"), boatName, partnerName, duration, owner); } }
public static async Task<string> SummarizeReservationAsync(this UserState userState, JToken reservation) { var startDate = userState.ConvertToLocalTime(reservation.StartDate()); var boatName = await BookedSchedulerCache .Instance[userState.ClubId] .GetResourceNameFromIdAsync(reservation.ResourceId()); return string.Format( "{0} {1} {2}", startDate.ToLocalTime().ToString("d"), startDate.ToLocalTime().ToString("t"), boatName); }