mirror of
https://gitlab.com/hibou-io/hibou-odoo/suite.git
synced 2025-01-20 12:37:31 +02:00
Add auth_admin for 11.0 from https://github.com/hibou-io/odoo-auth-admin
This commit is contained in:
4
auth_admin/__init__.py
Executable file
4
auth_admin/__init__.py
Executable file
@@ -0,0 +1,4 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from . import controllers
|
||||
from . import models
|
||||
from . import wizard
|
||||
30
auth_admin/__manifest__.py
Executable file
30
auth_admin/__manifest__.py
Executable file
@@ -0,0 +1,30 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
{
|
||||
'name': 'Auth Admin',
|
||||
'author': 'Hibou Corp. <hello@hibou.io>',
|
||||
'category': 'Hidden',
|
||||
'version': '11.0.0.0.0',
|
||||
'description':
|
||||
"""
|
||||
Login as other user
|
||||
===================
|
||||
|
||||
Provides a way for an authenticated user, with certain permissions, to login as a different user.
|
||||
Can also create a URL that logs in as that user.
|
||||
|
||||
Out of the box, only allows you to generate a login for an 'External User', e.g. portal users.
|
||||
|
||||
*2017-11-15* New button to generate the login on the Portal User Wizard (Action on Contact)
|
||||
""",
|
||||
'depends': [
|
||||
'base',
|
||||
'website',
|
||||
'portal',
|
||||
],
|
||||
'auto_install': False,
|
||||
'data': [
|
||||
'views/res_users.xml',
|
||||
'wizard/portal_wizard_views.xml',
|
||||
],
|
||||
}
|
||||
2
auth_admin/controllers/__init__.py
Executable file
2
auth_admin/controllers/__init__.py
Executable file
@@ -0,0 +1,2 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from . import main
|
||||
41
auth_admin/controllers/main.py
Executable file
41
auth_admin/controllers/main.py
Executable file
@@ -0,0 +1,41 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from odoo import http, exceptions
|
||||
from ..models.res_users import check_admin_auth_login
|
||||
|
||||
from logging import getLogger
|
||||
_logger = getLogger(__name__)
|
||||
|
||||
|
||||
class AuthAdmin(http.Controller):
|
||||
|
||||
@http.route(['/auth_admin'], type='http', auth='public', website=True)
|
||||
def index(self, *args, **post):
|
||||
u = post.get('u')
|
||||
e = post.get('e')
|
||||
o = post.get('o')
|
||||
h = post.get('h')
|
||||
|
||||
if not all([u, e, o, h]):
|
||||
exceptions.Warning('Invalid Request')
|
||||
|
||||
u = str(u)
|
||||
e = str(e)
|
||||
o = str(o)
|
||||
h = str(h)
|
||||
|
||||
try:
|
||||
user = check_admin_auth_login(http.request.env, u, e, o, h)
|
||||
|
||||
http.request.session.uid = user.id
|
||||
http.request.session.login = user.login
|
||||
http.request.session.password = ''
|
||||
http.request.session.auth_admin = int(o)
|
||||
http.request.uid = user.id
|
||||
uid = http.request.session.authenticate(http.request.session.db, user.login, 'x')
|
||||
if uid is not False:
|
||||
http.request.params['login_success'] = True
|
||||
return http.redirect_with_hash('/my/home')
|
||||
return http.local_redirect('/my/home')
|
||||
except (exceptions.Warning, ) as e:
|
||||
return http.Response(e.message, status=400)
|
||||
2
auth_admin/models/__init__.py
Executable file
2
auth_admin/models/__init__.py
Executable file
@@ -0,0 +1,2 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from . import res_users
|
||||
90
auth_admin/models/res_users.py
Executable file
90
auth_admin/models/res_users.py
Executable file
@@ -0,0 +1,90 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from odoo import models, api, exceptions
|
||||
from odoo.http import request
|
||||
from datetime import datetime
|
||||
from time import mktime
|
||||
import hmac
|
||||
from hashlib import sha256
|
||||
|
||||
from logging import getLogger
|
||||
_logger = getLogger(__name__)
|
||||
|
||||
def admin_auth_generate_login(env, user):
|
||||
"""
|
||||
Generates a URL to allow the current user to login as the portal user.
|
||||
|
||||
:param env: Odoo environment
|
||||
:param user: `res.users` in
|
||||
:return:
|
||||
"""
|
||||
if not env['res.partner'].check_access_rights('write'):
|
||||
return None
|
||||
u = str(user.id)
|
||||
now = datetime.utcnow()
|
||||
fifteen = int(mktime(now.timetuple())) + (15 * 60)
|
||||
e = str(fifteen)
|
||||
o = str(env.uid)
|
||||
|
||||
config = env['ir.config_parameter'].sudo()
|
||||
key = str(config.search([('key', '=', 'database.secret')], limit=1).value)
|
||||
h = hmac.new(key.encode(), (u + e + o).encode(), sha256)
|
||||
|
||||
base_url = str(config.search([('key', '=', 'web.base.url')], limit=1).value)
|
||||
|
||||
_logger.warn('login url for user id: ' + u + ' original user id: ' + o)
|
||||
|
||||
return base_url + '/auth_admin?u=' + u + '&e=' + e + '&o=' + o + '&h=' + h.hexdigest()
|
||||
|
||||
def check_admin_auth_login(env, u_user_id, e_expires, o_org_user_id, hash_):
|
||||
"""
|
||||
Checks that the parameters are valid and that the user exists.
|
||||
|
||||
:param env: Odoo environment
|
||||
:param u_user_id: Desired user id to login as.
|
||||
:param e_expires: Expiration timestamp
|
||||
:param o_org_user_id: Original user id.
|
||||
:param hash_: HMAC generated hash
|
||||
:return: `res.users`
|
||||
"""
|
||||
|
||||
now = datetime.utcnow()
|
||||
now = int(mktime(now.timetuple()))
|
||||
fifteen = now + (15 * 60)
|
||||
|
||||
config = env['ir.config_parameter'].sudo()
|
||||
key = str(config.search([('key', '=', 'database.secret')], limit=1).value)
|
||||
|
||||
myh = hmac.new(key.encode(), str(str(u_user_id) + str(e_expires) + str(o_org_user_id)).encode(), sha256)
|
||||
|
||||
if not hmac.compare_digest(hash_, myh.hexdigest()):
|
||||
raise exceptions.Warning('Invalid Request')
|
||||
|
||||
if not (now <= int(e_expires) <= fifteen):
|
||||
raise exceptions.Warning('Expired')
|
||||
|
||||
user = env['res.users'].sudo().search([('id', '=', int(u_user_id))], limit=1)
|
||||
if not user.id:
|
||||
raise exceptions.Warning('Invalid User')
|
||||
return user
|
||||
|
||||
|
||||
class ResUsers(models.Model):
|
||||
_inherit = 'res.users'
|
||||
|
||||
@api.multi
|
||||
def admin_auth_generate_login(self):
|
||||
self.ensure_one()
|
||||
|
||||
login_url = admin_auth_generate_login(self.env, self)
|
||||
if login_url:
|
||||
raise exceptions.Warning(login_url)
|
||||
|
||||
return False
|
||||
|
||||
@api.model
|
||||
def check_credentials(self, password):
|
||||
if request and hasattr(request, 'session') and request.session.get('auth_admin'):
|
||||
_logger.warn('check_credentials for user id: ' + str(request.session.uid) + ' original user id: ' + str(request.session.auth_admin))
|
||||
return True
|
||||
return super(ResUsers, self).check_credentials(password)
|
||||
14
auth_admin/views/res_users.xml
Executable file
14
auth_admin/views/res_users.xml
Executable file
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<odoo>
|
||||
<record id="auth_admin_view_users_tree" model="ir.ui.view">
|
||||
<field name="name">auth_admin.res.users.tree</field>
|
||||
<field name="model">res.users</field>
|
||||
<field name="inherit_id" ref="base.view_users_tree"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//tree" position="inside">
|
||||
<field name="share" invisible="1"/>
|
||||
<button string="Generate Login" type="object" name="admin_auth_generate_login" attrs="{'invisible': [('share', '=', False)]}"/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
</odoo>
|
||||
2
auth_admin/wizard/__init__.py
Executable file
2
auth_admin/wizard/__init__.py
Executable file
@@ -0,0 +1,2 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from . import portal_wizard
|
||||
27
auth_admin/wizard/portal_wizard.py
Executable file
27
auth_admin/wizard/portal_wizard.py
Executable file
@@ -0,0 +1,27 @@
|
||||
from odoo import api, fields, models
|
||||
from ..models.res_users import admin_auth_generate_login
|
||||
|
||||
|
||||
class PortalWizard(models.TransientModel):
|
||||
_inherit = 'portal.wizard'
|
||||
|
||||
@api.multi
|
||||
def admin_auth_generate_login(self):
|
||||
self.ensure_one()
|
||||
self.user_ids.admin_auth_generate_login()
|
||||
return {'type': 'ir.actions.do_nothing'}
|
||||
|
||||
|
||||
class PortalWizardUser(models.TransientModel):
|
||||
_inherit = 'portal.wizard.user'
|
||||
|
||||
force_login_url = fields.Char(string='Force Login URL')
|
||||
|
||||
@api.multi
|
||||
def admin_auth_generate_login(self):
|
||||
ir_model_access = self.env['ir.model.access']
|
||||
for row in self:
|
||||
row.force_login_url = ''
|
||||
user = row.partner_id.user_ids[0] if row.partner_id.user_ids else None
|
||||
if ir_model_access.check('res.partner', mode='unlink') and row.in_portal and user:
|
||||
row.force_login_url = admin_auth_generate_login(self.env, user)
|
||||
18
auth_admin/wizard/portal_wizard_views.xml
Executable file
18
auth_admin/wizard/portal_wizard_views.xml
Executable file
@@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<odoo>
|
||||
|
||||
<record id="portal_wizard" model="ir.ui.view">
|
||||
<field name="name">Portal Access Management - Auth Admin</field>
|
||||
<field name="model">portal.wizard</field>
|
||||
<field name="inherit_id" ref="portal.wizard_view"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//field[@name='in_portal']" position="after">
|
||||
<field name="force_login_url" readonly="1"/>
|
||||
</xpath>
|
||||
<xpath expr="//button[last()]" position="after">
|
||||
<button string="Generate Login URL" type="object" name="admin_auth_generate_login" class="btn-default" />
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
Reference in New Issue
Block a user