diff --git a/src/Cronofy.Example/Cronofy.Example.csproj b/src/Cronofy.Example/Cronofy.Example.csproj index 28d8c3d..4c525d0 100644 --- a/src/Cronofy.Example/Cronofy.Example.csproj +++ b/src/Cronofy.Example/Cronofy.Example.csproj @@ -23,7 +23,7 @@ Exe - netcoreapp3.1 + net7 false diff --git a/src/Cronofy.Example/Program.cs b/src/Cronofy.Example/Program.cs index a2b4552..9a5610f 100644 --- a/src/Cronofy.Example/Program.cs +++ b/src/Cronofy.Example/Program.cs @@ -34,6 +34,11 @@ public static void Main(string[] args) AttachmentsExample(); return; } + else if (args.Any(t => t == "availability-rules")) + { + AvailabilityRulesExample(); + return; + } Console.Write("Enter access token: "); var accessToken = Console.ReadLine(); @@ -241,6 +246,89 @@ private static void AttachmentsExample() Console.ReadLine(); } + /// + /// Availability rules usage example. + /// + private static void AvailabilityRulesExample() + { + Console.Write("Enter access token: "); + var accessToken = Console.ReadLine(); + + Console.WriteLine(); + var client = new CronofyAccountClient(accessToken); + + FetchAndPrintCalendars(client); + + Console.Write("Enter calendar ID: "); + var calendarId = Console.ReadLine(); + Console.WriteLine(); + + Console.WriteLine("Creating an example availability rule"); + Console.WriteLine(); + + const string AvailabilityRuleId = "CSharpExampleAvailabilityRule"; + + client.UpsertAvailabilityRule(new AvailabilityRule + { + AvailabilityRuleId = AvailabilityRuleId, + TimeZoneId = "America/Chicago", + CalendarIds = new[] { calendarId }, + WeeklyPeriods = new[] + { + new AvailabilityRule.WeeklyPeriod + { + Day = DayOfWeek.Monday, + StartTime = "09:30", + EndTime = "12:30", + }, + new AvailabilityRule.WeeklyPeriod + { + Day = DayOfWeek.Monday, + StartTime = "14:00", + EndTime = "17:00", + }, + new AvailabilityRule.WeeklyPeriod + { + Day = DayOfWeek.Wednesday, + StartTime = "09:30", + EndTime = "12:30", + }, + }, + }); + + Console.WriteLine("Availability rule created"); + Console.WriteLine(); + + Console.WriteLine("Fetching created availability rule..."); + var availabilityRule = client.GetAvailabilityRule(AvailabilityRuleId); + + Console.WriteLine(); + Console.WriteLine(availabilityRule.ToString()); + Console.WriteLine(); + + Console.WriteLine("Fetching all availability rules..."); + var availabilityRules = client.GetAvailabilityRules(); + + Console.WriteLine(); + + foreach (var rule in availabilityRules) + { + Console.WriteLine(rule.ToString()); + } + + Console.WriteLine(); + + Console.WriteLine("Press enter to delete the example rule..."); + Console.ReadLine(); + + client.DeleteAvailabilityRule(AvailabilityRuleId); + Console.WriteLine("Availability rule deleted"); + Console.WriteLine(); + + Console.WriteLine("Press enter to continue..."); + Console.ReadLine(); + } + /// /// Fetches a list of all of the users calendars and prints a summary to the console. /// diff --git a/src/Cronofy/AvailabilityRule.cs b/src/Cronofy/AvailabilityRule.cs new file mode 100644 index 0000000..401b9d6 --- /dev/null +++ b/src/Cronofy/AvailabilityRule.cs @@ -0,0 +1,181 @@ +namespace Cronofy +{ + using System; + using System.Linq; + + /// + /// Class for representing an availability rule. + /// + public sealed class AvailabilityRule + { + /// + /// Gets or sets the unique identifier of the availability rule. + /// + /// + /// The unique identifier of the availability rule. + /// + public string AvailabilityRuleId { get; set; } + + /// + /// Gets or sets the time zone for which the availability rule start and end times are represented in. + /// + /// + /// The time zone for which the availability rule start and end times are represented in. + /// + public string TimeZoneId { get; set; } + + /// + /// Gets or sets the calendars that should impact the user's availability. + /// + /// + /// The calendars that should impact the user's availability. + /// + public string[] CalendarIds { get; set; } + + /// + /// Gets or sets the weekly recurring periods for the availability rule. + /// + /// + /// The weekly recurring periods for the availability rule. + /// + public WeeklyPeriod[] WeeklyPeriods { get; set; } + + /// + public override int GetHashCode() + { + return this.AvailabilityRuleId.GetHashCode(); + } + + /// + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) + { + return false; + } + + if (ReferenceEquals(this, obj)) + { + return true; + } + + return obj is AvailabilityRule && this.Equals((AvailabilityRule)obj); + } + + /// + /// Determines whether the specified + /// is equal to the current . + /// + /// + /// The to compare with the current + /// . + /// + /// + /// true if the specified is + /// equal to the current ; otherwise, + /// false. + /// + public bool Equals(AvailabilityRule other) + { + return this.AvailabilityRuleId == other.AvailabilityRuleId && + this.TimeZoneId == other.TimeZoneId && + ((this.CalendarIds == null && other.CalendarIds == null) || (this.CalendarIds != null && other.CalendarIds != null && this.CalendarIds.SequenceEqual(other.CalendarIds))) && + this.WeeklyPeriods.SequenceEqual(other.WeeklyPeriods); + } + + /// + public override string ToString() + { + return string.Format( + "<{0} AvailabilityRuleId={1}, TimeZoneId={2}, CalendarIds={3}, WeeklyPeriods=[{4}]>", + this.GetType(), + this.AvailabilityRuleId, + this.TimeZoneId, + this.CalendarIds == null ? "null" : string.Format("[{0}]", string.Join(", ", this.CalendarIds)), + string.Join(", ", this.WeeklyPeriods.Select(weeklyPeriod => weeklyPeriod.ToString()))); + } + + /// + /// Class to represent a weekly period. + /// + public class WeeklyPeriod + { + /// + /// Gets or sets the week day the period applies to. + /// + /// + /// The week day the period applies to. + /// + public DayOfWeek Day { get; set; } + + /// + /// Gets or sets the time of day the period should start. + /// + /// + /// The time of day the period should start. + /// + public string StartTime { get; set; } + + /// + /// Gets or sets the time of day the period should end. + /// + /// + /// The time of day the period should end. + /// + public string EndTime { get; set; } + + /// + public override int GetHashCode() + { + return this.Day.GetHashCode() ^ this.StartTime.GetHashCode() ^ this.EndTime.GetHashCode(); + } + + /// + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) + { + return false; + } + + if (ReferenceEquals(this, obj)) + { + return true; + } + + return obj is WeeklyPeriod && this.Equals((WeeklyPeriod)obj); + } + + /// + /// Determines whether the specified + /// is equal to the current . + /// + /// + /// The to compare with the current + /// . + /// + /// + /// true if the specified is + /// equal to the current ; otherwise, + /// false. + /// + public bool Equals(WeeklyPeriod other) + { + return this.Day == other.Day && + this.StartTime == other.StartTime && + this.EndTime == other.EndTime; + } + + /// + public override string ToString() + { + return string.Format( + "<{0} Day={1}, StartTime={2}, EndTime={3}>", + this.GetType(), + this.Day, + this.StartTime, + this.EndTime); + } + } + } +} diff --git a/src/Cronofy/CronofyAccountClient.cs b/src/Cronofy/CronofyAccountClient.cs index d5fe8e6..0546407 100644 --- a/src/Cronofy/CronofyAccountClient.cs +++ b/src/Cronofy/CronofyAccountClient.cs @@ -560,6 +560,69 @@ public string GetConferencingServiceAuthorizationUrl(ConferencingServiceAuthoriz return response.AuthorizationRequest.Url; } + /// + public AvailabilityRule GetAvailabilityRule(string availabilityRuleId) + { + Preconditions.NotEmpty(nameof(availabilityRuleId), availabilityRuleId); + + var request = new HttpRequest(); + + request.Method = "GET"; + request.Url = string.Format(this.UrlProvider.AvailabilityRuleUrl, availabilityRuleId); + request.AddOAuthAuthorization(this.AccessToken); + + var response = this.HttpClient.GetJsonResponse(request); + + return response.AvailabilityRule.ToAvailabilityRule(); + } + + /// + public IEnumerable GetAvailabilityRules() + { + var request = new HttpRequest(); + + request.Method = "GET"; + request.Url = this.UrlProvider.AvailabilityRulesUrl; + request.AddOAuthAuthorization(this.AccessToken); + + var response = this.HttpClient.GetJsonResponse(request); + + return response.AvailabilityRules.Select(ap => ap.ToAvailabilityRule()); + } + + /// + public AvailabilityRule UpsertAvailabilityRule(AvailabilityRule availabilityRule) + { + Preconditions.NotNull(nameof(availabilityRule), availabilityRule); + + var request = new HttpRequest(); + + request.Method = "POST"; + request.Url = this.UrlProvider.AvailabilityRulesUrl; + request.AddOAuthAuthorization(this.AccessToken); + + var upsertAvailabilityRuleRequest = UpsertAvailabilityRuleRequest.FromAvailabilityRule(availabilityRule); + request.SetJsonBody(upsertAvailabilityRuleRequest); + + var response = this.HttpClient.GetJsonResponse(request); + + return response.AvailabilityRule.ToAvailabilityRule(); + } + + /// + public void DeleteAvailabilityRule(string availabilityRuleId) + { + Preconditions.NotEmpty(nameof(availabilityRuleId), availabilityRuleId); + + var request = new HttpRequest(); + + request.Method = "DELETE"; + request.Url = string.Format(this.UrlProvider.AvailabilityRuleUrl, availabilityRuleId); + request.AddOAuthAuthorization(this.AccessToken); + + this.HttpClient.GetValidResponse(request); + } + /// /// Creates a calendar. /// diff --git a/src/Cronofy/ICronofyAccountClient.cs b/src/Cronofy/ICronofyAccountClient.cs index 4bfdfdb..edeb7bc 100644 --- a/src/Cronofy/ICronofyAccountClient.cs +++ b/src/Cronofy/ICronofyAccountClient.cs @@ -554,11 +554,64 @@ public interface ICronofyAccountClient : ICronofyUserInfoClient /// /// The URL which the end-user should visit. /// - /// Thrown if if null, or it doesn't contain a Redirect URI. + /// Thrown if is null, or it doesn't contain a Redirect URI. /// /// /// Thrown if an error is encountered whilst making the request. /// string GetConferencingServiceAuthorizationUrl(ConferencingServiceAuthorizationRequest conferencingServiceAuthorizationRequest); + + /// + /// Reads a single availability rule. + /// + /// + /// The unique identifier of the availability rule. + /// + /// The availability rule. + /// + /// Thrown if is null, or empty. + /// + /// + /// Thrown if an error is encountered whilst making the request. + /// + AvailabilityRule GetAvailabilityRule(string availabilityRuleId); + + /// + /// Retrieves all availability rules saved against an account. + /// + /// The list of all availability rules. + /// + /// Thrown if an error is encountered whilst making the request. + /// + IEnumerable GetAvailabilityRules(); + + /// + /// Creates or updates an availability rule. + /// + /// + /// The availability rule to upsert, must not be null. + /// + /// The created or updated availability rule. + /// + /// Thrown if is null. + /// + /// + /// Thrown if an error is encountered whilst making the request. + /// + AvailabilityRule UpsertAvailabilityRule(AvailabilityRule availabilityRule); + + /// + /// Deletes an availability rule for the authenticated account. + /// + /// + /// The unique identifier of the availability rule. + /// + /// + /// Thrown if is null, or empty. + /// + /// + /// Thrown if an error is encountered whilst making the request. + /// + void DeleteAvailabilityRule(string availabilityRuleId); } } diff --git a/src/Cronofy/Requests/UpsertAvailabilityRuleRequest.cs b/src/Cronofy/Requests/UpsertAvailabilityRuleRequest.cs new file mode 100644 index 0000000..c26784f --- /dev/null +++ b/src/Cronofy/Requests/UpsertAvailabilityRuleRequest.cs @@ -0,0 +1,141 @@ +namespace Cronofy.Requests +{ + using System; + using System.Collections.Generic; + using System.Linq; + using Newtonsoft.Json; + + /// + /// Class for the serialization of an upsert availability rule request. + /// + public sealed class UpsertAvailabilityRuleRequest + { + /// + /// Gets or sets the unique identifier of the availability rule. + /// + /// + /// The unique identifier of the availability rule. + /// + [JsonProperty("availability_rule_id")] + public string AvailabilityRuleId { get; set; } + + /// + /// Gets or sets the time zone for which the availability rule start and end times are represented in. + /// + /// + /// The time zone for which the availability rule start and end times are represented in. + /// + [JsonProperty("tzid")] + public string TimeZoneId { get; set; } + + /// + /// Gets or sets the calendars that should impact the user's availability. + /// + /// + /// The calendars that should impact the user's availability. + /// + [JsonProperty("calendar_ids")] + public IEnumerable CalendarIds { get; set; } + + /// + /// Gets or sets the weekly recurring periods for the availability rule. + /// + /// + /// The weekly recurring periods for the availability rule. + /// + [JsonProperty("weekly_periods")] + public IEnumerable WeeklyPeriods { get; set; } + + /// + /// Creates an upsert request from an existing availability rule. + /// + /// Availability rule to create this upsert request from. + /// An upsert request for the given rule. + public static UpsertAvailabilityRuleRequest FromAvailabilityRule(AvailabilityRule availabilityRule) + { + return new UpsertAvailabilityRuleRequest + { + AvailabilityRuleId = availabilityRule.AvailabilityRuleId, + TimeZoneId = availabilityRule.TimeZoneId, + CalendarIds = availabilityRule.CalendarIds?.ToArray(), + WeeklyPeriods = availabilityRule.WeeklyPeriods.Select(WeeklyPeriod.FromWeeklyPeriod).ToArray(), + }; + } + + /// + /// Class for the serialization of a weekly period within an availability rule. + /// + public sealed class WeeklyPeriod + { + /// + /// Gets or sets the week day the period applies to. + /// + /// + /// The week day the period applies to. + /// + [JsonProperty("day")] + public string Day { get; set; } + + /// + /// Gets or sets the time of day the period should start. + /// + /// + /// The time of day the period should start. + /// + [JsonProperty("start_time")] + public string StartTime { get; set; } + + /// + /// Gets or sets the time of day the period should end. + /// + /// + /// The time of day the period should end. + /// + [JsonProperty("end_time")] + public string EndTime { get; set; } + + /// + /// Creates an upset weekly period request from a given weekly period. + /// + /// The weekly period to copy from. + /// The weekly period upsert request. + public static WeeklyPeriod FromWeeklyPeriod(AvailabilityRule.WeeklyPeriod weeklyPeriod) + { + return new WeeklyPeriod + { + Day = ToDayString(weeklyPeriod.Day), + StartTime = weeklyPeriod.StartTime, + EndTime = weeklyPeriod.EndTime, + }; + } + + /// + /// Converts a day of the week to its string representation. + /// + /// The day of the week. + /// The string representation of the day of the week. + private static string ToDayString(DayOfWeek day) + { + switch (day) + { + case DayOfWeek.Monday: + return "monday"; + case DayOfWeek.Tuesday: + return "tuesday"; + case DayOfWeek.Wednesday: + return "wednesday"; + case DayOfWeek.Thursday: + return "thursday"; + case DayOfWeek.Friday: + return "friday"; + case DayOfWeek.Saturday: + return "saturday"; + case DayOfWeek.Sunday: + return "sunday"; + default: + throw new ArgumentOutOfRangeException(nameof(day), "Unexpected day"); + } + } + } + } +} diff --git a/src/Cronofy/Responses/AvailabilityRuleResponse.cs b/src/Cronofy/Responses/AvailabilityRuleResponse.cs new file mode 100644 index 0000000..5726540 --- /dev/null +++ b/src/Cronofy/Responses/AvailabilityRuleResponse.cs @@ -0,0 +1,143 @@ +namespace Cronofy.Responses +{ + using System; + using System.Collections.Generic; + using System.Linq; + using Newtonsoft.Json; + + /// + /// Class for the deserialization of a read availability rule response. + /// + internal sealed class AvailabilityRuleResponse + { + /// + /// Gets or sets the unique identifier of the availability rule. + /// + /// + /// The unique identifier of the availability rule. + /// + [JsonProperty("availability_rule_id")] + public string AvailabilityRuleId { get; set; } + + /// + /// Gets or sets the time zone for which the availability rule start and end times are represented in. + /// + /// + /// The time zone for which the availability rule start and end times are represented in. + /// + [JsonProperty("tzid")] + public string TimeZoneId { get; set; } + + /// + /// Gets or sets the calendars that should impact the user's availability. + /// + /// + /// The calendars that should impact the user's availability. + /// + [JsonProperty("calendar_ids")] + public IEnumerable CalendarIds { get; set; } + + /// + /// Gets or sets the weekly recurring periods for the availability rule. + /// + /// + /// The weekly recurring periods for the availability rule. + /// + [JsonProperty("weekly_periods")] + public IEnumerable WeeklyPeriods { get; set; } + + /// + /// Converts the response to an . + /// + /// + /// An . + /// + public AvailabilityRule ToAvailabilityRule() + { + return new AvailabilityRule + { + AvailabilityRuleId = this.AvailabilityRuleId, + TimeZoneId = this.TimeZoneId, + CalendarIds = this.CalendarIds?.ToArray(), + WeeklyPeriods = this.WeeklyPeriods.Select(weeklyPeriod => weeklyPeriod.ToWeeklyPeriod()).ToArray(), + }; + } + + /// + /// Class for the deserialization of a weekly period within an availability rule. + /// + internal sealed class WeeklyPeriod + { + /// + /// Gets or sets the week day the period applies to. + /// + /// + /// The week day the period applies to. + /// + [JsonProperty("day")] + public string Day { get; set; } + + /// + /// Gets or sets the time of day the period should start. + /// + /// + /// The time of day the period should start. + /// + [JsonProperty("start_time")] + public string StartTime { get; set; } + + /// + /// Gets or sets the time of day the period should end. + /// + /// + /// The time of day the period should end. + /// + [JsonProperty("end_time")] + public string EndTime { get; set; } + + /// + /// Converts the response to an . + /// + /// + /// An . + /// + public AvailabilityRule.WeeklyPeriod ToWeeklyPeriod() + { + return new AvailabilityRule.WeeklyPeriod + { + Day = ToDayOfWeek(this.Day), + StartTime = this.StartTime, + EndTime = this.EndTime, + }; + } + + /// + /// Converts a day string to a day of the week representation. + /// + /// The string representation of the day of the week. + /// The day of the week represented by the string. + private static DayOfWeek ToDayOfWeek(string day) + { + switch (day) + { + case "monday": + return DayOfWeek.Monday; + case "tuesday": + return DayOfWeek.Tuesday; + case "wednesday": + return DayOfWeek.Wednesday; + case "thursday": + return DayOfWeek.Thursday; + case "friday": + return DayOfWeek.Friday; + case "saturday": + return DayOfWeek.Saturday; + case "sunday": + return DayOfWeek.Sunday; + default: + throw new ArgumentOutOfRangeException(nameof(day), "Unexpected day"); + } + } + } + } +} diff --git a/src/Cronofy/Responses/GetAvailabilityRuleResponse.cs b/src/Cronofy/Responses/GetAvailabilityRuleResponse.cs new file mode 100644 index 0000000..1a5306d --- /dev/null +++ b/src/Cronofy/Responses/GetAvailabilityRuleResponse.cs @@ -0,0 +1,21 @@ +namespace Cronofy.Responses +{ + using System; + using System.Collections.Generic; + using Newtonsoft.Json; + + /// + /// Class for the deserialization of a get availability rule response. + /// + internal sealed class GetAvailabilityRuleResponse + { + /// + /// Gets or sets the availability rule. + /// + /// + /// The availability rule. + /// + [JsonProperty("availability_rule")] + public AvailabilityRuleResponse AvailabilityRule { get; set; } + } +} diff --git a/src/Cronofy/Responses/ListAvailabilityRulesResponse.cs b/src/Cronofy/Responses/ListAvailabilityRulesResponse.cs new file mode 100644 index 0000000..17f2ff6 --- /dev/null +++ b/src/Cronofy/Responses/ListAvailabilityRulesResponse.cs @@ -0,0 +1,21 @@ +namespace Cronofy.Responses +{ + using System; + using System.Collections.Generic; + using Newtonsoft.Json; + + /// + /// Class for the deserialization of a list availability rules response. + /// + internal sealed class ListAvailabilityRulesResponse + { + /// + /// Gets or sets the list of discovered availability rules. + /// + /// + /// The list of discovered availability rules. + /// + [JsonProperty("availability_rules")] + public IEnumerable AvailabilityRules { get; set; } + } +} diff --git a/src/Cronofy/Responses/UpsertAvailabilityRuleResponse.cs b/src/Cronofy/Responses/UpsertAvailabilityRuleResponse.cs new file mode 100644 index 0000000..4147126 --- /dev/null +++ b/src/Cronofy/Responses/UpsertAvailabilityRuleResponse.cs @@ -0,0 +1,21 @@ +namespace Cronofy.Responses +{ + using System; + using System.Collections.Generic; + using Newtonsoft.Json; + + /// + /// Class for the deserialization of an upsert availability rules response. + /// + internal sealed class UpsertAvailabilityRuleResponse + { + /// + /// Gets or sets the created or updated availability rule. + /// + /// + /// The created or updated availability rule. + /// + [JsonProperty("availability_rule")] + public AvailabilityRuleResponse AvailabilityRule { get; set; } + } +} diff --git a/src/Cronofy/UrlProvider.cs b/src/Cronofy/UrlProvider.cs index 130dbbb..d8f2d48 100644 --- a/src/Cronofy/UrlProvider.cs +++ b/src/Cronofy/UrlProvider.cs @@ -175,6 +175,16 @@ public sealed class UrlProvider /// private const string AttachmentsUrlFormat = "https://api{0}.cronofy.com/v1/attachments"; + /// + /// The URL of the Availability Rule endpoint. + /// + private const string AvailabilityRulesUrlFormat = "https://api{0}.cronofy.com/v1/availability_rules"; + + /// + /// The URL of the Availability Rule endpoint for a specific rule. + /// + private const string AvailabilityRuleUrlFormat = "https://api{0}.cronofy.com/v1/availability_rules/{{0}}"; + /// /// Initializes a new instance of the class. /// @@ -224,6 +234,8 @@ internal UrlProvider(string dataCenter) this.ElementTokensUrl = string.Format(ElementTokensUrlFormat, suffix); this.ConferencingServiceAuthorizationUrl = string.Format(ConferencingServiceAuthorizationUrlFormat, suffix); this.AttachmentsUrl = string.Format(AttachmentsUrlFormat, suffix); + this.AvailabilityRulesUrl = string.Format(AvailabilityRulesUrlFormat, suffix); + this.AvailabilityRuleUrl = string.Format(AvailabilityRuleUrlFormat, suffix); } /// @@ -232,11 +244,7 @@ internal UrlProvider(string dataCenter) /// /// The authorization URL. /// - public string AuthorizationUrl - { - get; - private set; - } + public string AuthorizationUrl { get; private set; } /// /// Gets the Enterprise Connect authorization URL. @@ -244,11 +252,7 @@ public string AuthorizationUrl /// /// The Enterprise Connect authorization URL. /// - public string EnterpriseConnectAuthorizationUrl - { - get; - private set; - } + public string EnterpriseConnectAuthorizationUrl { get; private set; } /// /// Gets the OAuth token URL. @@ -256,11 +260,7 @@ public string EnterpriseConnectAuthorizationUrl /// /// The OAuth token URL. /// - public string TokenUrl - { - get; - private set; - } + public string TokenUrl { get; private set; } /// /// Gets the OAuth token revocation URL. @@ -268,11 +268,7 @@ public string TokenUrl /// /// The OAuth token revocation URL. /// - public string TokenRevocationUrl - { - get; - private set; - } + public string TokenRevocationUrl { get; private set; } /// /// Gets the userinfo URL. @@ -280,11 +276,7 @@ public string TokenRevocationUrl /// /// The userinfo URL. /// - public string UserInfoUrl - { - get; - private set; - } + public string UserInfoUrl { get; private set; } /// /// Gets the resources URL. @@ -292,11 +284,7 @@ public string UserInfoUrl /// /// The resources URL. /// - public string ResourcesUrl - { - get; - private set; - } + public string ResourcesUrl { get; private set; } /// /// Gets the authorize with service account URL. @@ -304,11 +292,7 @@ public string ResourcesUrl /// /// The authorize with service account URL. /// - public string AuthorizeWithServiceAccountUrl - { - get; - private set; - } + public string AuthorizeWithServiceAccountUrl { get; private set; } /// /// Gets the account URL. @@ -316,11 +300,7 @@ public string AuthorizeWithServiceAccountUrl /// /// The account URL. /// - public string AccountUrl - { - get; - private set; - } + public string AccountUrl { get; private set; } /// /// Gets the profiles URL. @@ -328,11 +308,7 @@ public string AccountUrl /// /// The profiles URL. /// - public string ProfilesUrl - { - get; - private set; - } + public string ProfilesUrl { get; private set; } /// /// Gets the calendars URL. @@ -340,11 +316,7 @@ public string ProfilesUrl /// /// The calendars URL. /// - public string CalendarsUrl - { - get; - private set; - } + public string CalendarsUrl { get; private set; } /// /// Gets the free busy URL. @@ -352,11 +324,7 @@ public string CalendarsUrl /// /// The free busy URL. /// - public string FreeBusyUrl - { - get; - private set; - } + public string FreeBusyUrl { get; private set; } /// /// Gets the events URL. @@ -364,11 +332,7 @@ public string FreeBusyUrl /// /// The events URL. /// - public string EventsUrl - { - get; - private set; - } + public string EventsUrl { get; private set; } /// /// Gets the managed event URL format. @@ -376,11 +340,7 @@ public string EventsUrl /// /// The managed event URL format. /// - public string ManagedEventUrlFormat - { - get; - private set; - } + public string ManagedEventUrlFormat { get; private set; } /// /// Gets the participation status URL format. @@ -388,11 +348,7 @@ public string ManagedEventUrlFormat /// /// The participation status URL format. /// - public string ParticipationStatusUrlFormat - { - get; - private set; - } + public string ParticipationStatusUrlFormat { get; private set; } /// /// Gets the channels URL. @@ -400,11 +356,7 @@ public string ParticipationStatusUrlFormat /// /// The channels URL. /// - public string ChannelsUrl - { - get; - private set; - } + public string ChannelsUrl { get; private set; } /// /// Gets the channel URL format. @@ -412,11 +364,7 @@ public string ChannelsUrl /// /// The channel URL format. /// - public string ChannelUrlFormat - { - get; - private set; - } + public string ChannelUrlFormat { get; private set; } /// /// Gets the permissions URL. @@ -424,11 +372,7 @@ public string ChannelUrlFormat /// /// The permissions URL. /// - public string PermissionsUrl - { - get; - private set; - } + public string PermissionsUrl { get; private set; } /// /// Gets the availability URL. @@ -436,11 +380,7 @@ public string PermissionsUrl /// /// The availability URL. /// - public string AvailabilityUrl - { - get; - private set; - } + public string AvailabilityUrl { get; private set; } /// /// Gets the add to calendar URL. @@ -448,11 +388,7 @@ public string AvailabilityUrl /// /// The add to calendar URL. /// - public string AddToCalendarUrl - { - get; - private set; - } + public string AddToCalendarUrl { get; private set; } /// /// Gets the real time scheduling URL. @@ -460,11 +396,7 @@ public string AddToCalendarUrl /// /// The real time scheduling URL. /// - public string RealTimeSchedulingUrl - { - get; - private set; - } + public string RealTimeSchedulingUrl { get; private set; } /// /// Gets the real time scheduling by ID URL. @@ -472,11 +404,7 @@ public string RealTimeSchedulingUrl /// /// The real time scheduling by ID URL. /// - public string RealTimeSchedulingByIdUrl - { - get; - private set; - } + public string RealTimeSchedulingByIdUrl { get; private set; } /// /// Gets the real time scheduling disable URL format. @@ -484,11 +412,7 @@ public string RealTimeSchedulingByIdUrl /// /// The real time scheduling disable URL format. /// - public string DisableRealTimeSchedulingUrlFormat - { - get; - private set; - } + public string DisableRealTimeSchedulingUrlFormat { get; private set; } /// /// Gets the link tokens URL. @@ -496,11 +420,7 @@ public string DisableRealTimeSchedulingUrlFormat /// /// The link tokens URL. /// - public string LinkTokensUrl - { - get; - private set; - } + public string LinkTokensUrl { get; private set; } /// /// Gets the revoke profile authorization URL format. @@ -508,11 +428,7 @@ public string LinkTokensUrl /// /// The revoke profile authorization URL format. /// - public string RevokeProfileAuthorizationUrlFormat - { - get; - private set; - } + public string RevokeProfileAuthorizationUrlFormat { get; private set; } /// /// Gets the Smart Invite URL. @@ -526,11 +442,7 @@ public string RevokeProfileAuthorizationUrlFormat /// /// The batch request URL. /// - public string BatchUrl - { - get; - private set; - } + public string BatchUrl { get; private set; } /// /// Gets the application calendars URL. @@ -579,5 +491,17 @@ public string BatchUrl /// /// The attachments URL. public string AttachmentsUrl { get; private set; } + + /// + /// Gets the Availability Rule URL. + /// + /// The Availability Rule URL. + public string AvailabilityRulesUrl { get; private set; } + + /// + /// Gets the Availability Rule URL for a specific rule. + /// + /// The Availability Rule URL for a specific rule. + public string AvailabilityRuleUrl { get; private set; } } } diff --git a/test/Cronofy.Test/CronofyAccountClientTests/DeleteAvailabilityRule.cs b/test/Cronofy.Test/CronofyAccountClientTests/DeleteAvailabilityRule.cs new file mode 100644 index 0000000..efdc012 --- /dev/null +++ b/test/Cronofy.Test/CronofyAccountClientTests/DeleteAvailabilityRule.cs @@ -0,0 +1,21 @@ +namespace Cronofy.Test.CronofyAccountClientTests +{ + using NUnit.Framework; + + internal sealed class DeleteAvailabilityRule : Base + { + private const string AvailabilityRuleId = "my_really_cool_rule_id"; + + [Test] + public void CanDeleteAvailabilityRule() + { + this.Http.Stub( + HttpDelete + .Url("https://api.cronofy.com/v1/availability_rules/" + AvailabilityRuleId) + .RequestHeader("Authorization", "Bearer " + AccessToken) + .ResponseCode(202)); + + this.Client.DeleteAvailabilityRule(AvailabilityRuleId); + } + } +} diff --git a/test/Cronofy.Test/CronofyAccountClientTests/GetAvailabilityRule.cs b/test/Cronofy.Test/CronofyAccountClientTests/GetAvailabilityRule.cs new file mode 100644 index 0000000..4f6d199 --- /dev/null +++ b/test/Cronofy.Test/CronofyAccountClientTests/GetAvailabilityRule.cs @@ -0,0 +1,149 @@ +namespace Cronofy.Test.CronofyAccountClientTests +{ + using System; + using NUnit.Framework; + + internal sealed class GetAvailabilityRule : Base + { + private const string AvailabilityRuleId = "my_really_cool_rule_id"; + + [Test] + public void CanGetAvailabilityRule() + { + this.Http.Stub( + HttpGet + .Url("https://api.cronofy.com/v1/availability_rules/" + AvailabilityRuleId) + .RequestHeader("Authorization", "Bearer " + AccessToken) + .ResponseCode(200) + .ResponseBodyFormat( + @" + {{ + ""availability_rule"": {{ + ""availability_rule_id"": ""{0}"", + ""tzid"": ""America/Chicago"", + ""calendar_ids"": [ + ""cal_n23kjnwrw2_jsdfjksn234"" + ], + ""weekly_periods"": [ + {{ + ""day"": ""monday"", + ""start_time"": ""09:30"", + ""end_time"": ""12:30"" + }}, + {{ + ""day"": ""monday"", + ""start_time"": ""14:00"", + ""end_time"": ""17:00"" + }}, + {{ + ""day"": ""wednesday"", + ""start_time"": ""09:30"", + ""end_time"": ""12:30"" + }} + ] + }} + }} + ", AvailabilityRuleId)); + + var actualResponse = this.Client.GetAvailabilityRule(AvailabilityRuleId); + + var expectedResponse = new AvailabilityRule + { + AvailabilityRuleId = AvailabilityRuleId, + TimeZoneId = "America/Chicago", + CalendarIds = new[] { "cal_n23kjnwrw2_jsdfjksn234" }, + WeeklyPeriods = new[] + { + new AvailabilityRule.WeeklyPeriod + { + Day = DayOfWeek.Monday, + StartTime = "09:30", + EndTime = "12:30", + }, + new AvailabilityRule.WeeklyPeriod + { + Day = DayOfWeek.Monday, + StartTime = "14:00", + EndTime = "17:00", + }, + new AvailabilityRule.WeeklyPeriod + { + Day = DayOfWeek.Wednesday, + StartTime = "09:30", + EndTime = "12:30", + }, + }, + }; + + Assert.AreEqual(expectedResponse, actualResponse); + } + + [Test] + public void CanGetAvailabilityRuleWithMissingCalendarIds() + { + this.Http.Stub( + HttpGet + .Url("https://api.cronofy.com/v1/availability_rules/" + AvailabilityRuleId) + .RequestHeader("Authorization", "Bearer " + AccessToken) + .ResponseCode(200) + .ResponseBodyFormat( + @" + {{ + ""availability_rule"": {{ + ""availability_rule_id"": ""{0}"", + ""tzid"": ""America/Chicago"", + ""weekly_periods"": [ + {{ + ""day"": ""monday"", + ""start_time"": ""09:30"", + ""end_time"": ""12:30"" + }}, + {{ + ""day"": ""monday"", + ""start_time"": ""14:00"", + ""end_time"": ""17:00"" + }}, + {{ + ""day"": ""wednesday"", + ""start_time"": ""09:30"", + ""end_time"": ""12:30"" + }} + ] + }} + }} + ", AvailabilityRuleId)); + + var actualResponse = this.Client.GetAvailabilityRule(AvailabilityRuleId); + + var expectedResponse = new AvailabilityRule + { + AvailabilityRuleId = AvailabilityRuleId, + TimeZoneId = "America/Chicago", + CalendarIds = null, + WeeklyPeriods = new[] + { + new AvailabilityRule.WeeklyPeriod + { + Day = DayOfWeek.Monday, + StartTime = "09:30", + EndTime = "12:30", + }, + new AvailabilityRule.WeeklyPeriod + { + Day = DayOfWeek.Monday, + StartTime = "14:00", + EndTime = "17:00", + }, + new AvailabilityRule.WeeklyPeriod + { + Day = DayOfWeek.Wednesday, + StartTime = "09:30", + EndTime = "12:30", + }, + }, + }; + + Assert.AreEqual(expectedResponse, actualResponse); + } + } +} diff --git a/test/Cronofy.Test/CronofyAccountClientTests/ListAvailabilityRules.cs b/test/Cronofy.Test/CronofyAccountClientTests/ListAvailabilityRules.cs new file mode 100644 index 0000000..a378a2e --- /dev/null +++ b/test/Cronofy.Test/CronofyAccountClientTests/ListAvailabilityRules.cs @@ -0,0 +1,154 @@ +namespace Cronofy.Test.CronofyAccountClientTests +{ + using System; + using NUnit.Framework; + + internal sealed class ListAvailabilityRules : Base + { + [Test] + public void CanListAvailabilityRules() + { + this.Http.Stub( + HttpGet + .Url("https://api.cronofy.com/v1/availability_rules") + .RequestHeader("Authorization", "Bearer " + AccessToken) + .ResponseCode(200) + .ResponseBody(@" + { + ""availability_rules"": [ + { + ""availability_rule_id"": ""default"", + ""tzid"": ""America/Chicago"", + ""calendar_ids"": [ + ""cal_n23kjnwrw2_jsdfjksn234"" + ], + ""weekly_periods"": [ + { + ""day"": ""monday"", + ""start_time"": ""09:30"", + ""end_time"": ""12:30"" + }, + { + ""day"": ""monday"", + ""start_time"": ""14:00"", + ""end_time"": ""17:00"" + }, + { + ""day"": ""wednesday"", + ""start_time"": ""09:30"", + ""end_time"": ""12:30"" + } + ] + }, + { + ""availability_rule_id"": ""another_rule"", + ""tzid"": ""Europe/London"", + ""calendar_ids"": [ + ""cal_n23kjnwrw2_jsdfjksn234"", + ""cal_n23kjnwrw2_th53tksn567"", + ], + ""weekly_periods"": [ + { + ""day"": ""saturday"", + ""start_time"": ""09:00"", + ""end_time"": ""17:30"" + }, + { + ""day"": ""sunday"", + ""start_time"": ""11:00"", + ""end_time"": ""17:40"" + } + ] + }, + { + ""availability_rule_id"": ""null_calendar_ids"", + ""tzid"": ""Europe/London"", + ""weekly_periods"": [ + { + ""day"": ""thursday"", + ""start_time"": ""09:00"", + ""end_time"": ""17:30"" + } + ] + } + ] + } + ")); + + var actualResponse = this.Client.GetAvailabilityRules(); + + var expectedResponse = new[] + { + new AvailabilityRule + { + AvailabilityRuleId = "default", + TimeZoneId = "America/Chicago", + CalendarIds = new[] { "cal_n23kjnwrw2_jsdfjksn234" }, + WeeklyPeriods = new[] + { + new AvailabilityRule.WeeklyPeriod + { + Day = DayOfWeek.Monday, + StartTime = "09:30", + EndTime = "12:30", + }, + new AvailabilityRule.WeeklyPeriod + { + Day = DayOfWeek.Monday, + StartTime = "14:00", + EndTime = "17:00", + }, + new AvailabilityRule.WeeklyPeriod + { + Day = DayOfWeek.Wednesday, + StartTime = "09:30", + EndTime = "12:30", + }, + }, + }, + new AvailabilityRule + { + AvailabilityRuleId = "another_rule", + TimeZoneId = "Europe/London", + CalendarIds = new[] + { + "cal_n23kjnwrw2_jsdfjksn234", + "cal_n23kjnwrw2_th53tksn567", + }, + WeeklyPeriods = new[] + { + new AvailabilityRule.WeeklyPeriod + { + Day = DayOfWeek.Saturday, + StartTime = "09:00", + EndTime = "17:30", + }, + new AvailabilityRule.WeeklyPeriod + { + Day = DayOfWeek.Sunday, + StartTime = "11:00", + EndTime = "17:40", + }, + }, + }, + new AvailabilityRule + { + AvailabilityRuleId = "null_calendar_ids", + TimeZoneId = "Europe/London", + CalendarIds = null, + WeeklyPeriods = new[] + { + new AvailabilityRule.WeeklyPeriod + { + Day = DayOfWeek.Thursday, + StartTime = "09:00", + EndTime = "17:30", + }, + }, + }, + }; + + Assert.AreEqual(expectedResponse, actualResponse); + } + } +} diff --git a/test/Cronofy.Test/CronofyAccountClientTests/UpsertAvailabilityRule.cs b/test/Cronofy.Test/CronofyAccountClientTests/UpsertAvailabilityRule.cs new file mode 100644 index 0000000..2fb5aba --- /dev/null +++ b/test/Cronofy.Test/CronofyAccountClientTests/UpsertAvailabilityRule.cs @@ -0,0 +1,194 @@ +namespace Cronofy.Test.CronofyAccountClientTests +{ + using System; + using NUnit.Framework; + + internal sealed class UpsertAvailabilityRule : Base + { + [Test] + public void CanUpsertAvailabilityRule() + { + this.Http.Stub( + HttpPost + .Url("https://api.cronofy.com/v1/availability_rules") + .RequestHeader("Authorization", "Bearer " + AccessToken) + .JsonRequest(@" + { + ""availability_rule_id"": ""default"", + ""tzid"": ""America/Chicago"", + ""calendar_ids"": [ + ""cal_n23kjnwrw2_jsdfjksn234"" + ], + ""weekly_periods"": [ + { + ""day"": ""monday"", + ""start_time"": ""09:30"", + ""end_time"": ""12:30"" + }, + { + ""day"": ""monday"", + ""start_time"": ""14:00"", + ""end_time"": ""17:00"" + }, + { + ""day"": ""wednesday"", + ""start_time"": ""09:30"", + ""end_time"": ""12:30"" + } + ] + } + ") + .ResponseCode(200) + .ResponseBody(@" + { + ""availability_rule"": { + ""availability_rule_id"": ""default"", + ""tzid"": ""America/Chicago"", + ""calendar_ids"": [ + ""cal_n23kjnwrw2_jsdfjksn234"" + ], + ""weekly_periods"": [ + { + ""day"": ""monday"", + ""start_time"": ""09:30"", + ""end_time"": ""12:30"" + }, + { + ""day"": ""monday"", + ""start_time"": ""14:00"", + ""end_time"": ""17:00"" + }, + { + ""day"": ""wednesday"", + ""start_time"": ""09:30"", + ""end_time"": ""12:30"" + } + ] + } + } + ")); + + var updatedAvailabilityRuleState = new AvailabilityRule + { + AvailabilityRuleId = "default", + TimeZoneId = "America/Chicago", + CalendarIds = new[] { "cal_n23kjnwrw2_jsdfjksn234" }, + WeeklyPeriods = new[] + { + new AvailabilityRule.WeeklyPeriod + { + Day = DayOfWeek.Monday, + StartTime = "09:30", + EndTime = "12:30", + }, + new AvailabilityRule.WeeklyPeriod + { + Day = DayOfWeek.Monday, + StartTime = "14:00", + EndTime = "17:00", + }, + new AvailabilityRule.WeeklyPeriod + { + Day = DayOfWeek.Wednesday, + StartTime = "09:30", + EndTime = "12:30", + }, + }, + }; + + var actualResponse = this.Client.UpsertAvailabilityRule(updatedAvailabilityRuleState); + + Assert.AreEqual(updatedAvailabilityRuleState, actualResponse); + } + + [Test] + public void CanUpsertAvailabilityRuleWithMissingCalendarIds() + { + this.Http.Stub( + HttpPost + .Url("https://api.cronofy.com/v1/availability_rules") + .RequestHeader("Authorization", "Bearer " + AccessToken) + .JsonRequest(@" + { + ""availability_rule_id"": ""default"", + ""tzid"": ""America/Chicago"", + ""weekly_periods"": [ + { + ""day"": ""monday"", + ""start_time"": ""09:30"", + ""end_time"": ""12:30"" + }, + { + ""day"": ""monday"", + ""start_time"": ""14:00"", + ""end_time"": ""17:00"" + }, + { + ""day"": ""wednesday"", + ""start_time"": ""09:30"", + ""end_time"": ""12:30"" + } + ] + } + ") + .ResponseCode(200) + .ResponseBody(@" + { + ""availability_rule"": { + ""availability_rule_id"": ""default"", + ""tzid"": ""America/Chicago"", + ""weekly_periods"": [ + { + ""day"": ""monday"", + ""start_time"": ""09:30"", + ""end_time"": ""12:30"" + }, + { + ""day"": ""monday"", + ""start_time"": ""14:00"", + ""end_time"": ""17:00"" + }, + { + ""day"": ""wednesday"", + ""start_time"": ""09:30"", + ""end_time"": ""12:30"" + } + ] + } + } + ")); + + var updatedAvailabilityRuleState = new AvailabilityRule + { + AvailabilityRuleId = "default", + TimeZoneId = "America/Chicago", + CalendarIds = null, + WeeklyPeriods = new[] + { + new AvailabilityRule.WeeklyPeriod + { + Day = DayOfWeek.Monday, + StartTime = "09:30", + EndTime = "12:30", + }, + new AvailabilityRule.WeeklyPeriod + { + Day = DayOfWeek.Monday, + StartTime = "14:00", + EndTime = "17:00", + }, + new AvailabilityRule.WeeklyPeriod + { + Day = DayOfWeek.Wednesday, + StartTime = "09:30", + EndTime = "12:30", + }, + }, + }; + + var actualResponse = this.Client.UpsertAvailabilityRule(updatedAvailabilityRuleState); + + Assert.AreEqual(updatedAvailabilityRuleState, actualResponse); + } + } +}