Delete a session without the client

There is nothing wrong with that. On every hit there may be dozens and even way more DB hits (depending on the applications complexity of your app) for a full page request. You may use a cache if you want to not have always a query. Using the application scope isnt the right place fore that. If you have a static list you may set the IDs into a component where you save the values. But a DB table is where you handle all of this.

Yeah, fair enough actually.

This just seems like a ā€œflinging shit at the wallā€ sort of solution, if Iā€™m to be frank; rather than a well-designed solution.

Andreas is on to something here:

OK, so have a UserService (and this is persisted in the application scope) which one talks to when servicing actions like user record updates.

When thereā€™s a ā€œdisable userā€ event (ie: someoneā€™s updated a user info form and deselected the ā€œactiveā€ value), then send a message to a RecentlyDisabledUsersManager (this could just be a method in the UserService which maintains an array of user IDs), which appends to that array.

When there is user activity - an incoming request from a user - call the UserService and tell it to go check with the RecentlyDisabledUsersManager. Itā€™ll respond telling the UserService ā€œyeah theyā€™re a no-goā€, and the UserService a) invalidates that session and b) passes that back to the controller method, and the controller method responds with a 403. Or maybe itā€™s the controllerā€™s job to invalidate the session, given itā€™s perhaps more a request/response-layer sort of thing?


Thinking about it some more, I donā€™t think you need to do any further persistence of that array, provided the application timeout is longer than the session timeout. Also provided that when the application restarts, sessions also restart. This is dependent on your session storage, and you will need to test this.

Also I donā€™t think you need some sort of GC on that array - ie: remove entries that have been ā€œdealt withā€. As you say, the same user might have a session on multiple client agents, so itā€™s not like itā€™s a one-and-done when locking them out. Also itā€™s not much data - some IDs - and I donā€™t think one will be deactivating so many users one needs to worry about it getting too big. Something to deal with if it ever becomes a problem, I guess.

1 Like

You are right, this is not something that Iā€™ll be doing on a regular basis, quite the opposite, but if an account is disabled itā€™s likely I want them out right away.

Unfortunately my skill set is such that I donā€™t understand what the userservice is doing and how that works. On the surface it sounds like a similar way to what I was thinking with a list that it just checks each time for the user ID, but I suspect I am just not getting it.

You oughtnā€™t be going ā€œdonā€™t currently understand, so not doing thatā€, you ought to be going ā€œrightā€¦ wellā€¦ I need to lift my gameā€.

Look around the room you are in. Do you just have stacks of books, piles of plates, random sheets of paper around the place? An area marked out with string with a sign ā€œcoffee cups in hereā€? Or have you got bookshelves, cupboards, separate rooms, etc? A place for everything, and everything in its place (to a degree, at least). I mean of course you have your meatspace considerations organised. Why is it - apparently - OK to not do the same in oneā€™s professional work? This is not aimed solely at you, @aspirenet ā€¦ itā€™s something I marvel about with really a lot of CFML devs I encounter.

A ā€œUserServiceā€ is just a file called UserService.cfc where one organises user-oriented functionality into.

A RecentlyDisabledUsersManager like I said could just be a method in that CFC, backed with an array.

Minimum level of organisation of oneā€™s code is table stakes for showing up to our jobs each day.


Second thingā€¦ lists are just strings with an acknowledged character delimiters. They are not a collection type, and should not be used for persisting multiple values. Thatā€™s what arrays, structs, objects, etc are for. List functionality should only be used when receiving a string from an external source that needs to be processed as a collection (converting a para of text to an array of words, for example); or - for some reason - coverting a collection type back into a string (emiting a word collection as a comma-delimited list in some text output, for example.

Donā€™t use them internally for storing collections of values.

2 Likes

Hey @AdamCameron a rather feisty reply, I did not say I was not going to do it, I said I didnā€™t understand. I actually would like to understand and improve on my skills :slight_smile:

2 Likes

Obvs communication is a two way street. I read your response - incorrectly it seems as - ā€œdonā€™t understand. Sticking with my approachā€.

Did my clarificationā€¦ ermā€¦ clarify? Happy to work with you to get it sorted if you give it a go.

Another approach you could take when encountering concepts you donā€™t understand isā€¦ look them up. Iā€™m not inventing my own jargon here: the concept of services and application design in general are well trod ground. In that they seem to be concepts that perplex you does - Iā€™m afraid - suggest to me a lack of technical investment on your part.

[from your ā€œbioā€ on these forums]: Never became a guru of CF despite developing in it since version 3 in 1998

This is - IMO - an indictment, not a badge of honour.

Obvs what you do with your time is entirely your call. And you are not even an exception in the CFML community. But equally itā€™s my call to be disheartened by this state of affairs.

1 Like

I donā€™t make any secret that I am no guru, I prefer it to be known, so that others understand there may be advanced concepts that I may not fully understand or need help with.

I use CFML to create my own projects, which may not be technically the very best, but they are adequate enough to get the job done.

Unfortunately as I wear many, many hats, I donā€™t have enough time and in reality I get by and the code serves me well with no issues.

I am interested in your approach, Iā€™m always interested in improving. In-fact I did try making some CFCā€™s after I read your post, but I could not get them working and yes, I did Google search and I even spoke to my friend ChatGPT which is actually pretty good at helping get to a solution.

2 Likes

Fair enough, all good. Your decision etc.

Happy to help with the CFCs. I mean I reckon given I complain about you know knowing themā€¦ I should do my bit to help you with them. Quid pro quo 'nā€™all.

How best to do that? I think it would be A-OK to post a separate thread here saying ā€œtrying to get this bloody CFC working but stuck onā€¦ etcā€?

Whoops I missed a few replies. I am certainly interested in improving on my skillset and that includes CFCā€™s. However I reflected on this particular task and how much time itā€™s taking and how much it will actually be used vs time needed to complete my project! I decided although not the most elegant as it requires a drop of manual maintenance to add a little code to the application.cfm where I maintain a list of user UIDā€™s that I need to block (which wonā€™t happen very often)

So if I want to block user 10000000 itā€™ll be

<CFIF ListFind(ā€œ10000000ā€, #session.aff_uid#)>
<CFSCRIPT>sessionInvalidate();</CFSCRIPT>
<CFLOCATION URL=ā€œ/inactiveaccount.cfmā€ addtoken=ā€œnoā€>
</CFIF>

Replaced < with & lt; to display all code. I must be missing an option in here somewhere to stop this

You can post code without the need for escaping angle brackets by enclosing it in backticks (``).

Example: <cfscript>

Or post an entire code block by either clicking the ā€œPreformatted textā€ icon or via the Ctrl+E keyboard shortcut:

<cfscript>
// example
</cfscript>

You can also delete a post by clicking the three dots then the trash can.

1 Like