From 14c01c00e8fe61f25f236135065f47121523c39e Mon Sep 17 00:00:00 2001 From: Garrett DeBruin <16618938+corranrogue9@users.noreply.github.com> Date: Mon, 31 Jul 2023 07:16:01 -0700 Subject: [PATCH 1/5] Create snapshots.md --- graph/patterns/snapshots.md | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 graph/patterns/snapshots.md diff --git a/graph/patterns/snapshots.md b/graph/patterns/snapshots.md new file mode 100644 index 00000000..26336e73 --- /dev/null +++ b/graph/patterns/snapshots.md @@ -0,0 +1,30 @@ +# Pattern name + +Microsoft Graph API Design Pattern + +*Provide a short description of the pattern.* + + +## Problem + +*Describe the business context relevant for the pattern.* + +*Provide a short description of the problem.* + +## Solution + +*Describe how to implement the solution to solve the problem.* + +*Describe related patterns.* + +## When to use this pattern + +*Describe when and why the solution is applicable and when it might not be.* + +## Issues and considerations + +*Describe tradeoffs of the solution.* + +## Example + +*Provide a short example from real life.* From 90720d08e359a086bf2181f9ab0aa679b9e15573 Mon Sep 17 00:00:00 2001 From: Garrett DeBruin <16618938+corranrogue9@users.noreply.github.com> Date: Mon, 31 Jul 2023 07:40:01 -0700 Subject: [PATCH 2/5] Update snapshots.md --- graph/patterns/snapshots.md | 51 ++++++++++++++++++++++++++++++++----- 1 file changed, 44 insertions(+), 7 deletions(-) diff --git a/graph/patterns/snapshots.md b/graph/patterns/snapshots.md index 26336e73..c9acbd4a 100644 --- a/graph/patterns/snapshots.md +++ b/graph/patterns/snapshots.md @@ -1,24 +1,61 @@ -# Pattern name +# Snapshots Microsoft Graph API Design Pattern -*Provide a short description of the pattern.* - +*The snapshots pattern allows access to data for an individual resource even when that resource no longer exists, while still allowing to easily correlate references to that resource.* ## Problem -*Describe the business context relevant for the pattern.* +There are often times when data on an entity (usually a subset) needs to be exposed even after the entity has been removed or updated. +This data is representating that entity during a snapshot in time. +However, simply duplicating the data prevents correlating that snapshot data with the entity itself or with other data that are also snapshots in time. -*Provide a short description of the problem.* +An example would be a log of `user`s who have signed in. +The log could have an entry for when the `user` signed in, as well as details about the user. +But without a way to correlate this sign in data to the `user` itself, further investigations becomes difficult. ## Solution -*Describe how to implement the solution to solve the problem.* +The solution is to have a complex type which represents the resource as a snapshot in time, while also providing a navigation property to the resource itself. +The following CSDL demonstrates this with the `user` sign in example: + +```xml + + + + + + + + + + + + + + + + + + + -*Describe related patterns.* + + + + + + + +``` ## When to use this pattern +//// TODO give alternative, anti-pattern approaches *Describe when and why the solution is applicable and when it might not be.* ## Issues and considerations From 158b797146d286b9e2b257a78297ac49fb5ffe2d Mon Sep 17 00:00:00 2001 From: Garrett DeBruin <16618938+corranrogue9@users.noreply.github.com> Date: Mon, 31 Jul 2023 07:52:50 -0700 Subject: [PATCH 3/5] Update snapshots.md --- graph/patterns/snapshots.md | 72 +++++++++++++++++++++++++++++++++---- 1 file changed, 66 insertions(+), 6 deletions(-) diff --git a/graph/patterns/snapshots.md b/graph/patterns/snapshots.md index c9acbd4a..c19c56ef 100644 --- a/graph/patterns/snapshots.md +++ b/graph/patterns/snapshots.md @@ -12,12 +12,12 @@ However, simply duplicating the data prevents correlating that snapshot data wit An example would be a log of `user`s who have signed in. The log could have an entry for when the `user` signed in, as well as details about the user. -But without a way to correlate this sign in data to the `user` itself, further investigations becomes difficult. +But without a way to correlate this signin data to the `user` itself, further investigations becomes difficult. ## Solution The solution is to have a complex type which represents the resource as a snapshot in time, while also providing a navigation property to the resource itself. -The following CSDL demonstrates this with the `user` sign in example: +The following CSDL demonstrates this with the `user` signin example: ```xml @@ -47,20 +47,80 @@ The following CSDL demonstrates this with the `user` sign in example: ``` +TODO example with nested snapshots? + ## When to use this pattern -//// TODO give alternative, anti-pattern approaches -*Describe when and why the solution is applicable and when it might not be.* +This pattern should be used whenever one resource is referring to another resource, but the data available for the second resource is specific to a point in time that the first resource is referring to. +Logs, reports, and events are the most common examples of this. ## Issues and considerations -*Describe tradeoffs of the solution.* +When these snapshot situations arise, it is common to attempt putting the `user` data on the `userSignIn` directly. +This should be avoided because it gives the impression that the data belongs to the signin event. +It also can cause naming conflicts. +Using our above `user` example, let's say that the `userSignIn` wants to include the `displayName` of the `user`: + +```xml + + + + + + + + ... + + + + + + + + + + + +``` + +This CSDL ships to customers who begin using it. +They relate back to the workload that they would find it very useful to have the time the `user` was created in the signin logs so that they can do certain kinds of investigations. +Following the same pattern, we sould update the CSDL: + +```xml + + + + + + + + ... + + + + + + + + + + + + +``` + +Except now, the `createdDateTime` property *appears* to be indicating when the `userSignIn` was created. +This could have been mitigated if the original CSDL had named the property `userDisplayName`, so the new property would be `userCreatedDateTime`. +However, doing this indicates a clear structuring of the data, which is already known to be the case because the `user` entity exists in the first place. +The guidance would generally be to have a navigation property to the entity referred to in such cases, but more generally the guidance is to factor these properties into their own type. +In the snapshot case, we want to do both: we factor the properties in a "snapshot" complex type, *and* that complex type has a navigation property to the entity being referred to. ## Example From 5af045380d1575c80d54b2b93e75ed21874f9d8b Mon Sep 17 00:00:00 2001 From: Garrett DeBruin <16618938+corranrogue9@users.noreply.github.com> Date: Mon, 31 Jul 2023 07:58:33 -0700 Subject: [PATCH 4/5] Update snapshots.md --- graph/patterns/snapshots.md | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/graph/patterns/snapshots.md b/graph/patterns/snapshots.md index c19c56ef..109644a0 100644 --- a/graph/patterns/snapshots.md +++ b/graph/patterns/snapshots.md @@ -124,4 +124,26 @@ In the snapshot case, we want to do both: we factor the properties in a "snapsho ## Example -*Provide a short example from real life.* +### {1} Retrieve signin events that contain user data + +```HTTP +GET /userSignIns + +200 OK +{ + "value": [ + { + "id": "{signinid}", + "attemptDateTime": "2023-07-31 7:56:00 AM", + "requestedPermissions": [ + "User.Read" + ], + "user": { + "id": "00000000-0000-0000-0000-000000000001", + "displayName": "some display name", + "userPrincipalName": "user@domain.com" + } + } + ] +} +``` From ae90ac48f026ce78c604087bf4a8765aa3c71ac3 Mon Sep 17 00:00:00 2001 From: Garrett DeBruin <16618938+corranrogue9@users.noreply.github.com> Date: Mon, 31 Jul 2023 08:00:18 -0700 Subject: [PATCH 5/5] Update snapshots.md --- graph/patterns/snapshots.md | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/graph/patterns/snapshots.md b/graph/patterns/snapshots.md index 109644a0..f409448d 100644 --- a/graph/patterns/snapshots.md +++ b/graph/patterns/snapshots.md @@ -39,7 +39,7 @@ The following CSDL demonstrates this with the `user` signin example: - + @@ -138,12 +138,27 @@ GET /userSignIns "requestedPermissions": [ "User.Read" ], - "user": { + "userSnapshot": { "id": "00000000-0000-0000-0000-000000000001", "displayName": "some display name", "userPrincipalName": "user@domain.com" } - } + }, + ... ] } ``` + +### {2} Retrieve the user associated with a signin event + +```HTTP +GET /userSignIns/{signinid}/userSnapshot/user + +200 OK +{ + "id": "00000000-0000-0000-0000-000000000001", + "displayName": "some display name", + "userPrincipalName": "user@domain.com", + ... +} +```