Skip to content
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

credentials not available via listener after authentication #3

Closed
Popl7 opened this issue Jul 28, 2016 · 19 comments
Closed

credentials not available via listener after authentication #3

Popl7 opened this issue Jul 28, 2016 · 19 comments

Comments

@Popl7
Copy link

Popl7 commented Jul 28, 2016

when using the JS bundle I am unable to get my credentials.
The authentication to the oAuth works and I do receive an access_token.
I would like to persist this.

@Popl7
Copy link
Author

Popl7 commented Jul 28, 2016

This is the code I have at the moment:

function startSpark() {
console.log('xxxxxxxxxxx starting spark xxxxxxxxxxx');
loadCache();
spark = window.spark = initSpark();
initListeners();
authSpark();
console.log('xxxxxxxxxxx done starting spark xxxxxxxxxxx');
}

function loadCache() {
    console.log('loading cached credentials');
    try {
        credentials = JSON.parse(localStorage.getItem('credentials'));
        if (credentials && credentials.refresh_token_expires < Date.now()) {
            credentials = undefined;
        }
        device = JSON.parse(localStorage.getItem('device'));
    }
    catch (error) {
        // ignore
    }
}

function initListeners() {
    console.log('initializing listeners');

    spark.listenToAndRun(spark, 'change:device', function () {
        console.log('change:device: ', JSON.stringify(spark.device));
        localStorage.setItem('device', JSON.stringify(spark.device));
    });

    spark.listenToAndRun(spark, 'change:credentials', function () {
        console.log('change:credentials: ', JSON.stringify(spark.credentials));
        localStorage.setItem('credentials', JSON.stringify(spark.credentials));
    });

    spark.listenToAndRun(spark, 'change:isAuthenticated', function() {
        console.log('change:isAuthenticated: ', spark.isAuthenticated);
    });

    spark.listenToAndRun(spark, 'change:isAuthenticating', function() {
        console.log('change:isAuthenticating: ', spark.isAuthenticating);
    });
}

function initSpark() {
    console.log('initializing spark');
    return new ciscospark.init({
        credentials: credentials,
        device: device,
        config: {
            credentials: {
                oauth: {
                    client_id: client_id,
                    client_secret: client_secret,
                    scope: scope,
                    redirect_uri: redirect_uri
                }
            }
        }
    });
}

function authSpark() {
    console.log('starting authentication');
    if (spark.isAuthenticated) {
        console.log(' => authenticated');
        spark.authenticate()
                .then(function() {
                    console.log('after authentication');
                })
                .catch(function(reason) {
                    console.error(reason);
                    alert(reason);
                });
    } else {
        console.log(' => NOT authenticated');
    }
}

function sparkLogin() {
    // spark.config.credentials.clientType = 'public';
    // spark.config.credentials.clientType = 'confidential';
    spark.authenticate()
            .catch(function(reason) {
                console.error(reason);
            });
}

window.onload = startSpark;

@Popl7
Copy link
Author

Popl7 commented Jul 28, 2016

This is the output I get:

spark.html:37 xxxxxxxxxxx starting spark xxxxxxxxxxx
2016-07-28 17:34:53.210 spark.html:46 loading cached credentials
2016-07-28 17:34:53.210 spark.html:82 initializing spark
2016-07-28 17:34:53.215 spark.html:60 initializing listeners
2016-07-28 17:34:53.216 spark.html:63 change:device: {"services":{},"features":{"developer":[],"entitlement":[],"user":[]}}
2016-07-28 17:34:53.217 spark.html:68 change:credentials: {}
2016-07-28 17:34:53.217 spark.html:73 change:isAuthenticated: false
2016-07-28 17:34:53.218 spark.html:77 change:isAuthenticating: undefined
2016-07-28 17:34:53.218 spark.html:100 starting authentication
2016-07-28 17:34:53.218 spark.html:112 => NOT authenticated
2016-07-28 17:34:53.218 spark.html:42 xxxxxxxxxxx done starting spark xxxxxxxxxxx
2016-07-28 17:34:55.935 spark.js:36811 credentials(shim): authenticating
2016-07-28 17:34:55.936 spark.js:36960 credentials(shim): generating csrf token
2016-07-28 17:34:55.937 spark.html:77 change:isAuthenticating: true
2016-07-28 17:34:55.938 spark.html:68 change:credentials: {}
2016-07-28 17:34:55.939 spark.js:36853 credentials(shim): initiating implicit grant flow
2016-07-28 17:34:56.246 Navigated to https://idbroker.webex.com/idb/saml2/jsp/doSSO.jsp?type=login&goto=https%3A…eams_write%2520spark%253Amemberships_write%26service%3Dspark&service=spark
2016-07-28 17:35:02.596 Navigated to https://idbroker.webex.com/idb/oauth2/oauth2Consent.jsp?clientID=C8da597e01…520spark%253Ateams_write%2520spark%253Amemberships_write%26service%3Dspark
2016-07-28 17:35:04.091 Navigated to http://localhost:5555/spark.html
2016-07-28 17:35:04.480 spark.html:37 xxxxxxxxxxx starting spark xxxxxxxxxxx
2016-07-28 17:35:04.483 spark.html:46 loading cached credentials
2016-07-28 17:35:04.483 spark.html:82 initializing spark
2016-07-28 17:35:04.489 spark.html:60 initializing listeners
2016-07-28 17:35:04.490 spark.html:63 change:device: {"services":{},"features":{"developer":[],"entitlement":[],"user":[]}}
2016-07-28 17:35:04.490 spark.html:68 change:credentials: {}
2016-07-28 17:35:04.491 spark.html:73 change:isAuthenticated: false
2016-07-28 17:35:04.491 spark.html:77 change:isAuthenticating: undefined
2016-07-28 17:35:04.491 spark.html:100 starting authentication
2016-07-28 17:35:04.491 spark.html:112 => NOT authenticated
2016-07-28 17:35:04.491 spark.html:42 xxxxxxxxxxx done starting spark xxxxxxxxxxx
2016-07-28 17:35:04.524 spark.js:36967 credentials(shim): verifying csrf token
2016-07-28 17:35:04.525 spark.js:36710 credentials: received authorization
2016-07-28 17:35:04.528 spark.js:36987 credentials(shim): updating browser location http://localhost:5555/spark.html

@Popl7
Copy link
Author

Popl7 commented Jul 28, 2016

After the 'credentials: received authorization' I am unable to get my access_token and I am not authenticated.

@ianwremmel
Copy link
Contributor

ok, i think you've stumbled across several subtle bugs. Can you change initSpark() to the below and (a) let me know if it works and (b) share the new logs?

function initSpark() {
    console.log('initializing spark');
    return new ciscospark.init({
        credentials: credentials,
        device: device,
        config: {
            credentials: {
                clientType: 'confidential',
                oauth: {
                    client_id: client_id,
                    client_secret: client_secret,
                    scope: scope,
                    redirect_uri: redirect_uri
                }
            }
        }
    });
}

@Popl7
Copy link
Author

Popl7 commented Jul 28, 2016

I tried clientType 'confidential' before too.
The error is still the same.
This is with a new bundle (0.7.0) and the clientType added to the init function.

The output is:

Navigated to http://localhost:5555/spark.html
2016-07-28 19:34:32.853 spark.html:37 xxxxxxxxxxx starting spark xxxxxxxxxxx
2016-07-28 19:34:32.856 spark.html:46 loading cached credentials
2016-07-28 19:34:32.856 spark.html:82 initializing spark
2016-07-28 19:34:32.862 spark.html:60 initializing listeners
2016-07-28 19:34:32.863 spark.html:63 change:device: {"services":{},"features":{"developer":[],"entitlement":[],"user":[]}}
2016-07-28 19:34:32.863 spark.html:68 change:credentials: {}
2016-07-28 19:34:32.864 spark.html:73 change:isAuthenticated: false
2016-07-28 19:34:32.864 spark.html:77 change:isAuthenticating: undefined
2016-07-28 19:34:32.864 spark.html:101 starting authentication
2016-07-28 19:34:32.864 spark.html:113 => NOT authenticated
2016-07-28 19:34:32.864 spark.html:42 xxxxxxxxxxx done starting spark xxxxxxxxxxx
2016-07-28 19:34:34.490 spark.js:36812 credentials(shim): authenticating
2016-07-28 19:34:34.491 spark.js:36961 credentials(shim): generating csrf token
2016-07-28 19:34:34.492 spark.html:77 change:isAuthenticating: true
2016-07-28 19:34:34.493 spark.html:68 change:credentials: {}
2016-07-28 19:34:34.494 spark.js:36877 credentials(shim): initiating authorization code grant flow
2016-07-28 19:34:35.444 Navigated to https://idbroker.webex.com/idb/oauth2/oauth2Consent.jsp?clientID=C8da597e01…520spark%253Ateams_write%2520spark%253Amemberships_write%26service%3Dspark
2016-07-28 19:34:36.786 Navigated to http://localhost:5555/spark.html?code=M2JhOWM5YzEtOTQzNy00N2Q3LTgwMmMtZWI5M…MzNi&state=Y3NyZl90b2tlbj1hN2NjYTRkYy0wMDM1LTRjZWYtYmU3NS04NWUzZDY4ZmMyMDg
2016-07-28 19:34:37.162 spark.html?code=M2JhOWM5YzEtOTQzNy00N2Q3LTgwMmMtZWI5MThlZDVkMDBhMmRlNjViYjQtMzNi&state=Y3NyZl90b2tl…:37 xxxxxxxxxxx starting spark xxxxxxxxxxx
2016-07-28 19:34:37.165 spark.html?code=M2JhOWM5YzEtOTQzNy00N2Q3LTgwMmMtZWI5MThlZDVkMDBhMmRlNjViYjQtMzNi&state=Y3NyZl90b2tl…:46 loading cached credentials
2016-07-28 19:34:37.165 spark.html?code=M2JhOWM5YzEtOTQzNy00N2Q3LTgwMmMtZWI5MThlZDVkMDBhMmRlNjViYjQtMzNi&state=Y3NyZl90b2tl…:82 initializing spark
2016-07-28 19:34:37.172 spark.html?code=M2JhOWM5YzEtOTQzNy00N2Q3LTgwMmMtZWI5MThlZDVkMDBhMmRlNjViYjQtMzNi&state=Y3NyZl90b2tl…:60 initializing listeners
2016-07-28 19:34:37.173 spark.html?code=M2JhOWM5YzEtOTQzNy00N2Q3LTgwMmMtZWI5MThlZDVkMDBhMmRlNjViYjQtMzNi&state=Y3NyZl90b2tl…:63 change:device: {"services":{},"features":{"developer":[],"entitlement":[],"user":[]}}
2016-07-28 19:34:37.173 spark.html?code=M2JhOWM5YzEtOTQzNy00N2Q3LTgwMmMtZWI5MThlZDVkMDBhMmRlNjViYjQtMzNi&state=Y3NyZl90b2tl…:68 change:credentials: {}
2016-07-28 19:34:37.174 spark.html?code=M2JhOWM5YzEtOTQzNy00N2Q3LTgwMmMtZWI5MThlZDVkMDBhMmRlNjViYjQtMzNi&state=Y3NyZl90b2tl…:73 change:isAuthenticated: false
2016-07-28 19:34:37.174 spark.html?code=M2JhOWM5YzEtOTQzNy00N2Q3LTgwMmMtZWI5MThlZDVkMDBhMmRlNjViYjQtMzNi&state=Y3NyZl90b2tl…:77 change:isAuthenticating: undefined
2016-07-28 19:34:37.174 spark.html?code=M2JhOWM5YzEtOTQzNy00N2Q3LTgwMmMtZWI5MThlZDVkMDBhMmRlNjViYjQtMzNi&state=Y3NyZl90b2tl…:101 starting authentication
2016-07-28 19:34:37.174 spark.html?code=M2JhOWM5YzEtOTQzNy00N2Q3LTgwMmMtZWI5MThlZDVkMDBhMmRlNjViYjQtMzNi&state=Y3NyZl90b2tl…:113 => NOT authenticated
2016-07-28 19:34:37.174 spark.html?code=M2JhOWM5YzEtOTQzNy00N2Q3LTgwMmMtZWI5MThlZDVkMDBhMmRlNjViYjQtMzNi&state=Y3NyZl90b2tl…:42 xxxxxxxxxxx done starting spark xxxxxxxxxxx
2016-07-28 19:34:37.208 spark.js:36988 credentials(shim): updating browser location http://localhost:5555/spark.html
2016-07-28 19:34:37.209 spark.js:36812 credentials(shim): authenticating
2016-07-28 19:34:37.211 spark.js:36342 credentials: auth code received, exchanging for access_token
2016-07-28 19:34:37.212 spark.js:36464 credentials: requesting authorization code grant
2016-07-28 19:34:38.474 idbroker.webex.com/idb/oauth2/v1/access_token:1 POST https://idbroker.webex.com/idb/oauth2/v1/access_token 400 (Bad Request)
2016-07-28 19:34:38.481 spark.js:14360 Uncaught (in promise) SubType {error: "invalid_client", errorDescription: "Invalid client", errorUri: undefined, res: Object, name: "InvalidClientError"…}SubType @ spark.js:14360(anonymous function) @ spark.js:36493
2016-07-28 19:34:38.484 spark.js:14360 Uncaught (in promise) SubType {error: "invalid_client", errorDescription: "Invalid client", errorUri: undefined, res: Object, name: "InvalidClientError"…}SubType @ spark.js:14360(anonymous function) @ spark.js:36493
2016-07-28 19:34:38.484 spark.js:14360 Uncaught (in promise) SubType {error: "invalid_client", errorDescription: "Invalid client", errorUri: undefined, res: Object, name: "InvalidClientError"…}

