Skip to content

Commit a79ee6b

Browse files
authored
feat(app&service): enable provider to decline subscription request (#1171)
* added /api/apps/subscription/{subscriptionId}/decline * added /api/services/subscription/{subscriptionId}/decline ------ Refs: #1140 Reviewed-by: Phil Schneider <[email protected]>
1 parent 2fafec7 commit a79ee6b

File tree

27 files changed

+11532
-4
lines changed

27 files changed

+11532
-4
lines changed

docs/api/apps-service.yaml

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1838,6 +1838,52 @@ paths:
18381838
$ref: '#/components/schemas/ErrorResponse'
18391839
'401':
18401840
description: The User is unauthorized
1841+
'/api/apps/subscription/{subscriptionId}/decline':
1842+
put:
1843+
tags:
1844+
- Apps
1845+
summary: 'Declines a pending app subscription. (Authorization required - Roles: decline_subscription)'
1846+
description: 'Example: PUT: /api/apps/subscription/{subscriptiondId}/decline'
1847+
parameters:
1848+
- name: subscriptionId
1849+
in: path
1850+
description: ID of the subscription to decline.
1851+
required: true
1852+
schema:
1853+
type: string
1854+
format: uuid
1855+
example: D3B1ECA2-6148-4008-9E6C-C1C2AEA5C645
1856+
responses:
1857+
'204':
1858+
description: App subscription was successfully declined.
1859+
'404':
1860+
description: 'If sub claim is empty/invalid or user does not exist, or any other parameters are invalid.'
1861+
content:
1862+
application/json:
1863+
schema:
1864+
$ref: '#/components/schemas/ErrorResponse'
1865+
'403':
1866+
description: Forbidden
1867+
content:
1868+
application/json:
1869+
schema:
1870+
$ref: '#/components/schemas/ErrorResponse'
1871+
'409':
1872+
description: Conflict
1873+
content:
1874+
application/json:
1875+
schema:
1876+
$ref: '#/components/schemas/ErrorResponse'
1877+
'500':
1878+
description: Internal Server Error.
1879+
content:
1880+
application/json:
1881+
schema:
1882+
$ref: '#/components/schemas/ErrorResponse'
1883+
'400':
1884+
description: 'If sub claim is empty/invalid or user does not exist, or any other parameters are invalid.'
1885+
'401':
1886+
description: The User is unauthorized
18411887
'/api/apps/{subscriptionId}/unsubscribe':
18421888
put:
18431889
tags:

docs/api/notifications-service.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -508,6 +508,8 @@ components:
508508
- CREDENTIAL_APPROVAL
509509
- CREDENTIAL_REJECTED
510510
- CREDENTIAL_EXPIRY
511+
- APP_SUBSCRIPTION_DECLINE
512+
- SERVICE_SUBSCRIPTION_DECLINE
511513
type: string
512514
SearchSemanticTypeId:
513515
enum:

docs/api/services-service.yaml

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1514,6 +1514,52 @@ paths:
15141514
$ref: '#/components/schemas/ErrorResponse'
15151515
'401':
15161516
description: The User is unauthorized
1517+
'/subscription/{subscriptionId}/decline':
1518+
put:
1519+
tags:
1520+
- Services
1521+
summary: 'Declines a pending service subscription. (Authorization required - Roles: decline_subscription)'
1522+
description: 'Example: PUT: /api/services/supscription/{subscriptiondId}/decline'
1523+
parameters:
1524+
- name: subscriptionId
1525+
in: path
1526+
description: ID of the subscription to decline.
1527+
required: true
1528+
schema:
1529+
type: string
1530+
format: uuid
1531+
example: D3B1ECA2-6148-4008-9E6C-C1C2AEA5C645
1532+
responses:
1533+
'204':
1534+
description: Service subscription was successfully declined.
1535+
'404':
1536+
description: Not Found
1537+
content:
1538+
application/json:
1539+
schema:
1540+
$ref: '#/components/schemas/ErrorResponse'
1541+
'403':
1542+
description: Forbidden
1543+
content:
1544+
application/json:
1545+
schema:
1546+
$ref: '#/components/schemas/ErrorResponse'
1547+
'409':
1548+
description: Conflict
1549+
content:
1550+
application/json:
1551+
schema:
1552+
$ref: '#/components/schemas/ErrorResponse'
1553+
'500':
1554+
description: Internal Server Error.
1555+
content:
1556+
application/json:
1557+
schema:
1558+
$ref: '#/components/schemas/ErrorResponse'
1559+
'400':
1560+
description: 'If sub claim is empty/invalid or user does not exist, or any other parameters are invalid.'
1561+
'401':
1562+
description: The User is unauthorized
15171563
components:
15181564
schemas:
15191565
AgreementConsentStatus:

src/mailing/Mailing.Template/EmailTemplates/app_subscription_decline.html

Lines changed: 473 additions & 0 deletions
Large diffs are not rendered by default.

src/mailing/Mailing.Template/EmailTemplates/service_subscription_decline.html

Lines changed: 473 additions & 0 deletions
Large diffs are not rendered by default.

src/mailing/Mailing.Template/Enums/EmailTemplateType.cs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,12 @@ public enum EmailTemplateType
8383
[Path("appprovider_subscription_request.html")]
8484
AppSubscriptionRequest,
8585

86+
/// <summary>
87+
/// Email template for notifying requester (subscriber) of subscription declination.
88+
/// </summary>
89+
[Path("app_subscription_decline.html")]
90+
AppSubscriptionDecline,
91+
8692
/// <summary>
8793
/// Email template for notifying app providers of subscription activition.
8894
/// </summary>
@@ -95,6 +101,12 @@ public enum EmailTemplateType
95101
[Path("serviceprovider_subscription_request.html")]
96102
ServiceSubscriptionRequest,
97103

104+
/// <summary>
105+
/// Email template for notifying requester (subscriber) of subscription declination.
106+
/// </summary>
107+
[Path("service_subscription_decline.html")]
108+
ServiceSubscriptionDecline,
109+
98110
/// <summary>
99111
/// Email template for notifying requester of subscription activations.
100112
/// </summary>

src/marketplace/Apps.Service/BusinessLogic/AppsBusinessLogic.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,10 @@ public async Task AddFavouriteAppForUserAsync(Guid appId)
185185
public Task<Guid> AddOwnCompanyAppSubscriptionAsync(Guid appId, IEnumerable<OfferAgreementConsentData> offerAgreementConsentData) =>
186186
_offerSubscriptionService.AddOfferSubscriptionAsync(appId, offerAgreementConsentData, OfferTypeId.APP, _settings.BasePortalAddress, _settings.SubscriptionManagerRoles, _settings.ServiceManagerRoles);
187187

188+
/// <inheritdoc/>
189+
public Task DeclineAppSubscriptionAsync(Guid subscriptionId) =>
190+
_offerSubscriptionService.RemoveOfferSubscriptionAsync(subscriptionId, OfferTypeId.APP, _settings.BasePortalAddress);
191+
188192
/// <inheritdoc/>
189193
public Task TriggerActivateOfferSubscription(Guid subscriptionId) =>
190194
_offerSetupService.TriggerActivateSubscription(subscriptionId);

src/marketplace/Apps.Service/BusinessLogic/IAppsBusinessLogic.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,12 @@ public interface IAppsBusinessLogic
9999
/// <param name="offerAgreementConsentData">The agreement consent data</param>
100100
public Task<Guid> AddOwnCompanyAppSubscriptionAsync(Guid appId, IEnumerable<OfferAgreementConsentData> offerAgreementConsentData);
101101

102+
/// <summary>
103+
/// Declines a pending app subscription of an app, provided by the current user's company.
104+
/// </summary>
105+
/// <param name="subscriptionId">ID of the pending app to be declined.</param>
106+
public Task DeclineAppSubscriptionAsync(Guid subscriptionId);
107+
102108
/// <summary>
103109
/// Activates a pending app subscription for an app provided by the current user's company.
104110
/// </summary>

src/marketplace/Apps.Service/Controllers/AppsController.cs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,31 @@ public async Task<IActionResult> ActivateOfferSubscription([FromRoute] Guid subs
248248
return NoContent();
249249
}
250250

251+
/// <summary>
252+
/// Declines a pending app subscription.
253+
/// </summary>
254+
/// <param name="subscriptionId" example="D3B1ECA2-6148-4008-9E6C-C1C2AEA5C645">ID of the subscription to decline.</param>
255+
/// <remarks>Example: PUT: /api/apps/subscription/{subscriptiondId}/decline</remarks>
256+
/// <response code="204">App subscription was successfully declined.</response>
257+
/// <response code="400">If sub claim is empty/invalid or user does not exist, or any other parameters are invalid.</response>
258+
/// <response code="404">If sub claim is empty/invalid or user does not exist, or any other parameters are invalid.</response>
259+
/// <response code="500">Internal Server Error.</response>
260+
[HttpPut]
261+
[Route("subscription/{subscriptionId}/decline")]
262+
[Authorize(Roles = "decline_subscription")]
263+
[Authorize(Policy = PolicyTypes.ValidIdentity)]
264+
[Authorize(Policy = PolicyTypes.ValidCompany)]
265+
[ProducesResponseType(StatusCodes.Status204NoContent)]
266+
[ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status404NotFound)]
267+
[ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status403Forbidden)]
268+
[ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status409Conflict)]
269+
[ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status500InternalServerError)]
270+
public async Task<IActionResult> DeclineAppSubscriptionAsync([FromRoute] Guid subscriptionId)
271+
{
272+
await _appsBusinessLogic.DeclineAppSubscriptionAsync(subscriptionId).ConfigureAwait(ConfigureAwaitOptions.None);
273+
return NoContent();
274+
}
275+
251276
/// <summary>
252277
/// Unsubscribes an app from the current user's company's subscriptions.
253278
/// </summary>
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/********************************************************************************
2+
* Copyright (c) 2024 Contributors to the Eclipse Foundation
3+
*
4+
* See the NOTICE file(s) distributed with this work for additional
5+
* information regarding copyright ownership.
6+
*
7+
* This program and the accompanying materials are made available under the
8+
* terms of the Apache License, Version 2.0 which is available at
9+
* https://www.apache.org/licenses/LICENSE-2.0.
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14+
* License for the specific language governing permissions and limitations
15+
* under the License.
16+
*
17+
* SPDX-License-Identifier: Apache-2.0
18+
********************************************************************************/
19+
20+
using Org.Eclipse.TractusX.Portal.Backend.Framework.ErrorHandling.Service;
21+
using System.Collections.Immutable;
22+
23+
namespace Org.Eclipse.TractusX.Portal.Backend.Offers.Library.ErrorHandling;
24+
25+
public class OfferSubscriptionServiceErrorMessageContainer : IErrorMessageContainer
26+
{
27+
private static readonly IReadOnlyDictionary<int, string> _messageContainer = new Dictionary<OfferSubscriptionServiceErrors, string> {
28+
{ OfferSubscriptionServiceErrors.OFFER_NOTFOUND, "Offer {offerId} does not exist." },
29+
{ OfferSubscriptionServiceErrors.SUBSCRIPTION_NOTFOUND, "Subscription {subscriptionId} does not exist." },
30+
{ OfferSubscriptionServiceErrors.NON_PROVIDER_IS_FORBIDDEN, "Only the providing company can decline the subscription request." },
31+
{ OfferSubscriptionServiceErrors.OFFER_STATUS_CONFLICT_INCORR_OFFER_STATUS, "Subscription of offer {offerName} should be in {offerStatus} state." },
32+
}.ToImmutableDictionary(x => (int)x.Key, x => x.Value);
33+
34+
public Type Type { get => typeof(OfferSubscriptionServiceErrors); }
35+
public IReadOnlyDictionary<int, string> MessageContainer { get => _messageContainer; }
36+
}
37+
38+
public enum OfferSubscriptionServiceErrors
39+
{
40+
OFFER_NOTFOUND,
41+
SUBSCRIPTION_NOTFOUND,
42+
NON_PROVIDER_IS_FORBIDDEN,
43+
OFFER_STATUS_CONFLICT_INCORR_OFFER_STATUS
44+
}

0 commit comments

Comments
 (0)