Compare commits

...

6 Commits

Author SHA1 Message Date
Tom Moor 9d54b0c260 Update User.ts 2025-09-15 08:29:14 -04:00
Tom Moor 6e73c22060 Update server/models/User.ts
Co-authored-by: graphite-app[bot] <96075541+graphite-app[bot]@users.noreply.github.com>
2025-09-15 08:27:26 -04:00
codegen-sh[bot] 47a02f9df7 Fix UserFlag enum accessibility in tests
- Add static UserFlag property to User class to make enum accessible as User.UserFlag
- This fixes the failing tests that were trying to access User.UserFlag.AvatarChanged
- The AvatarChanged flag was already defined in the enum but not accessible from tests
2025-09-15 03:57:22 +00:00
codegen-sh[bot] bd22941e44 Fix UserFlag import and avatar change logic
- Import UserFlag enum directly in test file
- Fix beforeSave hook logic to properly handle null values
- Update all test references to use imported UserFlag enum
2025-09-15 03:45:38 +00:00
codegen-sh[bot] 3d972af22a Refine avatarChanged flag to only trigger on value changes
- Update beforeSave hook to only set flag when avatarUrl changes from one existing value to another
- Exclude initial value setting (both on new records and first-time setting on existing records)
- Add comprehensive tests covering all edge cases:
  - No flag on new user creation with avatarUrl
  - No flag when initially setting avatarUrl on existing user
  - Flag set when changing from one value to another
  - No flag when setting same value
  - Flag set when changing to null from existing value
2025-09-15 03:34:00 +00:00
codegen-sh[bot] 3c377c4f03 Add UserFlag with beforeSave hook
- Add AvatarChanged flag to UserFlag enum
- Implement beforeSave hook to set flag when avatarUrl changes
- Add comprehensive tests for avatarChanged flag functionality
- Flag is set when avatarUrl is initially set or updated
2025-09-15 03:27:56 +00:00
2 changed files with 103 additions and 1 deletions
+88 -1
View File
@@ -9,7 +9,7 @@ import {
buildCollection,
buildAdmin,
} from "@server/test/factories";
import User from "./User";
import User, { UserFlag } from "./User";
import UserMembership from "./UserMembership";
beforeAll(() => {
@@ -234,4 +234,91 @@ describe("user model", () => {
expect(response[0]).toEqual(collection.id);
});
});
describe("avatarChanged flag", () => {
it("should NOT set avatarChanged flag when avatarUrl is set on new user", async () => {
const team = await buildTeam();
const user = await buildUser({
teamId: team.id,
avatarUrl: "https://example.com/avatar.jpg",
});
expect(user.getFlag(UserFlag.AvatarChanged)).toBe(0);
});
it("should NOT set avatarChanged flag when avatarUrl is initially set on existing user", async () => {
const team = await buildTeam();
const user = await buildUser({
teamId: team.id,
});
// Initially no flag should be set
expect(user.getFlag(UserFlag.AvatarChanged)).toBe(0);
// Set avatarUrl for the first time
user.avatarUrl = "https://example.com/new-avatar.jpg";
await user.save();
// Flag should still not be set since there was no previous value
expect(user.getFlag(UserFlag.AvatarChanged)).toBe(0);
});
it("should not set avatarChanged flag when avatarUrl is not changed", async () => {
const team = await buildTeam();
const user = await buildUser({
teamId: team.id,
});
// Update other field
user.name = "New Name";
await user.save();
expect(user.getFlag(UserFlag.AvatarChanged)).toBe(0);
});
it("should set avatarChanged flag when avatarUrl changes from one value to another", async () => {
const team = await buildTeam();
const user = await buildUser({
teamId: team.id,
avatarUrl: "https://example.com/old-avatar.jpg",
});
// Initially no flag should be set
expect(user.getFlag(UserFlag.AvatarChanged)).toBe(0);
// Change avatarUrl from existing value to new value
user.avatarUrl = "https://example.com/new-avatar.jpg";
await user.save();
expect(user.getFlag(UserFlag.AvatarChanged)).toBe(1);
});
it("should NOT set avatarChanged flag when avatarUrl is set to the same value", async () => {
const team = await buildTeam();
const user = await buildUser({
teamId: team.id,
avatarUrl: "https://example.com/avatar.jpg",
});
// Set to the same value
user.avatarUrl = "https://example.com/avatar.jpg";
await user.save();
expect(user.getFlag(UserFlag.AvatarChanged)).toBe(0);
});
it("should set avatarChanged flag when avatarUrl is changed to null from existing value", async () => {
const team = await buildTeam();
const user = await buildUser({
teamId: team.id,
avatarUrl: "https://example.com/avatar.jpg",
});
// Change to null
user.avatarUrl = null;
await user.save();
expect(user.getFlag(UserFlag.AvatarChanged)).toBe(1);
});
});
});
+15
View File
@@ -30,6 +30,7 @@ import {
AllowNull,
AfterUpdate,
BeforeUpdate,
BeforeSave,
} from "sequelize-typescript";
import { UserPreferenceDefaults } from "@shared/constants";
import { languages } from "@shared/i18n";
@@ -77,6 +78,7 @@ export enum UserFlag {
Desktop = "desktop",
DesktopWeb = "desktopWeb",
MobileWeb = "mobileWeb",
AvatarChanged = "avatarChanged",
}
@Scopes(() => ({
@@ -721,6 +723,19 @@ class User extends ParanoidModel<
model.jwtSecret = crypto.randomBytes(64).toString("hex");
};
@BeforeSave
static setAvatarChangedFlag = (model: User) => {
// Only set flag if avatarUrl changed and there was a previous value
if (model.changed("avatarUrl") && !model.isNewRecord) {
const previousAvatarUrl = model.previous("avatarUrl");
// Set flag only when changing from an existing avatar to a different value
if (previousAvatarUrl !== null) {
model.setFlag(UserFlag.AvatarChanged);
}
}
}
};
@BeforeUpdate
static async checkRoleChange(
model: User,