Login and register with (phone and OTP)

This commit is contained in:
eman 2025-01-12 02:03:11 +02:00
parent 743baeab48
commit 95b4298fc8
6 changed files with 96 additions and 31 deletions

View File

@ -11,10 +11,11 @@ class CreatePortalAccount(http.Controller):
data = {}
first_name = kw.get('first_name')
second_name = kw.get('second_name')
login = kw.get('mobile_phone')
login = kw.get('otp_mobile_phone')
email = kw.get('email')
# relation_type = kw.get('relation_type')
password = str(random.randint(100000, 999999))
# Validate required fields
if not login:
data = {
@ -27,8 +28,9 @@ class CreatePortalAccount(http.Controller):
user = request.env['res.users'].sudo().create({
'name': first_name + " " + second_name,
'login': login,
'mobile_phone': login,
'password': password,
'otp_mobile_phone':login,
'email' : email,
})
user.generate_otp()
user.otp_enabled = True
@ -38,6 +40,7 @@ class CreatePortalAccount(http.Controller):
'user_id': user.id,
'name': first_name + " " + second_name,
'sms_phone' : login,
'email' : email
})
# Return success response
@ -56,3 +59,27 @@ class CreatePortalAccount(http.Controller):
'message': f'An error occurred: {str(e)}'
}
return json.dumps(data)
@http.route('/validate_otp', type='http', auth="public", website=True)
def validate_otp(self, **kw):
user = request.env['res.users'].browse(int(kw.get('user_id')))
otp = kw.get('otp')
if user:
if user:
is_valid = user.validate_otp(otp)
if is_valid:
user.active = True
# Log the user in
request.session.uid = user.id
# Redirect to the desired link
return request.redirect('/') # Replace with your desired link
# If OTP validation fails, return an error
data = {
'status': 'Error',
'message': 'OTP not valid',
}
return request.make_response(json.dumps(data), headers={'Content-Type': 'application/json'})

View File

@ -1,2 +1,3 @@
# -*- coding: utf-8 -*-
from . import models
from . import controllers

View File

@ -1,22 +1,59 @@
from odoo import http
from odoo.http import request
from odoo.addons.web.controllers.main import Home
import random
import json
class AuthSignupHome(Home):
@http.route('/web/login', type='http', auth="public", website=True)
def web_login(self, redirect=None, **kw):
if request.httprequest.method == 'POST':
if kw.get('login'):
login = kw.get('login')
password = kw.get('password')
class AuthSignInHome(Home):
@http.route('/generate_otp', type='http', auth="public", website=True)
def generate_otp(self, **kw):
user = request.env['res.users'].search([('login', '=', kw.get('otp_mobile_phone'))], limit=1)
if not kw.get('otp_mobile_phone'):
data = {
'status': 'Error',
'message': 'No mobile phone number provided for OTP.',
}
return json.dumps(data)
user = request.env['res.users'].sudo().search([('mobile_phone', '=', login)], limit=1)
if user and user.otp_enabled:
if not user.validate_otp(password):
return request.render('auth_signup.signup', {
'error': 'Invalid OTP.',
'login': login,
'password': password,
})
return super(AuthSignupHome, self).web_login(redirect=redirect, **kw)
data = {
'status': 'Success',
'message': 'OTP is generated and sent successfully',
'otp': user.generate_otp(),
}
return json.dumps(data)
# @http.route('/web/login', type='http', auth="public", website=True)
# def web_login(self, redirect=None, **kw):
# if request.httprequest.method == 'POST':
# if kw.get('login'):
# login = kw.get('login')
# password = kw.get('password')
#
# user = request.env['res.users'].sudo().search([('otp_mobile_phone', '=', login)], limit=1)
# user.password = password
# if user and user.otp_enabled:
# if not user.validate_otp(otp):
# return request.render('auth_signup.signup', {
# 'error': 'Invalid OTP.',
# 'login': login,
# 'password': password,
# })
# else:
# user.active = True
# return super(AuthSignupHome, self).web_login(redirect=redirect, **kw)
@http.route('/web/login', type='http', auth='public', website=True, csrf=False)
def web_login(self, redirect=None, **kwargs):
if 'password' in kwargs:
# Validate OTP
user = request.env['res.users'].sudo().search([('login', '=', kwargs.get('login'))], limit=1)
if user and str(user.otp_code) == kwargs.get('password'):
# Perform login
# user.otp_code = False # Clear OTP after successful login
request.session.uid = user.id
return request.redirect(redirect or '/')
else:
# Invalid OTP
return request.render('web.login', {'error': 'Invalid OTP'})
return super(OTPAuthLogin, self).web_login(redirect, **kwargs)

View File

@ -7,17 +7,17 @@ import logging
_logger = logging.getLogger(__name__)
class ResUsers(models.Model):
class ResUsersInherit(models.Model):
_inherit = 'res.users'
otp_enabled = fields.Boolean(string="Enable OTP", default=False)
mobile_phone = fields.Char(string="Mobile Phone")
otp_mobile_phone = fields.Char(string="Mobile Phone")
otp_code = fields.Char(string="OTP Code", readonly=True)
def generate_otp(self):
"""Generate a random OTP and send via SMS."""
self.ensure_one()
if not self.mobile_phone:
if not self.otp_mobile_phone:
raise ValidationError("No mobile phone number provided for OTP.")
otp = str(random.randint(100000, 999999))
@ -30,7 +30,7 @@ class ResUsers(models.Model):
# SMS payload
payload = {
"recipients": [self.mobile_phone],
"recipients": [self.otp_mobile_phone],
"body": f"Your OTP code is: {otp}",
"sender": sender_name,
}
@ -45,15 +45,15 @@ class ResUsers(models.Model):
try:
response = requests.post(api_url, json=payload, headers=headers)
response.raise_for_status() # Raise an error for non-2xx responses
_logger.info(f"OTP {otp} sent successfully to {self.mobile_phone}")
_logger.info(f"OTP {otp} sent successfully to {self.otp_mobile_phone}")
except requests.exceptions.RequestException as e:
_logger.error(f"Failed to send OTP to {self.mobile_phone}: {e}")
_logger.error(f"Failed to send OTP to {self.otp_mobile_phone}: {e}")
raise ValueError("Failed to send OTP. Please try again later.")
return otp
def validate_otp(self, otp):
"""Validate the OTP."""
self.ensure_one()
return self.otp_code == otp
def validate_otp(self, otp):
"""Validate the OTP."""
self.ensure_one()
return self.otp_code == otp

View File

@ -1,2 +1,2 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_res_users_otp,res.users.otp,model_res_users,,1,1,0,0
access_res_users_otp,res.users.otp,model_res_users,,1,1,1,1
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 access_res_users_otp res.users.otp model_res_users 1 1 0 1 0 1

View File

@ -8,7 +8,7 @@
<page string="OTP Settings">
<group>
<field name="otp_enabled"/>
<field name="mobile_phone"/>
<field name="otp_mobile_phone"/>
<button name="generate_otp" string="Generate OTP" type="object" class="oe_highlight"/>
</group>
</page>