Skip to content

Module auth_session_timeout: Pluggability - #887

Merged
lasley merged 13 commits into
OCA:9.0from
jmorgannz:9.0
Sep 6, 2017
Merged

Module auth_session_timeout: Pluggability#887
lasley merged 13 commits into
OCA:9.0from
jmorgannz:9.0

Conversation

@jmorgannz

Copy link
Copy Markdown

  • Refactor to allow other modules to inherit and augment or override the following:
    • Session expiry time (deadline) calculation
    • Ignored URLs
    • Final session expiry (with possibility to late-abort)
  • Re-ordered functionality to remove unnecessary work, as this code is called very often.
  • Do not expire a session if delay gets set to zero (or unset / false)

---------------------------

* Refactor to allow other modules to inherit and augment or override the following:
** Session expiry time (deadline) calculation
** Ignored URLs
** Final session expiry (with possibility to late-abort)
* Re-ordered functionality to remove unnecessary work, as this code is called very often.
* Do not expire a session if delay gets set to zero (or unset / false)
@oca-clabot

Copy link
Copy Markdown

Hey @jmorgannz, thank you for your Pull Request.

It looks like some users haven't signed our Contributor License Agreement, yet.
You can read and sign our full Contributor License Agreement here: http://odoo-community.org/page/website.cla
Here is a list of the users:

Appreciation of efforts,
OCA CLAbot

@jmorgannz

jmorgannz commented Jul 5, 2017

Copy link
Copy Markdown
Author

I'm new at this (contributing); guess I might need to read up on the CLA.
The reason I did this is that I needed to add the ability to exempt certain users from the expiry functionality.

I didn't want to re-implement the entire thing, but the OCA copy was not easily pluggable.
I did this, then made my own module that adds the exempt-by-user functionality.

I am using this in production.

@lasley lasley left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the contribution @jmorgannz!

Information on the CLA is here. Let us know if you have questions.

I added some comments inline after reviewing. Also, it would be nice to see some tests for your added logic - we're dropping in coverage here.

Comment thread auth_session_timeout/__init__.py Outdated
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
# (c) 2015 ACSONE SA/NV, Dhinesh D
# (c) 2015 ACSONE SA/NV, Dhinesh D, Jesse Morgan

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please do not append to others' copyrights. Also, you did not change this file at all, so your claim to copyright on any aspect of it would be invalid.

Regarding the copyright headers & what happened here - we were significantly more lax on what happened with these headers previously. If you look at the history of this file, you'll see that Dhinesh D's copyright is actually invalid here too & I would argue it is invalid for the entire module. That argument isn't something to make for history though, but it's most certainly something to enforce going forwards.

Typically if you're going to claim copyright on a file in the header, you need to have written the whole thing. Otherwise, Git line-by-line attribution is an implicit copyright on things you do actually change.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the heads-up.
I did in fact only change the copyright headers on the files I modified to begin with, but when I was 'polishing it up' to submit as a pull request I went back and added to the other files.

I guess the thought was that the enter module would be subject to copyright rather than each file within it.

No matter, I will change it :)


@tools.ormcache(skiparg=0)
def get_session_parameters(self, db):
def _auth_timeout_get_parameter_delay(self, db):

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is changing the public external facing interface of a module that is already in production, and therefore is against a stable release policy.

Is the rename of this method actually necessary? If so, we'll need to provide a get_session_parameters method to use as an adaptation layer for old code.

@jmorgannz jmorgannz Jul 6, 2017

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was trying to be granular here.
With the new structure in ResUser each param is required in different places, so I split get_session_parameters in two.

Alternatively I could have just called get_session_parameters in all the now required places, using the parameter returned that I need and discarding the other; however I was feeling the need to be frugal given that from what I can see these methods are running in a fairly hot code-path.

The other thing that occurs to me now is that this code now opens more cursors than before.
Technically this new code would open and close a cursor for each parameter read, whereas they were both read in a single cursor before.

Am I barking up the wrong tree here?
Should I be being less frugal and instead trust the ORM layer to mitigate any repeat work ?

@lasley lasley Jul 7, 2017

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I 100% agree with your design choice. The solution here is to basically just create a get_session_parameters method that returns the output of the two new methods in a compatible tuple

EDIT: I'll comment inline about the cursors

finally:
cr.close()
return delay, urls
return urls

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is changing the external facing API. The adapter method would need to return compatibly

self.get_session_parameters.clear_cache(self)
if self.key == DELAY_KEY:
self._auth_timeout_get_parameter_delay.clear_cache(self)
if self.key == IGNORED_PATH_KEY:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

elif

_inherit = 'res.users'

