diff --git a/src/stores/acctMgmt.ts b/src/stores/acctMgmt.ts index 7fcc49b..5565de0 100644 --- a/src/stores/acctMgmt.ts +++ b/src/stores/acctMgmt.ts @@ -162,7 +162,7 @@ export const useAcctMgmtStore = defineStore('acctMgmtStore', { * @returns the result of whether the deletion is success or not. */ async deleteAccount(userToDelete: string): Promise { - const apiDelete = `/api/users/${userToDelete}`; + const apiDelete = `/api/users/${encodeURIComponent(userToDelete)}`; try { const response = await apiClient.delete(apiDelete); @@ -178,7 +178,7 @@ export const useAcctMgmtStore = defineStore('acctMgmtStore', { * @param {object} editDetail */ async editAccount(userToEdit: string, editDetail: EditDetail): Promise { - const apiEdit = `/api/users/${userToEdit}`; + const apiEdit = `/api/users/${encodeURIComponent(userToEdit)}`; try { const response = await apiClient.put(apiEdit, { @@ -194,7 +194,7 @@ export const useAcctMgmtStore = defineStore('acctMgmtStore', { } }, async editAccountName(userToEdit: string, newName: string): Promise { - const apiEdit = `/api/users/${userToEdit}`; + const apiEdit = `/api/users/${encodeURIComponent(userToEdit)}`; try { const response = await apiClient.put(apiEdit, { @@ -210,7 +210,7 @@ export const useAcctMgmtStore = defineStore('acctMgmtStore', { } }, async editAccountPwd(userToEdit: string, newPwd: string): Promise { - const apiEdit = `/api/users/${userToEdit}`; + const apiEdit = `/api/users/${encodeURIComponent(userToEdit)}`; try { const response = await apiClient.put(apiEdit, { @@ -231,7 +231,7 @@ export const useAcctMgmtStore = defineStore('acctMgmtStore', { * @param {string} roleCode */ async addRoleToUser(usernameToEdit: string, roleCode: string): Promise { - const apiAddRole = `/api/users/${usernameToEdit}/roles/${roleCode}`; + const apiAddRole = `/api/users/${encodeURIComponent(usernameToEdit)}/roles/${encodeURIComponent(roleCode)}`; try { const response = await apiClient.put(apiAddRole); @@ -246,7 +246,7 @@ export const useAcctMgmtStore = defineStore('acctMgmtStore', { * @param {string} roleCode */ async deleteRoleToUser(usernameToEdit: string, roleCode: string): Promise { - const apiDeleteRole = `/api/users/${usernameToEdit}/roles/${roleCode}`; + const apiDeleteRole = `/api/users/${encodeURIComponent(usernameToEdit)}/roles/${encodeURIComponent(roleCode)}`; try { const response = await apiClient.delete(apiDeleteRole); @@ -261,7 +261,7 @@ export const useAcctMgmtStore = defineStore('acctMgmtStore', { * @param {string} uniqueUsername */ async getUserDetail(uniqueUsername: string): Promise { - const apiUserDetail = `/api/users/${uniqueUsername}`; + const apiUserDetail = `/api/users/${encodeURIComponent(uniqueUsername)}`; try { const response = await apiClient.get(apiUserDetail); this.currentViewingUser = response.data; diff --git a/tests/stores/acctMgmt.test.js b/tests/stores/acctMgmt.test.js index 891fd7c..3cbe637 100644 --- a/tests/stores/acctMgmt.test.js +++ b/tests/stores/acctMgmt.test.js @@ -114,6 +114,16 @@ describe('acctMgmtStore', () => { expect(result).toBe(true); }); + it('encodes special characters in username', async () => { + mockDelete.mockResolvedValue({ status: 200 }); + + await store.deleteAccount('user@domain/name'); + + expect(mockDelete).toHaveBeenCalledWith( + '/api/users/user%40domain%2Fname', + ); + }); + it('returns false on error', async () => { mockDelete.mockRejectedValue(new Error('fail')); @@ -154,6 +164,16 @@ describe('acctMgmtStore', () => { ); expect(result).toBe(true); }); + + it('encodes special characters in username and role', async () => { + mockPut.mockResolvedValue({ status: 200 }); + + await store.addRoleToUser('user@org', 'role/special'); + + expect(mockPut).toHaveBeenCalledWith( + '/api/users/user%40org/roles/role%2Fspecial', + ); + }); }); describe('deleteRoleToUser', () => {