Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
92 changes: 85 additions & 7 deletions src/roktManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -252,15 +252,39 @@
}
}

public hashAttributes(attributes: IRoktPartnerAttributes): Promise<IRoktPartnerAttributes> {
if (!this.isReady()) {
return this.deferredCall<IRoktPartnerAttributes>('hashAttributes', attributes);
}

/**
* Hashes attributes and returns both original and hashed versions
* with Rokt-compatible key names (like emailsha256, mobilesha256)
*
*
* @param {IRoktPartnerAttributes} attributes - Attributes to hash
* @returns {Promise<IRoktPartnerAttributes>} Object with both original and hashed attributes
*
*/
public async hashAttributes(attributes: IRoktPartnerAttributes): Promise<IRoktPartnerAttributes> {
try {
return this.kit.hashAttributes(attributes);
if (!attributes || typeof attributes !== 'object') {
return {};
}

const hashedAttributes: IRoktPartnerAttributes = {};

for (const key in attributes) {
const attributeValue = attributes[key];

hashedAttributes[key] = attributeValue;

const hashedValue = await this.hashSha256(attributeValue);

if (hashedValue) {
hashedAttributes[`${key}sha256`] = hashedValue;
}
}

return hashedAttributes;

} catch (error) {
return Promise.reject(error instanceof Error ? error : new Error('Unknown error occurred'));
return Promise.reject(error instanceof Error ? error : new Error('Failed to hash attributes'));

Check failure on line 287 in src/roktManager.ts

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Prefer `throw error` over `return Promise.reject(error)`.

See more on https://sonarcloud.io/project/issues?id=mParticle_mparticle-web-sdk&issues=AZq3eERbMRocZF1ia7It&open=AZq3eERbMRocZF1ia7It&pullRequest=1116
}
}

Expand Down Expand Up @@ -290,6 +314,29 @@
}
}

/**
* Hashes an attribute using SHA-256
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One of the acceptance criteria is to embed the wSDK hashAttributes on line 255 for advertisers since they don't have the Rokt kit.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated!

*
* @param {string | number | boolean | undefined | null} attribute - The value to hash
* @returns {Promise<string | undefined | null>} SHA-256 hashed value or undefined/null
*
*/
public async hashSha256(attribute: string | number | boolean | undefined | null): Promise<string | undefined | null> {
if (attribute === null || attribute === undefined) {
this.logger.warning(`hashSha256 received ${attribute} as input`);
return attribute as null | undefined;
}

try {
const normalizedValue = String(attribute).trim().toLocaleLowerCase();
return await this.sha256Hex(normalizedValue);
} catch (error) {
const errorMessage = error instanceof Error ? error.message : String(error);
this.logger.error(`Failed to hash "${attribute}" and returning undefined, selectPlacements will continue: ${errorMessage}`);
return undefined;
}
}

public getLocalSessionAttributes(): LocalSessionAttributes {
return this.store.getLocalSessionAttributes();
}
Expand Down Expand Up @@ -400,6 +447,37 @@
this.messageQueue.delete(messageId);
}

/**
* Hashes a string input using SHA-256 and returns the hex digest
* Uses the Web Crypto API for secure hashing
*
* @param {string} input - The string to hash
* @returns {Promise<string>} The SHA-256 hash as a hexadecimal string
*/
private async sha256Hex(input: string): Promise<string> {
const encoder = new TextEncoder();
const encodedInput = encoder.encode(input);
const digest = await crypto.subtle.digest('SHA-256', encodedInput);
return this.arrayBufferToHex(digest);
}

/**
* Converts an ArrayBuffer to a hexadecimal string representation
* Each byte is converted to a 2-character hex string with leading zeros
*
* @param {ArrayBuffer} buffer - The buffer to convert
* @returns {string} The hexadecimal string representation
*/
private arrayBufferToHex(buffer: ArrayBuffer): string {
const bytes = new Uint8Array(buffer);
let hexString = '';
for (let i = 0; i < bytes.length; i++) {
const hexByte = bytes[i].toString(16).padStart(2, '0');
hexString += hexByte;
}

Check warning on line 477 in src/roktManager.ts

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Expected a `for-of` loop instead of a `for` loop with this simple iteration.

See more on https://sonarcloud.io/project/issues?id=mParticle_mparticle-web-sdk&issues=AZqSmPxPDSWE_JcWPgWV&open=AZqSmPxPDSWE_JcWPgWV&pullRequest=1116
return hexString;
}

/**
* Checks if an identity value has changed by comparing current and new values
*
Expand Down
Loading
Loading