@Popl7
Copy link
Author

Popl7 commented Jul 28, 2016

Before when I tried this, I could get rid of the 400 error by removing the auth from the POST request and adding the client_id, client_secret and redirect_uri.
This needed to be hard-coded because it didn't get this from the this.config hash.
After adding this I the POST succeeds but I still have no access_token available.

@ianwremmel
Copy link
Contributor

can you try generating your bundle with the following environment variables set? (and pass nothing to the config hash)

  • CISCOSPARK_CLIENT_ID
  • CISCOSPARK_CLIENT_SECRET
  • CISCOSPARK_REDIRECT_URI
  • CISCOSPARK_SCOPE

@ianwremmel
Copy link
Contributor

Also, did you explicitly install 0.7.0 or did npm install it automatically? According to semver, 0.7.0-* should be prerelease versions that you have to explicitly opt into (and they may or may not be ready yet)

@Popl7
Copy link
Author

Popl7 commented Jul 28, 2016

I build the bundle of master, version fa143e5 now.
I will test the building with the env variables.

@ianwremmel
Copy link
Contributor

I see. Building master is potentially dangerous, especially right now (i'm working on setting up tooling to make sure master always passes all tests, but at the moment, many tests are disabled).

You should use the latest stable version from npm: npm install ciscospark. Alternatively, c49ca68 corresponds to the commit for that release.

@Popl7
Copy link
Author

Popl7 commented Jul 28, 2016

using the environment vars and only passing clientType to the init works the same as before.
This is the log out it generates:

Navigated to http://localhost:5555/spark.html
2016-07-28 20:38:17.934 spark.html:37 xxxxxxxxxxx starting spark xxxxxxxxxxx
2016-07-28 20:38:17.938 spark.html:46 loading cached credentials
2016-07-28 20:38:17.938 spark.html:82 initializing spark
2016-07-28 20:38:17.949 spark.html:60 initializing listeners
2016-07-28 20:38:17.950 spark.html:63 change:device: {"services":{},"features":{"developer":[],"entitlement":[],"user":[]}}
2016-07-28 20:38:17.951 spark.html:68 change:credentials: {}
2016-07-28 20:38:17.952 spark.html:73 change:isAuthenticated: false
2016-07-28 20:38:17.952 spark.html:77 change:isAuthenticating: undefined
2016-07-28 20:38:17.953 spark.html:102 starting authentication
2016-07-28 20:38:17.953 spark.html:114 => NOT authenticated
2016-07-28 20:38:17.953 spark.html:42 xxxxxxxxxxx done starting spark xxxxxxxxxxx
2016-07-28 20:38:20.605 spark.js:36812 credentials(shim): authenticating
2016-07-28 20:38:20.606 spark.js:36961 credentials(shim): generating csrf token
2016-07-28 20:38:20.608 spark.html:77 change:isAuthenticating: true
2016-07-28 20:38:20.608 spark.html:68 change:credentials: {}
2016-07-28 20:38:20.609 spark.js:36877 credentials(shim): initiating authorization code grant flow
2016-07-28 20:38:21.187 Navigated to https://idbroker.webex.com/idb/oauth2/oauth2Consent.jsp?clientID=C8da597e01…520spark%253Ateams_write%2520spark%253Amemberships_write%26service%3Dspark
2016-07-28 20:38:23.031 Navigated to http://localhost:5555/spark.html?code=OTY3ZjdhMjUtZmM5MS00YmRhLWJkYmYtMmRlN…MzI5&state=Y3NyZl90b2tlbj1hMDQ4NzVhZi0yZTczLTRmNGYtYTgxZC03NzdkZDU1MTM1ZGQ
2016-07-28 20:38:23.503 spark.html?code=OTY3ZjdhMjUtZmM5MS00YmRhLWJkYmYtMmRlNzZiNWIwZTdkNzJmNzE5Y2UtMzI5&state=Y3NyZl90b2tl…:37 xxxxxxxxxxx starting spark xxxxxxxxxxx
2016-07-28 20:38:23.507 spark.html?code=OTY3ZjdhMjUtZmM5MS00YmRhLWJkYmYtMmRlNzZiNWIwZTdkNzJmNzE5Y2UtMzI5&state=Y3NyZl90b2tl…:46 loading cached credentials
2016-07-28 20:38:23.507 spark.html?code=OTY3ZjdhMjUtZmM5MS00YmRhLWJkYmYtMmRlNzZiNWIwZTdkNzJmNzE5Y2UtMzI5&state=Y3NyZl90b2tl…:82 initializing spark
2016-07-28 20:38:23.515 spark.html?code=OTY3ZjdhMjUtZmM5MS00YmRhLWJkYmYtMmRlNzZiNWIwZTdkNzJmNzE5Y2UtMzI5&state=Y3NyZl90b2tl…:60 initializing listeners
2016-07-28 20:38:23.516 spark.html?code=OTY3ZjdhMjUtZmM5MS00YmRhLWJkYmYtMmRlNzZiNWIwZTdkNzJmNzE5Y2UtMzI5&state=Y3NyZl90b2tl…:63 change:device: {"services":{},"features":{"developer":[],"entitlement":[],"user":[]}}
2016-07-28 20:38:23.517 spark.html?code=OTY3ZjdhMjUtZmM5MS00YmRhLWJkYmYtMmRlNzZiNWIwZTdkNzJmNzE5Y2UtMzI5&state=Y3NyZl90b2tl…:68 change:credentials: {}
2016-07-28 20:38:23.518 spark.html?code=OTY3ZjdhMjUtZmM5MS00YmRhLWJkYmYtMmRlNzZiNWIwZTdkNzJmNzE5Y2UtMzI5&state=Y3NyZl90b2tl…:73 change:isAuthenticated: false
2016-07-28 20:38:23.518 spark.html?code=OTY3ZjdhMjUtZmM5MS00YmRhLWJkYmYtMmRlNzZiNWIwZTdkNzJmNzE5Y2UtMzI5&state=Y3NyZl90b2tl…:77 change:isAuthenticating: undefined
2016-07-28 20:38:23.518 spark.html?code=OTY3ZjdhMjUtZmM5MS00YmRhLWJkYmYtMmRlNzZiNWIwZTdkNzJmNzE5Y2UtMzI5&state=Y3NyZl90b2tl…:102 starting authentication
2016-07-28 20:38:23.518 spark.html?code=OTY3ZjdhMjUtZmM5MS00YmRhLWJkYmYtMmRlNzZiNWIwZTdkNzJmNzE5Y2UtMzI5&state=Y3NyZl90b2tl…:114 => NOT authenticated
2016-07-28 20:38:23.519 spark.html?code=OTY3ZjdhMjUtZmM5MS00YmRhLWJkYmYtMmRlNzZiNWIwZTdkNzJmNzE5Y2UtMzI5&state=Y3NyZl90b2tl…:42 xxxxxxxxxxx done starting spark xxxxxxxxxxx
2016-07-28 20:38:23.573 spark.js:36988 credentials(shim): updating browser location http://localhost:5555/spark.html
2016-07-28 20:38:23.574 spark.js:36812 credentials(shim): authenticating
2016-07-28 20:38:23.575 spark.js:36342 credentials: auth code received, exchanging for access_token
2016-07-28 20:38:23.576 spark.js:36464 credentials: requesting authorization code grant
2016-07-28 20:38:24.692 spark.js:36710 credentials: received authorization

@Popl7
Copy link
Author

Popl7 commented Jul 28, 2016

I know in step: 'requesting authorization code grant' the POST gets done, but after that the token is not handled.

@Popl7
Copy link
Author

Popl7 commented Jul 28, 2016

ah, ok. I couldn't get the npm package build, but I have checked the version c49ca68 out and I will try this.

@Popl7
Copy link
Author

Popl7 commented Jul 28, 2016

This gives the same result. After I get the code this is the output:

spark.js:36988 credentials(shim): updating browser location http://localhost:5555/spark.html
2016-07-28 20:53:26.092 spark.js:36812 credentials(shim): authenticating
2016-07-28 20:53:26.093 spark.js:36342 credentials: auth code received, exchanging for access_token
2016-07-28 20:53:26.094 spark.js:36464 credentials: requesting authorization code grant
2016-07-28 20:53:27.710 idbroker.webex.com/idb/oauth2/v1/access_token:1 POST https://idbroker.webex.com/idb/oauth2/v1/access_token 400 (Bad Request)
2016-07-28 20:53:27.716 spark.js:14360 Uncaught (in promise) SubType {error: "invalid_client", errorDescription: "Invalid client", errorUri: undefined, res: Object, name: "InvalidClientError"…}SubType @ spark.js:14360(anonymous function) @ spark.js:36493

@ianwremmel
Copy link
Contributor

ok. i have a guess: ciscospark is an initialized instance of the sdk; ciscospark.init creates a second instance. I'm pretty sure that the first instance is grabbing the token from the address bar but the second instance is the one that has the event handlers wired up.

try this:

function initSpark() {
  console.log('initializing spark');
  Object.assign(ciscospark.config.credentials.oauth, {
    client_id: client_id,
    client_secret: client_secret,
    scope: scope,
    redirect_uri: redirect_uri
  });  
  return ciscospark;
}

I'm going to have to think about a proper solution a bit more, but I'm completely aware this area needs some cleanup.

@Popl7
Copy link
Author

Popl7 commented Jul 28, 2016

Ok, this sounds plausible.
I will try it tomorrow morning and let you know.

Op 28 jul. 2016 om 21:38 heeft Ian Remmel notifications@github.com het volgende geschreven:

ok. i have a guess: ciscospark is an initialized instance of the sdk; ciscospark.init creates a second instance. I'm pretty sure that the first instance is grabbing the token from the address bar but the second instance is the one that has the event handlers wired up.

try this:

function initSpark() {
console.log('initializing spark');
Object.assign(ciscospark.config.credentials.oauth, {
client_id: client_id,
client_secret: client_secret,
scope: scope,
redirect_uri: redirect_uri
});
return ciscospark;
}
I'm going to have to think about a proper solution a bit more, but I'm completely aware this area needs some cleanup.


You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub, or mute the thread.

@Popl7
Copy link
Author

Popl7 commented Jul 29, 2016

this seems to work! :-) the only thing I am missing is the loading of the credentials. How do I pass the credentials and device in the initSpark function?
I tried: Object.assign(ciscospark.credentials, credentials);
but this doesn't work.
The credentials variable gets filled from the localstorage where the authorization is saved.

@Popl7
Copy link
Author

Popl7 commented Jul 29, 2016

I managed to get the credentials working.
Thx for the help. I will be able to get going with my app now.

@ianwremmel
Copy link
Contributor

@Popl7 glad you got it figured out! I've opened issues for the (what i believe to be) all of the causes of the confusion.

saurjai3 referenced this issue in saurjai3/spark-js-sdk Mar 28, 2017
poke into the right part of the user object
spark-js-sdk-automation pushed a commit that referenced this issue Jun 27, 2019
Merging latest master
srinijay98 pushed a commit to srinijay98/webex-js-sdk that referenced this issue Oct 6, 2022
# This is the 1st commit message:

fix: voicea bugs

# This is the commit message webex#2:

fix(voicea): timestamp

# This is the commit message webex#3:

refactor: voicea

# This is the commit message webex#4:

refactor: voicea

# This is the commit message webex#5:

refactor: voicea
sreenara pushed a commit that referenced this issue Apr 18, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants