mirror of
https://github.com/bitwarden/browser
synced 2025-12-16 08:13:42 +00:00
[EC-639] Replacing apostrophe char for email values in Policies API request (#4390)
* [EC-639] Replacing single quote char for email values in Policies API request * [EC-639] Added Utils.encodeRFC3986URIComponent and used in PolicyApiService and TwoFactorAuthenticatorComponent * [EC-639] Added unit tests for Utils.encodeRFC3986URIComponent
This commit is contained in:
@@ -7,6 +7,7 @@ import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUti
|
|||||||
import { StateService } from "@bitwarden/common/abstractions/state.service";
|
import { StateService } from "@bitwarden/common/abstractions/state.service";
|
||||||
import { UserVerificationService } from "@bitwarden/common/abstractions/userVerification/userVerification.service.abstraction";
|
import { UserVerificationService } from "@bitwarden/common/abstractions/userVerification/userVerification.service.abstraction";
|
||||||
import { TwoFactorProviderType } from "@bitwarden/common/enums/twoFactorProviderType";
|
import { TwoFactorProviderType } from "@bitwarden/common/enums/twoFactorProviderType";
|
||||||
|
import { Utils } from "@bitwarden/common/misc/utils";
|
||||||
import { UpdateTwoFactorAuthenticatorRequest } from "@bitwarden/common/models/request/update-two-factor-authenticator.request";
|
import { UpdateTwoFactorAuthenticatorRequest } from "@bitwarden/common/models/request/update-two-factor-authenticator.request";
|
||||||
import { TwoFactorAuthenticatorResponse } from "@bitwarden/common/models/response/two-factor-authenticator.response";
|
import { TwoFactorAuthenticatorResponse } from "@bitwarden/common/models/response/two-factor-authenticator.response";
|
||||||
import { AuthResponse } from "@bitwarden/common/types/authResponse";
|
import { AuthResponse } from "@bitwarden/common/types/authResponse";
|
||||||
@@ -99,7 +100,7 @@ export class TwoFactorAuthenticatorComponent
|
|||||||
element: document.getElementById("qr"),
|
element: document.getElementById("qr"),
|
||||||
value:
|
value:
|
||||||
"otpauth://totp/Bitwarden:" +
|
"otpauth://totp/Bitwarden:" +
|
||||||
encodeURIComponent(email) +
|
Utils.encodeRFC3986URIComponent(email) +
|
||||||
"?secret=" +
|
"?secret=" +
|
||||||
encodeURIComponent(this.key) +
|
encodeURIComponent(this.key) +
|
||||||
"&issuer=Bitwarden",
|
"&issuer=Bitwarden",
|
||||||
|
|||||||
@@ -309,4 +309,21 @@ describe("Utils Service", () => {
|
|||||||
expect(Utils.recordToMap(map as any)).toEqual(map);
|
expect(Utils.recordToMap(map as any)).toEqual(map);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("encodeRFC3986URIComponent", () => {
|
||||||
|
it("returns input string with expected encoded chars", () => {
|
||||||
|
expect(Utils.encodeRFC3986URIComponent("test'user@example.com")).toBe(
|
||||||
|
"test%27user%40example.com"
|
||||||
|
);
|
||||||
|
expect(Utils.encodeRFC3986URIComponent("(test)user@example.com")).toBe(
|
||||||
|
"%28test%29user%40example.com"
|
||||||
|
);
|
||||||
|
expect(Utils.encodeRFC3986URIComponent("testuser!@example.com")).toBe(
|
||||||
|
"testuser%21%40example.com"
|
||||||
|
);
|
||||||
|
expect(Utils.encodeRFC3986URIComponent("Test*User@example.com")).toBe(
|
||||||
|
"Test%2AUser%40example.com"
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -486,6 +486,18 @@ export class Utils {
|
|||||||
return Object.assign(destination, source) as unknown as Merge<Destination, Source>;
|
return Object.assign(destination, source) as unknown as Merge<Destination, Source>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* encodeURIComponent escapes all characters except the following:
|
||||||
|
* alphabetic, decimal digits, - _ . ! ~ * ' ( )
|
||||||
|
* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent#encoding_for_rfc3986
|
||||||
|
*/
|
||||||
|
static encodeRFC3986URIComponent(str: string): string {
|
||||||
|
return encodeURIComponent(str).replace(
|
||||||
|
/[!'()*]/g,
|
||||||
|
(c) => `%${c.charCodeAt(0).toString(16).toUpperCase()}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
private static isMobile(win: Window) {
|
private static isMobile(win: Window) {
|
||||||
let mobile = false;
|
let mobile = false;
|
||||||
((a) => {
|
((a) => {
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import { PolicyApiServiceAbstraction } from "../../abstractions/policy/policy-ap
|
|||||||
import { InternalPolicyService } from "../../abstractions/policy/policy.service.abstraction";
|
import { InternalPolicyService } from "../../abstractions/policy/policy.service.abstraction";
|
||||||
import { StateService } from "../../abstractions/state.service";
|
import { StateService } from "../../abstractions/state.service";
|
||||||
import { PolicyType } from "../../enums/policyType";
|
import { PolicyType } from "../../enums/policyType";
|
||||||
|
import { Utils } from "../../misc/utils";
|
||||||
import { PolicyData } from "../../models/data/policy.data";
|
import { PolicyData } from "../../models/data/policy.data";
|
||||||
import { MasterPasswordPolicyOptions } from "../../models/domain/master-password-policy-options";
|
import { MasterPasswordPolicyOptions } from "../../models/domain/master-password-policy-options";
|
||||||
import { PolicyRequest } from "../../models/request/policy.request";
|
import { PolicyRequest } from "../../models/request/policy.request";
|
||||||
@@ -54,7 +55,7 @@ export class PolicyApiService implements PolicyApiServiceAbstraction {
|
|||||||
"token=" +
|
"token=" +
|
||||||
encodeURIComponent(token) +
|
encodeURIComponent(token) +
|
||||||
"&email=" +
|
"&email=" +
|
||||||
encodeURIComponent(email) +
|
Utils.encodeRFC3986URIComponent(email) +
|
||||||
"&organizationUserId=" +
|
"&organizationUserId=" +
|
||||||
organizationUserId,
|
organizationUserId,
|
||||||
null,
|
null,
|
||||||
|
|||||||
Reference in New Issue
Block a user