mirror of
https://github.com/GNS3/gns3-server.git
synced 2026-11-03 05:51:15 +02:00
Pydantic v2 migration
This commit is contained in:
1 parent
11f51b3809
commit
9c456532d0
46 files changed
+221
-277
No files matched your search
@@ -321,7 +321,7 @@ class ApplianceImage(BaseModel):
|
||||
|
||||
filename: str = Field(..., title='Filename')
|
||||
version: str = Field(..., title='Version of the file')
|
||||
md5sum: str = Field(..., title='md5sum of the file', regex='^[a-f0-9]{32}$')
|
||||
md5sum: str = Field(..., title='md5sum of the file', pattern='^[a-f0-9]{32}$')
|
||||
filesize: int = Field(..., title='File size in bytes')
|
||||
download_url: Optional[Union[AnyUrl, constr(max_length=0)]] = Field(
|
||||
None, title='Download url where you can download the appliance from a browser'
|
||||
@@ -351,7 +351,7 @@ class ApplianceVersionImages(BaseModel):
|
||||
class ApplianceVersion(BaseModel):
|
||||
|
||||
name: str = Field(..., title='Name of the version')
|
||||
idlepc: Optional[str] = Field(None, regex='^0x[0-9a-f]{8}')
|
||||
idlepc: Optional[str] = Field(None, pattern='^0x[0-9a-f]{8}')
|
||||
images: Optional[ApplianceVersionImages] = Field(None, title='Images used for this version')
|
||||
|
||||
|
||||
|
||||
@@ -21,5 +21,5 @@ from pydantic import BaseModel
|
||||
|
||||
class DateTimeModelMixin(BaseModel):
|
||||
|
||||
created_at: Optional[datetime]
|
||||
updated_at: Optional[datetime]
|
||||
created_at: Optional[datetime] = None
|
||||
updated_at: Optional[datetime] = None
|
||||
@@ -16,8 +16,15 @@
|
||||
|
||||
import uuid
|
||||
|
||||
from pydantic import BaseModel, Field, SecretStr, validator
|
||||
from typing import List, Optional, Union
|
||||
from pydantic import (
|
||||
ConfigDict,
|
||||
BaseModel,
|
||||
Field,
|
||||
SecretStr,
|
||||
field_validator,
|
||||
model_validator
|
||||
)
|
||||
from typing import List, Optional, Union, Any
|
||||
from enum import Enum
|
||||
|
||||
from .nodes import NodeType
|
||||
@@ -44,9 +51,7 @@ class ComputeBase(BaseModel):
|
||||
user: str = None
|
||||
password: Optional[SecretStr] = None
|
||||
name: Optional[str] = None
|
||||
|
||||
class Config:
|
||||
use_enum_values = True
|
||||
model_config = ConfigDict(use_enum_values=True)
|
||||
|
||||
|
||||
class ComputeCreate(ComputeBase):
|
||||
@@ -55,46 +60,28 @@ class ComputeCreate(ComputeBase):
|
||||
"""
|
||||
|
||||
compute_id: Union[str, uuid.UUID] = None
|
||||
|
||||
class Config:
|
||||
schema_extra = {
|
||||
"example": {
|
||||
"name": "My compute",
|
||||
"host": "127.0.0.1",
|
||||
"port": 3080,
|
||||
"user": "user",
|
||||
"password": "password"
|
||||
}
|
||||
model_config = ConfigDict(json_schema_extra={
|
||||
"example": {
|
||||
"name": "My compute",
|
||||
"host": "127.0.0.1",
|
||||
"port": 3080,
|
||||
"user": "user",
|
||||
"password": "password"
|
||||
}
|
||||
})
|
||||
|
||||
@validator("compute_id", pre=True, always=True)
|
||||
def default_compute_id(cls, v, values):
|
||||
@model_validator(mode='before')
|
||||
@classmethod
|
||||
def set_default_compute_id_and_name(cls, data: Any) -> Any:
|
||||
|
||||
if v is not None:
|
||||
return v
|
||||
else:
|
||||
protocol = values.get("protocol")
|
||||
host = values.get("host")
|
||||
port = values.get("port")
|
||||
return uuid.uuid5(uuid.NAMESPACE_URL, f"{protocol}://{host}:{port}")
|
||||
|
||||
@validator("name", pre=True, always=True)
|
||||
def generate_name(cls, name, values):
|
||||
|
||||
if name is not None:
|
||||
return name
|
||||
else:
|
||||
protocol = values.get("protocol")
|
||||
host = values.get("host")
|
||||
port = values.get("port")
|
||||
user = values.get("user")
|
||||
if user:
|
||||
# due to random user generated by 1.4 it's common to have a very long user
|
||||
if len(user) > 14:
|
||||
user = user[:11] + "..."
|
||||
return f"{protocol}://{user}@{host}:{port}"
|
||||
else:
|
||||
return f"{protocol}://{host}:{port}"
|
||||
if "compute_id" not in data:
|
||||
data['compute_id'] = uuid.uuid5(
|
||||
uuid.NAMESPACE_URL,
|
||||
f"{data.get('protocol')}://{data.get('host')}:{data.get('port')}"
|
||||
)
|
||||
if "name" not in data:
|
||||
data['name'] = f"{data.get('protocol')}://{data.get('user', '')}@{data.get('host')}:{data.get('port')}"
|
||||
return data
|
||||
|
||||
|
||||
class ComputeUpdate(ComputeBase):
|
||||
@@ -107,14 +94,12 @@ class ComputeUpdate(ComputeBase):
|
||||
port: Optional[int] = Field(None, gt=0, le=65535)
|
||||
user: Optional[str] = None
|
||||
password: Optional[SecretStr] = None
|
||||
|
||||
class Config:
|
||||
schema_extra = {
|
||||
"example": {
|
||||
"host": "10.0.0.1",
|
||||
"port": 8080,
|
||||
}
|
||||
model_config = ConfigDict(json_schema_extra={
|
||||
"example": {
|
||||
"host": "10.0.0.1",
|
||||
"port": 8080,
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
class Capabilities(BaseModel):
|
||||
@@ -143,9 +128,7 @@ class Compute(DateTimeModelMixin, ComputeBase):
|
||||
disk_usage_percent: Optional[float] = Field(None, description="Disk usage of the compute", ge=0, le=100)
|
||||
last_error: Optional[str] = Field(None, description="Last error found on the compute")
|
||||
capabilities: Optional[Capabilities] = None
|
||||
|
||||
class Config:
|
||||
orm_mode = True
|
||||
model_config = ConfigDict(from_attributes=True)
|
||||
|
||||
|
||||
class ComputeVirtualBoxVM(BaseModel):
|
||||
@@ -182,6 +165,4 @@ class AutoIdlePC(BaseModel):
|
||||
platform: str = Field(..., description="Cisco platform")
|
||||
image: str = Field(..., description="Image path")
|
||||
ram: int = Field(..., description="Amount of RAM in MB")
|
||||
|
||||
class Config:
|
||||
schema_extra = {"example": {"platform": "c7200", "image": "/path/to/c7200_image.bin", "ram": 256}}
|
||||
model_config = ConfigDict(json_schema_extra={"example": {"platform": "c7200", "image": "/path/to/c7200_image.bin", "ram": 256}})
|
||||
@@ -14,7 +14,7 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from pydantic import BaseModel, Field
|
||||
from pydantic import ConfigDict, BaseModel, Field
|
||||
from enum import Enum
|
||||
|
||||
from .base import DateTimeModelMixin
|
||||
@@ -41,6 +41,4 @@ class ImageBase(BaseModel):
|
||||
|
||||
|
||||
class Image(DateTimeModelMixin, ImageBase):
|
||||
|
||||
class Config:
|
||||
orm_mode = True
|
||||
model_config = ConfigDict(from_attributes=True)
|
||||
@@ -54,7 +54,7 @@ class LinkBase(BaseModel):
|
||||
Link data.
|
||||
"""
|
||||
|
||||
nodes: Optional[List[LinkNode]] = Field(None, min_items=0, max_items=2)
|
||||
nodes: Optional[List[LinkNode]] = Field(None, min_length=0, max_length=2)
|
||||
suspend: Optional[bool] = None
|
||||
link_style: Optional[LinkStyle] = None
|
||||
filters: Optional[dict] = None
|
||||
@@ -63,7 +63,7 @@ class LinkBase(BaseModel):
|
||||
class LinkCreate(LinkBase):
|
||||
|
||||
link_id: UUID = Field(default_factory=uuid4)
|
||||
nodes: List[LinkNode] = Field(..., min_items=2, max_items=2)
|
||||
nodes: List[LinkNode] = Field(..., min_length=2, max_length=2)
|
||||
|
||||
|
||||
class LinkUpdate(LinkBase):
|
||||
|
||||
@@ -14,8 +14,8 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from pydantic import BaseModel, Field, validator
|
||||
from typing import List, Optional, Union
|
||||
from pydantic import BaseModel, Field, model_validator
|
||||
from typing import List, Optional, Union, Any
|
||||
from enum import Enum
|
||||
from uuid import UUID, uuid4
|
||||
|
||||
@@ -96,7 +96,7 @@ class NodePort(BaseModel):
|
||||
port_number: int = Field(..., description="Port slot")
|
||||
link_type: LinkType = Field(..., description="Type of link")
|
||||
data_link_types: dict = Field(..., description="Available PCAP types for capture")
|
||||
mac_address: Union[str, None] = Field(None, regex="^([0-9a-fA-F]{2}[:]){5}([0-9a-fA-F]{2})$")
|
||||
mac_address: Union[str, None] = Field(None, pattern="^([0-9a-fA-F]{2}[:]){5}([0-9a-fA-F]{2})$")
|
||||
|
||||
|
||||
class NodeBase(BaseModel):
|
||||
@@ -117,7 +117,7 @@ class NodeBase(BaseModel):
|
||||
False, description="Automatically start the console when the node has started"
|
||||
)
|
||||
aux: Optional[int] = Field(None, gt=0, le=65535, description="Auxiliary console TCP port")
|
||||
aux_type: Optional[ConsoleType]
|
||||
aux_type: Optional[ConsoleType] = None
|
||||
properties: Optional[dict] = Field(default_factory=dict, description="Properties specific to an emulator")
|
||||
|
||||
label: Optional[Label] = None
|
||||
@@ -134,21 +134,18 @@ class NodeBase(BaseModel):
|
||||
first_port_name: Optional[str] = Field(None, description="Name of the first port")
|
||||
custom_adapters: Optional[List[CustomAdapter]] = None
|
||||
|
||||
@validator("port_name_format", pre=True, always=True)
|
||||
def default_port_name_format(cls, v, values):
|
||||
if v is None:
|
||||
if "node_type" in values and values["node_type"] == NodeType.iou:
|
||||
return "Ethernet{segment0}/{port0}"
|
||||
return "Ethernet{0}"
|
||||
return v
|
||||
@model_validator(mode='before')
|
||||
@classmethod
|
||||
def set_default_port_name_format_and_port_segment_size(cls, data: Any) -> Any:
|
||||
|
||||
@validator("port_segment_size", pre=True, always=True)
|
||||
def default_port_segment_size(cls, v, values):
|
||||
if v is None:
|
||||
if "node_type" in values and values["node_type"] == NodeType.iou:
|
||||
return 4
|
||||
return 0
|
||||
return v
|
||||
if "port_name_format" not in data:
|
||||
if data.get('node_type') == NodeType.iou:
|
||||
data['port_name_format'] = "Ethernet{segment0}/{port0}"
|
||||
data['port_segment_size'] = 4
|
||||
else:
|
||||
data['port_name_format'] = "Ethernet{0}"
|
||||
data['port_segment_size'] = 0
|
||||
return data
|
||||
|
||||
|
||||
class NodeCreate(NodeBase):
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from typing import Optional, List
|
||||
from pydantic import BaseModel, validator
|
||||
from pydantic import field_validator, ConfigDict, BaseModel
|
||||
from uuid import UUID
|
||||
from enum import Enum
|
||||
|
||||
@@ -53,11 +53,10 @@ class PermissionBase(BaseModel):
|
||||
path: str
|
||||
action: PermissionAction
|
||||
description: Optional[str] = None
|
||||
model_config = ConfigDict(use_enum_values=True)
|
||||
|
||||
class Config:
|
||||
use_enum_values = True
|
||||
|
||||
@validator("action", pre=True)
|
||||
@field_validator("action", mode="before")
|
||||
@classmethod
|
||||
def action_uppercase(cls, v):
|
||||
return v.upper()
|
||||
|
||||
@@ -81,9 +80,7 @@ class PermissionUpdate(PermissionBase):
|
||||
class Permission(DateTimeModelMixin, PermissionBase):
|
||||
|
||||
permission_id: UUID
|
||||
|
||||
class Config:
|
||||
orm_mode = True
|
||||
model_config = ConfigDict(from_attributes=True)
|
||||
|
||||
|
||||
class RoleBase(BaseModel):
|
||||
@@ -116,6 +113,4 @@ class Role(DateTimeModelMixin, RoleBase):
|
||||
role_id: UUID
|
||||
is_builtin: bool
|
||||
permissions: List[Permission]
|
||||
|
||||
class Config:
|
||||
orm_mode = True
|
||||
model_config = ConfigDict(from_attributes=True)
|
||||
@@ -14,7 +14,7 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from pydantic import BaseModel, Field
|
||||
from pydantic import ConfigDict, BaseModel, Field
|
||||
from typing import Optional, Union
|
||||
from enum import Enum
|
||||
from uuid import UUID
|
||||
@@ -58,15 +58,11 @@ class TemplateCreate(TemplateBase):
|
||||
|
||||
name: str
|
||||
template_type: NodeType
|
||||
|
||||
class Config:
|
||||
extra = "allow"
|
||||
model_config = ConfigDict(extra="allow")
|
||||
|
||||
|
||||
class TemplateUpdate(TemplateBase):
|
||||
|
||||
class Config:
|
||||
extra = "allow"
|
||||
model_config = ConfigDict(extra="allow")
|
||||
|
||||
|
||||
class Template(DateTimeModelMixin, TemplateBase):
|
||||
@@ -77,10 +73,7 @@ class Template(DateTimeModelMixin, TemplateBase):
|
||||
symbol: str
|
||||
builtin: bool
|
||||
template_type: NodeType
|
||||
|
||||
class Config:
|
||||
extra = "allow"
|
||||
orm_mode = True
|
||||
model_config = ConfigDict(extra="allow", from_attributes=True)
|
||||
|
||||
|
||||
class TemplateUsage(BaseModel):
|
||||
|
||||
@@ -44,7 +44,7 @@ class DockerTemplate(TemplateBase):
|
||||
description="Path of the web interface",
|
||||
)
|
||||
console_resolution: Optional[str] = Field(
|
||||
"1024x768", regex="^[0-9]+x[0-9]+$", description="Console resolution for VNC"
|
||||
"1024x768", pattern="^[0-9]+x[0-9]+$", description="Console resolution for VNC"
|
||||
)
|
||||
extra_hosts: Optional[str] = Field("", description="Docker extra hosts (added to /etc/hosts)")
|
||||
extra_volumes: Optional[List] = Field([], description="Additional directories to make persistent")
|
||||
|
||||
@@ -40,12 +40,12 @@ class DynamipsTemplate(TemplateBase):
|
||||
exec_area: Optional[int] = Field(64, description="Exec area value")
|
||||
mmap: Optional[bool] = Field(True, description="MMAP feature")
|
||||
mac_addr: Optional[str] = Field(
|
||||
"", description="Base MAC address", regex="^([0-9a-fA-F]{4}\\.){2}[0-9a-fA-F]{4}$|^$"
|
||||
"", description="Base MAC address", pattern="^([0-9a-fA-F]{4}\\.){2}[0-9a-fA-F]{4}$|^$"
|
||||
)
|
||||
system_id: Optional[str] = Field("FTX0945W0MY", description="System ID")
|
||||
startup_config: Optional[str] = Field("ios_base_startup-config.txt", description="IOS startup configuration file")
|
||||
private_config: Optional[str] = Field("", description="IOS private configuration file")
|
||||
idlepc: Optional[str] = Field("", description="Idle-PC value", regex="^(0x[0-9a-fA-F]+)?$|^$")
|
||||
idlepc: Optional[str] = Field("", description="Idle-PC value", pattern="^(0x[0-9a-fA-F]+)?$|^$")
|
||||
idlemax: Optional[int] = Field(500, description="Idlemax value")
|
||||
idlesleep: Optional[int] = Field(30, description="Idlesleep value")
|
||||
disk0: Optional[int] = Field(0, description="Disk0 size in MB")
|
||||
|
||||
@@ -22,14 +22,14 @@ from typing import Optional, List
|
||||
|
||||
|
||||
DEFAULT_PORTS = [
|
||||
dict(port_number=0, name="Ethernet0"),
|
||||
dict(port_number=1, name="Ethernet1"),
|
||||
dict(port_number=2, name="Ethernet2"),
|
||||
dict(port_number=3, name="Ethernet3"),
|
||||
dict(port_number=4, name="Ethernet4"),
|
||||
dict(port_number=5, name="Ethernet5"),
|
||||
dict(port_number=6, name="Ethernet6"),
|
||||
dict(port_number=7, name="Ethernet7"),
|
||||
EthernetHubPort(port_number=0, name="Ethernet0"),
|
||||
EthernetHubPort(port_number=1, name="Ethernet1"),
|
||||
EthernetHubPort(port_number=2, name="Ethernet2"),
|
||||
EthernetHubPort(port_number=3, name="Ethernet3"),
|
||||
EthernetHubPort(port_number=4, name="Ethernet4"),
|
||||
EthernetHubPort(port_number=5, name="Ethernet5"),
|
||||
EthernetHubPort(port_number=6, name="Ethernet6"),
|
||||
EthernetHubPort(port_number=7, name="Ethernet7"),
|
||||
]
|
||||
|
||||
|
||||
|
||||
@@ -23,14 +23,14 @@ from typing import Optional, List
|
||||
from enum import Enum
|
||||
|
||||
DEFAULT_PORTS = [
|
||||
dict(port_number=0, name="Ethernet0", vlan=1, type="access", ethertype="0x8100"),
|
||||
dict(port_number=1, name="Ethernet1", vlan=1, type="access", ethertype="0x8100"),
|
||||
dict(port_number=2, name="Ethernet2", vlan=1, type="access", ethertype="0x8100"),
|
||||
dict(port_number=3, name="Ethernet3", vlan=1, type="access", ethertype="0x8100"),
|
||||
dict(port_number=4, name="Ethernet4", vlan=1, type="access", ethertype="0x8100"),
|
||||
dict(port_number=5, name="Ethernet5", vlan=1, type="access", ethertype="0x8100"),
|
||||
dict(port_number=6, name="Ethernet6", vlan=1, type="access", ethertype="0x8100"),
|
||||
dict(port_number=7, name="Ethernet7", vlan=1, type="access", ethertype="0x8100"),
|
||||
EthernetSwitchPort(port_number=0, name="Ethernet0", vlan=1, type="access", ethertype="0x8100"),
|
||||
EthernetSwitchPort(port_number=1, name="Ethernet1", vlan=1, type="access", ethertype="0x8100"),
|
||||
EthernetSwitchPort(port_number=2, name="Ethernet2", vlan=1, type="access", ethertype="0x8100"),
|
||||
EthernetSwitchPort(port_number=3, name="Ethernet3", vlan=1, type="access", ethertype="0x8100"),
|
||||
EthernetSwitchPort(port_number=4, name="Ethernet4", vlan=1, type="access", ethertype="0x8100"),
|
||||
EthernetSwitchPort(port_number=5, name="Ethernet5", vlan=1, type="access", ethertype="0x8100"),
|
||||
EthernetSwitchPort(port_number=6, name="Ethernet6", vlan=1, type="access", ethertype="0x8100"),
|
||||
EthernetSwitchPort(port_number=7, name="Ethernet7", vlan=1, type="access", ethertype="0x8100"),
|
||||
]
|
||||
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ class QemuTemplate(TemplateBase):
|
||||
adapters: Optional[int] = Field(1, ge=0, le=275, description="Number of adapters")
|
||||
adapter_type: Optional[QemuAdapterType] = Field("e1000", description="QEMU adapter type")
|
||||
mac_address: Optional[str] = Field(
|
||||
"", description="QEMU MAC address", regex="^([0-9a-fA-F]{2}[:]){5}([0-9a-fA-F]{2})$|^$"
|
||||
"", description="QEMU MAC address", pattern="^([0-9a-fA-F]{2}[:]){5}([0-9a-fA-F]{2})$|^$"
|
||||
)
|
||||
first_port_name: Optional[str] = Field("", description="Optional name of the first networking port example: eth0")
|
||||
port_name_format: Optional[str] = Field(
|
||||
|
||||
@@ -75,7 +75,7 @@ def main():
|
||||
|
||||
with open(sys.argv[1]) as f:
|
||||
data = json.load(f)
|
||||
Topology.parse_obj(data)
|
||||
Topology.model_validate(data)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
from datetime import datetime
|
||||
from typing import Optional
|
||||
from pydantic import EmailStr, BaseModel, Field, SecretStr
|
||||
from pydantic import ConfigDict, EmailStr, BaseModel, Field, SecretStr
|
||||
from uuid import UUID
|
||||
|
||||
from .base import DateTimeModelMixin
|
||||
@@ -27,24 +27,24 @@ class UserBase(BaseModel):
|
||||
Common user properties.
|
||||
"""
|
||||
|
||||
username: Optional[str] = Field(None, min_length=3, regex="[a-zA-Z0-9_-]+$")
|
||||
username: Optional[str] = Field(None, min_length=3, pattern="[a-zA-Z0-9_-]+$")
|
||||
is_active: bool = True
|
||||
email: Optional[EmailStr]
|
||||
full_name: Optional[str]
|
||||
email: Optional[EmailStr] = None
|
||||
full_name: Optional[str] = None
|
||||
|
||||
|
||||
class UserCreate(UserBase):
|
||||
"""
|
||||
Properties to create an user.
|
||||
Properties to create a user.
|
||||
"""
|
||||
|
||||
username: str = Field(..., min_length=3, regex="[a-zA-Z0-9_-]+$")
|
||||
username: str = Field(..., min_length=3, pattern="[a-zA-Z0-9_-]+$")
|
||||
password: SecretStr = Field(..., min_length=6, max_length=100)
|
||||
|
||||
|
||||
class UserUpdate(UserBase):
|
||||
"""
|
||||
Properties to update an user.
|
||||
Properties to update a user.
|
||||
"""
|
||||
|
||||
password: Optional[SecretStr] = Field(None, min_length=6, max_length=100)
|
||||
@@ -56,8 +56,8 @@ class LoggedInUserUpdate(BaseModel):
|
||||
"""
|
||||
|
||||
password: Optional[SecretStr] = Field(None, min_length=6, max_length=100)
|
||||
email: Optional[EmailStr]
|
||||
full_name: Optional[str]
|
||||
email: Optional[EmailStr] = None
|
||||
full_name: Optional[str] = None
|
||||
|
||||
|
||||
class User(DateTimeModelMixin, UserBase):
|
||||
@@ -65,9 +65,7 @@ class User(DateTimeModelMixin, UserBase):
|
||||
user_id: UUID
|
||||
last_login: Optional[datetime] = None
|
||||
is_superadmin: bool = False
|
||||
|
||||
class Config:
|
||||
orm_mode = True
|
||||
model_config = ConfigDict(from_attributes=True)
|
||||
|
||||
|
||||
class UserGroupBase(BaseModel):
|
||||
@@ -75,20 +73,20 @@ class UserGroupBase(BaseModel):
|
||||
Common user group properties.
|
||||
"""
|
||||
|
||||
name: Optional[str] = Field(None, min_length=3, regex="[a-zA-Z0-9_-]+$")
|
||||
name: Optional[str] = Field(None, min_length=3, pattern="[a-zA-Z0-9_-]+$")
|
||||
|
||||
|
||||
class UserGroupCreate(UserGroupBase):
|
||||
"""
|
||||
Properties to create an user group.
|
||||
Properties to create a user group.
|
||||
"""
|
||||
|
||||
name: Optional[str] = Field(..., min_length=3, regex="[a-zA-Z0-9_-]+$")
|
||||
name: Optional[str] = Field(..., min_length=3, pattern="[a-zA-Z0-9_-]+$")
|
||||
|
||||
|
||||
class UserGroupUpdate(UserGroupBase):
|
||||
"""
|
||||
Properties to update an user group.
|
||||
Properties to update a user group.
|
||||
"""
|
||||
|
||||
pass
|
||||
@@ -98,9 +96,7 @@ class UserGroup(DateTimeModelMixin, UserGroupBase):
|
||||
|
||||
user_group_id: UUID
|
||||
is_builtin: bool
|
||||
|
||||
class Config:
|
||||
orm_mode = True
|
||||
model_config = ConfigDict(from_attributes=True)
|
||||
|
||||
|
||||
class Credentials(BaseModel):
|
||||
|
||||
Reference in new issue
Block a user