Skip to content

Commit d3c2ae3

Browse files
paradoxxxzerosebastienbeau
authored andcommitted
[MIG] fastapi_auth_partner: Migration to 18.0
1 parent c3aade5 commit d3c2ae3

9 files changed

Lines changed: 76 additions & 62 deletions

File tree

fastapi_auth_partner/__manifest__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
{
77
"name": "Fastapi Auth Partner",
88
"summary": """This provides an implementation of auth_partner for FastAPI""",
9-
"version": "16.0.1.0.0",
9+
"version": "18.0.1.0.0",
1010
"license": "AGPL-3",
1111
"author": "Akretion,Odoo Community Association (OCA)",
1212
"website": "https://github.com/OCA/rest-framework",
@@ -16,6 +16,7 @@
1616
],
1717
"data": [
1818
"security/res_group.xml",
19+
"security/ir_rule.xml",
1920
"security/ir.model.access.csv",
2021
"views/auth_partner_view.xml",
2122
"views/auth_directory_view.xml",

fastapi_auth_partner/dependencies.py

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,7 @@
33
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
44

55
import logging
6-
import sys
7-
from typing import Any
6+
from typing import Annotated, Any
87

98
from itsdangerous import URLSafeTimedSerializer
109
from starlette.status import HTTP_401_UNAUTHORIZED
@@ -17,11 +16,6 @@
1716

1817
from fastapi import Cookie, Depends, HTTPException, Request, Response
1918

20-
if sys.version_info >= (3, 9):
21-
from typing import Annotated
22-
else:
23-
from typing import Annotated
24-
2519
_logger = logging.getLogger(__name__)
2620

2721

fastapi_auth_partner/models/auth_partner.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
# @author Florian Mounier <florian.mounier@akretion.com>
44
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
55

6-
from odoo import _, models
6+
from odoo import models
77
from odoo.exceptions import AccessDenied, UserError
88
from odoo.http import request
99

@@ -16,11 +16,13 @@ def local_impersonate(self):
1616
self.ensure_one()
1717

1818
if not self.env.user._is_admin():
19-
raise AccessDenied(_("Only admin can impersonate locally"))
19+
raise AccessDenied(self.env._("Only admin can impersonate locally"))
2020

2121
if not hasattr(request, "future_response"):
2222
raise UserError(
23-
_("Please install base_future_response for local impersonate to work")
23+
self.env._(
24+
"Please install base_future_response for local impersonate to work"
25+
)
2426
)
2527

2628
for endpoint in self.directory_id.fastapi_endpoint_ids:
@@ -31,8 +33,8 @@ def local_impersonate(self):
3133
"type": "ir.actions.client",
3234
"tag": "display_notification",
3335
"params": {
34-
"title": _("Impersonation successful"),
35-
"message": _("You are now impersonating %s\n%%s") % self.login,
36+
"title": self.env._("Impersonation successful"),
37+
"message": self.env._("You are now impersonating %s\n%%s") % self.login,
3638
"links": [
3739
{
3840
"label": f"{endpoint.app.title()} api docs",

fastapi_auth_partner/routers/auth.py

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,12 @@
33
# @author Florian Mounier <florian.mounier@akretion.com>
44
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
55

6-
import sys
7-
8-
if sys.version_info >= (3, 9):
9-
from typing import Annotated
10-
else:
11-
from typing import Annotated
12-
136
from datetime import datetime, timedelta, timezone
7+
from typing import Annotated
148

159
from itsdangerous import URLSafeTimedSerializer
1610

17-
from odoo import _, fields, models, tools
11+
from odoo import fields, models, tools
1812
from odoo.api import Environment
1913
from odoo.exceptions import ValidationError
2014

@@ -157,23 +151,34 @@ class AuthService(models.AbstractModel):
157151
directory_id = fields.Many2one("auth.directory")
158152

159153
def new(self, vals, **kwargs):
154+
# As we are in an abstract model, we need to bypass cache since it's
155+
# based on the record id (and there is none)
156+
endpoint = vals.pop("endpoint_id")
157+
160158
rec = super().new(vals, **kwargs)
161159
# Can't have computed / related field in AbstractModel
160+
rec.endpoint_id = endpoint
162161
rec.directory_id = rec.endpoint_id.directory_id
163162
# Auto add endpoint context for mail context
164-
return rec.with_context(_fastapi_endpoint_id=vals["endpoint_id"].id)
163+
return rec.with_context(_fastapi_endpoint_id=endpoint.id)
165164

166165
def _get_auth_from_partner(self, partner):
167166
return partner._get_auth_partner_for_directory(self.directory_id)
168167

169168
def _signup(self, data):
170169
auth_partner = (
171-
self.env["auth.partner"].sudo()._signup(self.directory_id, **data.dict())
170+
self.env["auth.partner"]
171+
.sudo()
172+
._signup(self.directory_id, **data.model_dump())
172173
)
173174
return auth_partner
174175

175176
def _login(self, data):
176-
return self.env["auth.partner"].sudo()._login(self.directory_id, **data.dict())
177+
return (
178+
self.env["auth.partner"]
179+
.sudo()
180+
._login(self.directory_id, **data.model_dump())
181+
)
177182

178183
def _impersonate(self, token):
179184
return self.env["auth.partner"].sudo()._impersonating(self.directory_id, token)
@@ -224,7 +229,7 @@ def _prepare_cookie_payload(self, partner):
224229
def _prepare_cookie(self, partner):
225230
secret = self.directory_id.cookie_secret_key or self.directory_id.secret_key
226231
if not secret:
227-
raise ValidationError(_("No cookie secret key defined"))
232+
raise ValidationError(self.env._("No cookie secret key defined"))
228233
payload = self._prepare_cookie_payload(partner)
229234
value = URLSafeTimedSerializer(secret).dumps(payload)
230235
exp = (
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<?xml version="1.0" encoding="UTF-8" ?>
2+
<odoo>
3+
<record model="ir.rule" id="res_partner_api_rule">
4+
<field name="name">Auth API (res_partner)</field>
5+
<field name="model_id" ref="base.model_res_partner" />
6+
<field name="groups" eval="[(4, ref('auth_partner.group_auth_partner_api'))]" />
7+
<field name="domain_force">[('id','=', authenticated_partner_id)]</field>
8+
<field name="perm_read" eval="True" />
9+
<field name="perm_create" eval="False" />
10+
<field name="perm_write" eval="False" />
11+
<field name="perm_unlink" eval="False" />
12+
</record>
13+
14+
<record model="ir.rule" id="auth_partner_api_rule">
15+
<field name="name">Auth API (auth_partner)</field>
16+
<field name="model_id" ref="auth_partner.model_auth_partner" />
17+
<field name="groups" eval="[(4, ref('auth_partner.group_auth_partner_api'))]" />
18+
<field
19+
name="domain_force"
20+
>[('partner_id','=', authenticated_partner_id)]</field>
21+
<field name="perm_read" eval="True" />
22+
<field name="perm_create" eval="False" />
23+
<field name="perm_write" eval="False" />
24+
<field name="perm_unlink" eval="False" />
25+
</record>
26+
</odoo>

fastapi_auth_partner/tests/test_auth.py

Lines changed: 15 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
# @author Sébastien BEAU <sebastien.beau@akretion.com>
33
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
44

5-
import json
65
from contextlib import contextmanager
76
from functools import partial
87

@@ -45,26 +44,22 @@ def _register_partner(self):
4544
with self._create_test_client() as test_client, self.new_mails() as new_mails:
4645
response: Response = test_client.post(
4746
"/auth/register",
48-
content=json.dumps(
49-
{
50-
"name": "Loriot",
51-
"login": "loriot@example.org",
52-
"password": "supersecret",
53-
}
54-
),
47+
json={
48+
"name": "Loriot",
49+
"login": "loriot@example.org",
50+
"password": "supersecret",
51+
},
5552
)
5653
self.assertEqual(response.status_code, status.HTTP_201_CREATED, response.text)
5754
return response, new_mails
5855

5956
def _login(self, test_client, password="supersecret"):
6057
response: Response = test_client.post(
6158
"/auth/login",
62-
content=json.dumps(
63-
{
64-
"login": "loriot@example.org",
65-
"password": password,
66-
}
67-
),
59+
json={
60+
"login": "loriot@example.org",
61+
"password": password,
62+
},
6863
)
6964
self.assertEqual(response.status_code, status.HTTP_200_OK, response.text)
7065
return response
@@ -105,7 +100,7 @@ def test_request_reset_password(self):
105100
with self._create_test_client() as test_client, self.new_mails() as new_mails:
106101
response: Response = test_client.post(
107102
"/auth/request_reset_password",
108-
content=json.dumps({"login": "loriot@example.org"}),
103+
json={"login": "loriot@example.org"},
109104
)
110105
self.assertEqual(response.status_code, status.HTTP_200_OK, response.text)
111106
self.assertFalse(
@@ -121,12 +116,10 @@ def test_request_reset_password(self):
121116
token = str(new_mails.body).split("token=")[1].split('">')[0]
122117
response: Response = test_client.post(
123118
"/auth/set_password",
124-
content=json.dumps(
125-
{
126-
"password": "megasecret",
127-
"token": token,
128-
}
129-
),
119+
json={
120+
"password": "megasecret",
121+
"token": token,
122+
},
130123
)
131124
self.assertEqual(response.status_code, status.HTTP_200_OK, response.text)
132125

@@ -155,7 +148,7 @@ def test_validate_email(self):
155148
with self._create_test_client() as test_client:
156149
response: Response = test_client.post(
157150
"/auth/validate_email",
158-
content=json.dumps({"token": token}),
151+
json={"token": token},
159152
)
160153
self.assertEqual(response.status_code, status.HTTP_200_OK, response.text)
161154

fastapi_auth_partner/tests/test_fastapi_auth_partner_demo.py

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,23 +4,18 @@
44
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
55

66
import json
7-
import sys
7+
from typing import Annotated
88

99
from odoo import tests
10+
from odoo.tools import mute_logger
1011

1112
from odoo.addons.base.models.res_partner import Partner
1213
from odoo.addons.fastapi_auth_partner.dependencies import AuthPartner
13-
14-
from fastapi import Depends, status
15-
16-
if sys.version_info >= (3, 9):
17-
from typing import Annotated
18-
else:
19-
from typing import Annotated
20-
2114
from odoo.addons.fastapi_auth_partner.routers.auth import auth_router
2215
from odoo.addons.fastapi_auth_partner.schemas import AuthPartnerResponse
2316

17+
from fastapi import Depends, status
18+
2419

2520
@auth_router.get("/auth/whoami-public-or-partner")
2621
def whoami_public_or_partner(
@@ -48,6 +43,7 @@ def _register_partner(self):
4843
return self.url_open(
4944
"/fastapi_auth_partner_demo/auth/register",
5045
timeout=1000,
46+
headers={"Content-Type": "application/json"},
5147
data=json.dumps(
5248
{
5349
"name": "Loriot",
@@ -75,6 +71,7 @@ def test_profile(self):
7571
{"login": "loriot@example.org", "mail_verified": False},
7672
)
7773

74+
@mute_logger("odoo.http", "odoo.addons.base.models.assetsbundle")
7875
def test_profile_forbidden(self):
7976
"""A end-to-end test with negative authentication."""
8077
resp = self.url_open("/fastapi_auth_partner_demo/auth/profile")

fastapi_auth_partner/views/fastapi_endpoint_view.xml

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,10 @@
66
<field name="arch" type="xml">
77
<span name="configuration" position="after">
88
<group name="Auth Configuration">
9-
<field name="is_auth_partner" invisible="1" />
109
<field
1110
name="directory_id"
12-
attrs="{
13-
'invisible': [('is_auth_partner', '=', False)],
14-
'required': [('is_auth_partner', '=', True)]
15-
}"
11+
invisible="not is_auth_partner"
12+
required="is_auth_partner"
1613
/>
1714
</group>
1815
</span>

fastapi_auth_partner/wizards/wizard_auth_partner_impersonate_view.xml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
Please choose an endpoint:
88
<group>
99
<field name="auth_partner_id" readonly="1" />
10-
<field name="auth_directory_id" invisible="1" />
1110
<field
1211
name="fastapi_endpoint_id"
1312
domain="[('directory_id', '=', auth_directory_id)]"

0 commit comments

Comments
 (0)