Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: added id to attachments, ApiActions and GuiActions in DialogCreate #1670

Merged
merged 4 commits into from
Jan 13, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 25 additions & 5 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 Expand Up @@ -7012,4 +7032,4 @@
"url": "https://altinn-dev-api.azure-api.net/dialogporten"
}
]
}
}
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; }
Fargekritt marked this conversation as resolved.
Show resolved Hide resolved

/// <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);
}
});
}
Loading