diff --git a/src/model/UserDataSource.ts b/src/model/UserDataSource.ts index b4848f86..aa5f4bc8 100644 --- a/src/model/UserDataSource.ts +++ b/src/model/UserDataSource.ts @@ -57,7 +57,7 @@ export default class UserDataSource extends MongoDataSource { } /** - * Update user profile. Create a new user object if not defined. + * Update user profile. Create a new user object if not defined. Optional fields (displayName, bio, website, avatar) can take blank ("") and null. Blank to clear the field; null to skip the update. * @param updater UUID of the account doing the update * @param input profile params * @returns true if successful @@ -101,7 +101,7 @@ export default class UserDataSource extends MongoDataSource { throw new Error('Nothing to update. Must provide at least one field.') } - if (website != null && !isValidUrl(website)) { + if (website !== '' && website != null && !isValidUrl(website)) { throw new Error('Invalid website address.') } @@ -266,7 +266,11 @@ const isValidUsername = (username?: string): boolean => { ) } +/** + * Validate non-empty and non-null url + */ const isValidUrl = (url: string): boolean => { + if (url == null) return false try { const newUrl = new URL(url) return newUrl.protocol === 'http:' || newUrl.protocol === 'https:' diff --git a/src/model/__tests__/UserDataSource.ts b/src/model/__tests__/UserDataSource.ts index 2571eebf..2921b247 100644 --- a/src/model/__tests__/UserDataSource.ts +++ b/src/model/__tests__/UserDataSource.ts @@ -71,7 +71,7 @@ describe('UserDataSource', () => { await users.createOrUpdateUserProfile(updater, input) - const u2 = await users.getUserPublicProfile(username) + let u2 = await users.getUserPublicProfile(username) // check selected fields expect(u2).toMatchObject({ @@ -83,6 +83,20 @@ describe('UserDataSource', () => { }) expect(u2?._id.toUUID().toString()).toEqual(input.userUuid) + + // should allow website as an empty string to clear existing value + await users.createOrUpdateUserProfile(updater, { userUuid: input.userUuid, website: '' }) + + u2 = await users.getUserPublicProfile(username) + + // verify + expect(u2).toMatchObject({ + username: input.username, + displayName: input.displayName, + bio: input.bio, + website: '', + email: input.email + }) }) it('should require an email when creating new profile', async () => {