Step 1: Define User Groups
In nh_rest.api/data/groups.xml
, create two user roles:
<odoo>
<record id="group_myapp_admin" model="res.groups">
<field name="name">My App Admin</field>
</record>
<record id="group_myapp_user" model="res.groups">
<field name="name">My App User</field>
</record>
</odoo>
After updating the module, these two groups will appear in the Odoo user management interface:
Step 2: Modify Token Authentication to Include User Groups
We modify the token_required
function in the nh_rest_api
module to retrieve the user's group information:
import functools
import jwt
import odoo
from odoo import api
from odoo.http import request, SUPERUSER_ID
Secret_key = "your_secret_key" # Replace with your actual secret key
def token_required():
def decorator(f):
@functools.wraps(f)
def wrapper(*args, **kw):
headers = dict(request.httprequest.headers.items())
auth = headers.get("Authorization", None)
if not auth:
return {"error": {"code": 403, "message": "No Authorization"}}
token = auth
try:
data = jwt.decode(token, Secret_key, algorithms=["HS256"])
db_name = data["db"]
with api.Environment.manage():
registry = odoo.registry(db_name)
with registry.cursor() as cr:
env = api.Environment(cr, SUPERUSER_ID, {})
user = env["res.users"].search([( "login", "=", data["user"] )], limit=1)
if not user:
return {"error": {"code": 401, "message": "User not found"}}
# Assign user session without password
request.session.db = db_name
request.session.uid = user.id
kw["uid"] = user.id
# Retrieve user groups and store in kw
user_groups = user.groups_id.mapped("name")
kw["groups"] = ";".join(user_groups)
except jwt.ExpiredSignatureError:
return {"error": {"code": 401, "message": "Token is expired"}}
except jwt.DecodeError:
return {"error": {"code": 401, "message": "Token signature is invalid"}}
return f(*args, **kw)
return wrapper
return decorator
Step 3: Create a Role-Based Access Decorator
We define a decorator myapp_role_required
to check if the user belongs to a specific role:
def myapp_role_required(name):
def decorator(f):
@functools.wraps(f)
def wrapper(*args, **kwargs):
group_str = kwargs.get("groups", "")
groups = group_str.split(";") if group_str else []
if name not in groups:
return {"error": {"code": 403, "message": "Access Denied: Admin rights required"}}
return f(*args, **kwargs)
return wrapper
return decorator
Step 4: Apply the Decorator in the Controller
In nh_rest_api/controller/main.py
, apply the token_required
and myapp_role_required
decorators:
from odoo import http
from odoo.http import request
from ..constants import Api_Prefix
from ..jwt.rest_core import token_required, http_route_jwt, myapp_role_required
class MainController(http.Controller):
@http_route_jwt(f"{Api_Prefix}/simple_model/list", methods=["GET"])
@token_required()
@myapp_role_required("My App Admin")
def get_simple_model_list(self, **kwargs):
data = request.env["simple.model"].search([], order="id desc")
result = data.read(["id", "name", "date_start", "description"])
return {"result": result}
Notice that we added @myapp_role_required("My App Admin")
below @token_required()
to check whether the request contains the My App Admin group.
If a user without admin privileges attempts to access this endpoint, they will receive an Access Denied error:
Step 5: Login with an Admin Account
Now, let's test logging in with the mrhieu account, which has the My App Admin role:
async function login_odoo() {
return new Promise((resolve, reject) => {
var myHeaders = new Headers();
myHeaders.append("Content-Type", "application/json");
var requestOptions = {
method: 'POST',
headers: myHeaders,
body: JSON.stringify({
"username": "mrhieu",
"password": "1",
"dbname": "hieu_hr"
}),
};
fetch(`${odoo_url_api}/login`, requestOptions)
.then(response => response.json())
.then(json => {
if (json.error?.code) {
reject(json);
}
resolve(json.data);
})
.catch(error => reject(error));
});
}
Step 6: Verify the Data is Retrieved Successfully
After logging in with an account that has the My App Admin role, the data is displayed correctly:
Conclusion
- created two user groups (
My App Admin
andMy App User
). - modified token authentication to include user group information.
- created a decorator to restrict access based on user roles.
- applied role-based access control in an Odoo controller.
- tested the functionality to ensure only authorized users can access protected routes.
This approach ensures that only users with My App Admin privileges can access certain API endpoints while keeping the authentication process secure.
Like
Reply