Skip to content

Commit 15316d1

Browse files
Ticket #334 : Publish integration event RepresentationReferenceAttributeUpdatedEvent when the reference attribute is updated
1 parent c516b5b commit 15316d1

6 files changed

Lines changed: 53 additions & 4 deletions

File tree

src/Scim/SimpleIdServer.Scim.Startup/Consumers/IntegrationEventConsumer.cs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ namespace SimpleIdServer.Scim.Startup.Consumers
99
{
1010
public class IntegrationEventConsumer : IConsumer<RepresentationAddedEvent>,
1111
IConsumer<RepresentationRemovedEvent>,
12-
IConsumer<RepresentationUpdatedEvent>
12+
IConsumer<RepresentationUpdatedEvent>,
13+
IConsumer<RepresentationReferenceAttributeUpdatedEvent>
1314
{
1415
private readonly ILogger<IntegrationEventConsumer> _logger;
1516

@@ -35,5 +36,11 @@ public Task Consume(ConsumeContext<RepresentationUpdatedEvent> context)
3536
_logger.LogInformation($"Event received : Representation '{context.Message.ResourceType}' has been updated");
3637
return Task.CompletedTask;
3738
}
39+
40+
public Task Consume(ConsumeContext<RepresentationReferenceAttributeUpdatedEvent> context)
41+
{
42+
_logger.LogInformation($"Event received : Representation '{context.Message.ResourceType}' has been updated");
43+
return Task.CompletedTask;
44+
}
3845
}
3946
}

src/Scim/SimpleIdServer.Scim.Startup/Startup.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,15 @@ public void ConfigureServices(IServiceCollection services)
148148
.AddSchemas(schemas)
149149
.AddAttributeMapping(new List<SCIMAttributeMapping>
150150
{
151+
new SCIMAttributeMapping
152+
{
153+
Id = Guid.NewGuid().ToString(),
154+
SourceAttributeId = groupSchema.Attributes.First(a => a.Name == "members").Id,
155+
SourceResourceType = StandardSchemas.GroupSchema.ResourceType,
156+
SourceAttributeSelector = "members",
157+
TargetResourceType = StandardSchemas.UserSchema.ResourceType,
158+
TargetAttributeId = userSchema.Attributes.First(a => a.Name == "groups").Id
159+
},
151160
new SCIMAttributeMapping
152161
{
153162
Id = Guid.NewGuid().ToString(),

src/Scim/SimpleIdServer.Scim/Commands/Handlers/BaseCommandHandler.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ protected async Task Notify(RepresentationSyncResult result)
1919
{
2020
foreach(var removeAttr in result.RemoveAttrEvts) await _busControl.Publish(removeAttr);
2121
foreach(var addAttr in result.AddAttrEvts) await _busControl.Publish(addAttr);
22+
foreach (var updateAttr in result.UpdateAttrEvts) await _busControl.Publish(updateAttr);
2223
}
2324
}
2425
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// Copyright (c) SimpleIdServer. All rights reserved.
2+
// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information.
3+
using Newtonsoft.Json.Linq;
4+
5+
namespace SimpleIdServer.Scim.ExternalEvents
6+
{
7+
public class RepresentationReferenceAttributeUpdatedEvent : BaseReferenceAttributeEvent
8+
{
9+
public RepresentationReferenceAttributeUpdatedEvent()
10+
{
11+
}
12+
13+
public RepresentationReferenceAttributeUpdatedEvent(string id, int version, string resourceType, string representationAggregateId, string schemaAttributeId, string attributeFullPath, JObject representation) : base(id, version, resourceType, representationAggregateId, schemaAttributeId, attributeFullPath, representation)
14+
{
15+
}
16+
}
17+
}

src/Scim/SimpleIdServer.Scim/Helpers/RepresentationReferenceSync.cs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
// Copyright (c) SimpleIdServer. All rights reserved.
22
// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information.
3+
using Microsoft.CodeAnalysis;
34
using SimpleIdServer.Scim.Domains;
45
using SimpleIdServer.Scim.DTOs;
56
using SimpleIdServer.Scim.Exceptions;
@@ -10,6 +11,7 @@
1011
using System.Diagnostics;
1112
using System.Linq;
1213
using System.Threading.Tasks;
14+
using static MassTransit.ValidationResultExtensions;
1315

1416
namespace SimpleIdServer.Scim.Helpers
1517
{
@@ -96,7 +98,7 @@ public async Task<RepresentationSyncResult> Sync(string resourceType, SCIMRepre
9698
if (duplicateIds.Any()) throw new SCIMUniquenessAttributeException(string.Format(Global.DuplicateReference, string.Join(",", duplicateIds.Select(_ => _.Key).Distinct())));
9799
await RemoveReferenceAttributes(result, idsToBeRemoved, attributeMapping, newSourceScimRepresentation, location);
98100
await AddReferenceAttributes(result, newIds, attributeMapping, newSourceScimRepresentation, location, targetSchemas.First(s => s.ResourceType == attributeMapping.TargetResourceType));
99-
await UpdateReferenceAttributes(existingIds, attributeMapping, newSourceScimRepresentation, patchOperations, targetSchemas.First(s => s.ResourceType == attributeMapping.TargetResourceType));
101+
await UpdateReferenceAttributes(result, existingIds, attributeMapping, newSourceScimRepresentation, patchOperations, targetSchemas.First(s => s.ResourceType == attributeMapping.TargetResourceType), location: location);
100102
}
101103

102104
return result;
@@ -141,19 +143,21 @@ protected virtual async Task AddReferenceAttributes(RepresentationSyncResult res
141143
var sourceSchema = sourceScimRepresentation.Schemas.First(s => s.ResourceType == attributeMapping.SourceResourceType && s.GetAttributeById(attributeMapping.SourceAttributeId) != null);
142144
UpdateScimRepresentation(targetRepresentation, sourceScimRepresentation, attributeMapping.TargetAttributeId, attributeMapping.SourceResourceType, targetSchema, out isAttrUpdated);
143145
UpdateScimRepresentation(sourceScimRepresentation, targetRepresentation, attributeMapping.SourceAttributeId, attributeMapping.TargetResourceType, sourceSchema, out bool b);
144-
if (!isAttrUpdated && !string.IsNullOrWhiteSpace(attributeMapping.TargetAttributeId)) result.AddReferenceAttr(targetRepresentation, attributeMapping.TargetAttributeId, targetSchema.GetAttributeById(attributeMapping.TargetAttributeId).FullPath, sourceScimRepresentation.Id, location);
146+
if (!string.IsNullOrWhiteSpace(attributeMapping.TargetAttributeId) && !isAttrUpdated)
147+
result.AddReferenceAttr(targetRepresentation, attributeMapping.TargetAttributeId, targetSchema.GetAttributeById(attributeMapping.TargetAttributeId).FullPath, sourceScimRepresentation.Id, location);
145148
result.AddRepresentation(targetRepresentation);
146149
}
147150
}
148151
}
149152

150-
protected virtual async Task UpdateReferenceAttributes(IEnumerable<string> ids, SCIMAttributeMapping attributeMapping, SCIMRepresentation sourceScimRepresentation, ICollection<SCIMPatchResult> patchOperations, SCIMSchema targetSchema)
153+
protected virtual async Task UpdateReferenceAttributes(RepresentationSyncResult result, IEnumerable<string> ids, SCIMAttributeMapping attributeMapping, SCIMRepresentation sourceScimRepresentation, ICollection<SCIMPatchResult> patchOperations, SCIMSchema targetSchema, string location)
151154
{
152155
if (!patchOperations.Any(p => IsDisplayName(p.Attr.FullPath))) return;
153156
var targetRepresentations = await _scimRepresentationCommandRepository.FindSCIMRepresentationByIds(ids, attributeMapping.TargetResourceType);
154157
foreach (var targetRepresentation in targetRepresentations)
155158
{
156159
UpdateScimRepresentation(targetRepresentation, sourceScimRepresentation, attributeMapping.TargetAttributeId, attributeMapping.SourceResourceType, targetSchema, out bool isAttrUpdated);
160+
result.UpdateReferenceAttr(targetRepresentation, attributeMapping.TargetAttributeId, targetSchema.GetAttributeById(attributeMapping.TargetAttributeId).FullPath, sourceScimRepresentation.Id, location);
157161
targetRepresentation.SetUpdated(DateTime.UtcNow);
158162
}
159163
}

src/Scim/SimpleIdServer.Scim/Helpers/RepresentationSyncResult.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,14 @@ public RepresentationSyncResult(IResourceTypeResolver resourceTypeResolver)
1818
Representations = new List<SCIMRepresentation>();
1919
RemoveAttrEvts = new List<RepresentationReferenceAttributeRemovedEvent>();
2020
AddAttrEvts = new List<RepresentationReferenceAttributeAddedEvent>();
21+
UpdateAttrEvts = new List<RepresentationReferenceAttributeUpdatedEvent>();
2122
_resourceTypeResolver = resourceTypeResolver;
2223
}
2324