def _check_session_validity(self, db, uid, passwd):
def _auth_timeout_urls_get(self, session, db, uid):

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It could be argued that you are also changing the interfaces here, but they are private so you're somewhat in the clear. I would still recommend an adapter method though- you don't want to be the reason that someone's code breaks in production.


def _check_session_validity(self, db, uid, passwd):
def _auth_timeout_urls_get(self, session, db, uid):
# Pluggable method for calculating ignored urls

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Check out PEP-257, which describes Pythonic docblocks. This is more akin to a C docblock

def _auth_timeout_urls_get(self, session, db, uid):
# Pluggable method for calculating ignored urls
# Defaults to stored config param
param_obj = self.pool['ir.config_parameter']

@lasley lasley Jul 5, 2017

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

self.env - Pool is old API. Please don't use

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FYI, self.env is not defined in these methods.
Was able to use request.env, but I'd rather find out why self.env isn't working.

def _auth_timeout_deadline_calculate(self, session, db, uid):
# Pluggable method for calculating timeout deadline
# Defaults to current time minus delay using delay stored as session param
param_obj = self.pool['ir.config_parameter']

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

self.env

try:
expired = getmtime(path) < deadline
except OSError:
pass

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Never pass silently. Please add a _logger.debug here at minimum

except OSError:
pass
except OSError:
pass

@lasley lasley Jul 5, 2017

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know it's not your code, but you're already here & changing things. Never pass silently - _logger.debug

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

d

@lasley lasley added this to the 9.0 milestone Jul 5, 2017
@jmorgannz

Copy link
Copy Markdown
Author

@lasley Thanks for the input. Will investigate changes required!

def get_session_parameters(self, db):
def _auth_timeout_get_parameter_delay(self, db):
param_model = self.pool['ir.config_parameter']
cr = self.pool.cursor()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds like you're going for a real fix, I ❤️ it and thank you! Let's do like this in both of the cursor areas:

with openerp.registry(self.env.cr.dbname).cursor() as cr:
    ...operations...

This will kill the try/finally.

Now, I do have a question regarding this & forgive if it's basic - I don't know this module. Why are we opening new cursors in these spots?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wasn't sure why this was done originally, so followed the pattern in case it had good reason.

This is all complete conjecture, but:

Seems to me that the ResUser.check method could quite likely be called on requests that are at a stage that have not had their proper environment/context set up yet as part of request buildup/teardown.

I.e. Odoo should check a users validation credentials before opening them an active db cursor, etc.

Since this module hangs off ResUser.check, we get caught in that scenario.

The only scenario we are actually interested in though is (re)checks - we don't need to check for session expiry on the request that is logging a user into the system (but we do)

It would not surprise me if the manual cursor control was added as a workaround by the original developer(s) as they quickly realized that without them users could no longer log in!

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have taken the manual cursors out for now, and everything still appears to work correctly.

In order to use a manual cursor with the newer API, I will have to create a new env instance, from what I can see.

@jmorgannz

Copy link
Copy Markdown
Author

Man, minimum line width of 79 in conjunction with strict line-continuation indent rules presents an interesting challenge.

"""
param_model = self.env['ir.config_parameter']
delay = int(param_model.sudo().get_param(DELAY_KEY, 7200))
urls = param_model.sudo().get_param(IGNORED_PATH_KEY, '').split(',')

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Method no longer using the passed in db for database access

@tools.ormcache('db')
def get_session_parameters(self, db):
param_model = self.pool['ir.config_parameter']
cr = self.pool.cursor()

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

self.pool usage: reasoning listed in separate comment


def _auth_timeout_get_parameter_delay(self):
delay, urls = self.get_session_parameters(self.pool.db_name)
return delay

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

self.pool usage: reasoning listed in separate comment


def _auth_timeout_get_parameter_ignoredurls(self):
delay, urls = self.get_session_parameters(self.pool.db_name)
return urls

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

self.pool usage: reasoning listed in separate comment

"""Pluggable method for calculating ignored urls
Defaults to stored config param
"""
param_model = self.pool['ir.config_parameter']

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

self.pool usage: reasoning listed in separate comment

"""Pluggable method for calculating timeout deadline
Defaults to current time minus delay using delay stored as config param
"""
param_model = self.pool['ir.config_parameter']

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

self.pool usage: reasoning listed in separate comment

return True

def _auth_timeout_request_get(self):
return request

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See separate comment on tests/mocking

return request

def _auth_timeout_session_filename_get(self, sid):
return root.session_store.get_session_filename(sid)

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See separate comment on tests/mocking

return root.session_store.get_session_filename(sid)

def _auth_timeout_utime(self, path, dates=None):
return utime(path, dates)

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See separate comment on tests/mocking

return utime(path, dates)

def _auth_timeout_getmtime(self, path):
return getmtime(path)

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See separate comment on tests/mocking

except OSError as e:
_logger.warning(
'Exception reading session file modified time: %s'
% e

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am using warning for these log entries.
Any reason I should use debug instead?

@oca-clabot

Copy link
Copy Markdown

Hey @jmorgannz,
We acknowledge that the following users have signed our Contributor License Agreement:

Appreciation of efforts,
OCA CLAbot

@jmorgannz

Copy link
Copy Markdown
Author

facepalm
I better get my linters sorted out


'author': "ACSONE SA/NV, Dhinesh D, Odoo Community Association (OCA)",
'author': "ACSONE SA/NV, Dhinesh D, Jesse Morgan, \
Odoo Community Association (OCA)",

@jmorgannz jmorgannz Jul 11, 2017

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Used an escaped newline to fix issue with new author string length.
Mangles the file layout somewhat.
Wasn't sure if un-escaped newlines using """ would do funny things in the author string.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you don't like escaped new lines, you can also use multiple strings, like this:

    'author': 'ACSONE SA/NV, Dhinesh D, Jesse Morgan, '
              'Odoo Community Association (OCA)',

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is my preferred, although IMO it looks nicer one per line:

    'author': 'ACSONE SA/NV, '
              'Dhinesh D, '
              'Jesse Morgan, '
              'Odoo Community Association (OCA)',

