How can I tell if a user is logged in using straight SQL based on their email address?
We have a system that is highly coupled with ExpressionEngine and cannot use the Magento API in many of the EE templates.
Edit to show current login code:
Mage::getSingleton('core/session', array('name'=>'frontend'));
$session = Mage::getSingleton('customer/session');
$session->login($ParticipantInfo['PreferedEmailAddress'],'default_password');
$session->setCustomerAsLoggedIn($session->getCustomer());
TL;DR: As far as i know, even if session data is stored in the db, there is no definite way of telling only via plain SQL.
Question would also be: Which user? Customer, admin or api user? Assuming you store session data within the file system, I could think of some options:
API
For API-Users, have a look at the api_session table, you can do a join with the api_user table, which stores the email address. However, there is no way, the information in these two tables will suffice, as only session id and logdate are saved for a specific user id and you have no way of telling if a session is still active.
Querying for this data those would probably be something along the lines of:
SELECT *
FROM api_user
INNER JOIN api_session ON api_user.user_id = api_session.user_id
WHERE api_user.email = "<known_email>"
Admin & Customer
Admin users are stored within admin_user, however, like for api_user, no information is stored along for session management.
Customers are stored within the customer_* tables. You can look them up in the log_visitortable:
SELECT *
FROM log_visitor_online
INNER JOIN customer_entity ON customer_entity.entity_id = log_visitor_online.customer_id
WHERE c.email = "<known_email>"
Again, no information can be retrieved, if the session is still valid. EDIT: Tim showed how to do it correctly in his answer.
The bad news, in general
No information is stored directly, if a user is logged in currently, only, when the creation date of the session. With out-of-the box functionality you should not be able to tell accurately via SQL if a user is currently logged in or not - this would be insensible at best, as magento checks the user's session's validity against the stored session data in the db/filesystem, so without the user's session data, you can determine nothing with 100% accuracy.
The good news if you can write a module
With a little bit of work you can hook into the session management of Magento. There's a cheat sheet for events the core ships with. You can also create you own custom events, which you may listen to and execute code upon.
The idea here would be to write a module which could store extra information on the customer (admin or api user vice versa) or within an extra module table. You can hook into the login process and set a timestamp for the api_user/customer/admin has logged in and refresh that timestamp upon a request. If a user's timestamp hasn't been refreshed for, let's say, X Seconds, you assume the user is logged in any more. You delete the user's timestamp upon the logout event.
However, this is also not 100% accurate and it heavily depends on what a user does in you system.
Anyway, I hope I could provide some insight.
lg,
flo
Related
So for the login, since it doesn't really make anything new in the database but rather just returns if we've logged in, and possibly some user data, should it be a command or query?
And as for the register, since it creates a new user, should it be a command then? What if i want to return the users data or a jwt?
Should i run my commands and once the client receives a response run a query right after them?
As with most design related questions, I’d answer this one with ‘it depends’. I have seen both solutions implemented in different situations.
The main question you’d need to ask is whether you consider a user logging in as a state change of the system or not. Note that whether it changes state in de database isn’t relevant. The system is more than the database.
Log in as a command
For some systems, it’s important to know which users had been logged in and when, from where, etc. One example I had seen was a medical system that needed to record which doctor logged in when and where, and which medical records had been accessed. Also, logging in on one machine would stop tbe session on another. A reliable trace of these actions was essential to the application. As such, log in was implemented as a command which generated events that were stored in the Event Store. Projections kept the current logged in state for each user.
Log in as a query
Most systems I have seen, however, simple beed to know whether any given credentials can ve mapped to a user account. If that is the case, a token is generated containing the ‘proof’ of authentication. The system itself doesn’t really care who is logged in. It’s just that each request needs to be validated by checking the ‘proof’. In this case, logging in is a query.
With a surge of applications that can be used to pull information, my sql server is constantly getting tapped, and there are a couple of users that keeps running refresh. Is there a way to reject query based on specific client_app_name and nt_username?
Alternatively, is there a way to add the combination of the user and the app to security to decline access to SQL? i.e. Approve the user access if client_appname is excel but decline if the appname is 'Mashup Engine'.
What you really need is resource governance. With it you can restrict the resources a user can consume. This way the users can refresh as much as they like, but they won't be able to consume the server resources, their queries will instead slow down as they are exhausting the allowed resources. Other users will still be able to run queries at full speed.
The assignment of users to resource groups ('pools') is based on a classification function run at login time, and this function can consider user name, application name, workstation name, client IP etc.
Alright here is the situation.
I have been tasked at my work to integrate a coldfusion forum (Galleon) into the existing CRM that are using for the merchants.
The issue is, the original CRM itself has its own login and a 'user' table in the database. Galleon uses its own login page and 'user' file..
My partner and I on this are racking our brains trying to figure out this (admittedly simple) problem. We thought about the possibility of defining a global variable, like a session, and once triggered by the primary login for the CRM it would bypass the Galleon login.
But this doesn't solve the problem of telling Galleon who the user is so he can post..
I'm thinking one of the ways to solve this issue is to insert the entirety of the original CRM user file into the Galleon user file. That way it has a list of identical user\passes.
Any ideas guys?
Breakdown:
User logins in at CRM splash page----->Brought to CRM index.cfm\main panel. User can then click on "CRM FORUM!" and instead of being re prompted for a user\pass Galleon knows who he is and allows him to make threads and post.
There are definitely a number of ways to skin the cat on this. I downloaded the Galleon 2 forum code to take a peek at the user.cfc
You could modify the query in this function to pull the fields it requires from your CMS:
<cffunction name="getUser" access="public" returnType="struct" output="false" hint="Returns a user.">
<cfquery name="qGetUser" datasource="#variables.dsn#">
SELECT
[cmsusertable].cmsid as ID,
[cmsusertable].cmsuser as username,
[cmsusertable].cmspassword as password,
[cmsusertable].cmsemail as emailaddress,
[cmsusertable].createDate as datecreated,
[cmsusertable].cmsactive as confirmed,
[cmsusertable].cmssignature as signature,
[cmsusertable].cmsavatar as avatar
FROM
[cmsusertable]users
WHERE
[cmsusertable].username = <cfqueryparam value="#arguments.username#" cfsqltype="CF_SQL_VARCHAR" maxlength="50">
</cfquery>
Remember that you must return the fields from the query as Galleon expects them, so use the 'as' statement to rename your CMS database fields to what Galleon expects. Now some of these extraneous fields you might not have in your CMS table such as Signature / Avatar. If you can extend your CMS table and user routines to accommodate these fields, that might be good. Or you could modify the profile routines in Galleon to only update the Signature/Avatar instead of the whole profile. If you do use the Galleon tables to store this information, remember to add a join to include these fields where requested to reunify the user data.
You'll also have to modify the joins in about 4 files (user.cfc, conference.cfc, message.cfc, thread.cfc) in the project to join with your CMS user table instead.
Lastly, you'll have to modify the the login.cfm to simply attempt to set the session.user struct using the information in the CMS user session and failing that, redirect the user back to the CMS login page.
Overall I don't think it would be too difficult. I'm sure there's stuff I missed but perhaps that would get you going.
What you described is exactly how many sites work, regardless of the mechanism you use to authenticate (i.e.; OAuth, Twitter, etc.) You use the external service for authentication, and you get back a token of some kind from that external service that says "This person really is authenticated." It's up to your code -- Galleon in this case -- to say "This person is authenticated, but they don't have an account in our system. Let's make one." This usually requires you to go back to the external service to get a name, email address, etc.
You will most likely have to do some additional work in your external service to allow for updates of customer information in Galleon. If, for example, someone changes their email address, there's more than likely an email address in Galleon which should also be updated. This can get complicated, but is a necessity from the customer's point of view.
The best way to do this would be to sync up your Galleon forum user table with your CRM, then keep them in sync as you add/remove/update CRM users.
The key to doing this is by utilizing the Galleon business layer API-- a.k.a. the public methods in the Galleon CFCs. This will keep you from having to modify ANY of Galleon's code, which I would highly recommend if you'd like to easily install Galleon updates. (By the way, you should keep your 3rd party codebase up to date, since open source projects are popular targets for hackers-- especially forums.)
To sync up your existing users, you'll want to write a script that iterates through your current CRM's users and calls Galleon's User.addUser() method for each user, using the same user/pass combo as your CRM (or maybe use hashes of them). Be sure to break on any Galleon errors/failures so you don't miss any users.
To keep Galleon in sync with your CRM, add calls to Galleon's CFCs as needed. For instance, call User.deleteUser() when you delete a user from your CRM.
For authentication, you'll use User.authenticate(), passing in the same user/pass combo as your CRM.
Utilizing the business-layer API of 3rd-party libraries is a much better long-term solution than trying to modify them to suit your needs.
There is a database of all users in a network, I need to write a query where in when the user logs in. All the user id's should be displayed in page except his.
Lex's comment is valid. I will tell you what you'd need if this were an asp.net question: the general principle may help you.
'When the user logs in' means you have some system where people log in, and, presumably, you can detect this event - like in an asp.net login page.
You then want to show something: this means you probably have the flexibility (in your design / coding) to show it. Say: an asp.net page.
In that case, you can, when the page loads (page_load), get the user id for that user (using membership routines if asp.net) and then use that userid as a parameter
That parameter would be 'currentID' in Gaby's example, for instance.
I could give more detail, but given the general nature of your question, that might be wasted effort at this time.
If you want to select all users except the current one, you could use something like
SELECT id FROM members WHERE id <> currentID
In our system one client may have multiple operators. However there is a "wish" from client.
One company has an account, however there can be mulitple operators assigned to this company. Client wants us to prepare a solution that only one operator from company can log in to the system at same time. How can I achieve this?
Just by making sure they system has the ability to validate the login on each request. Either
Actively (by querying state -- possibly a database to compare some secrets) or
Passively -- using some form of cryptography and tokens (possibly in the cookie).
Option one is easiest, option 2 is fastest. If you validate on each request you can make sure that only one user remains logged in -- if another user signs in you can invalidate the existing active login -- perhaps with a cooldown period of n amount minutes.
You have to develop some form of login scheme -- kerberos is the defacto scheme -- read this easy to follow tutorial on kerberos Designing an Authentication System: a Dialogue in Four Scenes It should show you what you really need to do.
You could use a database field to flag that they are logged in. Update the field to 'logged in' when they do so, and then update it to 'logged out' when they log out.
You'd also need to monitor login sessions for expiry to update the field if a user never bothered to explicitly logout.
The best approach I've used:
Create a table used to track whether an operator is logged in (e.g. userid and last_accessed_dt)
On each page request by the operator update the last requested date/time
When an operator attempts to login they can only do so if the last requested data/time > timeout period of sessions on your website (E.g. 30 minutes) or if they are the Last Operator User ID ... this way they can quickly recover from a logoff etc.
When an operator logs off have the Last Accessed cleared
When the session times out have the Last Accessed cleared
"I am using WPF application and the server is written in WCF, however this can be achieved. But what in situation when user has an application opened and was inactive for 30min?"
This system is going to be single-user, so I suggest you start a counter thread when a user logs in. When counter reaches 30 minutes, write a value to the db indicating that user has timed out and other users are free to login. Obviously, you should do the same thing when user explicitly logs out.