I ran into this issue just recently when I wanted to test my app with multiple live ids. I have an Azure Mobile Service that I use the live id with. Basically I remember being asked for whether the app can use my credentials or not at least once. Now the LiveAuthClient CanLogout variable is always false so I can't log my account out in order to sign in with another account.
I found some reference saying that I would need to remove some single sign on stuff by hand, but I could only find one thing in Credential Manager that was seemingly similar and removing it (MicrosoftAccount:sth) had no effect. Here's the relevant piece of my code:
LiveAuthClient liveIdClient = new LiveAuthClient("myserviceredirecturi");
LiveLoginResult liveAuthResult = await liveIdClient.InitializeAsync(new[] { "wl.basic" });
if (liveIdClient.CanLogout)
liveIdClient.Logout(); // Code never goes here, ever.
LiveLoginResult liveLoginResult = await liveIdClient.LoginAsync(new[] { "wl.basic" });
The last line logs me in with the current windows 8 live id. How can I test with multiple live ids?
Related
I'm trying to have clients publish a A/V stream, turn them off, and then turn them back on. The first time I tell them to publish and then unpublish, it works fine. However, the next time I tell them to publish (Using the same session ID and token), I get the error "Cannot Connect, the session is already undefined".
Why is the "session" getting destroyed?.. is it the unpublish? My code is pretty much taken from the tutorials:
clientSession = OT.initSession(apiKey, sessionId);
clientSession.connect(token, function (error) {
if (error) {
handleError(error);
} else {
clientPublisher = OT.initPublisher(container, {
insertMode: 'append',
width: '100%',
height: '100%'
}, handleError);
}
});
}
To unpublish:
clientSession.unpublish(clientPublisher);
There are 2 ways you could do this. You could initialise a single publisher object once and keep reusing it everytime you republish. Or you could keep destroying and reinitialising a new publisher each time. I've written up an example of both approaches for you:
Reuse same publisher: https://jsbin.com/tobabos/edit?html
Create new publisher each time: https://jsbin.com/jawuxez/edit?html
Note: Please provide your own API key, session ID and token to run the above JSbins
The key difference is that to reuse a publisher you need to do this:
pub.on('streamDestroyed', e => e.preventDefault());
This is documented here: https://tokbox.com/developer/sdks/js/reference/Publisher.html#.event:streamDestroyed
It makes sure that when you unpublish, the publisher object is not destroyed so it can be reused.
What also happens is if you reuse a publisher, the publisher remains on the page and the user can still see themselves. Even if the publisher is not streaming to the session. You could use CSS or DOM manipulation to hide the publisher, but the webcam light will remain on.
However, if you destroy and recreate the publisher each time, the publisher disappears from the page and the webcam light turns off while unpublished. Depending on the browser and the user's settings, they may be asked to permit access to their webcam again.
We are starting to use Epicor 10 and we are wanting to leverage the DLLs/Services to talk to Epicor. That way we can add/update info from a custom app. So far things are going fine but we ran into an issue when we wanted to, lets say, add a job for a specific plant. It seems to always want to save to the plant the user last logged into via the client app.
So for example -- Lets say the user's last plant was plant "A". I want my custom app to log into Epicor (creating a session) and create a job for plant "B". I can add the job fine, but it will put it under plant "A" and not "B", even though I logged into plant "B" when I created the session.
We are calling SetPlant and passing in the right plant we want, but Epicor seems to always override what plant to save it as. Has anyone else run into this case? We are also having this issue with the Company. SetCompany doesnt seem to work at all.
More info: - We are using the net.tcp:///ERP/ICE/Lib/SessionMod.svc service. - We can login fine with Login() and get a SessionId back - Even calling GetValues() on the Session object says we are logged into plant "B" even though Epicor will still use plant "A".
The only work around we can come up with, which we do not want to do, is to have an app user by company and by plant so we can guarantee which company and plant the data gets saved to. This will work but it isnt ideal.
Anyone have any suggestions on how to get the system to take the new Company or Plant?
As user463132 points out, you can wrap your service connection with the temporary session context:
using (CallContext.Current.TemporarySessionCreator.SetCompanyID("YourCompanyHere").SetPlantID("B").Create())
{
}
Haso Keric Article Reference
I'll also add that if you are using the UI adapters, you can simply grab the session from the oTrans object instance and set the properties here which governs how oTrans interacts with your data.
Ice.Core.Session s1 = (Ice.Core.Session)this.oTrans.Session;
s1.CompanyID = "YourCompanyHere";
s1.PlantID = "B";
The plantID can be updated in the session using the SetPlant() method. It must be called after the SetCompany():
sessionModImpl = NetTcp_Helper.ClassAttributHelper.CreateBusObj<SessionModImpl>(Guid.Empty, SessionModImpl.UriPath, Settings);
sessionId = sessionModImpl.Login();
sessionModImpl.SessionID = sessionId;
sessionModImpl.SetCompany(epicorCompanyID, out companyName, out plantID, out plantName, out workstationID, out workstationDescription, out employeeID,
out countryGroupCode, out countryCode, out tenantID);
sessionModImpl.SetPlant(newSiteID, out plantName);
The first thing to understand is that a Server Session is not a single
instance but rather a .NET Stack of Session Instances. The
‘CallContext.Current.Session’ variable is just a pointer to the top of
the Stack. In most cases, there is just a single Session instance in
the CallContext stack. But when you need to iterate over Companies to
process something the Session Stack get pushed and popped around.
That’s where ‘TemporarySessions’ comes in.
Read about it at:
https://www.linkedin.com/pulse/snippet-epicor-change-companyplantuser-bpm-haso-keric/
We have a website that can be viwed from a kiosk in a shop.
When the inactivity is above 2 minutes, the site returns to the home.
Anyone knows how to refresh the session when this appens?
It could also serve make a refresh of the user id, but I don't know how it works.
I'm going to assume you are talking about Adobe Analytics javascript library and not the Android/iOS SDK, based on your tagging and lack of mention of it. If your kiosk is in fact using Android or iOS SDK, then please comment and I can update with instructions for that.
Adobe Analytics javascript library does not currently offer a direct method to force refresh an Adobe Analytics session/userID. However, you can effectively do it by explicitly setting s.visitorID yourself, which will override the default generated by the library.
So, when you want to start a new session, you can pop s.visitorID with for example the current timestamp:
s.visitorID = (new Date()).getTime().toString();
Or maybe you already have a "session" id you generate that you can use, instead.
Note: with this method, you must set s.visitorID (with the same value) for every hit for the duration of your session. So in practice, you would really do something more along the lines of generate the new value at start of session, put the value in a cookie, and put s.visitorID in s_doPlugin but it reads the cookie value.
Note: This will effectively make your visits and visitors metrics the same. Which is to be expected with a publicly shared device, but just mentioning it in case it comes up later.
pseudocode:
function startNewSession() {
// use whatever cookie writing utility you have to
// set a cookie named visitorID set to the generated
// value. In practice, the expiration doesn't really
// matter as long as it's something longer than
// your average session. Just setting it to default
// session expiration should be okay
var visitorID = (new Date()).getTime().toString();
setCookie('visitorID',visitorID);
}
// in your existing logic that times out returning
// home after 2 minutes of inactivity, call the function
// to generate a new id
startNewSession();
// this is AA's s_doPlugins callback function. This may look
// slightly different, maybe defined as s_doPlugins and then assigned
// to s.doPlugins, depending on what AA lib version you are using.
// This is AA's callback function that gets called whenever
// an s.t or s.tl call is made
s.usePlugins=true;
s.doPlugins=function(s) {
// make sure visitorID variable is addedto linkTrackVars
// so it gets 'registered' for s.tl calls.
s.linkTrackVars='visitorID';
// explicitly set the visitorID with the cookie, using
// whatever cookie reading utility you have.
s.visitorID=readCookie('visitorID');
}
I have been trying for some time solve a scheduling problem for an App that I used to work at. This problem is as follows...
Example Scenario:
ContactA is running Our App in the background. He just got into his car for his commute home. So, he is in #Evening Commute status.
His Valet settings state that he only wants to be notified to make Phone Calls when in #Evening Commute status (no text or email reminders).
Once Our app sees ContactA is in #Evening Commute status, and that he is available to make Phone Calls, the app will scan ALL his contacts to find any contacts that he has specified as preferred to Call.
Th algorithm identifies 3 potential matches for ContactA in his Agent list:
ContactX
ContactY
ContactZ
How does it decide which one to prompt ContactA to connect with during his #Evening Commute?
First, it should look to see if any of those three are using The app too. For example, it identifies that ContactX and ContactY are both using The app, but ContactZ is not.
So, it will then look further at ContactX and ContactY to see if either of them are currently in a Valet status that is accepting Phone Calls.
If both are, it will look to see if either is a Favorite. If so, that person takes priority.
If neither are, it can look back at history to see which is the oldest in terms of last contacted to choose which one to contact first.
If both ContactX and ContactY are showing as “unavailable” right now, based on their App Valet settings, the app could choose to prompt me to call ContactZ.
Thanks in advance
Pseudocode (you did not ask for any specific language, but this is a simple implementation of your algorithm in code). contactsSpecified would be an array of all contacts "specified as preferred to Call".
var contactsToCall[];
//Add all contacts that are using the app and are available
foreach(contact in contactsSepcified) {
if(contact.isUsingApp() && contact.isAvailable()) {
contactsToCall.add(contact);
}
}
//Add all contacts not using the app if none of the app users have been added
if(contactsToCall.size() == 0) {
foreach(contact in contactsSepcified) {
if(!contact.isUsingApp()) {
contactsToCall.add(contact);
}
}
}
foreach(contact in conctactsToCall) {
if(conctact.isFavorite()) {
call(contact);
return;
}
}
suggestContacts(contactsToCall);
We just upgraded our Heroku postgres database using the follower changeover method. We have over 50 dataclips attached to the old database, and now we need to move them over to the new database. However, doing them one by one will take a lot of time.
Is there a programatic way to update the database a dataclip is attached to, perhaps with the CLI tools?
At least once the old database has been deprovisioned, you can now (as of March 2016) reattach them to another database:
Go to https://dataclips.heroku.com/clips/recoverable. It will display your old database and a set of 'orphaned' dataclips and you can choose to transfer them to another database (in my case the promoted follower from the changeover).
Note that this only affects the dataclips that you created, it does not affect the dataclips one of your team members created and that you only had access to. So they will have to go through this process as well.
Official devcenter article: https://devcenter.heroku.com/articles/dataclips#dataclip-recovery
Thanks to Heroku CSRF measures, programmatically updating data clips is much more difficult than you might expect. You'll need to suck it up and start clicking buttons by hand, or beg their support team to do it for you, which is just as difficult.
There is no official support for programmatically moving the dataclips. That being said, you can script it out against their HTTP API.
The base URL is https://dataclips.heroku.com/api/v1/. There are three relevant endpoints:
clips /clips
resources (databases) /heroku_resources
move clip /clips/:slug/move
Find the slug of the clip you want to move, find the resource id of the new database, and make a post to the move clip endpoint:
POST /api/v1/clips/fjhwieufysdufnjqqueyuiewsr/move
Content-Type: application/json
{"heroku_resource_id":"resource123456789#heroku.com"}
I had over 300 dataclips to move. I used the following technique to update them all (essentially reverse engineering the dataclips API).
Open Chrome with Web Developer tools, Network tab.
Log into Heroku Dataclips
Observe the network call which returns all the dataclips, in JSON (https://dataclips.heroku.com/api/v1/clips). Take this response and extract out all dataclip slugs.
Update the database for one dataclip. Observe the network call which does this (https://dataclips.heroku.com/api/v1/clips/:slug/move). Right click, Copy as cURL. This is the easiest way to get all the correct parameters, since the API uses cookies for authentication.
Write a script that loops through each dataclip slug, and shells out to curl. In Ruby, this looks like:
slugs = <paste ids here>.split("\n")
slugs.each do |slug|
command = %Q(curl -v 'https://dataclips.heroku.com/api/v1/clips/#{slug}/move' -H 'Cookie: ...' --data '{"heroku_resource_id":"resource1234567#heroku.com"}')
puts command
system(command)
end
You can contact Heroku support, and they will bulk transfer the dataclips to your new database for you.
Batch working on dataclips
I've finally found a solution to work on my Dataclips as a batch using the javascript console and some scraping technique. I needed it to retrieve every dataclips. But it guess It can be updated as such:
// Go to the dataclip listing (https://data.heroku.com/dataclips).
// Then execute this script in your console.
// Be careful, this will focus a new window every 4 seconds, preventing
// you from working 4 seconds times the number of dataclips you have.
// Retrieve urls and titles
let dataclips = Array.
from(document.querySelectorAll('.rt-td:first-child a')).
map(el => ({ url: el.href, title: el.innerText }))
/**
* Allows waiting for a given timeout before execution.
* #param {number} seconds
*/
const timeout = function(seconds) {
return new Promise(resolve => {
setTimeout(() => {
resolve()
}, seconds);
})
}
/**
* Here are all the changes you want to apply to every single
* dataclip.
* #param {object} window
*/
const applyChanges = function(window) {
}
// With a fast connection, 4 seconds is OK. Dial it down if you
// have errors.
const expectedLoadTime = 4000 // ms
// This is the main loop, windows are opened one by one to ensure focus and a
// correct loading time.
for (const dataclip of dataclips) {
// This opens another window from the script, having access to its DOM.
// See https://github.com/buonomo/kazoo for a funnier example usage!
// And don't be shy to star and share :D
const externWindow = window.open(dataclip.url)
// A hack to wait for loading, this could be improved for sure.
await timeout(expectedLoadTime)
applyChanges(externWindow)
externWindow.close()
}
You'd still have to implement applyChanges yourself which I conceed is a bit tedious and I don't have time to do it know (if one does, please share!). But at least it can be done on all of your dataclips in a single function.
For an example usage of this script, you can take a look at the gist I made to scrape every dataclips and related errors.