@lasley

lasley commented Jul 11, 2017

Copy link
Copy Markdown
Contributor

@jmorgannz - take a look here for local lint

@jmorgannz

Copy link
Copy Markdown
Author

@lasley - thanks - I just hadn't got around to it. I've done it now.
That was mainly because I had adjusted all my editor apps to have a ruler at 79 characters, but forgot to adjust pycharm.

@jmorgannz

Copy link
Copy Markdown
Author

Hi all,
Have been indisposed, but still plan to add some code comments to this PR to finish it off - it's otherwise complete.

@chienandalu chienandalu left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @jmorgannz for the good job. I borrowed some ideas for v10 migration indeed 🙂 Some comments below:


@tools.ormcache(skiparg=0)
@tools.ormcache('db')
def get_session_parameters(self, db):

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I followed @yajo's advice here (#875 (comment)) and got rid of this whole file in favour of new api and method improvements (wich seem to be available in v9 as well: https://github.com/odoo/odoo/blob/9.0/openerp/addons/base/ir/ir_config_parameter.py#L57).

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@chienandalu
Glad you found my changes useful :)
Yes I struggled with the same thoughts myself - at first I couldn't see any reason why changes were required at all in ir_config_parameter.
The best I could come up with is that the original writer wanted to read both and cache once, rather than read twice and cache twice.
In any event it is indeed redundant, although I was advised against removing get_session_parameters (deceptively named for a public method :/) as its in the wild now and might be referenced by some unknown modules.

@lasley

lasley commented Sep 6, 2017

Copy link
Copy Markdown
Contributor

Ok before we continue with the v10, let's knock this one. @chienandalu - have your comments been attended to here?

@chienandalu

Copy link
Copy Markdown
Member

@lasley Yes, sure 🙂

@lasley

lasley commented Sep 6, 2017

Copy link
Copy Markdown
Contributor

Thanks @jmorgannz - congrats on your first OCA submission🥇 !

Look forward to seeing you around 🚀

@MiquelRForgeFlow MiquelRForgeFlow left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Line https://github.com/OCA/server-tools/pull/887/files#diff-42f066551d06ff9ed8b4c8c7fdc6c8f1R18 should have been changed to 9.0.1.0.1 or 9.0.1.1.0 or 9.0.2.0.0.

@jmorgannz

Copy link
Copy Markdown
Author

@lasley
Thanks Dave.
I was supposed to add some comments to this pull, but for various reasons have been a bit distracted.
This will not impact on the function of the pull, however.

Thanks for the help!

lasley pushed a commit to LasLabs/server-tools that referenced this pull request Nov 3, 2017
* Module auth_session_timeout:
---------------------------

* Refactor to allow other modules to inherit and augment or override the following:
** Session expiry time (deadline) calculation
** Ignored URLs
** Final session expiry (with possibility to late-abort)
* Re-ordered functionality to remove unnecessary work, as this code is called very often.
* Do not expire a session if delay gets set to zero (or unset / false)

* WIP

* Fixed flake8 lint errors

* Fixed flake8 lint errors

* WIP

* WIP

* WIP

* WIP

* WIP

