Add user profile and avatar upload feature

This commit is contained in:
Aaron Po
2026-08-30 04:13:47 -04:00
parent bd78fe6533
commit d1d089aa73
15 changed files with 325 additions and 47 deletions

View File

@@ -31,8 +31,24 @@ Table Photo {
Table UserAvatar {
UserAvatarID uniqueidentifier [pk, default: `newid()`]
UserAccountID uniqueidentifier [not null, unique]
UserProfileID uniqueidentifier [not null]
PhotoID uniqueidentifier [not null]
ValidFrom "datetime2(3)" [not null, default: `sysutcdatetime()`]
ValidTo "datetime2(3)" [note: 'NULL = currently active']
RowVersion rowversion
Note: 'Deleted when the user profile is deleted. At most one row per profile has ValidTo = NULL.'
Indexes {
UserProfileID [unique, name: 'UX_UserAvatar_ActiveOne', note: 'filtered: WHERE ValidTo IS NULL']
PhotoID [name: 'IX_UserAvatar_Photo']
}
}
Table UserProfile {
UserProfileID uniqueidentifier [pk, default: `newid()`]
Biography "nvarchar(max)" [not null]
UserAccountID uniqueidentifier [not null, unique]
RowVersion rowversion
Note: 'Deleted when the user account is deleted'
@@ -216,8 +232,9 @@ Table BeerPostComment {
}
Ref: Photo.UploadedByID > UserAccount.UserAccountID [delete: no action]
Ref: UserAvatar.UserAccountID - UserAccount.UserAccountID [delete: cascade]
Ref: UserAvatar.PhotoID > Photo.PhotoID
Ref: UserAvatar.PhotoID > Photo.PhotoID [delete: no action]
Ref: UserAvatar.UserProfileID > UserProfile.UserProfileID [delete: cascade]
Ref: UserProfile.UserAccountID - UserAccount.UserAccountID [delete: cascade]
Ref: UserVerification.UserAccountID - UserAccount.UserAccountID [delete: cascade]
Ref: UserCredential.UserAccountID > UserAccount.UserAccountID [delete: cascade]
Ref: UserFollow.UserAccountID > UserAccount.UserAccountID [delete: no action]

View File

@@ -29,3 +29,5 @@ CREATE TABLE dbo.UserAccount
CONSTRAINT AK_Email
UNIQUE (Email)
);

View File

@@ -1,29 +0,0 @@
CREATE TABLE UserAvatar -- delete avatar photo when user account is deleted
(
UserAvatarID UNIQUEIDENTIFIER
CONSTRAINT DF_UserAvatarID DEFAULT NEWID(),
UserAccountID UNIQUEIDENTIFIER NOT NULL,
PhotoID UNIQUEIDENTIFIER NOT NULL,
RowVersion ROWVERSION,
CONSTRAINT PK_UserAvatar PRIMARY KEY (UserAvatarID),
CONSTRAINT FK_UserAvatar_UserAccount
FOREIGN KEY (UserAccountID)
REFERENCES UserAccount (UserAccountID)
ON DELETE CASCADE,
CONSTRAINT FK_UserAvatar_PhotoID
FOREIGN KEY (PhotoID)
REFERENCES Photo (PhotoID),
CONSTRAINT AK_UserAvatar_UserAccountID
UNIQUE (UserAccountID)
);
CREATE
NONCLUSTERED INDEX IX_UserAvatar_UserAccount
ON UserAvatar(UserAccountID);

View File

@@ -0,0 +1,22 @@
CREATE TABLE dbo.UserProfile
(
UserProfileID UNIQUEIDENTIFIER
CONSTRAINT DF_UserProfileID DEFAULT NEWID(),
Biography NVARCHAR(MAX) NOT NULL,
UserAccountID UNIQUEIDENTIFIER NOT NULL,
RowVersion ROWVERSION,
CONSTRAINT PK_UserProfile
PRIMARY KEY (UserProfileID),
CONSTRAINT AK_UserProfile_UserAccountID
UNIQUE (UserAccountID),
CONSTRAINT FK_UserProfile_UserAccount
FOREIGN KEY (UserAccountID)
REFERENCES UserAccount (UserAccountID)
ON DELETE CASCADE
);

View File

@@ -0,0 +1,43 @@
CREATE TABLE dbo.UserAvatar
(
UserAvatarID UNIQUEIDENTIFIER
CONSTRAINT DF_UserAvatarID DEFAULT NEWID(),
UserProfileID UNIQUEIDENTIFIER NOT NULL,
PhotoID UNIQUEIDENTIFIER NOT NULL,
ValidFrom DATETIME2(3) NOT NULL
CONSTRAINT DF_UserAvatar_ValidFrom DEFAULT SYSUTCDATETIME(),
ValidTo DATETIME2(3) NULL, -- NULL = currently active
RowVersion ROWVERSION,
CONSTRAINT PK_UserAvatar PRIMARY KEY (UserAvatarID),
CONSTRAINT FK_UserAvatar_UserProfile
FOREIGN KEY (UserProfileID)
REFERENCES dbo.UserProfile (UserProfileID)
ON DELETE CASCADE,
CONSTRAINT FK_UserAvatar_Photo
FOREIGN KEY (PhotoID)
REFERENCES dbo.Photo (PhotoID)
ON DELETE NO ACTION
ON UPDATE NO ACTION,
CONSTRAINT CK_UserAvatar_ValidRange
CHECK (ValidTo IS NULL OR ValidTo > ValidFrom)
);
-- At most one active avatar per profile
CREATE UNIQUE NONCLUSTERED INDEX UX_UserAvatar_ActiveOne
ON dbo.UserAvatar (UserProfileID)
WHERE ValidTo IS NULL;
CREATE NONCLUSTERED INDEX IX_UserAvatar_Photo
ON dbo.UserAvatar (PhotoID);
CREATE NONCLUSTERED INDEX ix_UserAvatar_Profile
ON dbo.UserAvatar (UserProfileID)