-
Notifications
You must be signed in to change notification settings - Fork 12
feat: create web server identity token #52
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
0ad42f0
e03b07a
68692ea
fd8ec84
afd3834
d084ea4
dd402b9
dba95d4
f7b98ab
fd4c5f8
7ce311e
d13752c
0c52aa9
c6ed97b
6e2707d
803a2f6
eec1bba
84de0e7
ce4d828
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
/* | ||
* Copyright (c) 2024, salesforce.com, inc. | ||
* All rights reserved. | ||
* Licensed under the BSD 3-Clause license. | ||
* For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause | ||
*/ | ||
|
||
import type { ConfigPropertyMeta } from '@salesforce/core'; | ||
|
||
export const enum ConfigVars { | ||
/** | ||
* The Base64-encoded identity token of the local web server, used to | ||
* validate the web server's identity to the hmr-client. | ||
*/ | ||
LOCAL_WEB_SERVER_IDENTITY_TOKEN = 'local-web-server-identity-token', | ||
} | ||
|
||
export default [ | ||
{ | ||
key: ConfigVars.LOCAL_WEB_SERVER_IDENTITY_TOKEN, | ||
description: 'The Base64-encoded identity token of the local web server', | ||
hidden: true, | ||
encrypted: true, | ||
}, | ||
] as ConfigPropertyMeta[]; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
/* | ||
* Copyright (c) 2024, salesforce.com, inc. | ||
* All rights reserved. | ||
* Licensed under the BSD 3-Clause license. | ||
* For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause | ||
*/ | ||
|
||
import { CryptoUtils } from '@salesforce/lwc-dev-mobile-core'; | ||
import { Config, ConfigAggregator } from '@salesforce/core'; | ||
import configMeta, { ConfigVars } from './../configMeta.js'; | ||
|
||
export class IdentityUtils { | ||
public static async getOrCreateIdentityToken(): Promise<string> { | ||
let token = await this.getIdentityToken(); | ||
if (!token) { | ||
token = CryptoUtils.generateIdentityToken(); | ||
await this.writeIdentityToken(token); | ||
} | ||
return token; | ||
} | ||
|
||
public static async getIdentityToken(): Promise<string | undefined> { | ||
const config = await ConfigAggregator.create({ customConfigMeta: configMeta }); | ||
// Need to reload to make sure the values read are decrypted | ||
await config.reload(); | ||
sfdctaka marked this conversation as resolved.
Show resolved
Hide resolved
|
||
const identityToken = config.getPropertyValue(ConfigVars.LOCAL_WEB_SERVER_IDENTITY_TOKEN); | ||
|
||
return identityToken as string; | ||
} | ||
|
||
public static async writeIdentityToken(token: string): Promise<void> { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This method could be There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it is ok to leave it There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would however update the method signature to take an optional There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @maliroteh-sf I didn't add optional |
||
const config = await Config.create({ isGlobal: false }); | ||
Config.addAllowedProperties(configMeta); | ||
config.set(ConfigVars.LOCAL_WEB_SERVER_IDENTITY_TOKEN, token); | ||
await config.write(); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
/* | ||
* Copyright (c) 2024, salesforce.com, inc. | ||
* All rights reserved. | ||
* Licensed under the BSD 3-Clause license. | ||
* For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause | ||
*/ | ||
|
||
/* eslint-disable @typescript-eslint/no-unsafe-member-access */ | ||
/* eslint-disable @typescript-eslint/no-unsafe-call */ | ||
|
||
import { expect } from 'chai'; | ||
import { Config, ConfigAggregator } from '@salesforce/core'; | ||
import { TestContext } from '@salesforce/core/testSetup'; | ||
import { CryptoUtils } from '@salesforce/lwc-dev-mobile-core'; | ||
import { IdentityUtils } from '../../src/shared/identityUtils.js'; | ||
import { ConfigVars } from '../../src/configMeta.js'; | ||
|
||
describe('identityUtils', () => { | ||
const $$ = new TestContext(); | ||
|
||
afterEach(() => { | ||
$$.restore(); | ||
}); | ||
|
||
it('getOrCreateIdentityToken resolves if token is found', async () => { | ||
const fakeIdentityToken = 'fake identity token'; | ||
$$.SANDBOX.stub(IdentityUtils, 'getIdentityToken').resolves(fakeIdentityToken); | ||
|
||
const resolved = await IdentityUtils.getOrCreateIdentityToken(); | ||
expect(resolved).to.equal(fakeIdentityToken); | ||
}); | ||
|
||
it('getOrCreateIdentityToken resolves and writeIdentityToken is called when there is no token', async () => { | ||
const fakeIdentityToken = 'fake identity token'; | ||
$$.SANDBOX.stub(IdentityUtils, 'getIdentityToken').resolves(undefined); | ||
$$.SANDBOX.stub(CryptoUtils, 'generateIdentityToken').resolves(fakeIdentityToken); | ||
const writeIdentityTokenStub = $$.SANDBOX.stub(IdentityUtils, 'writeIdentityToken').resolves(); | ||
|
||
const resolved = await IdentityUtils.getOrCreateIdentityToken(); | ||
expect(resolved).to.equal(fakeIdentityToken); | ||
expect(writeIdentityTokenStub.calledOnce).to.be.true; | ||
}); | ||
|
||
it('getIdentityToken resolves to undefined when identity token is not available', async () => { | ||
$$.SANDBOX.stub(ConfigAggregator, 'create').resolves(ConfigAggregator.prototype); | ||
$$.SANDBOX.stub(ConfigAggregator.prototype, 'reload').resolves(); | ||
$$.SANDBOX.stub(ConfigAggregator.prototype, 'getPropertyValue').returns(undefined); | ||
const resolved = await IdentityUtils.getIdentityToken(); | ||
|
||
expect(resolved).to.equal(undefined); | ||
}); | ||
|
||
it('getIdentityToken resolves to a string when identity token is available', async () => { | ||
const fakeIdentityToken = 'fake identity token'; | ||
$$.SANDBOX.stub(ConfigAggregator, 'create').resolves(ConfigAggregator.prototype); | ||
$$.SANDBOX.stub(ConfigAggregator.prototype, 'reload').resolves(); | ||
$$.SANDBOX.stub(ConfigAggregator.prototype, 'getPropertyValue').returns(fakeIdentityToken); | ||
|
||
const resolved = await IdentityUtils.getIdentityToken(); | ||
expect(resolved).to.equal(fakeIdentityToken); | ||
}); | ||
|
||
it('writeIdentityToken resolves', async () => { | ||
const fakeIdentityToken = 'fake identity token'; | ||
$$.SANDBOX.stub(Config, 'create').withArgs($$.SANDBOX.match.any).resolves(Config.prototype); | ||
$$.SANDBOX.stub(Config, 'addAllowedProperties').withArgs($$.SANDBOX.match.any); | ||
$$.SANDBOX.stub(Config.prototype, 'set').withArgs( | ||
ConfigVars.LOCAL_WEB_SERVER_IDENTITY_TOKEN, | ||
$$.SANDBOX.match.string | ||
); | ||
$$.SANDBOX.stub(Config.prototype, 'write').resolves(); | ||
|
||
const resolved = await IdentityUtils.writeIdentityToken(fakeIdentityToken); | ||
expect(resolved).to.equal(undefined); | ||
}); | ||
}); |
Uh oh!
There was an error while loading. Please reload this page.