Skip to content

Commit

Permalink
Device deactivation (#4963)
Browse files Browse the repository at this point in the history
* Device deactivation

* Check active status in service

* Format and work around potential deadlocks
  • Loading branch information
withinfocus authored Oct 31, 2024
1 parent 751fd33 commit a04df4b
Show file tree
Hide file tree
Showing 19 changed files with 8,801 additions and 36 deletions.
6 changes: 3 additions & 3 deletions src/Api/Controllers/DevicesController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -196,16 +196,16 @@ public async Task PutClearToken(string identifier)
}

[HttpDelete("{id}")]
[HttpPost("{id}/delete")]
public async Task Delete(string id)
[HttpPost("{id}/deactivate")]
public async Task Deactivate(string id)
{
var device = await _deviceRepository.GetByIdAsync(new Guid(id), _userService.GetProperUserId(User).Value);
if (device == null)
{
throw new NotFoundException();
}

await _deviceService.DeleteAsync(device);
await _deviceService.DeactivateAsync(device);
}

[AllowAnonymous]
Expand Down
4 changes: 4 additions & 0 deletions src/Core/Entities/Device.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ public class Device : ITableObject<Guid>
/// </summary>
public string? EncryptedPrivateKey { get; set; }

/// <summary>
/// Whether the device is active for the user.
/// </summary>
public bool Active { get; set; } = true;

public void SetNewId()
{
Expand Down
2 changes: 1 addition & 1 deletion src/Core/Services/IDeviceService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ public interface IDeviceService
{
Task SaveAsync(Device device);
Task ClearTokenAsync(Device device);
Task DeleteAsync(Device device);
Task DeactivateAsync(Device device);
Task UpdateDevicesTrustAsync(string currentDeviceIdentifier,
Guid currentUserId,
DeviceKeysUpdateRequestModel currentDeviceUpdate,
Expand Down
13 changes: 11 additions & 2 deletions src/Core/Services/Implementations/DeviceService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,18 @@ public async Task ClearTokenAsync(Device device)
await _pushRegistrationService.DeleteRegistrationAsync(device.Id.ToString());
}

public async Task DeleteAsync(Device device)
public async Task DeactivateAsync(Device device)
{
await _deviceRepository.DeleteAsync(device);
// already deactivated
if (!device.Active)
{
return;
}

device.Active = false;
device.RevisionDate = DateTime.UtcNow;
await _deviceRepository.UpsertAsync(device);

await _pushRegistrationService.DeleteRegistrationAsync(device.Id.ToString());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ public void Configure(EntityTypeBuilder<Device> builder)
.HasIndex(d => d.Identifier)
.IsClustered(false);

builder.Property(c => c.Active)
.ValueGeneratedNever()
.HasDefaultValue(true);

builder.ToTable(nameof(Device));
}
}
9 changes: 6 additions & 3 deletions src/Sql/dbo/Stored Procedures/Device_Create.sql
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
@RevisionDate DATETIME2(7),
@EncryptedUserKey VARCHAR(MAX) = NULL,
@EncryptedPublicKey VARCHAR(MAX) = NULL,
@EncryptedPrivateKey VARCHAR(MAX) = NULL
@EncryptedPrivateKey VARCHAR(MAX) = NULL,
@Active BIT = 1
AS
BEGIN
SET NOCOUNT ON
Expand All @@ -26,7 +27,8 @@ BEGIN
[RevisionDate],
[EncryptedUserKey],
[EncryptedPublicKey],
[EncryptedPrivateKey]
[EncryptedPrivateKey],
[Active]
)
VALUES
(
Expand All @@ -40,6 +42,7 @@ BEGIN
@RevisionDate,
@EncryptedUserKey,
@EncryptedPublicKey,
@EncryptedPrivateKey
@EncryptedPrivateKey,
@Active
)
END
12 changes: 0 additions & 12 deletions src/Sql/dbo/Stored Procedures/Device_DeleteById.sql

This file was deleted.

