Skip to content

Commit 15c4af5

Browse files
authored
Merge pull request #10 from akretion/fast_user_mng_plus_2
Fast user mng plus 2
2 parents 1dbc51f + 377771f commit 15c4af5

File tree

8 files changed

+310
-102
lines changed

8 files changed

+310
-102
lines changed

fastapi_user_manager/__manifest__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
"fastapi",
1515
"pydantic",
1616
],
17+
"demo": ["demo/fastapi_endpoint_demo.xml"],
1718
"data": [
1819
"views/res_users_view.xml",
1920
"views/fastapi_endpoint_view.xml",

fastapi_user_manager/data/endpoint.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<odoo>
1+
<odoo noupdate="1">
22
<record id="user_manager_endpoint" model="fastapi.endpoint">
33
<field name="name">User Manager</field>
44
<field name="app">user_manager</field>
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
<?xml version="1.0" encoding="utf-8" ?>
2+
<!-- Copyright 2022 ACSONE SA/NV
3+
License LGPL-3.0 or later (http://www.gnu.org/licenses/LGPL). -->
4+
<odoo>
5+
<!-- This is the user that will be used to run the demo app -->
6+
<record
7+
id="my_demo_app_user_user"
8+
model="res.users"
9+
context="{'no_reset_password': True, 'no_reset_password': True}"
10+
>
11+
<field name="name">My Demo Endpoint User User</field>
12+
<field name="login">my_demo_app_user_user</field>
13+
<field name="groups_id" eval="[(6, 0, [])]" />
14+
</record>
15+
16+
<!-- This is the group that will be used to run the demo app
17+
This group will only depend on the "group_fastapi_endpoint_runner" group
18+
that provides the minimal access rights to retrieve the user running the
19+
endpoint handlers and performs authentication.
20+
-->
21+
<record id="my_demo_app_group" model="res.groups">
22+
<field name="name">My Demo Endpoint Group User</field>
23+
<field name="users" eval="[(4, ref('my_demo_app_user_user'))]" />
24+
<field name="implied_ids" eval="[(4, ref('group_fastapi_endpoint_runner'))]" />
25+
</record>
26+
27+
<!-- This is the endpoint that will be used to run the demo app
28+
This endpoint will be registered on the "/fastapi_demo" path
29+
-->
30+
31+
<record model="fastapi.endpoint" id="fastapi_endpoint_demo_user">
32+
<field name="name">Fastapi Demo Endpoint user</field>
33+
<field
34+
name="description"
35+
><![CDATA[
36+
# A Dummy FastApi Demo
37+
38+
This demo endpoint has been created by inhering from "fastapi.endpoint", registering
39+
a new app into the app selection field and implementing the `_get_fastapi_routers`
40+
methods. See documentation to learn more about how to create a new app.
41+
]]></field>
42+
<field name="app">user_manager</field>
43+
<field name="root_path">/fastapi_user</field>
44+
<field name="demo_auth_method">http_basic</field>
45+
<field name="user_id" ref="my_demo_app_user_user" />
46+
</record>
47+
48+
<!-- <record id="fastapi_endpoint_multislash_demo" model="fastapi.endpoint"> -->
49+
<!-- <field name="name">Fastapi Multi-Slash Demo Endpoint</field> -->
50+
<!-- <field name="description"> -->
51+
<!-- Like the other demo endpoint but with multi-slash -->
52+
<!-- </field> -->
53+
<!-- <field name="app">demo</field> -->
54+
<!-- <field name="root_path">/fastapi/demo-multi</field> -->
55+
<!-- <field name="demo_auth_method">http_basic</field> -->
56+
<!-- <field name="user_id" ref="my_demo_app_user" /> -->
57+
<!-- </record> -->
58+
</odoo>

fastapi_user_manager/models/fastapi_endpoint.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ def api_key_based_authenticated_partner_impl(
8686
env["res.users"]
8787
.sudo()
8888
.search([("api_key_user", "=", api_key)], limit=1)
89-
.parner_id
89+
.partner_id
9090
)
9191
if not partner:
9292
raise HTTPException(
Lines changed: 84 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from typing import Annotated
22

33
from odoo import api, models
4+
from odoo.fields import Command
45

56
from odoo.addons.base.models.res_users import Users as ResUsers
67
from odoo.addons.fastapi.dependencies import (
@@ -10,54 +11,72 @@
1011

1112
from fastapi import APIRouter, Depends
1213

13-
from ..schemas.schemas import UserSc, UserScUpdate
14+
from ..schemas.schemas import UserSc, UserScDel, UserScUpdate
1415

1516
# create a router
1617
user_router = APIRouter(tags=["user"])
1718

1819

19-
@user_router.post("/user")
20+
@user_router.post("/user/create")
21+
def create_user_data(
22+
data: list[UserSc],
23+
env: Annotated[api.Environment, Depends(odoo_env)],
24+
partner: Annotated[api.Environment, Depends(authenticated_partner_env)],
25+
) -> dict:
26+
"""
27+
create user personal data of authenticated user
28+
"""
29+
30+
result = {}
31+
for d in data:
32+
user = env["res.users"].search(
33+
["|", ("login", "=", d.login), ("login", "=", d.email)]
34+
)
35+
if user:
36+
result[f"{user.name}"] = "No_modif"
37+
else:
38+
user = env["api.user.router"].create_user(d)
39+
result[f"{user.name}"] = "New ok"
40+
41+
return result
42+
43+
44+
@user_router.post("/user/update")
2045
def update_user_data(
21-
data: UserSc,
46+
data: UserScUpdate,
2247
env: Annotated[api.Environment, Depends(odoo_env)],
2348
partner: Annotated[api.Environment, Depends(authenticated_partner_env)],
24-
# user: Annotated[ResUsers, Depends(odoo_env)],
25-
) -> UserSc:
49+
):
2650
"""
2751
update user personal data of authenticated user
2852
"""
29-
user = env["res.users"].search(
30-
[("name", "=", data.name), ("email", "=", data.email)]
53+
# UserScUpdate.to_user_vals(data)
54+
# helper = env["api.user.router"].new({"user": user})
55+
updated_user = env["api.user.router"]._update_user(data)
56+
if updated_user:
57+
return "Update OK"
58+
else:
59+
return "No update, no user found"
60+
#
61+
62+
63+
@user_router.post("/user/archive")
64+
def archive_user_data(
65+
data: UserScDel,
66+
env: Annotated[api.Environment, Depends(odoo_env)],
67+
partner: Annotated[api.Environment, Depends(authenticated_partner_env)],
68+
):
69+
""" """
70+
user_to_del = env["res.users"].search(
71+
[
72+
("login", "=", data.login),
73+
]
3174
)
32-
if user:
33-
return UserSc.from_res_user(user)
75+
if user_to_del:
76+
user_to_del.active = False
77+
return "Archived user ok"
3478
else:
35-
vals = {
36-
"name": data.name,
37-
"login": data.email,
38-
"phone": data.phone,
39-
"mobile": data.mobile,
40-
}
41-
user = env["res.users"].create(vals)
42-
return UserSc.from_res_user(user)
43-
# helper = env["api.user.router"].new()
44-
# user = helper.create(data)
45-
# return UserSc.from_res_user(user)
46-
47-
48-
# def update_user_data(
49-
# data: UserScUpdate,
50-
# env: Annotated[api.Environment, Depends(odoo_env)],
51-
# # env: Annotated[api.Environment, Depends(authenticated_partner_env)],
52-
# # user: Annotated[ResUsers, Depends(odoo_env)],
53-
# ) -> ResUsers:
54-
# """
55-
# update user personal data of authenticated user
56-
# """
57-
# UserScUpdate.to_user_vals(data)
58-
# helper = env["api.user.router"].new({"user": user})
59-
# updated_user = helper._update_user(data)
60-
# return UserSc.from_res_user(updated_user)
79+
return "Error"
6180

6281

6382
class ApiUserRouter(models.AbstractModel):
@@ -67,68 +86,38 @@ class ApiUserRouter(models.AbstractModel):
6786
# user = fields.Many2one(comodel_name="res.users")
6887

6988
def _update_user(self, data: UserScUpdate) -> ResUsers:
70-
self.ensure_one()
89+
user = self.env["res.users"].search([("login", "=", data.login)])
7190
values = self._get_user_values(data)
72-
user = self.user
7391
user.write(values)
7492
# self._handle_shopinvader_customer_opt_in(data)
7593
return user
7694

77-
def _create_user(self, data: UserSc) -> ResUsers:
78-
self.ensure_one()
79-
user = self.env["res.users"].search(
80-
[("name", "=", data.name), ("email", "=", data.email)]
81-
)
82-
if user:
83-
return user
84-
else:
85-
vals = {
86-
"name": data.name,
87-
"email": data.email,
88-
"phone": data.phone,
89-
"mobile": data.mobile,
90-
}
91-
user = self.env["res.users"].create(vals)
92-
return user
93-
94-
# def _get_user_values(self, data: CustomerUpdate) -> dict:
95-
# values = data.to_user_vals()
96-
# lang_id = data.lang_id
97-
# if bool(lang_id):
98-
# values["lang"] = self.env["res.lang"].browse(lang_id).code
99-
# return values
100-
101-
102-
# @user_router.get("/users", response_model=list[UserInfo])
103-
# def get_users(env: Annotated[Environment, Depends(odoo_env)]) -> list[UserInfo]:
104-
# return [
105-
# UserInfo(name=user.name, email=user.email or "")
106-
# for user in env["res.users"].search([])
107-
# ]
108-
109-
110-
# @customer_router.get("/customer")
111-
# def get_customer_data(
112-
# partner: Annotated[ResPartner, Depends(authenticated_partner)],
113-
# ) -> Customer:
114-
# """
115-
# Get customer personal data of authenticated user
116-
# """
117-
# return Customer.from_res_partner(partner)
118-
119-
120-
# @customer_router.post(
121-
# "/customer",
122-
# )
123-
# def update_customer_data(
124-
# data: CustomerUpdate,
125-
# env: Annotated[api.Environment, Depends(authenticated_partner_env)],
126-
# partner: Annotated[ResPartner, Depends(authenticated_partner)],
127-
# ) -> Customer:
128-
# """
129-
# update customer personal data of authenticated user
130-
# """
131-
# CustomerUpdate.to_res_partner_vals(data)
132-
# helper = env["shopinvader_api_customer.router.helper"].new({"partner": partner})
133-
# updated_partner = helper._update_shopinvader_customer(data)
134-
# return Customer.from_res_partner(updated_partner)
95+
def create_user(self, data: UserSc):
96+
vals = {
97+
"name": data.name,
98+
"login": data.login,
99+
"email": data.email,
100+
"phone": data.phone,
101+
"mobile": data.mobile,
102+
}
103+
company_id = self.env["res.company"].search([("name", "=", data.company)])
104+
vals["company_id"] = company_id.id
105+
if hasattr(self.env["res.users"], "role_ids"):
106+
roles = self.env["res.users.role"].search([("name", "in", data.role)])
107+
vals["role_line_ids"] = [
108+
Command.create({"role_id": rol_id}) for rol_id in roles.ids
109+
]
110+
user = self.env["res.users"].create(vals)
111+
user = self._post_process_user_creation(user, data.misc)
112+
return user
113+
114+
def _post_process_user_creation(self, user, misc):
115+
"""inherit it to adapt to your needs"""
116+
if misc:
117+
user = user.write(misc)
118+
return user
119+
120+
def _get_user_values(self, data: UserScUpdate):
121+
"""inherit it to adapt to your needs"""
122+
values = data.misc
123+
return values

fastapi_user_manager/schemas/schemas.py

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,8 @@ class UserScUpdate(StrictExtendableBaseModel, extra="ignore"):
66
used to update user details
77
"""
88

9-
name: str | None = None
10-
mobile: str | None = None
11-
opt_in: bool | None = None
12-
lang_id: int | None = None
9+
login: str | None = None
10+
misc: dict | None = None
1311

1412
def to_user_vals(self) -> dict:
1513
fields = self._get_user_update_fields()
@@ -22,6 +20,7 @@ def _get_user_update_fields(self):
2220
"name",
2321
"phone",
2422
"mobile",
23+
"misc",
2524
]
2625

2726

@@ -30,10 +29,14 @@ class UserSc(StrictExtendableBaseModel):
3029
used to get user details
3130
"""
3231

33-
email: str
32+
login: str
33+
email: str | None = None
3434
name: str | None = None
3535
phone: str | None = None
3636
mobile: str | None = None
37+
company: str | None = None
38+
role: list | None = None
39+
misc: dict | None = None
3740

3841
@classmethod
3942
def from_res_user(cls, odoo_rec):
@@ -42,4 +45,12 @@ def from_res_user(cls, odoo_rec):
4245
name=odoo_rec.name or None,
4346
phone=odoo_rec.phone or None,
4447
mobile=odoo_rec.mobile or None,
48+
compny=odoo_rec.company_id.name or None,
49+
role=odoo_rec.role_id.name or None,
4550
)
51+
52+
53+
class UserScDel(StrictExtendableBaseModel):
54+
email: str
55+
name: str
56+
login: str
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
from . import test_fastapi_user_manager

0 commit comments

Comments
 (0)