* WIP

* Module: auth-session-timeout: Refactor ResUser tests to use `unittest.mock` patching

* Module: auth_session_timeout: Fixed flake8 lint errors

* Module: auth_session_timeout: Fixed flake8 lint errors
lasley pushed a commit to LasLabs/server-tools that referenced this pull request Nov 3, 2017
* Module auth_session_timeout:
---------------------------

* Refactor to allow other modules to inherit and augment or override the following:
** Session expiry time (deadline) calculation
** Ignored URLs
** Final session expiry (with possibility to late-abort)
* Re-ordered functionality to remove unnecessary work, as this code is called very often.
* Do not expire a session if delay gets set to zero (or unset / false)

* WIP

* Fixed flake8 lint errors

* Fixed flake8 lint errors

* WIP

* WIP

* WIP

* WIP

* WIP

* WIP

* Module: auth-session-timeout: Refactor ResUser tests to use `unittest.mock` patching

* Module: auth_session_timeout: Fixed flake8 lint errors

* Module: auth_session_timeout: Fixed flake8 lint errors
lasley pushed a commit to LasLabs/server-tools that referenced this pull request Nov 6, 2017
* Module auth_session_timeout:
---------------------------

* Refactor to allow other modules to inherit and augment or override the following:
** Session expiry time (deadline) calculation
** Ignored URLs
** Final session expiry (with possibility to late-abort)
* Re-ordered functionality to remove unnecessary work, as this code is called very often.
* Do not expire a session if delay gets set to zero (or unset / false)

* WIP

* Fixed flake8 lint errors

* Fixed flake8 lint errors

* WIP

* WIP

* WIP

* WIP

* WIP

* WIP

* Module: auth-session-timeout: Refactor ResUser tests to use `unittest.mock` patching

* Module: auth_session_timeout: Fixed flake8 lint errors

* Module: auth_session_timeout: Fixed flake8 lint errors
lasley pushed a commit to LasLabs/server-tools that referenced this pull request Nov 7, 2017
* Module auth_session_timeout:
---------------------------

* Refactor to allow other modules to inherit and augment or override the following:
** Session expiry time (deadline) calculation
** Ignored URLs
** Final session expiry (with possibility to late-abort)
* Re-ordered functionality to remove unnecessary work, as this code is called very often.
* Do not expire a session if delay gets set to zero (or unset / false)

* WIP

* Fixed flake8 lint errors

* Fixed flake8 lint errors

* WIP

* WIP

* WIP

* WIP

* WIP

* WIP

* Module: auth-session-timeout: Refactor ResUser tests to use `unittest.mock` patching

* Module: auth_session_timeout: Fixed flake8 lint errors

* Module: auth_session_timeout: Fixed flake8 lint errors
lasley pushed a commit to LasLabs/server-tools that referenced this pull request Nov 8, 2017
* Module auth_session_timeout:
---------------------------

* Refactor to allow other modules to inherit and augment or override the following:
** Session expiry time (deadline) calculation
** Ignored URLs
** Final session expiry (with possibility to late-abort)
* Re-ordered functionality to remove unnecessary work, as this code is called very often.
* Do not expire a session if delay gets set to zero (or unset / false)

* WIP

* Fixed flake8 lint errors

* Fixed flake8 lint errors

* WIP

* WIP

* WIP

* WIP

* WIP

* WIP

* Module: auth-session-timeout: Refactor ResUser tests to use `unittest.mock` patching

* Module: auth_session_timeout: Fixed flake8 lint errors

* Module: auth_session_timeout: Fixed flake8 lint errors
nadiaafa pushed a commit to nadiaafa/server-tools that referenced this pull request Feb 18, 2018
* Module auth_session_timeout:
---------------------------

* Refactor to allow other modules to inherit and augment or override the following:
** Session expiry time (deadline) calculation
** Ignored URLs
** Final session expiry (with possibility to late-abort)
* Re-ordered functionality to remove unnecessary work, as this code is called very often.
* Do not expire a session if delay gets set to zero (or unset / false)

* WIP

* Fixed flake8 lint errors

* Fixed flake8 lint errors

* WIP

* WIP

* WIP

* WIP

* WIP

* WIP

* Module: auth-session-timeout: Refactor ResUser tests to use `unittest.mock` patching

* Module: auth_session_timeout: Fixed flake8 lint errors

* Module: auth_session_timeout: Fixed flake8 lint errors
SiesslPhillip pushed a commit to grueneerde/OCA-server-tools that referenced this pull request Nov 20, 2024
Syncing from upstream OCA/server-tools (14.0)
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

Successfully merging this pull request may close these issues.

6 participants