6 changes: 4 additions & 2 deletions src/Sql/dbo/Stored Procedures/Device_Update.sql
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
@RevisionDate DATETIME2(7),
@EncryptedUserKey VARCHAR(MAX) = NULL,
@EncryptedPublicKey VARCHAR(MAX) = NULL,
@EncryptedPrivateKey VARCHAR(MAX) = NULL
@EncryptedPrivateKey VARCHAR(MAX) = NULL,
@Active BIT = 1
AS
BEGIN
SET NOCOUNT ON
Expand All @@ -26,7 +27,8 @@ BEGIN
[RevisionDate] = @RevisionDate,
[EncryptedUserKey] = @EncryptedUserKey,
[EncryptedPublicKey] = @EncryptedPublicKey,
[EncryptedPrivateKey] = @EncryptedPrivateKey
[EncryptedPrivateKey] = @EncryptedPrivateKey,
[Active] = @Active
WHERE
[Id] = @Id
END
25 changes: 12 additions & 13 deletions src/Sql/dbo/Tables/Device.sql
Original file line number Diff line number Diff line change
@@ -1,25 +1,24 @@
CREATE TABLE [dbo].[Device] (
[Id] UNIQUEIDENTIFIER NOT NULL,
[UserId] UNIQUEIDENTIFIER NOT NULL,
[Name] NVARCHAR (50) NOT NULL,
[Type] SMALLINT NOT NULL,
[Identifier] NVARCHAR (50) NOT NULL,
[PushToken] NVARCHAR (255) NULL,
[CreationDate] DATETIME2 (7) NOT NULL,
[RevisionDate] DATETIME2 (7) NOT NULL,
[EncryptedUserKey] VARCHAR (MAX) NULL,
[EncryptedPublicKey] VARCHAR (MAX) NULL,
[EncryptedPrivateKey] VARCHAR (MAX) NULL,
[Id] UNIQUEIDENTIFIER NOT NULL,
[UserId] UNIQUEIDENTIFIER NOT NULL,
[Name] NVARCHAR (50) NOT NULL,
[Type] SMALLINT NOT NULL,
[Identifier] NVARCHAR (50) NOT NULL,
[PushToken] NVARCHAR (255) NULL,
[CreationDate] DATETIME2 (7) NOT NULL,
[RevisionDate] DATETIME2 (7) NOT NULL,
[EncryptedUserKey] VARCHAR (MAX) NULL,
[EncryptedPublicKey] VARCHAR (MAX) NULL,
[EncryptedPrivateKey] VARCHAR (MAX) NULL,
[Active] BIT NOT NULL CONSTRAINT [DF_Device_Active] DEFAULT (1),
CONSTRAINT [PK_Device] PRIMARY KEY CLUSTERED ([Id] ASC),
CONSTRAINT [FK_Device_User] FOREIGN KEY ([UserId]) REFERENCES [dbo].[User] ([Id])
);


GO
CREATE UNIQUE NONCLUSTERED INDEX [UX_Device_UserId_Identifier]
ON [dbo].[Device]([UserId] ASC, [Identifier] ASC);


GO
CREATE NONCLUSTERED INDEX [IX_Device_Identifier]
ON [dbo].[Device]([Identifier] ASC);
118 changes: 118 additions & 0 deletions util/Migrator/DbScripts/2024-10-31-00_DeviceActivation.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
SET DEADLOCK_PRIORITY HIGH
GO

-- add column
IF COL_LENGTH('[dbo].[Device]', 'Active') IS NULL
BEGIN
ALTER TABLE
[dbo].[Device]
ADD
[Active] BIT NOT NULL CONSTRAINT [DF_Device_Active] DEFAULT (1)
END
GO

-- refresh view
CREATE OR ALTER VIEW [dbo].[DeviceView]
AS
SELECT
*
FROM
[dbo].[Device]
GO

-- drop now-unused proc for deletion
IF OBJECT_ID('[dbo].[Device_DeleteById]') IS NOT NULL
BEGIN
DROP PROCEDURE [dbo].[Device_DeleteById]
END
GO

-- refresh procs
CREATE OR ALTER PROCEDURE [dbo].[Device_Create]
@Id UNIQUEIDENTIFIER OUTPUT,
@UserId UNIQUEIDENTIFIER,
@Name NVARCHAR(50),
@Type TINYINT,
@Identifier NVARCHAR(50),
@PushToken NVARCHAR(255),
@CreationDate DATETIME2(7),
@RevisionDate DATETIME2(7),
@EncryptedUserKey VARCHAR(MAX) = NULL,
@EncryptedPublicKey VARCHAR(MAX) = NULL,
@EncryptedPrivateKey VARCHAR(MAX) = NULL,
@Active BIT = 1
AS
BEGIN
SET NOCOUNT ON

INSERT INTO [dbo].[Device]
(
[Id],
[UserId],
[Name],
[Type],
[Identifier],
[PushToken],
[CreationDate],
[RevisionDate],
[EncryptedUserKey],
[EncryptedPublicKey],
[EncryptedPrivateKey],
[Active]
)
VALUES
(
@Id,
@UserId,
@Name,
@Type,
@Identifier,
@PushToken,
@CreationDate,
@RevisionDate,
@EncryptedUserKey,
@EncryptedPublicKey,
@EncryptedPrivateKey,
@Active
)
END
GO

CREATE OR ALTER PROCEDURE [dbo].[Device_Update]
@Id UNIQUEIDENTIFIER,
@UserId UNIQUEIDENTIFIER,
@Name NVARCHAR(50),
@Type TINYINT,
@Identifier NVARCHAR(50),
@PushToken NVARCHAR(255),
@CreationDate DATETIME2(7),
@RevisionDate DATETIME2(7),
@EncryptedUserKey VARCHAR(MAX) = NULL,
@EncryptedPublicKey VARCHAR(MAX) = NULL,
@EncryptedPrivateKey VARCHAR(MAX) = NULL,
@Active BIT = 1
AS
BEGIN
SET NOCOUNT ON

UPDATE
[dbo].[Device]
SET
[UserId] = @UserId,
[Name] = @Name,
[Type] = @Type,
[Identifier] = @Identifier,
[PushToken] = @PushToken,
[CreationDate] = @CreationDate,
[RevisionDate] = @RevisionDate,
[EncryptedUserKey] = @EncryptedUserKey,
[EncryptedPublicKey] = @EncryptedPublicKey,
[EncryptedPrivateKey] = @EncryptedPrivateKey,
[Active] = @Active
WHERE
[Id] = @Id
END
GO

SET DEADLOCK_PRIORITY NORMAL
GO
Loading

0 comments on commit a04df4b

Please sign in to comment.