Skip to content

Commit

Permalink
feat: added id to attachments, ApiActions and GuiActions in DialogCre…
Browse files Browse the repository at this point in the history
…ate (#1670)

## Description

Added Id to Attachment, ApiActions and GuiActions in DialogCreate

## Related Issue(s)

*  #1623

## Verification

- [x] **Your** code builds clean without any errors or warnings
- [x] Manual testing done (required)
- [x] Relevant automated test added (if you find this hard, leave it and
we'll help out)

## Documentation

- [ ] Documentation is updated (either in `docs`-directory, Altinnpedia
or a separate linked PR in
[altinn-studio-docs.](https://github.com/Altinn/altinn-studio-docs), if
applicable)
  • Loading branch information
Fargekritt authored Jan 13, 2025
1 parent 1a71763 commit 470e5a9
Show file tree
Hide file tree
Showing 9 changed files with 112 additions and 9 deletions.
28 changes: 24 additions & 4 deletions docs/schema/V1/swagger.verified.json
Original file line number Diff line number Diff line change
Expand Up @@ -2094,6 +2094,13 @@
},
"nullable": true,
"type": "array"
},
"id": {
"description": "A self-defined UUIDv7 may be provided to support idempotent creation of Api Actions. If not provided, a new UUIDv7 will be generated.",
"example": "01913cd5-784f-7d3b-abef-4c77b1f0972d",
"format": "guid",
"nullable": true,
"type": "string"
}
},
"type": "object"
Expand Down Expand Up @@ -2161,6 +2168,12 @@
"nullable": true,
"type": "array"
},
"id": {
"description": "A self-defined UUIDv7 may be provided to support idempotent creation of attachments. If not provided, a new UUIDv7 will be generated.",
"format": "guid",
"nullable": true,
"type": "string"
},
"urls": {
"description": "The URLs associated with the attachment, each referring to a different representation of the attachment.",
"items": {
Expand Down Expand Up @@ -2432,6 +2445,13 @@
}
]
},
"id": {
"description": "A self-defined UUIDv7 may be provided to support idempotent creation of Gui Actions. If not provided, a new UUIDv7 will be generated.",
"example": "01913cd5-784f-7d3b-abef-4c77b1f0972d",
"format": "guid",
"nullable": true,
"type": "string"
},
"isDeleteDialogAction": {
"description": "Indicates whether the action results in the dialog being deleted. Used by frontends to implement custom UX\nfor delete actions.",
"type": "boolean"
Expand Down Expand Up @@ -2710,7 +2730,7 @@
"type": "array"
},
"id": {
"description": "A UUIDv7 used for merging existing data, unknown IDs will be ignored as this entity does not support user-defined IDs.",
"description": "A self-defined UUIDv7 may be provided to support idempotent additions of Api Actions. If not provided, a new UUIDv7 will be generated.",
"example": "01913cd5-784f-7d3b-abef-4c77b1f0972d",
"format": "guid",
"nullable": true,
Expand Down Expand Up @@ -2790,7 +2810,7 @@
"type": "array"
},
"id": {
"description": "A UUIDv7 used for merging existing data, unknown IDs will be ignored as this entity does not support user-defined IDs.",
"description": "A self-defined UUIDv7 may be provided to support idempotent additions of attachments. If not provided, a new UUIDv7 will be generated.",
"example": "01913cd5-784f-7d3b-abef-4c77b1f0972d",
"format": "guid",
"nullable": true,
Expand Down Expand Up @@ -3027,7 +3047,7 @@
]
},
"id": {
"description": "A UUIDv7 used for merging existing data, unknown IDs will be ignored as this entity does not support user-defined IDs.",
"description": "A self-defined UUIDv7 may be provided to support idempotent additions of Gui Actions. If not provided, a new UUIDv7 will be generated.",
"example": "01913cd5-784f-7d3b-abef-4c77b1f0972d",
"format": "guid",
"nullable": true,
Expand Down Expand Up @@ -3160,7 +3180,7 @@
"type": "array"
},
"id": {
"description": "A self-defined UUIDv7 may be provided to support idempotent creation of transmission attachments. If not provided, a new UUIDv7 will be generated.",
"description": "A self-defined UUIDv7 may be provided to support idempotent additions of transmission attachments. If not provided, a new UUIDv7 will be generated.",
"example": "01913cd5-784f-7d3b-abef-4c77b1f0972d",
"format": "guid",
"nullable": true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
using Digdir.Domain.Dialogporten.Domain.Actors;
using Digdir.Domain.Dialogporten.Domain.Common;
using Digdir.Domain.Dialogporten.Domain.Dialogs.Entities;
using Digdir.Domain.Dialogporten.Domain.Dialogs.Entities.Actions;
using Digdir.Domain.Dialogporten.Domain.Dialogs.Entities.Activities;
using Digdir.Domain.Dialogporten.Domain.Dialogs.Entities.Transmissions;
using Digdir.Domain.Dialogporten.Domain.Parties;
Expand All @@ -20,7 +21,6 @@
namespace Digdir.Domain.Dialogporten.Application.Features.V1.ServiceOwner.Dialogs.Commands.Create;

public sealed class CreateDialogCommand : CreateDialogDto, IRequest<CreateDialogResult>;

public sealed record CreateDialogSuccess(Guid DialogId, Guid Revision);

[GenerateOneOf]
Expand Down Expand Up @@ -145,5 +145,23 @@ private async Task EnsureNoExistingUserDefinedIds(DialogEntity dialog, Cancellat
{
_domainContext.AddError(DomainFailure.EntityExists<DialogTransmissionAttachment>(existingTransmissionAttachmentIds));
}

var existingAttachmentIds = await _db.GetExistingIds(dialog.Attachments, cancellationToken);
if (existingAttachmentIds.Count != 0)
{
_domainContext.AddError(DomainFailure.EntityExists<DialogAttachment>(existingAttachmentIds));
}

var existingGuiActionIds = await _db.GetExistingIds(dialog.GuiActions, cancellationToken);
if (existingGuiActionIds.Count != 0)
{
_domainContext.AddError(DomainFailure.EntityExists<DialogGuiAction>(existingGuiActionIds));
}

var existingApiActionIds = await _db.GetExistingIds(dialog.ApiActions, cancellationToken);
if (existingApiActionIds.Count != 0)
{
_domainContext.AddError(DomainFailure.EntityExists<DialogApiAction>(existingApiActionIds));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,9 @@ public CreateDialogDialogAttachmentDtoValidator(
IValidator<IEnumerable<LocalizationDto>> localizationsValidator,
IValidator<AttachmentUrlDto> urlValidator)
{
RuleFor(x => x.Id)
.IsValidUuidV7()
.UuidV7TimestampIsInPast();
RuleFor(x => x.DisplayName)
.SetValidator(localizationsValidator);
RuleFor(x => x.Urls)
Expand Down Expand Up @@ -336,6 +339,9 @@ internal sealed class CreateDialogDialogGuiActionDtoValidator : AbstractValidato
public CreateDialogDialogGuiActionDtoValidator(
IValidator<IEnumerable<LocalizationDto>> localizationsValidator)
{
RuleFor(x => x.Id)
.IsValidUuidV7()
.UuidV7TimestampIsInPast();
RuleFor(x => x.Action)
.NotEmpty()
.MaximumLength(Constants.DefaultMaxStringLength);
Expand Down Expand Up @@ -365,6 +371,9 @@ internal sealed class CreateDialogDialogApiActionDtoValidator : AbstractValidato
public CreateDialogDialogApiActionDtoValidator(
IValidator<ApiActionEndpointDto> apiActionEndpointValidator)
{
RuleFor(x => x.Id)
.IsValidUuidV7()
.UuidV7TimestampIsInPast();
RuleFor(x => x.Action)
.NotEmpty()
.MaximumLength(Constants.DefaultMaxStringLength);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,12 @@ public sealed class ActivityDto

public sealed class ApiActionDto
{
/// <summary>
/// A self-defined UUIDv7 may be provided to support idempotent creation of Api Actions. If not provided, a new UUIDv7 will be generated.
/// </summary>
/// <example>01913cd5-784f-7d3b-abef-4c77b1f0972d</example>
public Guid? Id { get; set; }

/// <summary>
/// String identifier for the action, corresponding to the "action" attributeId used in the XACML service policy,
/// which by default is the policy belonging to the service referred to by "serviceResource" in the dialog.
Expand Down Expand Up @@ -393,6 +399,12 @@ public sealed class ApiActionEndpointDto

public sealed class GuiActionDto
{
/// <summary>
/// A self-defined UUIDv7 may be provided to support idempotent creation of Gui Actions. If not provided, a new UUIDv7 will be generated.
/// </summary>
/// <example>01913cd5-784f-7d3b-abef-4c77b1f0972d</example>
public Guid? Id { get; set; }

/// <summary>
/// The action identifier for the action, corresponding to the "action" attributeId used in the XACML service policy.
/// </summary>
Expand Down Expand Up @@ -455,6 +467,11 @@ public sealed class GuiActionDto

public sealed class AttachmentDto
{
/// <summary>
/// A self-defined UUIDv7 may be provided to support idempotent creation of attachments. If not provided, a new UUIDv7 will be generated.
/// </summary>
public Guid? Id { get; set; }

/// <summary>
/// The display name of the attachment that should be used in GUIs.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,7 @@ public class ActivityDto
public sealed class ApiActionDto
{
/// <summary>
/// A UUIDv7 used for merging existing data, unknown IDs will be ignored as this entity does not support user-defined IDs.
/// A self-defined UUIDv7 may be provided to support idempotent additions of Api Actions. If not provided, a new UUIDv7 will be generated.
/// </summary>
/// <example>01913cd5-784f-7d3b-abef-4c77b1f0972d</example>
public Guid? Id { get; set; }
Expand Down Expand Up @@ -353,7 +353,7 @@ public sealed class ApiActionEndpointDto
public sealed class GuiActionDto
{
/// <summary>
/// A UUIDv7 used for merging existing data, unknown IDs will be ignored as this entity does not support user-defined IDs.
/// A self-defined UUIDv7 may be provided to support idempotent additions of Gui Actions. If not provided, a new UUIDv7 will be generated.
/// </summary>
/// <example>01913cd5-784f-7d3b-abef-4c77b1f0972d</example>
public Guid? Id { get; set; }
Expand Down Expand Up @@ -421,7 +421,7 @@ public sealed class GuiActionDto
public sealed class AttachmentDto
{
/// <summary>
/// A UUIDv7 used for merging existing data, unknown IDs will be ignored as this entity does not support user-defined IDs.
/// A self-defined UUIDv7 may be provided to support idempotent additions of attachments. If not provided, a new UUIDv7 will be generated.
/// </summary>
/// <example>01913cd5-784f-7d3b-abef-4c77b1f0972d</example>
public Guid? Id { get; set; }
Expand Down Expand Up @@ -468,7 +468,7 @@ public sealed class AttachmentUrlDto
public sealed class TransmissionAttachmentDto
{
/// <summary>
/// A self-defined UUIDv7 may be provided to support idempotent creation of transmission attachments. If not provided, a new UUIDv7 will be generated.
/// A self-defined UUIDv7 may be provided to support idempotent additions of transmission attachments. If not provided, a new UUIDv7 will be generated.
/// </summary>
/// <example>01913cd5-784f-7d3b-abef-4c77b1f0972d</example>
public Guid? Id { get; set; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,7 @@ public static List<ActivityDto> GenerateFakeDialogActivities(int? count = null,
public static List<ApiActionDto> GenerateFakeDialogApiActions()
{
return new Faker<ApiActionDto>()
.RuleFor(o => o.Id, () => IdentifiableExtensions.CreateVersion7())
.RuleFor(o => o.Action, f => f.Random.AlphaNumeric(8))
.RuleFor(o => o.Endpoints, _ => GenerateFakeDialogApiActionEndpoints())
.Generate(new Randomizer().Number(1, 4));
Expand All @@ -299,6 +300,7 @@ public static List<GuiActionDto> GenerateFakeDialogGuiActions()
var hasPrimary = false;
var hasSecondary = false;
return new Faker<GuiActionDto>()
.RuleFor(o => o.Id, () => IdentifiableExtensions.CreateVersion7())
.RuleFor(o => o.Action, f => f.Random.AlphaNumeric(8))
.RuleFor(o => o.Priority, _ =>
{
Expand Down Expand Up @@ -327,6 +329,7 @@ public static AttachmentDto GenerateFakeDialogAttachment()
public static List<AttachmentDto> GenerateFakeDialogAttachments(int? count = null)
{
return new Faker<AttachmentDto>()
.RuleFor(o => o.Id, _ => IdentifiableExtensions.CreateVersion7())
.RuleFor(o => o.DisplayName, f => GenerateFakeLocalizations(f.Random.Number(2, 5)))
.RuleFor(o => o.Urls, _ => GenerateFakeDialogAttachmentUrls())
.Generate(count ?? new Randomizer().Number(1, 6));
Expand Down
2 changes: 2 additions & 0 deletions tests/k6/tests/enduser/all-tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@
import { default as dialogDetails } from './dialogDetails.js';
import { default as dialogSearch } from './dialogSearch.js';
import { default as dialogSystemLabelLog } from './dialogSystemLabelLog.js';
import { default as enduserSearchWithThresholds } from './enduserSearchWithThresholds.js';
import { default as parties } from './parties.js';

export default function() {
dialogDetails();
dialogSearch();
dialogSystemLabelLog();
enduserSearchWithThresholds();
parties();
}
4 changes: 4 additions & 0 deletions tests/k6/tests/serviceowner/all-tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import { default as authentication } from './authentication.js';
import { default as authorization } from './authorization.js';
import { default as concurrency } from './concurrency.js';
import { default as createDialogWithThresholds } from './createDialogWithThresholds.js';
import { default as dialogCreateActivity } from './dialogCreateActivity.js';
import { default as dialogCreateExternalResource } from './dialogCreateExternalResource.js';
import { default as dialogCreateInvalidActionCount } from './dialogCreateInvalidActionCount.js';
Expand All @@ -11,11 +12,13 @@ import { default as dialogCreateUpdatePatchDeleteCorrespondenceResource } from '
import { default as dialogDetails } from './dialogDetails.js';
import { default as dialogSearch } from './dialogSearch.js';
import { default as dialogUpdateActivity } from './dialogUpdateActivity.js';
import { default as serviceOwnerSearchWithThresholds } from './serviceOwnerSearchWithThresholds.js';

export default function() {
authentication();
authorization();
concurrency();
createDialogWithThresholds();
dialogCreateActivity();
dialogCreateExternalResource();
dialogCreateInvalidActionCount();
Expand All @@ -25,4 +28,5 @@ export default function() {
dialogDetails();
dialogSearch();
dialogUpdateActivity();
serviceOwnerSearchWithThresholds();
}
30 changes: 30 additions & 0 deletions tests/k6/tests/serviceowner/dialogCreatePatchDelete.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ import {default as dialogToInsert} from './testdata/01-create-dialog.js';

export default function () {

let dialogIds = [];
let dialogId = null;
let attachmentId = null;
let eTag = null;
let newApiActionEndpointUrl = null;

Expand All @@ -28,6 +30,28 @@ export default function () {
dialogId = r.json();
});


describe('Perform dialog create with specifed attachmentId', () => {
let dialog = dialogToInsert();
attachmentId = uuidv7();
dialog.transmissions[0].attachments[0].id = attachmentId;
let r = postSO('dialogs', dialog);
expectStatusFor(r).to.equal(201);
expect(r, 'response').to.have.validJsonBody();
expect(r.json(), 'response json').to.match(/^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/)

dialogIds.push(r.json());
});

describe('Perform dialog create with taken specifed attachmentId', () => {
let dialog = dialogToInsert();
dialog.transmissions[0].attachments[0].id = attachmentId;
let r = postSO('dialogs', dialog);
expectStatusFor(r).to.equal(422);
expect(r, 'response').to.have.validJsonBody();
expect(r.json(), 'response json').to.have.property('errors');

});
describe('Perform dialog get', () => {
let r = getSO('dialogs/' + dialogId);
expectStatusFor(r).to.equal(200);
Expand Down Expand Up @@ -190,4 +214,10 @@ export default function () {
expect(r.json(), 'response json').to.have.property('errors');
});

describe('Clean up', () => {
for (let i = 0; i < dialogIds.length; i++) {
let r = purgeSO('dialogs/' + dialogIds[i]);
expectStatusFor(r).to.equal(204);
}
});
}

0 comments on commit 470e5a9

Please sign in to comment.