Browse Source

Merge 502ccce860 into 1685f28736

pull/347/merge
drpsyko101 9 months ago
committed by GitHub
parent
commit
3578cc0bf5
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 257
      rest_api_odoo/Postman Collections/Odoo REST Api.postman_collection.json
  2. BIN
      rest_api_odoo/Postman Collections/Odoo REST Api.postman_collection.zip
  3. 2
      rest_api_odoo/__manifest__.py
  4. 434
      rest_api_odoo/controllers/rest_api_odoo.py
  5. 1
      rest_api_odoo/models/__init__.py
  6. 44
      rest_api_odoo/models/res_users.py
  7. 32
      rest_api_odoo/security/res_api_odoo_security.xml
  8. BIN
      rest_api_odoo/static/description/assets/screenshots/rest_api_2.png
  9. 308
      rest_api_odoo/static/description/index.html
  10. 18
      rest_api_odoo/views/res_users_views.xml

257
rest_api_odoo/Postman Collections/Odoo REST Api.postman_collection.json

@ -1,257 +0,0 @@
{
"info": {
"_postman_id": "83d9071d-626d-41ed-9800-78570ed11a7c",
"name": "Odoo REST Api",
"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json",
"_exporter_id": "28148668"
},
"item": [
{
"name": "Authentication",
"request": {
"method": "GET",
"header": [
{
"key": "db",
"value": "sep_db",
"type": "text"
},
{
"key": "login",
"value": "123",
"type": "text"
},
{
"key": "password",
"value": "123",
"type": "text"
},
{
"key": "",
"value": "",
"type": "text",
"disabled": true
}
],
"url": {
"raw": "http://cybrosys:8016/odoo_connect",
"protocol": "http",
"host": [
"cybrosys"
],
"port": "8016",
"path": [
"odoo_connect"
]
}
},
"response": []
},
{
"name": "GET records",
"protocolProfileBehavior": {
"disableBodyPruning": true
},
"request": {
"method": "GET",
"header": [
{
"key": "login",
"value": "123",
"type": "text"
},
{
"key": "password",
"value": "123",
"type": "text"
},
{
"key": "api-key",
"value": "4314c30b-994e-435d-a493-50cb0d33e99d",
"type": "text"
}
],
"body": {
"mode": "raw",
"raw": "{\n \"fields\": [\"name\",\"product_id\"]\n \n}",
"options": {
"raw": {
"language": "json"
}
}
},
"url": {
"raw": "http://cybrosys:8016/send_request?model=mrp.production&Id=10",
"protocol": "http",
"host": [
"cybrosys"
],
"port": "8016",
"path": [
"send_request"
],
"query": [
{
"key": "model",
"value": "mrp.production"
},
{
"key": "Id",
"value": "10"
}
]
}
},
"response": []
},
{
"name": "Create Records",
"request": {
"method": "POST",
"header": [
{
"key": "login",
"value": "123",
"type": "text"
},
{
"key": "password",
"value": "123",
"type": "text"
},
{
"key": "api_key",
"value": "4314c30b-994e-435d-a493-50cb0d33e99d",
"type": "text"
}
],
"body": {
"mode": "raw",
"raw": "{\n \"fields\" :[\"name\",\"phone\"] ,\n \"values\": {\"name\": \"abc\",\n \"phone\":\"55962441552\"\n }\n\n}",
"options": {
"raw": {
"language": "json"
}
}
},
"url": {
"raw": "http://cybrosys:8016/send_request?model=res.partner",
"protocol": "http",
"host": [
"cybrosys"
],
"port": "8016",
"path": [
"send_request"
],
"query": [
{
"key": "model",
"value": "res.partner"
}
]
}
},
"response": []
},
{
"name": "Update Records",
"request": {
"method": "PUT",
"header": [
{
"key": "login",
"value": "123",
"type": "text"
},
{
"key": "password",
"value": "123",
"type": "text"
},
{
"key": "api-key",
"value": "d52cd3de-ad4c-49ab-a5cb-727940b8117a",
"type": "text"
}
],
"body": {
"mode": "raw",
"raw": "{\n \"fields\" :[\"name\",\"phone\"] ,\n \"values\": {\"name\": \"abc\",\n \"phone\":\"55962441552\"\n }\n\n}",
"options": {
"raw": {
"language": "json"
}
}
},
"url": {
"raw": "http://cybrosys:8016/send_request?model=res.partner&Id=48",
"protocol": "http",
"host": [
"cybrosys"
],
"port": "8016",
"path": [
"send_request"
],
"query": [
{
"key": "model",
"value": "res.partner"
},
{
"key": "Id",
"value": "48"
}
]
}
},
"response": []
},
{
"name": "Delete Records",
"request": {
"method": "DELETE",
"header": [
{
"key": "login",
"value": "123",
"type": "text"
},
{
"key": "password",
"value": "123",
"type": "text"
},
{
"key": "api-key",
"value": "d52cd3de-ad4c-49ab-a5cb-727940b8117a",
"type": "text"
}
],
"url": {
"raw": "http://cybrosys:8016/send_request?model=res.partner&Id=48",
"protocol": "http",
"host": [
"cybrosys"
],
"port": "8016",
"path": [
"send_request"
],
"query": [
{
"key": "model",
"value": "res.partner"
},
{
"key": "Id",
"value": "48"
}
]
}
},
"response": []
}
]
}