2425
public ICollection<SCIMRepresentation> Representations { get; set; }
2526
public ICollection<RepresentationReferenceAttributeRemovedEvent> RemoveAttrEvts { get; set; }
2627
public ICollection<RepresentationReferenceAttributeAddedEvent> AddAttrEvts { get; set; }
28+
public ICollection<RepresentationReferenceAttributeUpdatedEvent> UpdateAttrEvts { get; set; }
2729

2830
public void AddRepresentation(SCIMRepresentation representation)
2931
{
@@ -48,6 +50,15 @@ public void RemoveReferenceAttr(SCIMRepresentation representation, string schema
4850
ProcessReferenceAttr(RemoveAttrEvts, representation, schemaAttributeId, newEvt, value);
4951
}
5052

53+
public void UpdateReferenceAttr(SCIMRepresentation representation, string schemaAttributeId, string fullPath, string value, string location)
54+
{
55+
location = $"{location}/{_resourceTypeResolver.ResolveByResourceType(representation.ResourceType).ControllerName}/{representation.Id}";
56+
var obj = representation.Duplicate().ToResponse(location, false, addEmptyArray: true);
57+
var newEvt = new RepresentationReferenceAttributeUpdatedEvent(Guid.NewGuid().ToString(), representation.Version, representation.ResourceType, representation.Id, schemaAttributeId, fullPath, obj);
58+
newEvt.Values.Add(value);
59+
ProcessReferenceAttr(UpdateAttrEvts, representation, schemaAttributeId, newEvt, value);
60+
}
61+
5162
private void ProcessReferenceAttr<T>(ICollection<T> evts, SCIMRepresentation representation, string schemaAttributeId, T newEvt, string value) where T : BaseReferenceAttributeEvent
5263
{
5364
var evt = evts.FirstOrDefault(e => e.RepresentationAggregateId == representation.Id && e.SchemaAttributeId == schemaAttributeId);

0 commit comments

Comments
 (0)