diff --git a/.gitignore b/.gitignore index 2176ca2..818ba3a 100644 --- a/.gitignore +++ b/.gitignore @@ -24,6 +24,8 @@ bld/ # Visual Studio 2015 cache/options directory .vs/ +.vscode/ + # Uncomment if you have tasks that create the project's static files in wwwroot #wwwroot/ diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index 3796783..0000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "yaml.schemas": { - "https://json.schemastore.org/github-workflow.json": "file:///c%3A/Users/andre/Projects/school/analogio/shifty-webapp/.github/workflows/deploy.yml" - } -} diff --git a/Shifty.Api/Generated/AnalogCoreV1/AnalogCoreV1.cs b/Shifty.Api/Generated/AnalogCoreV1/AnalogCoreV1.cs index bef8708..1194070 100644 --- a/Shifty.Api/Generated/AnalogCoreV1/AnalogCoreV1.cs +++ b/Shifty.Api/Generated/AnalogCoreV1/AnalogCoreV1.cs @@ -261,9 +261,8 @@ public virtual async System.Threading.Tasks.Task ApiV1AccountLoginAsyn /// /// Returns basic data about the account /// - /// Successful request /// A server side error occurred. - public virtual System.Threading.Tasks.Task ApiV1AccountGetAsync() + public virtual System.Threading.Tasks.Task ApiV1AccountGetAsync() { return ApiV1AccountGetAsync(System.Threading.CancellationToken.None); } @@ -272,9 +271,8 @@ public virtual System.Threading.Tasks.Task ApiV1AccountGetAsync() /// /// Returns basic data about the account /// - /// Successful request /// A server side error occurred. - public virtual async System.Threading.Tasks.Task ApiV1AccountGetAsync(System.Threading.CancellationToken cancellationToken) + public virtual async System.Threading.Tasks.Task ApiV1AccountGetAsync(System.Threading.CancellationToken cancellationToken) { var urlBuilder_ = new System.Text.StringBuilder(); urlBuilder_.Append("api/v1/Account"); @@ -286,7 +284,6 @@ public virtual async System.Threading.Tasks.Task ApiV1AccountGetAsync(S using (var request_ = new System.Net.Http.HttpRequestMessage()) { request_.Method = new System.Net.Http.HttpMethod("GET"); - request_.Headers.Accept.Add(System.Net.Http.Headers.MediaTypeWithQualityHeaderValue.Parse("application/json")); PrepareRequest(client_, request_, urlBuilder_); @@ -309,20 +306,17 @@ public virtual async System.Threading.Tasks.Task ApiV1AccountGetAsync(S ProcessResponse(client_, response_); var status_ = (int)response_.StatusCode; - if (status_ == 200) + if (status_ == 410) { - var objectResponse_ = await ReadObjectResponseAsync(response_, headers_, cancellationToken).ConfigureAwait(false); - if (objectResponse_.Object == null) - { - throw new ApiException("Response was null which was not expected.", status_, objectResponse_.Text, headers_, null); - } - return objectResponse_.Object; + string responseText_ = ( response_.Content == null ) ? string.Empty : await response_.Content.ReadAsStringAsync().ConfigureAwait(false); + throw new ApiException("Deprecated", status_, responseText_, headers_, null); } else - if (status_ == 401) + + if (status_ == 200 || status_ == 204) { - string responseText_ = ( response_.Content == null ) ? string.Empty : await response_.Content.ReadAsStringAsync().ConfigureAwait(false); - throw new ApiException("Invalid credentials", status_, responseText_, headers_, null); + + return; } else { @@ -350,9 +344,8 @@ public virtual async System.Threading.Tasks.Task ApiV1AccountGetAsync(S /// /// Update account information request. All properties are optional as the server only ///
updates the values of the properties which are present - /// Successful request /// A server side error occurred. - public virtual System.Threading.Tasks.Task ApiV1AccountPutAsync(UpdateUserDto updateUserDto) + public virtual System.Threading.Tasks.Task ApiV1AccountPutAsync(UpdateUserDto updateUserDto) { return ApiV1AccountPutAsync(updateUserDto, System.Threading.CancellationToken.None); } @@ -364,9 +357,8 @@ public virtual System.Threading.Tasks.Task ApiV1AccountPutAsync(UpdateU /// /// Update account information request. All properties are optional as the server only ///
updates the values of the properties which are present - /// Successful request /// A server side error occurred. - public virtual async System.Threading.Tasks.Task ApiV1AccountPutAsync(UpdateUserDto updateUserDto, System.Threading.CancellationToken cancellationToken) + public virtual async System.Threading.Tasks.Task ApiV1AccountPutAsync(UpdateUserDto updateUserDto, System.Threading.CancellationToken cancellationToken) { if (updateUserDto == null) throw new System.ArgumentNullException("updateUserDto"); @@ -385,7 +377,6 @@ public virtual async System.Threading.Tasks.Task ApiV1AccountPutAsync(U content_.Headers.ContentType = System.Net.Http.Headers.MediaTypeHeaderValue.Parse("application/json"); request_.Content = content_; request_.Method = new System.Net.Http.HttpMethod("PUT"); - request_.Headers.Accept.Add(System.Net.Http.Headers.MediaTypeWithQualityHeaderValue.Parse("application/json")); PrepareRequest(client_, request_, urlBuilder_); @@ -408,20 +399,17 @@ public virtual async System.Threading.Tasks.Task ApiV1AccountPutAsync(U ProcessResponse(client_, response_); var status_ = (int)response_.StatusCode; - if (status_ == 200) + if (status_ == 410) { - var objectResponse_ = await ReadObjectResponseAsync(response_, headers_, cancellationToken).ConfigureAwait(false); - if (objectResponse_.Object == null) - { - throw new ApiException("Response was null which was not expected.", status_, objectResponse_.Text, headers_, null); - } - return objectResponse_.Object; + string responseText_ = ( response_.Content == null ) ? string.Empty : await response_.Content.ReadAsStringAsync().ConfigureAwait(false); + throw new ApiException("Deprecated", status_, responseText_, headers_, null); } else - if (status_ == 401) + + if (status_ == 200 || status_ == 204) { - string responseText_ = ( response_.Content == null ) ? string.Empty : await response_.Content.ReadAsStringAsync().ConfigureAwait(false); - throw new ApiException("Invalid credentials", status_, responseText_, headers_, null); + + return; } else { @@ -539,9 +527,9 @@ public virtual async System.Threading.Tasks.Task ApiV1Accoun /// /// Get app configuration /// - /// Successful request /// A server side error occurred. - public virtual System.Threading.Tasks.Task ApiV1AppConfigAsync() + [System.Obsolete] + public virtual System.Threading.Tasks.Task ApiV1AppConfigAsync() { return ApiV1AppConfigAsync(System.Threading.CancellationToken.None); } @@ -550,9 +538,9 @@ public virtual System.Threading.Tasks.Task ApiV1AppConfigAsync() /// /// Get app configuration /// - /// Successful request /// A server side error occurred. - public virtual async System.Threading.Tasks.Task ApiV1AppConfigAsync(System.Threading.CancellationToken cancellationToken) + [System.Obsolete] + public virtual async System.Threading.Tasks.Task ApiV1AppConfigAsync(System.Threading.CancellationToken cancellationToken) { var urlBuilder_ = new System.Text.StringBuilder(); urlBuilder_.Append("api/v1/AppConfig"); @@ -564,7 +552,6 @@ public virtual async System.Threading.Tasks.Task ApiV1AppConfigAsy using (var request_ = new System.Net.Http.HttpRequestMessage()) { request_.Method = new System.Net.Http.HttpMethod("GET"); - request_.Headers.Accept.Add(System.Net.Http.Headers.MediaTypeWithQualityHeaderValue.Parse("application/json")); PrepareRequest(client_, request_, urlBuilder_); @@ -587,20 +574,17 @@ public virtual async System.Threading.Tasks.Task ApiV1AppConfigAsy ProcessResponse(client_, response_); var status_ = (int)response_.StatusCode; - if (status_ == 200) + if (status_ == 410) { - var objectResponse_ = await ReadObjectResponseAsync(response_, headers_, cancellationToken).ConfigureAwait(false); - if (objectResponse_.Object == null) - { - throw new ApiException("Response was null which was not expected.", status_, objectResponse_.Text, headers_, null); - } - return objectResponse_.Object; + string responseText_ = ( response_.Content == null ) ? string.Empty : await response_.Content.ReadAsStringAsync().ConfigureAwait(false); + throw new ApiException("Deprecated", status_, responseText_, headers_, null); } else - if (status_ == 401) + + if (status_ == 200 || status_ == 204) { - string responseText_ = ( response_.Content == null ) ? string.Empty : await response_.Content.ReadAsStringAsync().ConfigureAwait(false); - throw new ApiException("Invalid credentials", status_, responseText_, headers_, null); + + return; } else { @@ -713,9 +697,8 @@ public virtual async System.Threading.Tasks.Task ApiV1CoffeeCards /// /// Leaderboard preset. 0 - Monthly, 1 - Semester and 2 - Total /// Number of results to return - /// Successful request /// A server side error occurred. - public virtual System.Threading.Tasks.Task> ApiV1LeaderboardAsync(int? preset, int? top) + public virtual System.Threading.Tasks.Task ApiV1LeaderboardAsync(int? preset, int? top) { return ApiV1LeaderboardAsync(preset, top, System.Threading.CancellationToken.None); } @@ -726,9 +709,8 @@ public virtual async System.Threading.Tasks.Task ApiV1CoffeeCards /// /// Leaderboard preset. 0 - Monthly, 1 - Semester and 2 - Total /// Number of results to return - /// Successful request /// A server side error occurred. - public virtual async System.Threading.Tasks.Task> ApiV1LeaderboardAsync(int? preset, int? top, System.Threading.CancellationToken cancellationToken) + public virtual async System.Threading.Tasks.Task ApiV1LeaderboardAsync(int? preset, int? top, System.Threading.CancellationToken cancellationToken) { var urlBuilder_ = new System.Text.StringBuilder(); urlBuilder_.Append("api/v1/Leaderboard?"); @@ -749,7 +731,6 @@ public virtual async System.Threading.Tasks.Task ApiV1CoffeeCards using (var request_ = new System.Net.Http.HttpRequestMessage()) { request_.Method = new System.Net.Http.HttpMethod("GET"); - request_.Headers.Accept.Add(System.Net.Http.Headers.MediaTypeWithQualityHeaderValue.Parse("application/json")); PrepareRequest(client_, request_, urlBuilder_); @@ -772,20 +753,17 @@ public virtual async System.Threading.Tasks.Task ApiV1CoffeeCards ProcessResponse(client_, response_); var status_ = (int)response_.StatusCode; - if (status_ == 200) + if (status_ == 410) { - var objectResponse_ = await ReadObjectResponseAsync>(response_, headers_, cancellationToken).ConfigureAwait(false); - if (objectResponse_.Object == null) - { - throw new ApiException("Response was null which was not expected.", status_, objectResponse_.Text, headers_, null); - } - return objectResponse_.Object; + string responseText_ = ( response_.Content == null ) ? string.Empty : await response_.Content.ReadAsStringAsync().ConfigureAwait(false); + throw new ApiException("Deprecated", status_, responseText_, headers_, null); } else - if (status_ == 401) + + if (status_ == 200 || status_ == 204) { - string responseText_ = ( response_.Content == null ) ? string.Empty : await response_.Content.ReadAsStringAsync().ConfigureAwait(false); - throw new ApiException("Invalid credentials", status_, responseText_, headers_, null); + + return; } else { @@ -811,9 +789,9 @@ public virtual async System.Threading.Tasks.Task ApiV1CoffeeCards /// Initiates a purchase from the given productId and returns an orderId /// /// Initiate purchase request - /// Successful request /// A server side error occurred. - public virtual System.Threading.Tasks.Task ApiV1MobilePayInitiateAsync(InitiatePurchaseDto initiatePurchaseDto) + [System.Obsolete] + public virtual System.Threading.Tasks.Task ApiV1MobilePayInitiateAsync(InitiatePurchaseDto initiatePurchaseDto) { return ApiV1MobilePayInitiateAsync(initiatePurchaseDto, System.Threading.CancellationToken.None); } @@ -823,9 +801,9 @@ public virtual System.Threading.Tasks.Task ApiV1Mob /// Initiates a purchase from the given productId and returns an orderId /// /// Initiate purchase request - /// Successful request /// A server side error occurred. - public virtual async System.Threading.Tasks.Task ApiV1MobilePayInitiateAsync(InitiatePurchaseDto initiatePurchaseDto, System.Threading.CancellationToken cancellationToken) + [System.Obsolete] + public virtual async System.Threading.Tasks.Task ApiV1MobilePayInitiateAsync(InitiatePurchaseDto initiatePurchaseDto, System.Threading.CancellationToken cancellationToken) { if (initiatePurchaseDto == null) throw new System.ArgumentNullException("initiatePurchaseDto"); @@ -844,7 +822,6 @@ public virtual async System.Threading.Tasks.Task Ap content_.Headers.ContentType = System.Net.Http.Headers.MediaTypeHeaderValue.Parse("application/json"); request_.Content = content_; request_.Method = new System.Net.Http.HttpMethod("POST"); - request_.Headers.Accept.Add(System.Net.Http.Headers.MediaTypeWithQualityHeaderValue.Parse("application/json")); PrepareRequest(client_, request_, urlBuilder_); @@ -867,20 +844,17 @@ public virtual async System.Threading.Tasks.Task Ap ProcessResponse(client_, response_); var status_ = (int)response_.StatusCode; - if (status_ == 200) + if (status_ == 410) { - var objectResponse_ = await ReadObjectResponseAsync(response_, headers_, cancellationToken).ConfigureAwait(false); - if (objectResponse_.Object == null) - { - throw new ApiException("Response was null which was not expected.", status_, objectResponse_.Text, headers_, null); - } - return objectResponse_.Object; + string responseText_ = ( response_.Content == null ) ? string.Empty : await response_.Content.ReadAsStringAsync().ConfigureAwait(false); + throw new ApiException("Deprecated", status_, responseText_, headers_, null); } else - if (status_ == 401) + + if (status_ == 200 || status_ == 204) { - string responseText_ = ( response_.Content == null ) ? string.Empty : await response_.Content.ReadAsStringAsync().ConfigureAwait(false); - throw new ApiException("Invalid credentials", status_, responseText_, headers_, null); + + return; } else { @@ -906,9 +880,9 @@ public virtual async System.Threading.Tasks.Task Ap /// Validates the purchase against MobilePay and delivers the tickets if succeeded /// /// Complete purchase request with MobilePay reference - /// Purchase successfully fulfilled /// A server side error occurred. - public virtual System.Threading.Tasks.Task ApiV1MobilePayCompleteAsync(CompletePurchaseDto dto) + [System.Obsolete] + public virtual System.Threading.Tasks.Task ApiV1MobilePayCompleteAsync(CompletePurchaseDto dto) { return ApiV1MobilePayCompleteAsync(dto, System.Threading.CancellationToken.None); } @@ -918,9 +892,9 @@ public virtual System.Threading.Tasks.Task ApiV1MobilePayCom /// Validates the purchase against MobilePay and delivers the tickets if succeeded /// /// Complete purchase request with MobilePay reference - /// Purchase successfully fulfilled /// A server side error occurred. - public virtual async System.Threading.Tasks.Task ApiV1MobilePayCompleteAsync(CompletePurchaseDto dto, System.Threading.CancellationToken cancellationToken) + [System.Obsolete] + public virtual async System.Threading.Tasks.Task ApiV1MobilePayCompleteAsync(CompletePurchaseDto dto, System.Threading.CancellationToken cancellationToken) { if (dto == null) throw new System.ArgumentNullException("dto"); @@ -939,7 +913,6 @@ public virtual async System.Threading.Tasks.Task ApiV1Mobile content_.Headers.ContentType = System.Net.Http.Headers.MediaTypeHeaderValue.Parse("application/json"); request_.Content = content_; request_.Method = new System.Net.Http.HttpMethod("POST"); - request_.Headers.Accept.Add(System.Net.Http.Headers.MediaTypeWithQualityHeaderValue.Parse("application/json")); PrepareRequest(client_, request_, urlBuilder_); @@ -962,20 +935,17 @@ public virtual async System.Threading.Tasks.Task ApiV1Mobile ProcessResponse(client_, response_); var status_ = (int)response_.StatusCode; - if (status_ == 200) + if (status_ == 410) { - var objectResponse_ = await ReadObjectResponseAsync(response_, headers_, cancellationToken).ConfigureAwait(false); - if (objectResponse_.Object == null) - { - throw new ApiException("Response was null which was not expected.", status_, objectResponse_.Text, headers_, null); - } - return objectResponse_.Object; + string responseText_ = ( response_.Content == null ) ? string.Empty : await response_.Content.ReadAsStringAsync().ConfigureAwait(false); + throw new ApiException("Deprecated", status_, responseText_, headers_, null); } else - if (status_ == 401) + + if (status_ == 200 || status_ == 204) { - string responseText_ = ( response_.Content == null ) ? string.Empty : await response_.Content.ReadAsStringAsync().ConfigureAwait(false); - throw new ApiException("Invalid credentials", status_, responseText_, headers_, null); + + return; } else { @@ -1002,6 +972,7 @@ public virtual async System.Threading.Tasks.Task ApiV1Mobile /// /// Successful request /// A server side error occurred. + [System.Obsolete] public virtual System.Threading.Tasks.Task ApiV1PingAsync() { return ApiV1PingAsync(System.Threading.CancellationToken.None); @@ -1013,6 +984,7 @@ public virtual System.Threading.Tasks.Task ApiV1PingAsync() /// /// Successful request /// A server side error occurred. + [System.Obsolete] public virtual async System.Threading.Tasks.Task ApiV1PingAsync(System.Threading.CancellationToken cancellationToken) { var urlBuilder_ = new System.Text.StringBuilder(); @@ -1326,9 +1298,9 @@ public virtual async System.Threading.Tasks.Task ApiV1PingAsync(System.T /// /// Returns a list of purchases for the given user via the supplied token in the header /// - /// Successful request /// A server side error occurred. - public virtual System.Threading.Tasks.Task> ApiV1PurchasesAsync() + [System.Obsolete] + public virtual System.Threading.Tasks.Task ApiV1PurchasesAsync() { return ApiV1PurchasesAsync(System.Threading.CancellationToken.None); } @@ -1337,9 +1309,9 @@ public virtual async System.Threading.Tasks.Task ApiV1PingAsync(System.T /// /// Returns a list of purchases for the given user via the supplied token in the header /// - /// Successful request /// A server side error occurred. - public virtual async System.Threading.Tasks.Task> ApiV1PurchasesAsync(System.Threading.CancellationToken cancellationToken) + [System.Obsolete] + public virtual async System.Threading.Tasks.Task ApiV1PurchasesAsync(System.Threading.CancellationToken cancellationToken) { var urlBuilder_ = new System.Text.StringBuilder(); urlBuilder_.Append("api/v1/Purchases"); @@ -1351,7 +1323,6 @@ public virtual async System.Threading.Tasks.Task ApiV1PingAsync(System.T using (var request_ = new System.Net.Http.HttpRequestMessage()) { request_.Method = new System.Net.Http.HttpMethod("GET"); - request_.Headers.Accept.Add(System.Net.Http.Headers.MediaTypeWithQualityHeaderValue.Parse("application/json")); PrepareRequest(client_, request_, urlBuilder_); @@ -1374,20 +1345,17 @@ public virtual async System.Threading.Tasks.Task ApiV1PingAsync(System.T ProcessResponse(client_, response_); var status_ = (int)response_.StatusCode; - if (status_ == 200) + if (status_ == 410) { - var objectResponse_ = await ReadObjectResponseAsync>(response_, headers_, cancellationToken).ConfigureAwait(false); - if (objectResponse_.Object == null) - { - throw new ApiException("Response was null which was not expected.", status_, objectResponse_.Text, headers_, null); - } - return objectResponse_.Object; + string responseText_ = ( response_.Content == null ) ? string.Empty : await response_.Content.ReadAsStringAsync().ConfigureAwait(false); + throw new ApiException("Deprecated", status_, responseText_, headers_, null); } else - if (status_ == 401) + + if (status_ == 200 || status_ == 204) { - string responseText_ = ( response_.Content == null ) ? string.Empty : await response_.Content.ReadAsStringAsync().ConfigureAwait(false); - throw new ApiException("Invalid credentials", status_, responseText_, headers_, null); + + return; } else { @@ -1476,7 +1444,7 @@ public virtual async System.Threading.Tasks.Task ApiV1PurchasesRede return objectResponse_.Object; } else - if (status_ == 400) + if (status_ == 409) { var objectResponse_ = await ReadObjectResponseAsync(response_, headers_, cancellationToken).ConfigureAwait(false); if (objectResponse_.Object == null) @@ -1524,9 +1492,9 @@ public virtual async System.Threading.Tasks.Task ApiV1PurchasesRede /// /// Issue purchase used by the ipad in the cafe /// - /// Successful request /// A server side error occurred. - public virtual System.Threading.Tasks.Task ApiV1PurchasesIssueproductAsync(IssueProductDto issueProduct) + [System.Obsolete] + public virtual System.Threading.Tasks.Task ApiV1PurchasesIssueproductAsync(IssueProductDto issueProduct) { return ApiV1PurchasesIssueproductAsync(issueProduct, System.Threading.CancellationToken.None); } @@ -1535,9 +1503,9 @@ public virtual System.Threading.Tasks.Task ApiV1PurchasesIssueprodu /// /// Issue purchase used by the ipad in the cafe /// - /// Successful request /// A server side error occurred. - public virtual async System.Threading.Tasks.Task ApiV1PurchasesIssueproductAsync(IssueProductDto issueProduct, System.Threading.CancellationToken cancellationToken) + [System.Obsolete] + public virtual async System.Threading.Tasks.Task ApiV1PurchasesIssueproductAsync(IssueProductDto issueProduct, System.Threading.CancellationToken cancellationToken) { if (issueProduct == null) throw new System.ArgumentNullException("issueProduct"); @@ -1556,7 +1524,6 @@ public virtual async System.Threading.Tasks.Task ApiV1PurchasesIssu content_.Headers.ContentType = System.Net.Http.Headers.MediaTypeHeaderValue.Parse("application/json"); request_.Content = content_; request_.Method = new System.Net.Http.HttpMethod("POST"); - request_.Headers.Accept.Add(System.Net.Http.Headers.MediaTypeWithQualityHeaderValue.Parse("application/json")); PrepareRequest(client_, request_, urlBuilder_); @@ -1579,20 +1546,17 @@ public virtual async System.Threading.Tasks.Task ApiV1PurchasesIssu ProcessResponse(client_, response_); var status_ = (int)response_.StatusCode; - if (status_ == 200) + if (status_ == 410) { - var objectResponse_ = await ReadObjectResponseAsync(response_, headers_, cancellationToken).ConfigureAwait(false); - if (objectResponse_.Object == null) - { - throw new ApiException("Response was null which was not expected.", status_, objectResponse_.Text, headers_, null); - } - return objectResponse_.Object; + string responseText_ = ( response_.Content == null ) ? string.Empty : await response_.Content.ReadAsStringAsync().ConfigureAwait(false); + throw new ApiException("Deprecated", status_, responseText_, headers_, null); } else - if (status_ == 401) + + if (status_ == 200 || status_ == 204) { - string responseText_ = ( response_.Content == null ) ? string.Empty : await response_.Content.ReadAsStringAsync().ConfigureAwait(false); - throw new ApiException("Invalid credentials", status_, responseText_, headers_, null); + + return; } else { @@ -1818,7 +1782,7 @@ public virtual async System.Threading.Tasks.Task ApiV1PurchasesIssu /// Use ticket request /// Successful request /// A server side error occurred. - public virtual System.Threading.Tasks.Task ApiV1TicketsUseAsync(UseTicketDTO dto) + public virtual System.Threading.Tasks.Task ApiV1TicketsUseAsync(UseTicketDTO dto) { return ApiV1TicketsUseAsync(dto, System.Threading.CancellationToken.None); } @@ -1830,7 +1794,7 @@ public virtual System.Threading.Tasks.Task ApiV1TicketsUseAsync(UseTi /// Use ticket request /// Successful request /// A server side error occurred. - public virtual async System.Threading.Tasks.Task ApiV1TicketsUseAsync(UseTicketDTO dto, System.Threading.CancellationToken cancellationToken) + public virtual async System.Threading.Tasks.Task ApiV1TicketsUseAsync(UseTicketDTO dto, System.Threading.CancellationToken cancellationToken) { if (dto == null) throw new System.ArgumentNullException("dto"); @@ -1874,7 +1838,7 @@ public virtual async System.Threading.Tasks.Task ApiV1TicketsUseAsync var status_ = (int)response_.StatusCode; if (status_ == 200) { - var objectResponse_ = await ReadObjectResponseAsync(response_, headers_, cancellationToken).ConfigureAwait(false); + var objectResponse_ = await ReadObjectResponseAsync(response_, headers_, cancellationToken).ConfigureAwait(false); if (objectResponse_.Object == null) { throw new ApiException("Response was null which was not expected.", status_, objectResponse_.Text, headers_, null); @@ -2029,7 +1993,7 @@ public partial class MessageResponseDto /// /// Message with API response /// - [Newtonsoft.Json.JsonProperty("message", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + [Newtonsoft.Json.JsonProperty("message", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] public string Message { get; set; } } @@ -2072,7 +2036,7 @@ public partial class TokenDto /// /// Bearer JWT token used for authentication /// - [Newtonsoft.Json.JsonProperty("token", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + [Newtonsoft.Json.JsonProperty("token", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] public string Token { get; set; } } @@ -2114,76 +2078,6 @@ public partial class LoginDto } - /// - /// User information - /// - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "13.18.0.0 (NJsonSchema v10.8.0.0 (Newtonsoft.Json v10.0.0.0))")] - public partial class UserDto - { - /// - /// User Id - /// - [Newtonsoft.Json.JsonProperty("id", Required = Newtonsoft.Json.Required.Always)] - public int Id { get; set; } - - /// - /// Full Name of user - /// - [Newtonsoft.Json.JsonProperty("name", Required = Newtonsoft.Json.Required.Always)] - [System.ComponentModel.DataAnnotations.Required] - public string Name { get; set; } - - /// - /// Email of user - /// - [Newtonsoft.Json.JsonProperty("email", Required = Newtonsoft.Json.Required.Always)] - [System.ComponentModel.DataAnnotations.Required] - public string Email { get; set; } - - /// - /// Privacy Activated - /// - [Newtonsoft.Json.JsonProperty("privacyActivated", Required = Newtonsoft.Json.Required.Always)] - public bool PrivacyActivated { get; set; } - - /// - /// Study Programme Id of user - /// - [Newtonsoft.Json.JsonProperty("programmeId", Required = Newtonsoft.Json.Required.Always)] - public int ProgrammeId { get; set; } - - /// - /// User Level - /// - [Newtonsoft.Json.JsonProperty("level", Required = Newtonsoft.Json.Required.Always)] - public int Level { get; set; } - - /// - /// User Experience Level - /// - [Newtonsoft.Json.JsonProperty("requiredExp", Required = Newtonsoft.Json.Required.Always)] - public int RequiredExp { get; set; } - - /// - /// User's Rank all time - /// - [Newtonsoft.Json.JsonProperty("rankAllTime", Required = Newtonsoft.Json.Required.Always)] - public int RankAllTime { get; set; } - - /// - /// User's rank current semester - /// - [Newtonsoft.Json.JsonProperty("rankSemester", Required = Newtonsoft.Json.Required.Always)] - public int RankSemester { get; set; } - - /// - /// User's rank current month - /// - [Newtonsoft.Json.JsonProperty("rankMonth", Required = Newtonsoft.Json.Required.Always)] - public int RankMonth { get; set; } - - } - /// /// Update User information request object. All properties are optional as the server only updates the values of the properties which are present /// @@ -2193,13 +2087,13 @@ public partial class UpdateUserDto /// /// Full Name of user /// - [Newtonsoft.Json.JsonProperty("name", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + [Newtonsoft.Json.JsonProperty("name", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] public string Name { get; set; } /// /// Email of user /// - [Newtonsoft.Json.JsonProperty("email", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + [Newtonsoft.Json.JsonProperty("email", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] public string Email { get; set; } /// @@ -2217,7 +2111,7 @@ public partial class UpdateUserDto /// /// Pin Code as first UTF8 encoded, then SHA256 hashed, and then Base64 encoded string /// - [Newtonsoft.Json.JsonProperty("password", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + [Newtonsoft.Json.JsonProperty("password", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] public string Password { get; set; } } @@ -2237,44 +2131,6 @@ public partial class EmailDto } - /// - /// App Configuration - /// - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "13.18.0.0 (NJsonSchema v10.8.0.0 (Newtonsoft.Json v10.0.0.0))")] - public partial class AppConfigDto - { - /// - /// Environment type for indicating production or test system - /// - [Newtonsoft.Json.JsonProperty("environmentType", Required = Newtonsoft.Json.Required.Always)] - [System.ComponentModel.DataAnnotations.Required(AllowEmptyStrings = true)] - [Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.StringEnumConverter))] - public EnvironmentType EnvironmentType { get; set; } - - /// - /// MobilePay MerchantId - /// - [Newtonsoft.Json.JsonProperty("merchantId", Required = Newtonsoft.Json.Required.Always)] - [System.ComponentModel.DataAnnotations.Required] - public string MerchantId { get; set; } - - } - - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "13.18.0.0 (NJsonSchema v10.8.0.0 (Newtonsoft.Json v10.0.0.0))")] - public enum EnvironmentType - { - - [System.Runtime.Serialization.EnumMember(Value = @"Production")] - Production = 0, - - [System.Runtime.Serialization.EnumMember(Value = @"Test")] - Test = 1, - - [System.Runtime.Serialization.EnumMember(Value = @"LocalDevelopment")] - LocalDevelopment = 2, - - } - /// /// A CoffeeCard is a union datatype of a product and unused tickets associated with the product. /// @@ -2314,41 +2170,6 @@ public partial class CoffeeCardDto } - /// - /// A user on the leaderboard - /// - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "13.18.0.0 (NJsonSchema v10.8.0.0 (Newtonsoft.Json v10.0.0.0))")] - public partial class LeaderboardDto - { - /// - /// Account name - /// - [Newtonsoft.Json.JsonProperty("name", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] - public string Name { get; set; } - - /// - /// Account score - /// - [Newtonsoft.Json.JsonProperty("score", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] - public int Score { get; set; } - - } - - /// - /// Initiation of a new purchase response - /// - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "13.18.0.0 (NJsonSchema v10.8.0.0 (Newtonsoft.Json v10.0.0.0))")] - public partial class InitiatePurchaseResponseDto - { - /// - /// Order Id - /// - [Newtonsoft.Json.JsonProperty("orderId", Required = Newtonsoft.Json.Required.Always)] - [System.ComponentModel.DataAnnotations.Required] - public string OrderId { get; set; } - - } - /// /// Initiate a new purchase request /// @@ -2595,6 +2416,41 @@ public partial class UseMultipleTicketDto } + /// + /// Representing a used ticket for a product + /// + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "13.18.0.0 (NJsonSchema v10.8.0.0 (Newtonsoft.Json v10.0.0.0))")] + public partial class UsedTicketResponse + { + /// + /// Ticket Id + /// + [Newtonsoft.Json.JsonProperty("id", Required = Newtonsoft.Json.Required.Always)] + public int Id { get; set; } + + /// + /// Issuing date time for ticket in Utc format + /// + [Newtonsoft.Json.JsonProperty("dateCreated", Required = Newtonsoft.Json.Required.Always)] + [System.ComponentModel.DataAnnotations.Required] + public System.DateTimeOffset DateCreated { get; set; } + + /// + /// Used date time for ticket in Utc format + /// + [Newtonsoft.Json.JsonProperty("dateUsed", Required = Newtonsoft.Json.Required.Always)] + [System.ComponentModel.DataAnnotations.Required] + public System.DateTimeOffset DateUsed { get; set; } + + /// + /// Name of product a ticket is for + /// + [Newtonsoft.Json.JsonProperty("productName", Required = Newtonsoft.Json.Required.Always)] + [System.ComponentModel.DataAnnotations.Required] + public string ProductName { get; set; } + + } + /// /// Use ticket request /// diff --git a/Shifty.Api/Generated/AnalogCoreV2/AnalogCoreV2.cs b/Shifty.Api/Generated/AnalogCoreV2/AnalogCoreV2.cs index 6053a12..de6c4eb 100644 --- a/Shifty.Api/Generated/AnalogCoreV2/AnalogCoreV2.cs +++ b/Shifty.Api/Generated/AnalogCoreV2/AnalogCoreV2.cs @@ -193,7 +193,7 @@ public virtual async System.Threading.Tasks.Task ApiV2AccountDeleteAsync(System. ProcessResponse(client_, response_); var status_ = (int)response_.StatusCode; - if (status_ == 204) + if (status_ == 202) { return; } @@ -513,6 +513,109 @@ public virtual async System.Threading.Tasks.Task ApiV2Accou } } + /// + /// Resend account verification email if account is not already verified + /// + /// Email to be verified + /// Email has been sent + /// A server side error occurred. + public virtual System.Threading.Tasks.Task ApiV2AccountResendVerificationEmailAsync(ResendAccountVerificationEmailRequest request) + { + return ApiV2AccountResendVerificationEmailAsync(request, System.Threading.CancellationToken.None); + } + + /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. + /// + /// Resend account verification email if account is not already verified + /// + /// Email to be verified + /// Email has been sent + /// A server side error occurred. + public virtual async System.Threading.Tasks.Task ApiV2AccountResendVerificationEmailAsync(ResendAccountVerificationEmailRequest request, System.Threading.CancellationToken cancellationToken) + { + if (request == null) + throw new System.ArgumentNullException("request"); + + var urlBuilder_ = new System.Text.StringBuilder(); + urlBuilder_.Append("api/v2/account/resend-verification-email"); + + var client_ = _httpClient; + var disposeClient_ = false; + try + { + using (var request_ = new System.Net.Http.HttpRequestMessage()) + { + var json_ = Newtonsoft.Json.JsonConvert.SerializeObject(request, _settings.Value); + var content_ = new System.Net.Http.StringContent(json_); + content_.Headers.ContentType = System.Net.Http.Headers.MediaTypeHeaderValue.Parse("application/json"); + request_.Content = content_; + request_.Method = new System.Net.Http.HttpMethod("POST"); + + PrepareRequest(client_, request_, urlBuilder_); + + var url_ = urlBuilder_.ToString(); + request_.RequestUri = new System.Uri(url_, System.UriKind.RelativeOrAbsolute); + + PrepareRequest(client_, request_, url_); + + var response_ = await client_.SendAsync(request_, System.Net.Http.HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false); + var disposeResponse_ = true; + try + { + var headers_ = System.Linq.Enumerable.ToDictionary(response_.Headers, h_ => h_.Key, h_ => h_.Value); + if (response_.Content != null && response_.Content.Headers != null) + { + foreach (var item_ in response_.Content.Headers) + headers_[item_.Key] = item_.Value; + } + + ProcessResponse(client_, response_); + + var status_ = (int)response_.StatusCode; + if (status_ == 200) + { + return; + } + else + if (status_ == 404) + { + var objectResponse_ = await ReadObjectResponseAsync(response_, headers_, cancellationToken).ConfigureAwait(false); + if (objectResponse_.Object == null) + { + throw new ApiException("Response was null which was not expected.", status_, objectResponse_.Text, headers_, null); + } + throw new ApiException("Email not found", status_, objectResponse_.Text, headers_, objectResponse_.Object, null); + } + else + if (status_ == 409) + { + var objectResponse_ = await ReadObjectResponseAsync(response_, headers_, cancellationToken).ConfigureAwait(false); + if (objectResponse_.Object == null) + { + throw new ApiException("Response was null which was not expected.", status_, objectResponse_.Text, headers_, null); + } + throw new ApiException("Account already verified", status_, objectResponse_.Text, headers_, objectResponse_.Object, null); + } + else + { + var responseData_ = response_.Content == null ? null : await response_.Content.ReadAsStringAsync().ConfigureAwait(false); + throw new ApiException("The HTTP status code of the response was not expected (" + status_ + ").", status_, responseData_, headers_, null); + } + } + finally + { + if (disposeResponse_) + response_.Dispose(); + } + } + } + finally + { + if (disposeClient_) + client_.Dispose(); + } + } + /// /// Get app configuration /// @@ -593,6 +696,176 @@ public virtual async System.Threading.Tasks.Task ApiV2AppconfigAsync( } } + /// + /// Ping + /// + /// Successful request + /// A server side error occurred. + public virtual System.Threading.Tasks.Task ApiV2HealthPingAsync() + { + return ApiV2HealthPingAsync(System.Threading.CancellationToken.None); + } + + /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. + /// + /// Ping + /// + /// Successful request + /// A server side error occurred. + public virtual async System.Threading.Tasks.Task ApiV2HealthPingAsync(System.Threading.CancellationToken cancellationToken) + { + var urlBuilder_ = new System.Text.StringBuilder(); + urlBuilder_.Append("api/v2/health/ping"); + + var client_ = _httpClient; + var disposeClient_ = false; + try + { + using (var request_ = new System.Net.Http.HttpRequestMessage()) + { + request_.Method = new System.Net.Http.HttpMethod("GET"); + request_.Headers.Accept.Add(System.Net.Http.Headers.MediaTypeWithQualityHeaderValue.Parse("application/json")); + + PrepareRequest(client_, request_, urlBuilder_); + + var url_ = urlBuilder_.ToString(); + request_.RequestUri = new System.Uri(url_, System.UriKind.RelativeOrAbsolute); + + PrepareRequest(client_, request_, url_); + + var response_ = await client_.SendAsync(request_, System.Net.Http.HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false); + var disposeResponse_ = true; + try + { + var headers_ = System.Linq.Enumerable.ToDictionary(response_.Headers, h_ => h_.Key, h_ => h_.Value); + if (response_.Content != null && response_.Content.Headers != null) + { + foreach (var item_ in response_.Content.Headers) + headers_[item_.Key] = item_.Value; + } + + ProcessResponse(client_, response_); + + var status_ = (int)response_.StatusCode; + if (status_ == 200) + { + var objectResponse_ = await ReadObjectResponseAsync(response_, headers_, cancellationToken).ConfigureAwait(false); + if (objectResponse_.Object == null) + { + throw new ApiException("Response was null which was not expected.", status_, objectResponse_.Text, headers_, null); + } + return objectResponse_.Object; + } + else + { + var responseData_ = response_.Content == null ? null : await response_.Content.ReadAsStringAsync().ConfigureAwait(false); + throw new ApiException("The HTTP status code of the response was not expected (" + status_ + ").", status_, responseData_, headers_, null); + } + } + finally + { + if (disposeResponse_) + response_.Dispose(); + } + } + } + finally + { + if (disposeClient_) + client_.Dispose(); + } + } + + /// + /// Check service health + /// + /// Healthy service + /// A server side error occurred. + public virtual System.Threading.Tasks.Task ApiV2HealthCheckAsync() + { + return ApiV2HealthCheckAsync(System.Threading.CancellationToken.None); + } + + /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. + /// + /// Check service health + /// + /// Healthy service + /// A server side error occurred. + public virtual async System.Threading.Tasks.Task ApiV2HealthCheckAsync(System.Threading.CancellationToken cancellationToken) + { + var urlBuilder_ = new System.Text.StringBuilder(); + urlBuilder_.Append("api/v2/health/check"); + + var client_ = _httpClient; + var disposeClient_ = false; + try + { + using (var request_ = new System.Net.Http.HttpRequestMessage()) + { + request_.Method = new System.Net.Http.HttpMethod("GET"); + request_.Headers.Accept.Add(System.Net.Http.Headers.MediaTypeWithQualityHeaderValue.Parse("application/json")); + + PrepareRequest(client_, request_, urlBuilder_); + + var url_ = urlBuilder_.ToString(); + request_.RequestUri = new System.Uri(url_, System.UriKind.RelativeOrAbsolute); + + PrepareRequest(client_, request_, url_); + + var response_ = await client_.SendAsync(request_, System.Net.Http.HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false); + var disposeResponse_ = true; + try + { + var headers_ = System.Linq.Enumerable.ToDictionary(response_.Headers, h_ => h_.Key, h_ => h_.Value); + if (response_.Content != null && response_.Content.Headers != null) + { + foreach (var item_ in response_.Content.Headers) + headers_[item_.Key] = item_.Value; + } + + ProcessResponse(client_, response_); + + var status_ = (int)response_.StatusCode; + if (status_ == 200) + { + var objectResponse_ = await ReadObjectResponseAsync(response_, headers_, cancellationToken).ConfigureAwait(false); + if (objectResponse_.Object == null) + { + throw new ApiException("Response was null which was not expected.", status_, objectResponse_.Text, headers_, null); + } + return objectResponse_.Object; + } + else + if (status_ == 503) + { + var objectResponse_ = await ReadObjectResponseAsync(response_, headers_, cancellationToken).ConfigureAwait(false); + if (objectResponse_.Object == null) + { + throw new ApiException("Response was null which was not expected.", status_, objectResponse_.Text, headers_, null); + } + throw new ApiException("Unhealthy service", status_, objectResponse_.Text, headers_, objectResponse_.Object, null); + } + else + { + var responseData_ = response_.Content == null ? null : await response_.Content.ReadAsStringAsync().ConfigureAwait(false); + throw new ApiException("A server side error occurred.", status_, responseData_, headers_, null); + } + } + finally + { + if (disposeResponse_) + response_.Dispose(); + } + } + } + finally + { + if (disposeClient_) + client_.Dispose(); + } + } + /// /// Gets the top leaderboard by the specified preset /// @@ -659,7 +932,376 @@ public virtual async System.Threading.Tasks.Task ApiV2AppconfigAsync( var status_ = (int)response_.StatusCode; if (status_ == 200) { - var objectResponse_ = await ReadObjectResponseAsync>(response_, headers_, cancellationToken).ConfigureAwait(false); + var objectResponse_ = await ReadObjectResponseAsync>(response_, headers_, cancellationToken).ConfigureAwait(false); + if (objectResponse_.Object == null) + { + throw new ApiException("Response was null which was not expected.", status_, objectResponse_.Text, headers_, null); + } + return objectResponse_.Object; + } + else + { + var responseData_ = response_.Content == null ? null : await response_.Content.ReadAsStringAsync().ConfigureAwait(false); + throw new ApiException("The HTTP status code of the response was not expected (" + status_ + ").", status_, responseData_, headers_, null); + } + } + finally + { + if (disposeResponse_) + response_.Dispose(); + } + } + } + finally + { + if (disposeClient_) + client_.Dispose(); + } + } + + /// + /// Get leaderboard stats for authenticated user. A user will have rank 0 if they do not have any valid swipes + /// + /// Leaderboard preset for date filtering. See LeaderboardPreset for possible values + /// Leaderboard entry for user + /// A server side error occurred. + public virtual System.Threading.Tasks.Task ApiV2LeaderboardAsync(LeaderboardPreset? preset) + { + return ApiV2LeaderboardAsync(preset, System.Threading.CancellationToken.None); + } + + /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. + /// + /// Get leaderboard stats for authenticated user. A user will have rank 0 if they do not have any valid swipes + /// + /// Leaderboard preset for date filtering. See LeaderboardPreset for possible values + /// Leaderboard entry for user + /// A server side error occurred. + public virtual async System.Threading.Tasks.Task ApiV2LeaderboardAsync(LeaderboardPreset? preset, System.Threading.CancellationToken cancellationToken) + { + var urlBuilder_ = new System.Text.StringBuilder(); + urlBuilder_.Append("api/v2/leaderboard?"); + if (preset != null) + { + urlBuilder_.Append(System.Uri.EscapeDataString("preset") + "=").Append(System.Uri.EscapeDataString(ConvertToString(preset, System.Globalization.CultureInfo.InvariantCulture))).Append("&"); + } + urlBuilder_.Length--; + + var client_ = _httpClient; + var disposeClient_ = false; + try + { + using (var request_ = new System.Net.Http.HttpRequestMessage()) + { + request_.Method = new System.Net.Http.HttpMethod("GET"); + request_.Headers.Accept.Add(System.Net.Http.Headers.MediaTypeWithQualityHeaderValue.Parse("application/json")); + + PrepareRequest(client_, request_, urlBuilder_); + + var url_ = urlBuilder_.ToString(); + request_.RequestUri = new System.Uri(url_, System.UriKind.RelativeOrAbsolute); + + PrepareRequest(client_, request_, url_); + + var response_ = await client_.SendAsync(request_, System.Net.Http.HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false); + var disposeResponse_ = true; + try + { + var headers_ = System.Linq.Enumerable.ToDictionary(response_.Headers, h_ => h_.Key, h_ => h_.Value); + if (response_.Content != null && response_.Content.Headers != null) + { + foreach (var item_ in response_.Content.Headers) + headers_[item_.Key] = item_.Value; + } + + ProcessResponse(client_, response_); + + var status_ = (int)response_.StatusCode; + if (status_ == 200) + { + var objectResponse_ = await ReadObjectResponseAsync(response_, headers_, cancellationToken).ConfigureAwait(false); + if (objectResponse_.Object == null) + { + throw new ApiException("Response was null which was not expected.", status_, objectResponse_.Text, headers_, null); + } + return objectResponse_.Object; + } + else + if (status_ == 401) + { + string responseText_ = ( response_.Content == null ) ? string.Empty : await response_.Content.ReadAsStringAsync().ConfigureAwait(false); + throw new ApiException("Invalid credentials", status_, responseText_, headers_, null); + } + else + { + var responseData_ = response_.Content == null ? null : await response_.Content.ReadAsStringAsync().ConfigureAwait(false); + throw new ApiException("The HTTP status code of the response was not expected (" + status_ + ").", status_, responseData_, headers_, null); + } + } + finally + { + if (disposeResponse_) + response_.Dispose(); + } + } + } + finally + { + if (disposeClient_) + client_.Dispose(); + } + } + + /// + /// Webhook to be invoked by MobilePay backend + /// + /// Webhook signature + /// Webhook request + /// Webhook processed + /// A server side error occurred. + public virtual System.Threading.Tasks.Task ApiV2MobilepayWebhookAsync(string mpSignatureHeader, MobilePayWebhook request) + { + return ApiV2MobilepayWebhookAsync(mpSignatureHeader, request, System.Threading.CancellationToken.None); + } + + /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. + /// + /// Webhook to be invoked by MobilePay backend + /// + /// Webhook signature + /// Webhook request + /// Webhook processed + /// A server side error occurred. + public virtual async System.Threading.Tasks.Task ApiV2MobilepayWebhookAsync(string mpSignatureHeader, MobilePayWebhook request, System.Threading.CancellationToken cancellationToken) + { + if (request == null) + throw new System.ArgumentNullException("request"); + + var urlBuilder_ = new System.Text.StringBuilder(); + urlBuilder_.Append("api/v2/mobilepay/webhook"); + + var client_ = _httpClient; + var disposeClient_ = false; + try + { + using (var request_ = new System.Net.Http.HttpRequestMessage()) + { + + if (mpSignatureHeader != null) + request_.Headers.TryAddWithoutValidation("x-mobilepay-signature", ConvertToString(mpSignatureHeader, System.Globalization.CultureInfo.InvariantCulture)); + var json_ = Newtonsoft.Json.JsonConvert.SerializeObject(request, _settings.Value); + var content_ = new System.Net.Http.StringContent(json_); + content_.Headers.ContentType = System.Net.Http.Headers.MediaTypeHeaderValue.Parse("application/json"); + request_.Content = content_; + request_.Method = new System.Net.Http.HttpMethod("POST"); + + PrepareRequest(client_, request_, urlBuilder_); + + var url_ = urlBuilder_.ToString(); + request_.RequestUri = new System.Uri(url_, System.UriKind.RelativeOrAbsolute); + + PrepareRequest(client_, request_, url_); + + var response_ = await client_.SendAsync(request_, System.Net.Http.HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false); + var disposeResponse_ = true; + try + { + var headers_ = System.Linq.Enumerable.ToDictionary(response_.Headers, h_ => h_.Key, h_ => h_.Value); + if (response_.Content != null && response_.Content.Headers != null) + { + foreach (var item_ in response_.Content.Headers) + headers_[item_.Key] = item_.Value; + } + + ProcessResponse(client_, response_); + + var status_ = (int)response_.StatusCode; + if (status_ == 204) + { + return; + } + else + if (status_ == 400) + { + var objectResponse_ = await ReadObjectResponseAsync(response_, headers_, cancellationToken).ConfigureAwait(false); + if (objectResponse_.Object == null) + { + throw new ApiException("Response was null which was not expected.", status_, objectResponse_.Text, headers_, null); + } + throw new ApiException("Signature is not valid", status_, objectResponse_.Text, headers_, objectResponse_.Object, null); + } + else + { + var responseData_ = response_.Content == null ? null : await response_.Content.ReadAsStringAsync().ConfigureAwait(false); + throw new ApiException("A server side error occurred.", status_, responseData_, headers_, null); + } + } + finally + { + if (disposeResponse_) + response_.Dispose(); + } + } + } + finally + { + if (disposeClient_) + client_.Dispose(); + } + } + + /// + /// Adds a new product to the database. + /// + /// The request containing the details of the product to be added and allowed user groups. + /// The request was successful, and the product was added. + /// A server side error occurred. + public virtual System.Threading.Tasks.Task ApiV2ProductsPostAsync(AddProductRequest addProductRequest) + { + return ApiV2ProductsPostAsync(addProductRequest, System.Threading.CancellationToken.None); + } + + /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. + /// + /// Adds a new product to the database. + /// + /// The request containing the details of the product to be added and allowed user groups. + /// The request was successful, and the product was added. + /// A server side error occurred. + public virtual async System.Threading.Tasks.Task ApiV2ProductsPostAsync(AddProductRequest addProductRequest, System.Threading.CancellationToken cancellationToken) + { + if (addProductRequest == null) + throw new System.ArgumentNullException("addProductRequest"); + + var urlBuilder_ = new System.Text.StringBuilder(); + urlBuilder_.Append("api/v2/products"); + + var client_ = _httpClient; + var disposeClient_ = false; + try + { + using (var request_ = new System.Net.Http.HttpRequestMessage()) + { + var json_ = Newtonsoft.Json.JsonConvert.SerializeObject(addProductRequest, _settings.Value); + var content_ = new System.Net.Http.StringContent(json_); + content_.Headers.ContentType = System.Net.Http.Headers.MediaTypeHeaderValue.Parse("application/json"); + request_.Content = content_; + request_.Method = new System.Net.Http.HttpMethod("POST"); + request_.Headers.Accept.Add(System.Net.Http.Headers.MediaTypeWithQualityHeaderValue.Parse("application/json")); + + PrepareRequest(client_, request_, urlBuilder_); + + var url_ = urlBuilder_.ToString(); + request_.RequestUri = new System.Uri(url_, System.UriKind.RelativeOrAbsolute); + + PrepareRequest(client_, request_, url_); + + var response_ = await client_.SendAsync(request_, System.Net.Http.HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false); + var disposeResponse_ = true; + try + { + var headers_ = System.Linq.Enumerable.ToDictionary(response_.Headers, h_ => h_.Key, h_ => h_.Value); + if (response_.Content != null && response_.Content.Headers != null) + { + foreach (var item_ in response_.Content.Headers) + headers_[item_.Key] = item_.Value; + } + + ProcessResponse(client_, response_); + + var status_ = (int)response_.StatusCode; + if (status_ == 200) + { + var objectResponse_ = await ReadObjectResponseAsync(response_, headers_, cancellationToken).ConfigureAwait(false); + if (objectResponse_.Object == null) + { + throw new ApiException("Response was null which was not expected.", status_, objectResponse_.Text, headers_, null); + } + return objectResponse_.Object; + } + else + { + var responseData_ = response_.Content == null ? null : await response_.Content.ReadAsStringAsync().ConfigureAwait(false); + throw new ApiException("The HTTP status code of the response was not expected (" + status_ + ").", status_, responseData_, headers_, null); + } + } + finally + { + if (disposeResponse_) + response_.Dispose(); + } + } + } + finally + { + if (disposeClient_) + client_.Dispose(); + } + } + + /// + /// Updates a product with the specified changes. + /// + /// The request containing the changes to be applied to the product. + /// The request was successful, and the product was updated. + /// A server side error occurred. + public virtual System.Threading.Tasks.Task ApiV2ProductsPutAsync(UpdateProductRequest product) + { + return ApiV2ProductsPutAsync(product, System.Threading.CancellationToken.None); + } + + /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. + /// + /// Updates a product with the specified changes. + /// + /// The request containing the changes to be applied to the product. + /// The request was successful, and the product was updated. + /// A server side error occurred. + public virtual async System.Threading.Tasks.Task ApiV2ProductsPutAsync(UpdateProductRequest product, System.Threading.CancellationToken cancellationToken) + { + if (product == null) + throw new System.ArgumentNullException("product"); + + var urlBuilder_ = new System.Text.StringBuilder(); + urlBuilder_.Append("api/v2/products"); + + var client_ = _httpClient; + var disposeClient_ = false; + try + { + using (var request_ = new System.Net.Http.HttpRequestMessage()) + { + var json_ = Newtonsoft.Json.JsonConvert.SerializeObject(product, _settings.Value); + var content_ = new System.Net.Http.StringContent(json_); + content_.Headers.ContentType = System.Net.Http.Headers.MediaTypeHeaderValue.Parse("application/json"); + request_.Content = content_; + request_.Method = new System.Net.Http.HttpMethod("PUT"); + request_.Headers.Accept.Add(System.Net.Http.Headers.MediaTypeWithQualityHeaderValue.Parse("application/json")); + + PrepareRequest(client_, request_, urlBuilder_); + + var url_ = urlBuilder_.ToString(); + request_.RequestUri = new System.Uri(url_, System.UriKind.RelativeOrAbsolute); + + PrepareRequest(client_, request_, url_); + + var response_ = await client_.SendAsync(request_, System.Net.Http.HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false); + var disposeResponse_ = true; + try + { + var headers_ = System.Linq.Enumerable.ToDictionary(response_.Headers, h_ => h_.Key, h_ => h_.Value); + if (response_.Content != null && response_.Content.Headers != null) + { + foreach (var item_ in response_.Content.Headers) + headers_[item_.Key] = item_.Value; + } + + ProcessResponse(client_, response_); + + var status_ = (int)response_.StatusCode; + if (status_ == 200) + { + var objectResponse_ = await ReadObjectResponseAsync(response_, headers_, cancellationToken).ConfigureAwait(false); if (objectResponse_.Object == null) { throw new ApiException("Response was null which was not expected.", status_, objectResponse_.Text, headers_, null); @@ -687,32 +1329,25 @@ public virtual async System.Threading.Tasks.Task ApiV2AppconfigAsync( } /// - /// Get leaderboard stats for authenticated user. A user will have rank 0 if they do not have any valid swipes + /// Returns a list of available products based on a account's user group /// - /// Leaderboard preset for date filtering. See LeaderboardPreset for possible values - /// Leaderboard entry for user + /// Successful request /// A server side error occurred. - public virtual System.Threading.Tasks.Task ApiV2LeaderboardAsync(LeaderboardPreset? preset) + public virtual System.Threading.Tasks.Task> ApiV2ProductsGetAsync() { - return ApiV2LeaderboardAsync(preset, System.Threading.CancellationToken.None); + return ApiV2ProductsGetAsync(System.Threading.CancellationToken.None); } /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. /// - /// Get leaderboard stats for authenticated user. A user will have rank 0 if they do not have any valid swipes + /// Returns a list of available products based on a account's user group /// - /// Leaderboard preset for date filtering. See LeaderboardPreset for possible values - /// Leaderboard entry for user + /// Successful request /// A server side error occurred. - public virtual async System.Threading.Tasks.Task ApiV2LeaderboardAsync(LeaderboardPreset? preset, System.Threading.CancellationToken cancellationToken) + public virtual async System.Threading.Tasks.Task> ApiV2ProductsGetAsync(System.Threading.CancellationToken cancellationToken) { var urlBuilder_ = new System.Text.StringBuilder(); - urlBuilder_.Append("api/v2/leaderboard?"); - if (preset != null) - { - urlBuilder_.Append(System.Uri.EscapeDataString("preset") + "=").Append(System.Uri.EscapeDataString(ConvertToString(preset, System.Globalization.CultureInfo.InvariantCulture))).Append("&"); - } - urlBuilder_.Length--; + urlBuilder_.Append("api/v2/products"); var client_ = _httpClient; var disposeClient_ = false; @@ -746,7 +1381,7 @@ public virtual async System.Threading.Tasks.Task ApiV2Leaderbo var status_ = (int)response_.StatusCode; if (status_ == 200) { - var objectResponse_ = await ReadObjectResponseAsync(response_, headers_, cancellationToken).ConfigureAwait(false); + var objectResponse_ = await ReadObjectResponseAsync>(response_, headers_, cancellationToken).ConfigureAwait(false); if (objectResponse_.Object == null) { throw new ApiException("Response was null which was not expected.", status_, objectResponse_.Text, headers_, null); @@ -754,12 +1389,6 @@ public virtual async System.Threading.Tasks.Task ApiV2Leaderbo return objectResponse_.Object; } else - if (status_ == 401) - { - string responseText_ = ( response_.Content == null ) ? string.Empty : await response_.Content.ReadAsStringAsync().ConfigureAwait(false); - throw new ApiException("Invalid credentials", status_, responseText_, headers_, null); - } - else { var responseData_ = response_.Content == null ? null : await response_.Content.ReadAsStringAsync().ConfigureAwait(false); throw new ApiException("The HTTP status code of the response was not expected (" + status_ + ").", status_, responseData_, headers_, null); @@ -780,32 +1409,25 @@ public virtual async System.Threading.Tasks.Task ApiV2Leaderbo } /// - /// Webhook to be invoked by MobilePay backend + /// Returns a list of all products /// - /// Webhook mpSignatureHeader - /// Webhook request - /// Webhook processed + /// Successful request /// A server side error occurred. - public virtual System.Threading.Tasks.Task ApiV2MobilepayWebhookAsync(string mpSignatureHeader, MobilePayWebhook request) + public virtual System.Threading.Tasks.Task> ApiV2ProductsAllAsync() { - return ApiV2MobilepayWebhookAsync(mpSignatureHeader, request, System.Threading.CancellationToken.None); + return ApiV2ProductsAllAsync(System.Threading.CancellationToken.None); } /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. /// - /// Webhook to be invoked by MobilePay backend + /// Returns a list of all products /// - /// Webhook mpSignatureHeader - /// Webhook request - /// Webhook processed + /// Successful request /// A server side error occurred. - public virtual async System.Threading.Tasks.Task ApiV2MobilepayWebhookAsync(string mpSignatureHeader, MobilePayWebhook request, System.Threading.CancellationToken cancellationToken) + public virtual async System.Threading.Tasks.Task> ApiV2ProductsAllAsync(System.Threading.CancellationToken cancellationToken) { - if (request == null) - throw new System.ArgumentNullException("request"); - var urlBuilder_ = new System.Text.StringBuilder(); - urlBuilder_.Append("api/v2/mobilepay/webhook"); + urlBuilder_.Append("api/v2/products/all"); var client_ = _httpClient; var disposeClient_ = false; @@ -813,14 +1435,8 @@ public virtual async System.Threading.Tasks.Task ApiV2MobilepayWebhookAsync(stri { using (var request_ = new System.Net.Http.HttpRequestMessage()) { - - if (mpSignatureHeader != null) - request_.Headers.TryAddWithoutValidation("x-mobilepay-signature", ConvertToString(mpSignatureHeader, System.Globalization.CultureInfo.InvariantCulture)); - var json_ = Newtonsoft.Json.JsonConvert.SerializeObject(request, _settings.Value); - var content_ = new System.Net.Http.StringContent(json_); - content_.Headers.ContentType = System.Net.Http.Headers.MediaTypeHeaderValue.Parse("application/json"); - request_.Content = content_; - request_.Method = new System.Net.Http.HttpMethod("POST"); + request_.Method = new System.Net.Http.HttpMethod("GET"); + request_.Headers.Accept.Add(System.Net.Http.Headers.MediaTypeWithQualityHeaderValue.Parse("application/json")); PrepareRequest(client_, request_, urlBuilder_); @@ -843,24 +1459,19 @@ public virtual async System.Threading.Tasks.Task ApiV2MobilepayWebhookAsync(stri ProcessResponse(client_, response_); var status_ = (int)response_.StatusCode; - if (status_ == 204) - { - return; - } - else - if (status_ == 400) + if (status_ == 200) { - var objectResponse_ = await ReadObjectResponseAsync(response_, headers_, cancellationToken).ConfigureAwait(false); + var objectResponse_ = await ReadObjectResponseAsync>(response_, headers_, cancellationToken).ConfigureAwait(false); if (objectResponse_.Object == null) { throw new ApiException("Response was null which was not expected.", status_, objectResponse_.Text, headers_, null); } - throw new ApiException("Signature is not valid", status_, objectResponse_.Text, headers_, objectResponse_.Object, null); + return objectResponse_.Object; } else { var responseData_ = response_.Content == null ? null : await response_.Content.ReadAsStringAsync().ConfigureAwait(false); - throw new ApiException("A server side error occurred.", status_, responseData_, headers_, null); + throw new ApiException("The HTTP status code of the response was not expected (" + status_ + ").", status_, responseData_, headers_, null); } } finally @@ -880,7 +1491,7 @@ public virtual async System.Threading.Tasks.Task ApiV2MobilepayWebhookAsync(stri /// /// Get all purchases /// - /// All purchases + /// Purchases /// A server side error occurred. public virtual System.Threading.Tasks.Task> ApiV2PurchasesGetAsync() { @@ -891,7 +1502,7 @@ public virtual async System.Threading.Tasks.Task ApiV2MobilepayWebhookAsync(stri /// /// Get all purchases /// - /// All purchases + /// Purchases /// A server side error occurred. public virtual async System.Threading.Tasks.Task> ApiV2PurchasesGetAsync(System.Threading.CancellationToken cancellationToken) { @@ -938,12 +1549,6 @@ public virtual async System.Threading.Tasks.Task ApiV2MobilepayWebhookAsync(stri return objectResponse_.Object; } else - if (status_ == 204) - { - string responseText_ = ( response_.Content == null ) ? string.Empty : await response_.Content.ReadAsStringAsync().ConfigureAwait(false); - throw new ApiException("No purchases", status_, responseText_, headers_, null); - } - else if (status_ == 401) { string responseText_ = ( response_.Content == null ) ? string.Empty : await response_.Content.ReadAsStringAsync().ConfigureAwait(false); @@ -1599,7 +2204,7 @@ public partial class MessageResponseDto /// /// Message with API response /// - [Newtonsoft.Json.JsonProperty("message", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + [Newtonsoft.Json.JsonProperty("message", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] public string Message { get; set; } } @@ -1769,13 +2374,13 @@ public partial class UpdateUserRequest /// /// Full Name of user /// - [Newtonsoft.Json.JsonProperty("name", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + [Newtonsoft.Json.JsonProperty("name", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] public string Name { get; set; } /// /// Email of user /// - [Newtonsoft.Json.JsonProperty("email", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + [Newtonsoft.Json.JsonProperty("email", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] public string Email { get; set; } /// @@ -1793,7 +2398,7 @@ public partial class UpdateUserRequest /// /// Pin Code as first UTF8 encoded, then SHA256 hashed, and then Base64 encoded string /// - [Newtonsoft.Json.JsonProperty("password", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + [Newtonsoft.Json.JsonProperty("password", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] public string Password { get; set; } } @@ -1827,6 +2432,21 @@ public partial class EmailExistsRequest } + /// + /// Resend Invite email request + /// + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "13.18.0.0 (NJsonSchema v10.8.0.0 (Newtonsoft.Json v10.0.0.0))")] + public partial class ResendAccountVerificationEmailRequest + { + /// + /// User email + /// + [Newtonsoft.Json.JsonProperty("email", Required = Newtonsoft.Json.Required.Always)] + [System.ComponentModel.DataAnnotations.Required] + public string Email { get; set; } + + } + /// /// App Configuration /// @@ -1858,6 +2478,26 @@ public enum EnvironmentType } + /// + /// Service Health + /// + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "13.18.0.0 (NJsonSchema v10.8.0.0 (Newtonsoft.Json v10.0.0.0))")] + public partial class ServiceHealthResponse + { + /// + /// MobilePay connected + /// + [Newtonsoft.Json.JsonProperty("mobilePay", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public bool MobilePay { get; set; } + + /// + /// Database connected + /// + [Newtonsoft.Json.JsonProperty("database", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public bool Database { get; set; } + + } + /// /// A user on the leaderboard /// @@ -1974,6 +2614,236 @@ public partial class EventData } + /// + /// Represents the product response. + /// + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "13.18.0.0 (NJsonSchema v10.8.0.0 (Newtonsoft.Json v10.0.0.0))")] + public partial class ChangedProductResponse + { + /// + /// Gets or sets the price of the product. + /// + [Newtonsoft.Json.JsonProperty("price", Required = Newtonsoft.Json.Required.Always)] + [System.ComponentModel.DataAnnotations.Range(0, 2147483647)] + public int Price { get; set; } + + /// + /// Gets or sets the number of tickets associated with the product. + /// + [Newtonsoft.Json.JsonProperty("numberOfTickets", Required = Newtonsoft.Json.Required.Always)] + [System.ComponentModel.DataAnnotations.Range(0, 2147483647)] + public int NumberOfTickets { get; set; } + + /// + /// Gets or sets the name of the product. + /// + [Newtonsoft.Json.JsonProperty("name", Required = Newtonsoft.Json.Required.Always)] + [System.ComponentModel.DataAnnotations.Required] + public string Name { get; set; } + + /// + /// Gets or sets the description of the product. + /// + [Newtonsoft.Json.JsonProperty("description", Required = Newtonsoft.Json.Required.Always)] + [System.ComponentModel.DataAnnotations.Required] + public string Description { get; set; } + + /// + /// Gets or sets the visibility of the product. + /// + [Newtonsoft.Json.JsonProperty("visible", Required = Newtonsoft.Json.Required.Always)] + public bool Visible { get; set; } + + /// + /// Gets or sets the user groups that can access the product. + /// + [Newtonsoft.Json.JsonProperty("allowedUserGroups", Required = Newtonsoft.Json.Required.Always, ItemConverterType = typeof(Newtonsoft.Json.Converters.StringEnumConverter))] + [System.ComponentModel.DataAnnotations.Required] + public System.Collections.Generic.ICollection AllowedUserGroups { get; set; } = new System.Collections.ObjectModel.Collection(); + + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "13.18.0.0 (NJsonSchema v10.8.0.0 (Newtonsoft.Json v10.0.0.0))")] + public enum UserGroup + { + + [System.Runtime.Serialization.EnumMember(Value = @"Customer")] + Customer = 0, + + [System.Runtime.Serialization.EnumMember(Value = @"Barista")] + Barista = 1, + + [System.Runtime.Serialization.EnumMember(Value = @"Manager")] + Manager = 2, + + [System.Runtime.Serialization.EnumMember(Value = @"Board")] + Board = 3, + + } + + /// + /// Initiate a new product add request. + /// + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "13.18.0.0 (NJsonSchema v10.8.0.0 (Newtonsoft.Json v10.0.0.0))")] + public partial class AddProductRequest + { + /// + /// Gets or sets the price of the product. + /// + [Newtonsoft.Json.JsonProperty("price", Required = Newtonsoft.Json.Required.Always)] + [System.ComponentModel.DataAnnotations.Range(0, 2147483647)] + public int Price { get; set; } + + /// + /// Gets or sets the number of tickets associated with the product. + /// + [Newtonsoft.Json.JsonProperty("numberOfTickets", Required = Newtonsoft.Json.Required.Always)] + [System.ComponentModel.DataAnnotations.Range(0, 2147483647)] + public int NumberOfTickets { get; set; } + + /// + /// Gets or sets the name of the product. + /// + [Newtonsoft.Json.JsonProperty("name", Required = Newtonsoft.Json.Required.Always)] + [System.ComponentModel.DataAnnotations.Required] + public string Name { get; set; } + + /// + /// Gets or sets the description of the product. + /// + [Newtonsoft.Json.JsonProperty("description", Required = Newtonsoft.Json.Required.Always)] + [System.ComponentModel.DataAnnotations.Required] + public string Description { get; set; } + + /// + /// Gets or sets the visibility of the product. Default is true. + /// + [Newtonsoft.Json.JsonProperty("visible", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public bool Visible { get; set; } = true; + + /// + /// Gets or sets the user groups that can access the product. + /// + [Newtonsoft.Json.JsonProperty("allowedUserGroups", Required = Newtonsoft.Json.Required.Always, ItemConverterType = typeof(Newtonsoft.Json.Converters.StringEnumConverter))] + [System.ComponentModel.DataAnnotations.Required] + public System.Collections.Generic.ICollection AllowedUserGroups { get; set; } = new System.Collections.ObjectModel.Collection(); + + } + + /// + /// Initiate an update product request. + /// + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "13.18.0.0 (NJsonSchema v10.8.0.0 (Newtonsoft.Json v10.0.0.0))")] + public partial class UpdateProductRequest + { + /// + /// Gets or sets the ID of the product to update. + /// + [Newtonsoft.Json.JsonProperty("id", Required = Newtonsoft.Json.Required.Always)] + public int Id { get; set; } + + /// + /// Gets or sets the updated price of the product. + /// + [Newtonsoft.Json.JsonProperty("price", Required = Newtonsoft.Json.Required.Always)] + [System.ComponentModel.DataAnnotations.Range(0, 2147483647)] + public int Price { get; set; } + + /// + /// Gets or sets the updated number of tickets associated with the product. + /// + [Newtonsoft.Json.JsonProperty("numberOfTickets", Required = Newtonsoft.Json.Required.Always)] + [System.ComponentModel.DataAnnotations.Range(0, 2147483647)] + public int NumberOfTickets { get; set; } + + /// + /// Gets or sets the updated name of the product. + /// + [Newtonsoft.Json.JsonProperty("name", Required = Newtonsoft.Json.Required.Always)] + [System.ComponentModel.DataAnnotations.Required] + public string Name { get; set; } + + /// + /// Gets or sets the updated description of the product. + /// + [Newtonsoft.Json.JsonProperty("description", Required = Newtonsoft.Json.Required.Always)] + [System.ComponentModel.DataAnnotations.Required] + public string Description { get; set; } + + /// + /// Gets or sets the updated visibility of the product. Default is true. + /// + [Newtonsoft.Json.JsonProperty("visible", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public bool Visible { get; set; } = true; + + /// + /// Gets or sets the user groups that can access the product. + /// + [Newtonsoft.Json.JsonProperty("allowedUserGroups", Required = Newtonsoft.Json.Required.Always, ItemConverterType = typeof(Newtonsoft.Json.Converters.StringEnumConverter))] + [System.ComponentModel.DataAnnotations.Required] + public System.Collections.Generic.ICollection AllowedUserGroups { get; set; } = new System.Collections.ObjectModel.Collection(); + + } + + /// + /// Represents a purchasable product + /// + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "13.18.0.0 (NJsonSchema v10.8.0.0 (Newtonsoft.Json v10.0.0.0))")] + public partial class ProductResponse + { + /// + /// Id of product + /// + [Newtonsoft.Json.JsonProperty("id", Required = Newtonsoft.Json.Required.Always)] + public int Id { get; set; } + + /// + /// Product price + /// + [Newtonsoft.Json.JsonProperty("price", Required = Newtonsoft.Json.Required.Always)] + public int Price { get; set; } + + /// + /// Number of tickets in product + /// + [Newtonsoft.Json.JsonProperty("numberOfTickets", Required = Newtonsoft.Json.Required.Always)] + public int NumberOfTickets { get; set; } + + /// + /// Name of product + /// + [Newtonsoft.Json.JsonProperty("name", Required = Newtonsoft.Json.Required.Always)] + [System.ComponentModel.DataAnnotations.Required] + public string Name { get; set; } + + /// + /// Description of products + /// + [Newtonsoft.Json.JsonProperty("description", Required = Newtonsoft.Json.Required.Always)] + [System.ComponentModel.DataAnnotations.Required] + public string Description { get; set; } + + /// + /// Eligible due to a user perk privilege + /// + [Newtonsoft.Json.JsonProperty("isPerk", Required = Newtonsoft.Json.Required.Always)] + public bool IsPerk { get; set; } + + /// + /// Visibility of products for users + /// + [Newtonsoft.Json.JsonProperty("visible", Required = Newtonsoft.Json.Required.Always)] + public bool Visible { get; set; } + + /// + /// Decides the user groups that can access the product. + /// + [Newtonsoft.Json.JsonProperty("allowedUserGroups", Required = Newtonsoft.Json.Required.Always, ItemConverterType = typeof(Newtonsoft.Json.Converters.StringEnumConverter))] + [System.ComponentModel.DataAnnotations.Required] + public System.Collections.Generic.ICollection AllowedUserGroups { get; set; } = new System.Collections.ObjectModel.Collection(); + + } + /// /// Represents a purchase /// diff --git a/Shifty.App/Components/ProductManager.razor b/Shifty.App/Components/ProductManager.razor new file mode 100644 index 0000000..e0733d5 --- /dev/null +++ b/Shifty.App/Components/ProductManager.razor @@ -0,0 +1,262 @@ +@namespace Components +@using System.ComponentModel.DataAnnotations +@using Shifty.App.Services +@using Shifty.Api.Generated.AnalogCoreV1 +@using Shifty.Api.Generated.AnalogCoreV2 +@using Shared +@using LanguageExt.UnsafeValueAccess +@using Components +@inject ISnackbar Snackbar +@inject IProductService ProductService + + + + @if (_loading) + { + + + + } + + + + + + + + + + @{ + if (context.Item.Visible) + { + + } + else + { + + } + } + + + + + + + + + + + + Visible to: + @foreach (var group in Enum.GetValues()) + { + + @group + } + + + + + @{ + if (context.Item.IsPerk) + { + + } + else + { + + } + } + + + + + + + + + + Add Product + + + +@code +{ + private MudDataGrid _dataGrid; + private IEnumerable _products = new List(); + private Dictionary UserGroupDict = new(); + + private void StartedEditingItem(ProductResponse item) + { + UserGroupDict = new(); + foreach (var group in Enum.GetValues()) + { + UserGroupDict.Add(group, item.AllowedUserGroups.Contains(group)); + } + } + + private bool _loading = true; + private bool _showNonvisible = true; + protected override async Task OnInitializedAsync() + { + var result = await ProductService.GetProducts(); + _loading = false; + result.Match( + Succ: products => { + _products = products; + }, + Fail: error => { + Snackbar.Add(error.Message, Severity.Error); + } + ); + } + + void CanceledEditingItem(ProductResponse item) + { + Snackbar.Add("Cancelled product changes", Severity.Info); + } + + async Task CommittedItemChanges(ProductResponse item) + { + List AllowedUserGroups = + UserGroupDict.Where(e => e.Value) + .ToDictionary(kv => kv.Key, kv => kv.Value) + .Keys + .ToList(); + + if (item.Id == 0) + { + var result = await addProduct(item, AllowedUserGroups); + + result.Match( + Succ: async product => + { + // Succesfully added product + Snackbar.Add("Product added", Severity.Success); + + // Retrieve all items again in order to update id + var retrieveItems = await ProductService.GetProducts(); + retrieveItems.Match( + Succ: items => { + _products = items; + }, + Fail: error => { + // Errors while re-retrieving items, non-fatal (just means _products are slightly outdated) + Snackbar.Add(error.Message, Severity.Warning); + } + ); + }, + Fail: error => { + Snackbar.Add(error.Message, Severity.Error); + } + ); + } + else + { + var result = await updateProduct(item, AllowedUserGroups); + + result.Match( + Succ: async result => + { + Snackbar.Add("Product updated", Severity.Success); + + var retrieveItems = await ProductService.GetProducts(); + retrieveItems.Match( + Succ: items => { + _products = items; + }, + Fail: error => { + // Errors while re-retrieving items, non-fatal (just means _products are slightly outdated) + Snackbar.Add(error.Message, Severity.Warning); + } + ); + }, + Fail: error => + { + Snackbar.Add(error.Message, Severity.Warning); + } + ); + } + } + + async Task> updateProduct(ProductResponse item, List + AllowedUserGroups) + { + return await ProductService.UpdateProduct(new UpdateProductRequest{ + Id = item.Id, + Name = item.Name, + Description = item.Description, + NumberOfTickets = item.NumberOfTickets, + Price = item.Price, + Visible = item.Visible, + AllowedUserGroups = AllowedUserGroups + }); + } + + async Task> addProduct(ProductResponse item, List + AllowedUserGroups) + { + return await ProductService.AddProduct(new AddProductRequest{ + Name = item.Name, + Description = item.Description, + NumberOfTickets = item.NumberOfTickets, + Price = item.Price, + Visible = item.Visible, + AllowedUserGroups = AllowedUserGroups + }); + } + + void AddItemToDataGrid() + { + _products = _products.Append(new ProductResponse{ + Id = 0, + Name = "", + Description = "", + IsPerk = false, + NumberOfTickets = 1, + Price = 0, + Visible = true, + AllowedUserGroups = new List() + }); + _dataGrid.SetEditingItemAsync(_products.Last()); + } + + private Func _RowStyleFunc => (x, i) => + { + if (!x.Visible) + { + return "background-color:#ebebeb;font-style:italic;font-color:#8a8686;"; + } + return ""; + }; +} diff --git a/Shifty.App/Components/Voucher.razor b/Shifty.App/Components/Voucher.razor index 14895a2..9d7d9b2 100644 --- a/Shifty.App/Components/Voucher.razor +++ b/Shifty.App/Components/Voucher.razor @@ -5,6 +5,7 @@ @using Shifty.Api.Generated.AnalogCoreV2 @using Shared @using LanguageExt.UnsafeValueAccess +@using Shifty.App.Repositories @inject IProductService _productService @inject IVoucherService _voucherService @inject ISnackbar Snackbar @@ -15,7 +16,7 @@ Issue Voucher Form - + @bind-Value="_voucherForm.Product"/> _products = new List(); + private IEnumerable _products = new List(); private IEnumerable _vouchers; private string _voucherCodes; private MudTextField _multilineReference; @@ -108,7 +109,7 @@ { [Required] public string Description { get; set; } - public ProductDto Product { get; set; } + public ProductResponse Product { get; set; } public int Amount { get; set; } = 1; public string Requester { get; set; } public string Prefix { get; set; } @@ -116,7 +117,6 @@ protected override async Task OnInitializedAsync() { - Snackbar.Configuration.PositionClass = Defaults.Classes.Position.BottomRight; var result = await _productService.GetProducts(); result.Match( @@ -130,7 +130,7 @@ ); } - private async Task> Products(string value) + private async Task> Products(string value) { if (string.IsNullOrEmpty(value)) return _products; @@ -159,7 +159,7 @@ Succ: response => { _showProgressBar = false; _vouchers = response; - _voucherCodes = string.Join("\n", _vouchers.Select(response => response.VoucherCode)); + _voucherCodes = string.Join("\n", _vouchers.Select(issueVoucherResponse => issueVoucherResponse.VoucherCode)); }, Fail: ex => { _showProgressBar = false; @@ -168,6 +168,6 @@ ); } - Func _converter = p => p != null ? $"{p.Name} - {p.NumberOfTickets} ticket" + (p.NumberOfTickets == 1 ? "" : "s") : ""; - Func prefixValidation = str => str.Length == 3 ? null : "Prefix must be 3 letters"; + Func _converter = p => p != null ? $"{p.Name} - {p.NumberOfTickets} ticket" + (p.NumberOfTickets == 1 ? "" : "s") : ""; + Func _prefixValidation = str => str.Length == 3 ? null : "Prefix must be 3 letters"; } \ No newline at end of file diff --git a/Shifty.App/Pages/ProductManagement.razor b/Shifty.App/Pages/ProductManagement.razor new file mode 100644 index 0000000..d06ac6d --- /dev/null +++ b/Shifty.App/Pages/ProductManagement.razor @@ -0,0 +1,24 @@ +@page "/Products" +@using Components +@inject NavigationManager NavManager + +@if (_user is not null && _user.IsInRole("Board")) +{ + +} + +@code { + [CascadingParameter] public Task AuthTask { get; set; } + private System.Security.Claims.ClaimsPrincipal _user; + + protected override async Task OnInitializedAsync() + { + var authState = await AuthTask; + _user = authState.User; + + if (_user is null || !_user.IsInRole("Board")) + { + NavManager.NavigateTo("/"); + } + } +} \ No newline at end of file diff --git a/Shifty.App/Program.cs b/Shifty.App/Program.cs index 2120cfa..4fdaf4d 100644 --- a/Shifty.App/Program.cs +++ b/Shifty.App/Program.cs @@ -6,6 +6,7 @@ using Microsoft.AspNetCore.Components.WebAssembly.Hosting; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; +using MudBlazor; using MudBlazor.Services; using Shifty.Api.Generated.AnalogCoreV1; using Shifty.Api.Generated.AnalogCoreV2; @@ -17,7 +18,6 @@ namespace Shifty.App { public class Program { - private const string apiUrl = "https://core.dev.analogio.dk/"; public static async Task Main(string[] args) { var builder = WebAssemblyHostBuilder.CreateDefault(args); @@ -61,6 +61,20 @@ public static void ConfigureServices(IServiceCollection services, IConfiguration services.AddScoped(); services.AddScoped(); services.AddScoped(); + + services.AddMudServices(config => + { + config.SnackbarConfiguration.PositionClass = Defaults.Classes.Position.BottomRight; + + config.SnackbarConfiguration.PreventDuplicates = false; + config.SnackbarConfiguration.NewestOnTop = false; + config.SnackbarConfiguration.ShowCloseIcon = true; + config.SnackbarConfiguration.VisibleStateDuration = 10000; + config.SnackbarConfiguration.HideTransitionDuration = 500; + config.SnackbarConfiguration.ShowTransitionDuration = 500; + config.SnackbarConfiguration.SnackbarVariant = Variant.Filled; + }); + } } diff --git a/Shifty.App/Repositories/IProductRepository.cs b/Shifty.App/Repositories/IProductRepository.cs index fc8512b..44e439c 100644 --- a/Shifty.App/Repositories/IProductRepository.cs +++ b/Shifty.App/Repositories/IProductRepository.cs @@ -2,11 +2,14 @@ using LanguageExt; using LanguageExt.Common; using Shifty.Api.Generated.AnalogCoreV1; +using Shifty.Api.Generated.AnalogCoreV2; namespace Shifty.App.Repositories { public interface IProductRepository { - public Task>> GetProducts(); + Task> AddProduct(AddProductRequest addProductRequest); + public Task>> GetProducts(); + Task> UpdateProduct(UpdateProductRequest product); } } \ No newline at end of file diff --git a/Shifty.App/Repositories/ProductRepository.cs b/Shifty.App/Repositories/ProductRepository.cs index 792505f..b6dfa61 100644 --- a/Shifty.App/Repositories/ProductRepository.cs +++ b/Shifty.App/Repositories/ProductRepository.cs @@ -5,6 +5,7 @@ using LanguageExt; using LanguageExt.Common; using Shifty.Api.Generated.AnalogCoreV1; +using Shifty.Api.Generated.AnalogCoreV2; using Shifty.App.Services; using static LanguageExt.Prelude; @@ -12,16 +13,26 @@ namespace Shifty.App.Repositories { public class ProductRepository : IProductRepository { - private readonly AnalogCoreV1 _client; + private readonly AnalogCoreV2 _client; - public ProductRepository(AnalogCoreV1 client) + public ProductRepository(AnalogCoreV2 client) { _client = client; } - - async Task>> IProductRepository.GetProducts() + + public async Task> AddProduct(AddProductRequest addProductRequest) + { + return await TryAsync(async () => await _client.ApiV2ProductsPostAsync(addProductRequest)); + } + + public async Task> UpdateProduct(UpdateProductRequest product) + { + return await TryAsync(async () => await _client.ApiV2ProductsPutAsync(product)); + } + + async Task>> IProductRepository.GetProducts() { - return await TryAsync(async () => (await _client.ApiV1ProductsAsync()).AsEnumerable()); + return await TryAsync(async () => (await _client.ApiV2ProductsAllAsync()).AsEnumerable()); } } } \ No newline at end of file diff --git a/Shifty.App/Services/IProductService.cs b/Shifty.App/Services/IProductService.cs index eda8485..a005028 100644 --- a/Shifty.App/Services/IProductService.cs +++ b/Shifty.App/Services/IProductService.cs @@ -3,6 +3,7 @@ using LanguageExt; using LanguageExt.Common; using Shifty.Api.Generated.AnalogCoreV1; +using Shifty.Api.Generated.AnalogCoreV2; namespace Shifty.App.Services { @@ -12,6 +13,20 @@ public interface IProductService /// Gives products available to user /// /// Collection of products in the form of ProductDtos. The Collection is null if an error happens. - Task>> GetProducts(); + Task>> GetProducts(); + + /// + /// Updates a product + /// + /// The product request containing the updated product information + /// The updated product + Task> UpdateProduct(UpdateProductRequest product); + + /// + /// Adds a product + /// + /// The product request containing the new product information + /// The newly created product + Task> AddProduct(AddProductRequest product); } } \ No newline at end of file diff --git a/Shifty.App/Services/ProductService.cs b/Shifty.App/Services/ProductService.cs index 3571de7..ae545cd 100644 --- a/Shifty.App/Services/ProductService.cs +++ b/Shifty.App/Services/ProductService.cs @@ -6,6 +6,7 @@ using LanguageExt.Common; using LanguageExt.UnsafeValueAccess; using Shifty.Api.Generated.AnalogCoreV1; +using Shifty.Api.Generated.AnalogCoreV2; using Shifty.App.Authentication; using Shifty.App.Repositories; @@ -20,9 +21,19 @@ public ProductService(IProductRepository productRepository) _productRepository = productRepository; } - public async Task>> GetProducts() + public async Task>> GetProducts() { return await _productRepository.GetProducts(); } + + public async Task> UpdateProduct(UpdateProductRequest product) + { + return await _productRepository.UpdateProduct(product); + } + + public async Task> AddProduct(AddProductRequest product) + { + return await _productRepository.AddProduct(product); + } } } \ No newline at end of file diff --git a/Shifty.App/Shared/MainLayout.razor b/Shifty.App/Shared/MainLayout.razor index 189a2d4..4d206fb 100644 --- a/Shifty.App/Shared/MainLayout.razor +++ b/Shifty.App/Shared/MainLayout.razor @@ -53,6 +53,7 @@ Error = new MudColor("#893c24"), Warning = new MudColor("#fed521"), Success = new MudColor("#738d4b"), + Dark = Colors.Grey.Darken3, } }; diff --git a/Shifty.App/Shared/NavMenu.razor b/Shifty.App/Shared/NavMenu.razor index cef0651..c5d6743 100644 --- a/Shifty.App/Shared/NavMenu.razor +++ b/Shifty.App/Shared/NavMenu.razor @@ -3,6 +3,7 @@ @if (_user is not null && _user.IsInRole("Board")) { Issue vouchers + Product Management } diff --git a/Shifty.App/Shifty.App.csproj b/Shifty.App/Shifty.App.csproj index 66f93b0..7cd5450 100755 --- a/Shifty.App/Shifty.App.csproj +++ b/Shifty.App/Shifty.App.csproj @@ -14,7 +14,7 @@ - + diff --git a/Shifty.App/wwwroot/appsettings.json b/Shifty.App/wwwroot/appsettings.json index 09a6cb5..b219808 100644 --- a/Shifty.App/wwwroot/appsettings.json +++ b/Shifty.App/wwwroot/appsettings.json @@ -1,3 +1,3 @@ { - "ApiHost": "http://localhost:8080" + "ApiHost": "https://core.dev.analogio.dk/" } diff --git a/Shifty.GenerateApi/OpenApiSpecs/AnalogCoreV1.json b/Shifty.GenerateApi/OpenApiSpecs/AnalogCoreV1.json index 7bcada6..0fac624 100644 --- a/Shifty.GenerateApi/OpenApiSpecs/AnalogCoreV1.json +++ b/Shifty.GenerateApi/OpenApiSpecs/AnalogCoreV1.json @@ -1,5 +1,5 @@ { - "x-generator": "NSwag v13.15.5.0 (NJsonSchema v10.6.6.0 (Newtonsoft.Json v13.0.0.0))", + "x-generator": "NSwag v13.17.0.0 (NJsonSchema v10.8.0.0 (Newtonsoft.Json v13.0.0.0))", "openapi": "3.0.0", "info": { "title": "Cafe Analog CoffeeCard API", @@ -17,7 +17,7 @@ }, "servers": [ { - "url": "https://localhost:5001" + "url": "https://core.dev.analogio.dk" } ], "paths": { @@ -130,23 +130,16 @@ "summary": "Returns basic data about the account", "operationId": "Account_Get", "responses": { - "200": { - "description": "Successful request", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UserDto" - } - } - } - }, - "401": { - "description": "Invalid credentials" + "410": { + "description": "Deprecated" } }, "security": [ { - "Bearer": [] + "jwt": [] + }, + { + "apikey": [] } ] }, @@ -170,23 +163,16 @@ "x-position": 1 }, "responses": { - "200": { - "description": "Successful request", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UserDto" - } - } - } - }, - "401": { - "description": "Invalid credentials" + "410": { + "description": "Deprecated" } }, "security": [ { - "Bearer": [] + "jwt": [] + }, + { + "apikey": [] } ] } @@ -242,23 +228,17 @@ "summary": "Get app configuration", "operationId": "AppConfig_Get", "responses": { - "200": { - "description": "Successful request", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AppConfigDto" - } - } - } - }, - "401": { - "description": "Invalid credentials" + "410": { + "description": "Deprecated" } }, + "deprecated": true, "security": [ { - "Bearer": [] + "jwt": [] + }, + { + "apikey": [] } ] } @@ -287,7 +267,10 @@ }, "security": [ { - "Bearer": [] + "jwt": [] + }, + { + "apikey": [] } ] } @@ -323,21 +306,8 @@ } ], "responses": { - "200": { - "description": "Successful request", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/LeaderboardDto" - } - } - } - } - }, - "401": { - "description": "Invalid credentials" + "410": { + "description": "Deprecated" } } } @@ -363,23 +333,17 @@ "x-position": 1 }, "responses": { - "200": { - "description": "Successful request", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/InitiatePurchaseResponseDto" - } - } - } - }, - "401": { - "description": "Invalid credentials" + "410": { + "description": "Deprecated" } }, + "deprecated": true, "security": [ { - "Bearer": [] + "jwt": [] + }, + { + "apikey": [] } ] } @@ -405,23 +369,17 @@ "x-position": 1 }, "responses": { - "200": { - "description": "Purchase successfully fulfilled", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/MessageResponseDto" - } - } - } - }, - "401": { - "description": "Invalid credentials" + "410": { + "description": "Deprecated" } }, + "deprecated": true, "security": [ { - "Bearer": [] + "jwt": [] + }, + { + "apikey": [] } ] } @@ -444,7 +402,8 @@ } } } - } + }, + "deprecated": true } }, "/api/v1/Products": { @@ -498,7 +457,10 @@ }, "security": [ { - "Bearer": [] + "jwt": [] + }, + { + "apikey": [] } ] } @@ -535,26 +497,17 @@ "summary": "Returns a list of purchases for the given user via the supplied token in the header", "operationId": "Purchases_Get", "responses": { - "200": { - "description": "Successful request", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/PurchaseDto" - } - } - } - } - }, - "401": { - "description": "Invalid credentials" + "410": { + "description": "Deprecated" } }, + "deprecated": true, "security": [ { - "Bearer": [] + "jwt": [] + }, + { + "apikey": [] } ] } @@ -587,7 +540,7 @@ } } }, - "400": { + "409": { "description": "Voucher code already used", "content": { "application/json": { @@ -613,7 +566,10 @@ }, "security": [ { - "Bearer": [] + "jwt": [] + }, + { + "apikey": [] } ] } @@ -638,20 +594,11 @@ "x-position": 1 }, "responses": { - "200": { - "description": "Successful request", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/PurchaseDto" - } - } - } - }, - "401": { - "description": "Invalid credentials" + "410": { + "description": "Deprecated" } - } + }, + "deprecated": true } }, "/api/v1/Tickets": { @@ -692,7 +639,10 @@ }, "security": [ { - "Bearer": [] + "jwt": [] + }, + { + "apikey": [] } ] } @@ -747,7 +697,10 @@ }, "security": [ { - "Bearer": [] + "jwt": [] + }, + { + "apikey": [] } ] } @@ -778,7 +731,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/TicketDto" + "$ref": "#/components/schemas/UsedTicketResponse" } } } @@ -799,7 +752,10 @@ }, "security": [ { - "Bearer": [] + "jwt": [] + }, + { + "apikey": [] } ] } @@ -818,6 +774,7 @@ "message": { "type": "string", "description": "Message with API response", + "nullable": true, "example": "Successful completion" } } @@ -869,6 +826,7 @@ "token": { "type": "string", "description": "Bearer JWT token used for authentication", + "nullable": true, "example": "[no example provided]" } } @@ -918,96 +876,6 @@ } } }, - "UserDto": { - "type": "object", - "description": "User information", - "example": { - "id": 123, - "name": "John Doe", - "email": "john@doe.com", - "privacyActivated": true, - "programmeId": 1, - "level": 1, - "requiredExp": 12, - "rankAllTime": 15, - "rankSemester": 4, - "rankMonth": 5 - }, - "additionalProperties": false, - "required": [ - "id", - "name", - "email", - "privacyActivated", - "programmeId", - "level", - "requiredExp", - "rankAllTime", - "rankSemester", - "rankMonth" - ], - "properties": { - "id": { - "type": "integer", - "description": "User Id", - "format": "int32", - "example": 123 - }, - "name": { - "type": "string", - "description": "Full Name of user", - "minLength": 1, - "example": "John Doe" - }, - "email": { - "type": "string", - "description": "Email of user", - "minLength": 1, - "example": "john@doe.com" - }, - "privacyActivated": { - "type": "boolean", - "description": "Privacy Activated", - "example": true - }, - "programmeId": { - "type": "integer", - "description": "Study Programme Id of user", - "format": "int32", - "example": 1 - }, - "level": { - "type": "integer", - "description": "User Level", - "format": "int32", - "example": 1 - }, - "requiredExp": { - "type": "integer", - "description": "User Experience Level", - "format": "int32", - "example": 12 - }, - "rankAllTime": { - "type": "integer", - "description": "User's Rank all time", - "format": "int32", - "example": 15 - }, - "rankSemester": { - "type": "integer", - "description": "User's rank current semester", - "format": "int32", - "example": 4 - }, - "rankMonth": { - "type": "integer", - "description": "User's rank current month", - "format": "int32", - "example": 5 - } - } - }, "UpdateUserDto": { "type": "object", "description": "Update User information request object. All properties are optional as the server only updates the values of the properties which are present", @@ -1023,12 +891,14 @@ "name": { "type": "string", "description": "Full Name of user", + "nullable": true, "example": "John Doe" }, "email": { "type": "string", "description": "Email of user", "format": "email", + "nullable": true, "example": "john@doe.com" }, "privacyActivated": { @@ -1047,6 +917,7 @@ "password": { "type": "string", "description": "Pin Code as first UTF8 encoded, then SHA256 hashed, and then Base64 encoded string", + "nullable": true, "example": "[no example provided]" } } @@ -1071,50 +942,6 @@ } } }, - "AppConfigDto": { - "type": "object", - "description": "App Configuration", - "example": { - "environmentType": "Production", - "merchantId": "APP1234" - }, - "additionalProperties": false, - "required": [ - "environmentType", - "merchantId" - ], - "properties": { - "environmentType": { - "description": "Environment type for indicating production or test system", - "example": "Production", - "oneOf": [ - { - "$ref": "#/components/schemas/EnvironmentType" - } - ] - }, - "merchantId": { - "type": "string", - "description": "MobilePay MerchantId", - "minLength": 1, - "example": "APP1234" - } - } - }, - "EnvironmentType": { - "type": "string", - "description": "", - "x-enumNames": [ - "Production", - "Test", - "LocalDevelopment" - ], - "enum": [ - "Production", - "Test", - "LocalDevelopment" - ] - }, "CoffeeCardDto": { "type": "object", "description": "A CoffeeCard is a union datatype of a product and unused tickets associated with the product. ", @@ -1166,47 +993,6 @@ } } }, - "LeaderboardDto": { - "type": "object", - "description": "A user on the leaderboard", - "example": { - "name": "John Doe", - "score": 25 - }, - "additionalProperties": false, - "properties": { - "name": { - "type": "string", - "description": "Account name", - "example": "John Doe" - }, - "score": { - "type": "integer", - "description": "Account score", - "format": "int32", - "example": 25 - } - } - }, - "InitiatePurchaseResponseDto": { - "type": "object", - "description": "Initiation of a new purchase response", - "example": { - "orderId": "ae76a5ba-82e8-46d8-8431-6cbb3130b94a" - }, - "additionalProperties": false, - "required": [ - "orderId" - ], - "properties": { - "orderId": { - "type": "string", - "description": "Order Id", - "minLength": 1, - "example": "ae76a5ba-82e8-46d8-8431-6cbb3130b94a" - } - } - }, "InitiatePurchaseDto": { "type": "object", "description": "Initiate a new purchase request", @@ -1511,6 +1297,46 @@ } } }, + "UsedTicketResponse": { + "type": "object", + "description": "Representing a used ticket for a product", + "example": "{\n \"id\": 122,\n \"dateCreated\": \"2022-01-09T21:03:52.2283208Z\",\n \"dateUsed\": \"2022-01-09T21:03:52.2283208Z\",\n \"productName: \"Coffee\"\n}", + "additionalProperties": false, + "required": [ + "id", + "dateCreated", + "dateUsed", + "productName" + ], + "properties": { + "id": { + "type": "integer", + "description": "Ticket Id", + "format": "int32", + "example": 122 + }, + "dateCreated": { + "type": "string", + "description": "Issuing date time for ticket in Utc format", + "format": "date-time", + "minLength": 1, + "example": "2022-01-09T21:03:52.2283208Z" + }, + "dateUsed": { + "type": "string", + "description": "Used date time for ticket in Utc format", + "format": "date-time", + "minLength": 1, + "example": "2022-01-09T21:03:52.2283208Z" + }, + "productName": { + "type": "string", + "description": "Name of product a ticket is for", + "minLength": 1, + "example": "Coffee" + } + } + }, "UseTicketDTO": { "type": "object", "description": "Use ticket request", @@ -1532,13 +1358,19 @@ } }, "securitySchemes": { - "Bearer": { + "jwt": { "type": "http", - "description": "Insert a JWT Bearer token: Bearer {token}", + "description": "JWT Bearer token", "name": "Authorization", "in": "header", "scheme": "bearer", "bearerFormat": "JWT" + }, + "apikey": { + "type": "apiKey", + "description": "Api Key used for health endpoints", + "name": "x-api-key", + "in": "header" } } } diff --git a/Shifty.GenerateApi/OpenApiSpecs/AnalogCoreV2.json b/Shifty.GenerateApi/OpenApiSpecs/AnalogCoreV2.json index d0ccc39..fddc00f 100644 --- a/Shifty.GenerateApi/OpenApiSpecs/AnalogCoreV2.json +++ b/Shifty.GenerateApi/OpenApiSpecs/AnalogCoreV2.json @@ -1,5 +1,5 @@ { - "x-generator": "NSwag v13.15.5.0 (NJsonSchema v10.6.6.0 (Newtonsoft.Json v13.0.0.0))", + "x-generator": "NSwag v13.17.0.0 (NJsonSchema v10.8.0.0 (Newtonsoft.Json v13.0.0.0))", "openapi": "3.0.0", "info": { "title": "Cafe Analog CoffeeCard API", @@ -17,7 +17,7 @@ }, "servers": [ { - "url": "https://localhost:5001" + "url": "https://core.dev.analogio.dk" } ], "paths": { @@ -71,7 +71,7 @@ "summary": "Request the deletion of the user coupled to the provided token", "operationId": "Account_Delete", "responses": { - "204": { + "202": { "description": "Successful initiation of account deletion process" }, "401": { @@ -90,7 +90,10 @@ }, "security": [ { - "Bearer": [] + "jwt": [] + }, + { + "apikey": [] } ] }, @@ -117,7 +120,10 @@ }, "security": [ { - "Bearer": [] + "jwt": [] + }, + { + "apikey": [] } ] }, @@ -157,7 +163,10 @@ }, "security": [ { - "Bearer": [] + "jwt": [] + }, + { + "apikey": [] } ] } @@ -199,6 +208,53 @@ } } }, + "/api/v2/account/resend-verification-email": { + "post": { + "tags": [ + "Account" + ], + "summary": "Resend account verification email if account is not already verified", + "operationId": "Account_ResendVerificationEmail", + "requestBody": { + "x-name": "request", + "description": "Email to be verified", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ResendAccountVerificationEmailRequest" + } + } + }, + "required": true, + "x-position": 1 + }, + "responses": { + "200": { + "description": "Email has been sent" + }, + "404": { + "description": "Email not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + } + }, + "409": { + "description": "Account already verified", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + } + } + } + } + }, "/api/v2/appconfig": { "get": { "tags": [ @@ -220,6 +276,77 @@ } } }, + "/api/v2/health/ping": { + "get": { + "tags": [ + "Health" + ], + "summary": "Ping", + "operationId": "Health_Ping", + "responses": { + "200": { + "description": "Successful request", + "content": { + "application/json": { + "schema": { + "type": "string" + } + } + } + } + }, + "security": [ + { + "jwt": [] + }, + { + "apikey": [] + } + ] + } + }, + "/api/v2/health/check": { + "get": { + "tags": [ + "Health" + ], + "summary": "Check service health", + "operationId": "Health_Healthcheck", + "responses": { + "200": { + "description": "Healthy service", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ServiceHealthResponse" + } + } + } + }, + "503": { + "description": "Unhealthy service", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ServiceHealthResponse" + } + } + } + }, + "default": { + "description": "" + } + }, + "security": [ + { + "jwt": [] + }, + { + "apikey": [] + } + ] + } + }, "/api/v2/leaderboard/top": { "get": { "tags": [ @@ -311,7 +438,10 @@ }, "security": [ { - "Bearer": [] + "jwt": [] + }, + { + "apikey": [] } ] } @@ -328,7 +458,7 @@ "name": "x-mobilepay-signature", "x-originalName": "mpSignatureHeader", "in": "header", - "description": "Webhook mpSignatureHeader", + "description": "Webhook signature", "schema": { "type": "string" }, @@ -368,6 +498,142 @@ } } }, + "/api/v2/products": { + "post": { + "tags": [ + "Products" + ], + "summary": "Adds a new product to the database.", + "operationId": "Products_AddProduct", + "requestBody": { + "x-name": "addProductRequest", + "description": "The request containing the details of the product to be added and allowed user groups.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AddProductRequest" + } + } + }, + "required": true, + "x-position": 1 + }, + "responses": { + "200": { + "description": "The request was successful, and the product was added.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ChangedProductResponse" + } + } + } + } + }, + "security": [ + { + "jwt": [] + }, + { + "apikey": [] + } + ] + }, + "put": { + "tags": [ + "Products" + ], + "summary": "Updates a product with the specified changes.", + "operationId": "Products_UpdateProduct", + "requestBody": { + "x-name": "product", + "description": "The request containing the changes to be applied to the product.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateProductRequest" + } + } + }, + "required": true, + "x-position": 1 + }, + "responses": { + "200": { + "description": "The request was successful, and the product was updated.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ChangedProductResponse" + } + } + } + } + }, + "security": [ + { + "jwt": [] + }, + { + "apikey": [] + } + ] + }, + "get": { + "tags": [ + "Products" + ], + "summary": "Returns a list of available products based on a account's user group", + "operationId": "Products_GetProducts", + "responses": { + "200": { + "description": "Successful request", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ProductResponse" + } + } + } + } + } + } + } + }, + "/api/v2/products/all": { + "get": { + "tags": [ + "Products" + ], + "summary": "Returns a list of all products", + "operationId": "Products_GetAllProducts", + "responses": { + "200": { + "description": "Successful request", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ProductResponse" + } + } + } + } + } + }, + "security": [ + { + "jwt": [] + }, + { + "apikey": [] + } + ] + } + }, "/api/v2/purchases": { "get": { "tags": [ @@ -377,7 +643,7 @@ "operationId": "Purchases_GetAllPurchases", "responses": { "200": { - "description": "All purchases", + "description": "Purchases", "content": { "application/json": { "schema": { @@ -389,9 +655,6 @@ } } }, - "204": { - "description": "No purchases" - }, "401": { "description": "Invalid credentials" }, @@ -401,7 +664,10 @@ }, "security": [ { - "Bearer": [] + "jwt": [] + }, + { + "apikey": [] } ] }, @@ -444,7 +710,10 @@ }, "security": [ { - "Bearer": [] + "jwt": [] + }, + { + "apikey": [] } ] } @@ -496,7 +765,10 @@ }, "security": [ { - "Bearer": [] + "jwt": [] + }, + { + "apikey": [] } ] } @@ -539,7 +811,10 @@ }, "security": [ { - "Bearer": [] + "jwt": [] + }, + { + "apikey": [] } ] } @@ -597,7 +872,10 @@ }, "security": [ { - "Bearer": [] + "jwt": [] + }, + { + "apikey": [] } ] } @@ -658,7 +936,10 @@ }, "security": [ { - "Bearer": [] + "jwt": [] + }, + { + "apikey": [] } ] } @@ -677,6 +958,7 @@ "message": { "type": "string", "description": "Message with API response", + "nullable": true, "example": "Successful completion" } } @@ -888,12 +1170,14 @@ "name": { "type": "string", "description": "Full Name of user", + "nullable": true, "example": "John Doe" }, "email": { "type": "string", "description": "Email of user", "format": "email", + "nullable": true, "example": "john@doe.com" }, "privacyActivated": { @@ -912,6 +1196,7 @@ "password": { "type": "string", "description": "Pin Code as first UTF8 encoded, then SHA256 hashed, and then Base64 encoded string", + "nullable": true, "example": "[no example provided]" } } @@ -953,6 +1238,26 @@ } } }, + "ResendAccountVerificationEmailRequest": { + "type": "object", + "description": "Resend Invite email request", + "example": { + "email": "john@doe.com" + }, + "additionalProperties": false, + "required": [ + "email" + ], + "properties": { + "email": { + "type": "string", + "description": "User email", + "format": "email", + "minLength": 1, + "example": "john@doe.com" + } + } + }, "AppConfig": { "type": "object", "description": "App Configuration", @@ -989,6 +1294,27 @@ "LocalDevelopment" ] }, + "ServiceHealthResponse": { + "type": "object", + "description": "Service Health", + "example": { + "mobilePay": true, + "database": true + }, + "additionalProperties": false, + "properties": { + "mobilePay": { + "type": "boolean", + "description": "MobilePay connected", + "example": true + }, + "database": { + "type": "boolean", + "description": "Database connected", + "example": true + } + } + }, "LeaderboardEntry": { "type": "object", "description": "A user on the leaderboard", @@ -1099,6 +1425,297 @@ } } }, + "ChangedProductResponse": { + "type": "object", + "description": "Represents the product response.", + "additionalProperties": false, + "required": [ + "price", + "numberOfTickets", + "name", + "description", + "visible", + "allowedUserGroups" + ], + "properties": { + "price": { + "type": "integer", + "description": "Gets or sets the price of the product.", + "format": "int32", + "maximum": 2147483647.0, + "minimum": 0.0, + "example": 150 + }, + "numberOfTickets": { + "type": "integer", + "description": "Gets or sets the number of tickets associated with the product.", + "format": "int32", + "maximum": 2147483647.0, + "minimum": 0.0, + "example": 5 + }, + "name": { + "type": "string", + "description": "Gets or sets the name of the product.", + "minLength": 1, + "example": "Espresso " + }, + "description": { + "type": "string", + "description": "Gets or sets the description of the product.", + "minLength": 1, + "example": "A homemade espresso from fresh beans " + }, + "visible": { + "type": "boolean", + "description": "Gets or sets the visibility of the product.", + "example": true + }, + "allowedUserGroups": { + "type": "array", + "description": "Gets or sets the user groups that can access the product.", + "example": "Manager, Board ", + "items": { + "$ref": "#/components/schemas/UserGroup" + } + } + } + }, + "UserGroup": { + "type": "string", + "description": "", + "x-enumNames": [ + "Customer", + "Barista", + "Manager", + "Board" + ], + "enum": [ + "Customer", + "Barista", + "Manager", + "Board" + ] + }, + "AddProductRequest": { + "type": "object", + "description": "Initiate a new product add request.", + "example": { + "Name": "Latte", + "Price": 25, + "NumberOfTickets": 10, + "Description": "xxx", + "Visible": true, + "AllowedUserGroups": [ + "Manager", + "Board" + ] + }, + "additionalProperties": false, + "required": [ + "price", + "numberOfTickets", + "name", + "description", + "allowedUserGroups" + ], + "properties": { + "price": { + "type": "integer", + "description": "Gets or sets the price of the product.", + "format": "int32", + "maximum": 2147483647.0, + "minimum": 0.0, + "example": 10 + }, + "numberOfTickets": { + "type": "integer", + "description": "Gets or sets the number of tickets associated with the product.", + "format": "int32", + "maximum": 2147483647.0, + "minimum": 0.0, + "example": 5 + }, + "name": { + "type": "string", + "description": "Gets or sets the name of the product.", + "minLength": 1, + "example": "Latte " + }, + "description": { + "type": "string", + "description": "Gets or sets the description of the product.", + "minLength": 1, + "example": "A homemade latte with soy milk " + }, + "visible": { + "type": "boolean", + "description": "Gets or sets the visibility of the product. Default is true.", + "default": true, + "example": true + }, + "allowedUserGroups": { + "type": "array", + "description": "Gets or sets the user groups that can access the product.", + "example": "Manager, Board ", + "items": { + "$ref": "#/components/schemas/UserGroup" + } + } + } + }, + "UpdateProductRequest": { + "type": "object", + "description": "Initiate an update product request.", + "example": { + "Id": 1, + "Price": 150, + "NumberOfTickets": 10, + "Name": "Espresso", + "Description": "A coffee made by forcing steam through ground coffee beans.", + "Visible": false, + "AllowedUserGroups": [ + "Manager", + "Board" + ] + }, + "additionalProperties": false, + "required": [ + "id", + "price", + "numberOfTickets", + "name", + "description", + "allowedUserGroups" + ], + "properties": { + "id": { + "type": "integer", + "description": "Gets or sets the ID of the product to update.", + "format": "int32", + "example": 1 + }, + "price": { + "type": "integer", + "description": "Gets or sets the updated price of the product.", + "format": "int32", + "maximum": 2147483647.0, + "minimum": 0.0, + "example": 10 + }, + "numberOfTickets": { + "type": "integer", + "description": "Gets or sets the updated number of tickets associated with the product.", + "format": "int32", + "maximum": 2147483647.0, + "minimum": 0.0, + "example": 5 + }, + "name": { + "type": "string", + "description": "Gets or sets the updated name of the product.", + "minLength": 1, + "example": "Espresso " + }, + "description": { + "type": "string", + "description": "Gets or sets the updated description of the product.", + "minLength": 1, + "example": "A homemade espresso from fresh beans " + }, + "visible": { + "type": "boolean", + "description": "Gets or sets the updated visibility of the product. Default is true.", + "default": true, + "example": true + }, + "allowedUserGroups": { + "type": "array", + "description": "Gets or sets the user groups that can access the product.", + "example": "Manager, Board ", + "items": { + "$ref": "#/components/schemas/UserGroup" + } + } + } + }, + "ProductResponse": { + "type": "object", + "description": "Represents a purchasable product", + "example": { + "id": 1, + "price": 300, + "numberOfTickets": 10, + "name": "Coffee clip card", + "description": "Coffee clip card of 10 clips", + "isPerk": true, + "AllowedUserGroups": [ + "Manager", + "Board" + ] + }, + "additionalProperties": false, + "required": [ + "id", + "price", + "numberOfTickets", + "name", + "description", + "isPerk", + "visible", + "allowedUserGroups" + ], + "properties": { + "id": { + "type": "integer", + "description": "Id of product", + "format": "int32", + "example": 1 + }, + "price": { + "type": "integer", + "description": "Product price", + "format": "int32", + "example": 300 + }, + "numberOfTickets": { + "type": "integer", + "description": "Number of tickets in product", + "format": "int32", + "example": 10 + }, + "name": { + "type": "string", + "description": "Name of product", + "minLength": 1, + "example": "Coffee clip card" + }, + "description": { + "type": "string", + "description": "Description of products", + "minLength": 1, + "example": "Coffee clip card of 10 clips" + }, + "isPerk": { + "type": "boolean", + "description": "Eligible due to a user perk privilege ", + "example": true + }, + "visible": { + "type": "boolean", + "description": "Visibility of products for users ", + "example": true + }, + "allowedUserGroups": { + "type": "array", + "description": "Decides the user groups that can access the product.", + "example": "Manager, Board ", + "items": { + "$ref": "#/components/schemas/UserGroup" + } + } + } + }, "SimplePurchaseResponse": { "type": "object", "description": "Represents a purchase", @@ -1622,13 +2239,19 @@ } }, "securitySchemes": { - "Bearer": { + "jwt": { "type": "http", - "description": "Insert a JWT Bearer token: Bearer {token}", + "description": "JWT Bearer token", "name": "Authorization", "in": "header", "scheme": "bearer", "bearerFormat": "JWT" + }, + "apikey": { + "type": "apiKey", + "description": "Api Key used for health endpoints", + "name": "x-api-key", + "in": "header" } } }