BIN
rest_api_odoo/Postman Collections/Odoo REST Api.postman_collection.zip

Binary file not shown.

2
rest_api_odoo/__manifest__.py

@ -34,7 +34,7 @@
"depends": ['base', 'web'], "depends": ['base', 'web'],
"data": [ "data": [
'security/ir.model.access.csv', 'security/ir.model.access.csv',
'views/res_users_views.xml', 'security/res_api_odoo_security.xml',
'views/connection_api_views.xml' 'views/connection_api_views.xml'
], ],
'images': ['static/description/banner.jpg'], 'images': ['static/description/banner.jpg'],

434
rest_api_odoo/controllers/rest_api_odoo.py

@ -19,237 +19,247 @@
# If not, see <http://www.gnu.org/licenses/>. # If not, see <http://www.gnu.org/licenses/>.
# #
############################################################################# #############################################################################
import json import json
import logging import logging
from datetime import datetime
from odoo import http from datetime import datetime
from odoo.http import request from odoo import http, models
from odoo.http import request, Response
from ast import literal_eval
_logger = logging.getLogger(__name__) _logger = logging.getLogger(__name__)
class IrHttp(models.AbstractModel):
"""This model is used to authenticate the api-key when sending a request"""
_inherit = "ir.http"
@classmethod
def _auth_method_rest_api(cls):
"""This function is used to authenticate the api-key when sending a
request"""
try:
api_key = request.httprequest.headers.get("Authorization").lstrip("Bearer ")
if not api_key:
raise PermissionError("Invalid API key provided.")
user_id = request.env["res.users.apikeys"]._check_credentials(
scope="rpc", key=api_key
)
request.update_env(user_id)
except Exception as e:
_logger.error(e)
return Response(
json.dumps({"message": e.args[0]}),
status=401,
content_type="application/json",
)
class RestApi(http.Controller): class RestApi(http.Controller):
"""This is a controller which is used to generate responses based on the """This is a controller which is used to generate responses based on the
api requests""" api requests"""
def auth_api_key(self, api_key): def simplest_type(self, input):
"""This function is used to authenticate the api-key when sending a """Try cast input into native Python class, otherwise return as string"""
request""" try:
user_id = request.env['res.users'].sudo().search([('api_key', '=', api_key)]) return literal_eval(input)
if api_key is not None and user_id: except Exception:
response = True # Handle lowercase booleans
elif not user_id: if input == "true":
response = ('<html><body><h2>Invalid <i>API Key</i> ' return True
'!</h2></body></html>') if input == "false":
else: return False
response = ("<html><body><h2>No <i>API Key</i> Provided " return input
"!</h2></body></html>")
return response def sanitize_records(self, records):
"""Sanitize records for response"""
def generate_response(self, method, model, rec_id): for record in records:
for key, value in record.items():
# Manually convert datetime fields to string format
if isinstance(value, datetime):
record[key] = value.isoformat()
return records
def generate_response(self, method, **query):
"""This function is used to generate the response based on the type """This function is used to generate the response based on the type
of request and the parameters given""" of request and the parameters given"""
option = request.env['connection.api'].search(
[('model_id', '=', model)], limit=1)
model_name = option.model_id.model
if method != 'DELETE':
data = json.loads(request.httprequest.data)
else:
data = {}
fields = []
if data:
for field in data['fields']:
fields.append(field)
if not fields and method != 'DELETE':
return ("<html><body><h2>No fields selected for the model"
"</h2></body></html>")
if not option:
return ("<html><body><h2>No Record Created for the model"
"</h2></body></html>")
try: try:
if method == 'GET': model = query.pop("model")
fields = [] option = request.env["connection.api"].search(
for field in data['fields']: [("model_id", "=", model)], limit=1
)
model_name = option.model_id.model
model_display_name = option.model_id.name
try:
data = json.loads(request.httprequest.data)
except Exception:
data = {}
fields = []
if data:
for field in data["fields"]:
fields.append(field) fields.append(field)
# Return records' ID by default if not specified
if not fields:
fields.append("id")
# Get all model's fields if wildcard is used
if "*" in fields:
fields = []
record_fields = request.env[str(model_name)].fields_get(
[], attributes=["type"]
)
for field, value in record_fields.items():
value_type = value.get("type")
if not (value_type == "binary"):
fields.append(field)
if not option:
raise NotImplementedError("No Record Created for the model. ")
if method == "GET":
if not option.is_get: if not option.is_get:
return ("<html><body><h2>Method Not Allowed" raise NameError()
"</h2></body></html>") limit = 0
else: if query.get("limit"):
datas = [] limit = int(str(query.get("limit")))
if rec_id != 0: offset = 0
partner_records = request.env[ if query.get("offset"):
str(model_name) offset = int(str(query.get("offset")))
].search_read(
domain=[('id', '=', rec_id)], domains = []
fields=fields for key, value in query.items():
) if not (key == "limit" or key == "offset"):
domains.append((key, "=", self.simplest_type(value)))
# Manually convert datetime fields to string format partner_records = request.env[str(model_name)].search_read(
for record in partner_records: domains, fields, limit=limit, offset=offset
for key, value in record.items(): )
if isinstance(value, datetime):
record[key] = value.isoformat() return Response(
data = json.dumps({ json.dumps({"records": self.sanitize_records(partner_records)}),
'records': partner_records content_type="application/json",
}) )
datas.append(data) if method == "POST":
return request.make_response(data=datas) if not option.is_post:
else: raise NotImplementedError()
partner_records = request.env[ if not data or "values" not in data:
str(model_name) raise ValueError("No Data Provided")
].search_read(
domain=[], data = json.loads(request.httprequest.data)
fields=fields new_resource = request.env[str(model_name)].create(data["values"])
) partner_records = request.env[str(model_name)].search_read(
[("id", "=", new_resource.id)], fields
# Manually convert datetime fields to string format )
for record in partner_records: return Response(
for key, value in record.items(): json.dumps({"new_record": self.sanitize_records(partner_records)}),
if isinstance(value, datetime): status=201,
record[key] = value.isoformat() content_type="application/json",
)
data = json.dumps({ if method == "PUT":
'records': partner_records if not option.is_put:
}) raise NotImplementedError()
datas.append(data)
return request.make_response(data=datas) if "id" not in query:
except: raise ValueError("No ID Provided")
return ("<html><body><h2>Invalid JSON Data" if not data or "values" not in data:
"</h2></body></html>") raise ValueError("No Data Provided")
if method == 'POST':
if not option.is_post: resource_id = str(query.get("id"))
return ("<html><body><h2>Method Not Allowed" resource = request.env[str(model_name)].browse(int(resource_id))
"</h2></body></html>") if not resource.exists():
else: raise ValueError("Resource not found")
try:
data = json.loads(request.httprequest.data) data = json.loads(request.httprequest.data)
datas = [] resource.write(data["values"])
new_resource = request.env[str(model_name)].create( partner_records = request.env[str(model_name)].search_read(
data['values']) [("id", "=", resource.id)], fields
partner_records = request.env[ )
str(model_name)].search_read( return Response(
domain=[('id', '=', new_resource.id)], json.dumps(
fields=fields {"updated_record": self.sanitize_records(partner_records)}
) ),
new_data = json.dumps({'New resource': partner_records, }) content_type="application/json",
datas.append(new_data) )
return request.make_response(data=datas) if method == "DELETE":
except: if not option.is_delete:
return ("<html><body><h2>Invalid JSON Data" raise NotImplementedError()
"</h2></body></html>")
if method == 'PUT': if "id" not in query:
if not option.is_put: raise ValueError("No ID Provided")
return ("<html><body><h2>Method Not Allowed"
"</h2></body></html>") resource_id = str(query.get("id"))
else: resource = request.env[str(model_name)].browse(int(resource_id))
if rec_id == 0: if not resource.exists():
return ("<html><body><h2>No ID Provided" raise ValueError("Resource not found")
"</h2></body></html>")
else: partner_records = request.env[str(model_name)].search_read(
resource = request.env[str(model_name)].browse( [("id", "=", resource.id)], fields
int(rec_id)) )
if not resource.exists(): resource.unlink()
return ("<html><body><h2>Resource not found" return Response(
"</h2></body></html>") json.dumps(
else: {
try: "message": "Resource deleted",
datas = [] "data": self.sanitize_records(partner_records),
data = json.loads(request.httprequest.data) }
resource.write(data['values']) ),
partner_records = request.env[ status=202,
str(model_name)].search_read( content_type="application/json",
domain=[('id', '=', resource.id)], )
fields=fields
) # If not using any method above, simply return an error
new_data = json.dumps( raise NotImplementedError()
{'Updated resource': partner_records, except ValueError as e:
}) return Response(
datas.append(new_data) json.dumps({"message": e.args[0]}),
return request.make_response(data=datas) status=403,
content_type="application/json",
except: )
return ("<html><body><h2>Invalid JSON Data " except NotImplementedError as e:
"!</h2></body></html>") return Response(
if method == 'DELETE': json.dumps(
if not option.is_delete: {
return ("<html><body><h2>Method Not Allowed" "message": f"Method not allowed. {e.args[0]}Please contact your admininstrator to enable {method} method for {model_display_name or 'this'} record."
"</h2></body></html>") }
else: ),
if rec_id == 0: status=405,
return ("<html><body><h2>No ID Provided" content_type="application/json",
"</h2></body></html>") )
else: except Exception as e:
resource = request.env[str(model_name)].browse( _logger.error(e)
int(rec_id)) return Response(
if not resource.exists(): json.dumps({"message": f"Internal server error. {e.args[0]}"}),
return ("<html><body><h2>Resource not found" status=500,
"</h2></body></html>") content_type="application/json",
else: )
records = request.env[ @http.route(
str(model_name)].search_read( ["/send_request"],
domain=[('id', '=', resource.id)], type="http",
fields=['id', 'display_name'] auth="rest_api",
) methods=["GET", "POST", "PUT", "DELETE"],
remove = json.dumps( csrf=False,
{"Resource deleted": records, )
})
resource.unlink()
return request.make_response(data=remove)
@http.route(['/send_request'], type='http',
auth='none',
methods=['GET', 'POST', 'PUT', 'DELETE'], csrf=False)
def fetch_data(self, **kw): def fetch_data(self, **kw):
"""This controller will be called when sending a request to the """This controller will be called when sending a request to the
specified url, and it will authenticate the api-key and then will specified url, and it will authenticate the api-key and then will
generate the result""" generate the result"""
http_method = request.httprequest.method http_method = request.httprequest.method
api_key = request.httprequest.headers.get('api-key') model = kw.pop("model")
auth_api = self.auth_api_key(api_key) model_id = request.env["ir.model"].search([("model", "=", model)])
model = kw.get('model')
username = request.httprequest.headers.get('login')
password = request.httprequest.headers.get('password')
request.session.authenticate(request.session.db, username,
password)
model_id = request.env['ir.model'].search(
[('model', '=', model)])
if not model_id: if not model_id:
return ("<html><body><h3>Invalid model, check spelling or maybe " return Response(
"the related " json.dumps(
"module is not installed" {
"</h3></body></html>") "message": "Invalid model, check spelling or maybe the related module is not installed"
}
if auth_api == True: ),
if not kw.get('Id'): status=403,
rec_id = 0 content_type="application/json",
else: )
rec_id = int(kw.get('Id'))
result = self.generate_response(http_method, model_id.id, rec_id) return self.generate_response(http_method, model=model_id.id, **kw)
return result
else:
return auth_api
@http.route(['/odoo_connect'], type="http", auth="none", csrf=False,
methods=['GET'])
def odoo_connect(self, **kw):
"""This is the controller which initializes the api transaction by
generating the api-key for specific user and database"""
username = request.httprequest.headers.get('login')
password = request.httprequest.headers.get('password')
db = request.httprequest.headers.get('db')
try:
request.session.update(http.get_default_session(), db=db)
auth = request.session.authenticate(request.session.db, username,
password)
user = request.env['res.users'].browse(auth)
api_key = request.env.user.generate_api(username)
datas = json.dumps({"Status": "auth successful",
"User": user.name,
"api-key": api_key})
return request.make_response(data=datas)
except:
return ("<html><body><h2>wrong login credentials"
"</h2></body></html>")

1
rest_api_odoo/models/__init__.py

@ -20,4 +20,3 @@
# #
############################################################################# #############################################################################
from . import connection_api from . import connection_api
from . import res_users

44
rest_api_odoo/models/res_users.py

@ -1,44 +0,0 @@
# -*- coding:utf-8 -*-
#############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
# Author: Sruthi Pavithran (odoo@cybrosys.com)
#
# You can modify it under the terms of the GNU LESSER
# GENERAL PUBLIC LICENSE (LGPL v3), Version 3.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details.
#
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE
# (LGPL v3) along with this program.
# If not, see <http://www.gnu.org/licenses/>.
#
#############################################################################
import uuid
from odoo import fields, models
class ResUsers(models.Model):
"""This class is used to inherit users and add api key generation"""
_inherit = 'res.users'
api_key = fields.Char(string="API Key", readonly=True,
help="Api key for connecting with the "
"Database.The key will be "
"generated when authenticating "
"rest api.")
def generate_api(self, username):
"""This function is used to generate api-key for each user"""
users = self.env['res.users'].sudo().search([('login', '=', username)])
if not users.api_key:
users.api_key = str(uuid.uuid4())
key = users.api_key
else:
key = users.api_key
return key

32
rest_api_odoo/security/res_api_odoo_security.xml

@ -0,0 +1,32 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data noupdate="1">
<record model="ir.module.category" id="module_category_rest_api_odoo">
<field name="name">REST API</field>
<field name="description">Helps you manage your REST API records.</field>
<field name="sequence">17</field>
</record>
<record id="group_rest_api_odoo_manager" model="res.groups">
<field name="name">Manager</field>
<field name="category_id"
ref="rest_api_odoo.module_category_rest_api_odoo" />
<field name="users" eval="[(4, ref('base.user_root')), (4, ref('base.user_admin'))]" />
</record>
<record id="base.default_user" model="res.users">
<field name="groups_id"
eval="[(4,ref('rest_api_odoo.group_rest_api_odoo_manager'))]" />
</record>
<record id="rest_api_odoo_rule_manager" model="ir.rule">
<field name="name">All REST APIs</field>
<field name="model_id" ref="model_connection_api" />
<field name="domain_force">[(1,'=',1)]</field>
<field name="groups"
eval="[(4, ref('rest_api_odoo.group_rest_api_odoo_manager'))]" />
</record>
</data>
</odoo>

BIN
rest_api_odoo/static/description/assets/screenshots/rest_api_2.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 95 KiB

After

Width:  |  Height:  |  Size: 116 KiB

308
rest_api_odoo/static/description/index.html

@ -44,7 +44,7 @@
style="margin: 80px 0px !important;"> style="margin: 80px 0px !important;">
<h1 style="font-size: 2.8rem;font-weight: 700; color: <h1 style="font-size: 2.8rem;font-weight: 700; color:
#1A202C;"> #1A202C;">
Odoo rest API</h1> Odoo Rest API</h1>
<p class="my-3 mb-4" <p class="my-3 mb-4"
style="max-width: 80%; font-weight: 400 !important; line-height: 32px; color: #718096;"> style="max-width: 80%; font-weight: 400 !important; line-height: 32px; color: #718096;">
The odoo Rest API module allow us to connect to database The odoo Rest API module allow us to connect to database
@ -64,27 +64,6 @@
</p> </p>
</div> </div>
<div class="row py-4"> <div class="row py-4">
<div class="col-md-6 col-sm-12 p-3">
<div class="d-flex h-100" style="padding: 30px;border-radius: 12px;
background: #FFF;
box-shadow: 1px 2px 3px 0px rgba(0, 0, 0, 0.25); ">
<div style="width: 36px; height: 36px; border-radius: 50%; background: #714B67;
display: flex; justify-content: center; align-items: center;
margin-right: 10px; flex-shrink: 0;">
<i class="fa-solid fa-star "
style="color: #fff;font-size:14px;"></i>
</div>
<div>
<p style="color: #1A202C;font-weight: 600;
font-size: 1.2rem; margin-bottom: 2px;">
Api Key Generation</p>
<p class="m-0" style="color:#718096">This module
Api key generation using database
authentication.
</p>
</div>
</div>
</div>
<div class="col-md-6 col-sm-12 p-3"> <div class="col-md-6 col-sm-12 p-3">
<div class="d-flex h-100" style="padding: 30px;border-radius: 12px; <div class="d-flex h-100" style="padding: 30px;border-radius: 12px;
background: #FFF; background: #FFF;
@ -201,55 +180,48 @@
<div <div
style="border: 1px solid #d8d6d6; border-radius: 4px; background: #fff; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);"> style="border: 1px solid #d8d6d6; border-radius: 4px; background: #fff; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);">
<div class="row justify-content-center p-3 w-100 m-0"> <div class="row justify-content-center p-3 w-100 m-0">
<img src="assets/screenshots/rest_api_1.png"
class="img-responsive" width="100%"
height="auto">
</div>
<div class="row justify-content-center p-3 w-100 m-0">
<img src="assets/screenshots/rest_api.png"
class="img-responsive" width="100%"
height="auto">
</div>
<div class="px-3">
<h4 class="mt-2" <h4 class="mt-2"
style=" font-weight:600 !important; color:#282F33 !important; font-size:1.3rem !important"> style=" font-weight:600 !important; color:#282F33 !important; font-size:1.3rem !important">
<ul> Installation
<li>First of all, we have to add a new
parameter in odoo conf.
file.
</li>
<li><b>server_wide_modules = web, base,
rest_api_odoo</b><br/>
- This will allow us to send request
to
server without
selecting database first.<br/>-
Incase
if you have to
uninstall the module , you have to
remove this parameter.
<br/>- Next we can install the
module.
</li>
<li>After installing the Rest api app we
can
see a new api key
field in users.
</li>
- Next we have to generate the api-key
for
the current
user.<br/>
<li>You can import the postman
collections
provided in the app
folder for authentication and
interacting with database in
various methods.
</li>
</ul>
</h4> </h4>
</div> </div>
<div class="px-3">
<ul>
<li>First of all, we have to add a new
parameter in the <code>odoo.conf</code>
file.
</li>
<li><code>server_wide_modules = web, base,
rest_api_odoo</code><br/>
<ul>
<li>
This will allow us to send request to
server without
selecting database first.
</li>
<li>
Incase if you have to
uninstall the module , you have to
remove this parameter.
</li>
<li>
Next we can install the module.
</li>
</ul>
</li>
<li>After installing the Rest api app we
can
see a new api key
field in users.
<ul>
<li>
Next we have to generate the API key
for the current user.
</li>
</ul>
</li>
</ul>
</div>
</div> </div>
</div> </div>
<div class="col-lg-12 py-2" <div class="col-lg-12 py-2"
@ -257,54 +229,19 @@
<div <div
style="border: 1px solid #d8d6d6; border-radius: 4px; background: #fff; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);"> style="border: 1px solid #d8d6d6; border-radius: 4px; background: #fff; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);">
<div class="row justify-content-center p-3 w-100 m-0"> <div class="row justify-content-center p-3 w-100 m-0">
<h4 class="mt-2"
style=" font-weight:600 !important; color:#282F33 !important; font-size:1.3rem !important">
Generate API Key
</h4>
<img src="assets/screenshots/rest_api_2.png" <img src="assets/screenshots/rest_api_2.png"
class="img-responsive" width="100%" class="img-responsive" width="100%"
height="auto"> height="auto">
</div> </div>
<div class="px-3"> <div class="px-3">
<h4 class="mt-2" <ul>
style=" font-weight:600 !important; color:#282F33 !important; font-size:1.3rem !important"> <li>Next you have to generate the API key under <b>My Profile</b> > <b>Account Security</b>.</li>
<ul> <li>Set the name of the API key according to your needs.</li>
<li>We have attached <b>Postman </ul>
collections</b> through which
you can
authenticate rest api.
</li>
<li>First, extract the <b>zip</b> file.
Then, you will obtain the
JSON-format
file, which you can directly import
into
<b>POSTMAN.</b></li>
<li>The url format will be like this -
<b>http://localhost:8017/odoo_connect</b>
Replace 'localhost:8016' with your
localhost port number.
</li>
<li>You have to provide database name,
username and password
through the headers while sending
request.
</li>
<li>If the authentication is successful
, an
api key will be
generated for the current user.
</li>
<li>This key will be used when sending
api
requests to
database.
</li>
<li>The response will be like this - <b>
{"Status": "auth
successful", "User": "Mitchell
Admin",
"api-key":
"66c2ebab-d4dc-42f0-87d0-d1646e887569"}.</b>
</li>
</ul>
</h4>
</div> </div>
</div> </div>
</div> </div>
@ -313,6 +250,10 @@
<div <div
style="border: 1px solid #d8d6d6; border-radius: 4px; background: #fff; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);"> style="border: 1px solid #d8d6d6; border-radius: 4px; background: #fff; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);">
<div class="row justify-content-center p-3 w-100 m-0"> <div class="row justify-content-center p-3 w-100 m-0">
<h4 class="mt-2"
style=" font-weight:600 !important; color:#282F33 !important; font-size:1.3rem !important">
Create API Records
</h4>
<img src="assets/screenshots/rest_api_3.png" <img src="assets/screenshots/rest_api_3.png"
class="img-responsive" width="100%" class="img-responsive" width="100%"
height="auto"> height="auto">
@ -328,13 +269,11 @@
height="auto"> height="auto">
</div> </div>
<div class="px-3"> <div class="px-3">
<h4 class="mt-2"
style=" font-weight:600 !important; color:#282F33 !important; font-size:1.3rem !important">
<ul> <ul>
<li>After rest api authentication, we <li>After Rest API authentication, we
can can
create records in the create records in the
rest api app. Rest API app.
</li> </li>
<li>Here we can choose the model, and <li>Here we can choose the model, and
also also
@ -346,7 +285,6 @@
records. records.
</li> </li>
</ul> </ul>
</h4>
</div> </div>
</div> </div>
</div> </div>
@ -358,51 +296,29 @@
<h4 class="mt-2" <h4 class="mt-2"
style=" font-weight:600 !important; color:#282F33 !important; font-size:1.3rem !important"> style=" font-weight:600 !important; color:#282F33 !important; font-size:1.3rem !important">
Get Records</h4> Get Records</h4>
</div>
</div>
</div>
<div class="col-lg-12 py-2"
style="padding: 1rem 4rem !important;">
<div
style="border: 1px solid #d8d6d6; border-radius: 4px; background: #fff; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);">
<div class="px-3">
<ul> <ul>
<li>You can send GET request to retrieve <li>You can send <code>GET</code> request to retrieve data from the
data from the
database. database.
</li> </li>
<li>The postman collection has been provided <li>You have to provide the API key in the header: <code>Authorization: Bearer {API_KEY}</code>
with--> where <code>{API_KEY}</code> should be replaced with the actual API key.</li>
app files for
sending request from postman.
</li>
<li>You have to provide username, password
and api
key through
the header.
</li> </li>
<li>Model can be passed as argument as the <li>Model can be passed as argument as the technical name, and
technical also if you want to get a specific record you can provide any
name , and of the related fields to the module as well.
also if you want </li>
specific record you can provide the id <li>The format for GET method will be like this - <code>http://cybrosys:8016/send_request?model=res.partner&id=10</code>.
as well, </li>
<li>We can specify the fields inside the JSON data, and it will
be like this - <code>{"fields": ["name", "email"]}</code>.
If no fields are passed , it will returns just the record's ID.
To get all of the fields, set the fields to wildcard - <code>{"fields": ["*"]}</code>.
Pagination can also be used by adding <code>{"limit": 10, "offset": 0}</code>
to the query parameter above.
</li> </li>
<li>The format for GET method will be like <li>This is the format of API response - <code>{"records": [{"id":
this 10, "email": "deco.addict82@example.com", "name": "Deco
<b>http://localhost:8016/send_request?model=res.partner&Id=10.</b> Addict"}]}</code>.
</li>
<li>We can specify the fields inside the
JSON data,
and it will
be like this - <b>{"fields": ["name",
"email"]}.</b></li>
<li>This is the format of api response - <b>{"records":
[{"id":
10, "email":
"deco.addict82@example.com",
"name": "Deco
Addict"}]}.</b>
</li> </li>
</ul> </ul>
@ -416,27 +332,16 @@
<div class="px-3"> <div class="px-3">
<h4 class="mt-2" <h4 class="mt-2"
style=" font-weight:600 !important; color:#282F33 !important; font-size:1.3rem !important"> style=" font-weight:600 !important; color:#282F33 !important; font-size:1.3rem !important">
Create Records</h4> Create Record
</div> </h4>
</div>
</div>
<div class="col-lg-12 py-2"
style="padding: 1rem 4rem !important;">
<div
style="border: 1px solid #d8d6d6; border-radius: 4px; background: #fff; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);">
<div class="px-3">
<h4 class="mt-2"
style=" font-weight:600 !important; color:#282F33 !important; font-size:1.3rem !important">
<ul> <ul>
<li>Using POST method , you can create <li>Using <code>POST</code> method , you can create new records in the
new records
in the
database. database.
</li> </li>
<li>Just make sure you enabled POST <li>Just make sure you enabled POST
method for the method for the
model record model record
in rest api app , otherwise you will in Rest API app , otherwise you will
get <b>'method get <b>'method
not not
allowed'</b> message. allowed'</b> message.
@ -453,41 +358,29 @@
</li> </li>
<li>The format for sending POST request <li>The format for sending POST request
will be like will be like
this - <b>http://localhost:8016/send_request?model=res.partner.</b> this - <code>http://localhost:8016/send_request?model=res.partner</code>.
</li> </li>
<li>This is the format for JSON data - <li>This is the format for JSON data -
<b>{ <code>{
"fields" :["name", "phone"] , "fields" :["name", "phone"] ,
"values": {"name": "abc", "values": {"name": "abc",
"phone":"55962441552" "phone":"55962441552"
} }.</b> } }</code>.
</li> </li>
<li>Make sure the data entered in <li>Make sure the data entered in
correct format correct format
otherwise you otherwise you
will get <b>'Invalid JSON data' will get <code>Invalid JSON data'
message.</b> </code> message.
</li> </li>
<li>Response will be in this format - <li>Response will be in this format -
<b>{"New <code>{"New
resource": resource":
[{"id": 51, "name": "abc", [{"id": 51, "name": "abc",
"phone": "phone":
"55962441552"}]}.</b> "55962441552"}]}</code>.
</li> </li>
</ul> </ul>
</h4>
</div>
</div>
</div>
<div class="col-lg-12 py-2"
style="padding: 1rem 4rem !important;">
<div
style="border: 1px solid #d8d6d6; border-radius: 4px; background: #fff; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);">
<div class="px-3">
<h4 class="mt-2"
style=" font-weight:600 !important; color:#282F33 !important; font-size:1.3rem !important">
Update Records</h4>
</div> </div>
</div> </div>
</div> </div>
@ -498,10 +391,12 @@
<div class="px-3"> <div class="px-3">
<h4 class="mt-2" <h4 class="mt-2"
style=" font-weight:600 !important; color:#282F33 !important; font-size:1.3rem !important"> style=" font-weight:600 !important; color:#282F33 !important; font-size:1.3rem !important">
Update Record
</h4>
<ul> <ul>
<li>Updation of records in the database <li>Updation of records in the database
can be done can be done
with PUT with <code>PUT</code>
method. method.
</li> </li>
<li>You have to provide the model and <li>You have to provide the model and
@ -521,7 +416,7 @@
</li> </li>
<li>The format for sending PUT request <li>The format for sending PUT request
will be like will be like
this - <b>http://localhost:8016/send_request?model=res.partner&Id=46.</b> this - <code>http://localhost:8016/send_request?model=res.partner&id=46</code>.
</li> </li>
<li>Here too you have to provide the <li>Here too you have to provide the
JSON data JSON data
@ -529,23 +424,11 @@
updates will be done. updates will be done.
</li> </li>
<li>The response format will be like <li>The response format will be like
this - <b>{"Updated this - <code>{"Updated
resource": [{"id": 46, "email": resource": [{"id": 46, "email":
"abc@example.com", "name": "abc@example.com", "name":
"Toni"}]}.</b></li> "Toni"}]}</code>.</li>
</ul> </ul>
</h4>
</div>
</div>
</div>
<div class="col-lg-12 py-2"
style="padding: 1rem 4rem !important;">
<div
style="border: 1px solid #d8d6d6; border-radius: 4px; background: #fff; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);">
<div class="px-3">
<h4 class="mt-2"
style=" font-weight:600 !important; color:#282F33 !important; font-size:1.3rem !important">
Delete Records</h4>
</div> </div>
</div> </div>
</div> </div>
@ -556,10 +439,12 @@
<div class="px-3"> <div class="px-3">
<h4 class="mt-2" <h4 class="mt-2"
style=" font-weight:600 !important; color:#282F33 !important; font-size:1.3rem !important"> style=" font-weight:600 !important; color:#282F33 !important; font-size:1.3rem !important">
Delete Record
</h4>
<ul> <ul>
<li>Database records can be deleted by <li>Database records can be deleted by
sending sending
DELETE method <code>DELETE</code> method
request. request.
</li> </li>
<li>For the deletion we have to provide <li>For the deletion we have to provide
@ -570,22 +455,21 @@
<li>Make sure you have permission to <li>Make sure you have permission to
delete files delete files
for the for the
selected model in the rest api selected model in the Rest API
record. record.
</li> </li>
<li>The delete request format will be <li>The delete request format will be
like this - like this -
<b>http://localhost:8016/send_request?model=res.partner&Id=46.</b> <code>http://localhost:8016/send_request?model=res.partner&Id=46</code>.
</li> </li>
<li> The response after successful <li> The response after successful
deletion will be deletion will be
-<b> -<code>
{"Resource deleted": [{"id": 46, {"Resource deleted": [{"id": 46,
"email": "email":
"abc@example.com", "abc@example.com",
"name": "Toni"}]}.</b></li> "name": "Toni"}]}</code>.</li>
</ul> </ul>
</h4>
</div> </div>
</div> </div>
</div> </div>
@ -599,7 +483,7 @@
src="assets/misc/star (1) 2.svg" src="assets/misc/star (1) 2.svg"
alt="" alt=""
width="16px"></span>We can create width="16px"></span>We can create
records in the rest api app. records in the Rest API app.
</li> </li>
<li class="py-3" <li class="py-3"
style="font-weight: 500;background-color: #fff; border-radius: 4px; padding: 1rem; margin-bottom: 1rem; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);"> style="font-weight: 500;background-color: #fff; border-radius: 4px; padding: 1rem; margin-bottom: 1rem; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);">

18
rest_api_odoo/views/res_users_views.xml

@ -1,18 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- Inherited user view for Adding API key. -->
<record id="view_users_form" model="ir.ui.view">
<field name="name">view.users.form.inherit.rest.api.odoo</field>
<field name="inherit_id" ref="base.view_users_form"/>
<field name="model">res.users</field>
<field name="arch" type="xml">
<xpath expr="//page[@name='access_rights']" position="after">
<page string="API" name="rest-api">
<group>
<field name="api_key" groups="base.group_user"/>
</group>
</page>
</xpath>
</field>
</record>
</odoo>
Loading…
Cancel
Save