Skip to content

Commit

Permalink
Convert SMB share ACL methods to api_method (#15075)
Browse files Browse the repository at this point in the history
This commit convert smb.getacl and smb.setacl to new api_method.
  • Loading branch information
anodos325 authored Dec 2, 2024
1 parent 553ee97 commit 2670e83
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 25 deletions.
1 change: 1 addition & 0 deletions src/middlewared/middlewared/api/v25_04_0/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
from .rdma import * # noqa
from .rdma_interface import * # noqa
from .smartctl import * # noqa
from .smb import * # noqa
from .snmp import * # noqa
from .static_route import * # noqa
from .system_lifecycle import * # noqa
Expand Down
65 changes: 65 additions & 0 deletions src/middlewared/middlewared/api/v25_04_0/smb.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
from middlewared.api.base import (
BaseModel,
NonEmptyString,
single_argument_args,
SID,
)
from pydantic import Field, model_validator
from typing import Literal, Self

__all__ = [
'GetSmbAclArgs', 'GetSmbAclResult',
'SetSmbAclArgs', 'SetSmbAclResult',
]


class SMBShareAclEntryWhoId(BaseModel):
id_type: Literal['USER', 'GROUP', 'BOTH']
xid: int = Field(alias='id')


class SMBShareAclEntry(BaseModel):
ae_perm: Literal['FULL', 'CHANGE', 'READ']
""" Permissions granted to the principal. """
ae_type: Literal['ALLOWED', 'DENIED']
""" The type of SMB share ACL entry. """
ae_who_sid: SID | None = None
""" SID value of principle for whom ACL entry applies. """
ae_who_id: SMBShareAclEntryWhoId | None = None
""" Unix ID of principle for whom ACL entry applies. """
ae_who_str: NonEmptyString | None = None

@model_validator(mode='after')
def check_ae_who(self) -> Self:
if self.ae_who_sid is None and self.ae_who_id is None and self.ae_who_str is None:
raise ValueError(
'Either ae_who_sid or ae_who_id or ae_who_str is required to identify user or group '
'to which the ACL entry applies.'
)

return self


class SMBShareAcl(BaseModel):
share_name: NonEmptyString
""" Name of the SMB share. """
share_acl: list[SMBShareAclEntry] = [SMBShareAclEntry(ae_who_sid='S-1-1-0', ae_perm='FULL', ae_type='ALLOWED')]
""" List of SMB share ACL entries """


@single_argument_args('smb_setacl')
class SetSmbAclArgs(SMBShareAcl):
pass


class SetSmbAclResult(BaseModel):
result: SMBShareAcl


@single_argument_args('smb_getacl')
class GetSmbAclArgs(BaseModel):
share_name: NonEmptyString


class GetSmbAclResult(SetSmbAclResult):
pass
43 changes: 18 additions & 25 deletions src/middlewared/middlewared/plugins/smb.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,14 @@

from copy import deepcopy

from middlewared.api import api_method
from middlewared.api.current import (
GetSmbAclArgs, GetSmbAclResult,
SetSmbAclArgs, SetSmbAclResult,
)
from middlewared.common.attachment import LockableFSAttachmentDelegate
from middlewared.common.listen import SystemServiceListenMultipleDelegate
from middlewared.schema import Bool, Dict, IPAddr, List, NetbiosName, NetbiosDomain, Ref, returns, SID, Str, Int, Patch
from middlewared.schema import Bool, Dict, IPAddr, List, NetbiosName, NetbiosDomain, Str, Int, Patch
from middlewared.schema import Path as SchemaPath
# List schema defaults to [], supplying NOT_PROVIDED avoids having audit update that
# defaults for ignore_list or watch_list from overrwriting previous value
Expand Down Expand Up @@ -1529,25 +1534,12 @@ async def presets(self):
"""
return {x.name: x.value for x in SMBSharePreset}

@accepts(Dict(
'smb_share_acl',
Str('share_name', required=True),
List('share_acl', items=[
Dict(
'aclentry',
SID('ae_who_sid', default=None),
Dict(
'ae_who_id',
Str('id_type', enum=['USER', 'GROUP', 'BOTH']),
Int('id')
),
Str('ae_perm', enum=['FULL', 'CHANGE', 'READ'], required=True),
Str('ae_type', enum=['ALLOWED', 'DENIED'], required=True)
),
], default=[{'ae_who_sid': 'S-1-1-0', 'ae_perm': 'FULL', 'ae_type': 'ALLOWED'}]),
register=True
), roles=['SHARING_SMB_WRITE'], audit='Setacl SMB share', audit_extended=lambda data: data['share_name'])
@returns(Ref('smb_share_acl'))
@api_method(
SetSmbAclArgs, SetSmbAclResult,
roles=['SHARING_SMB_WRITE'],
audit='Setacl SMB share',
audit_extended=lambda data: data['share_name']
)
async def setacl(self, data):
"""
Set an ACL on `share_name`. This only impacts access through the SMB protocol.
Expand Down Expand Up @@ -1657,11 +1649,12 @@ async def setacl(self, data):
})
return await self.getacl({'share_name': data['share_name']})

@accepts(Dict(
'smb_getacl',
Str('share_name', required=True)
), roles=['SHARING_SMB_READ'], audit='Getacl SMB share', audit_extended=lambda data: data['share_name'])
@returns(Ref('smb_share_acl'))
@api_method(
GetSmbAclArgs, GetSmbAclResult,
roles=['SHARING_SMB_READ'],
audit='Getacl SMB share',
audit_extended=lambda data: data['share_name']
)
async def getacl(self, data):
verrors = ValidationErrors()

Expand Down

0 comments on commit 2670e83

Please sign in to comment.