pub struct PermissionResource;Expand description
Editable adminx_permissions rows: one grant = (role, resource, action).
Trait Implementations§
Source§impl Clone for PermissionResource
impl Clone for PermissionResource
Source§fn clone(&self) -> PermissionResource
fn clone(&self) -> PermissionResource
Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
Performs copy-assignment from
source. Read moreSource§impl Resource for PermissionResource
impl Resource for PermissionResource
fn resource_name(&self) -> &'static str
fn base_path(&self) -> &'static str
Source§fn table_name(&self) -> &'static str
fn table_name(&self) -> &'static str
Backing table (SQL) or collection (Mongo) name.
fn clone_box(&self) -> Box<dyn Resource>
Source§fn permit_keys(&self) -> Vec<&'static str>
fn permit_keys(&self) -> Vec<&'static str>
Mass-assignment allow-list for create/update.
Source§fn create<'life0, 'life1, 'async_trait>(
&'life0 self,
ctx: &'life1 ReqCtx,
body: Value,
) -> Pin<Box<dyn Future<Output = ApiResponse> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn create<'life0, 'life1, 'async_trait>(
&'life0 self,
ctx: &'life1 ReqCtx,
body: Value,
) -> Pin<Box<dyn Future<Output = ApiResponse> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Create. The body lives in
crud::create so an
overriding impl can delegate to it and keep the audit recording; see that
module for why.Source§fn update<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
ctx: &'life1 ReqCtx,
id: &'life2 str,
body: Value,
) -> Pin<Box<dyn Future<Output = ApiResponse> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn update<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
ctx: &'life1 ReqCtx,
id: &'life2 str,
body: Value,
) -> Pin<Box<dyn Future<Output = ApiResponse> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Update. Body in
crud::update.Source§fn delete<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
ctx: &'life1 ReqCtx,
id: &'life2 str,
) -> Pin<Box<dyn Future<Output = ApiResponse> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn delete<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
ctx: &'life1 ReqCtx,
id: &'life2 str,
) -> Pin<Box<dyn Future<Output = ApiResponse> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Delete. Body in
crud::delete.fn primary_key(&self) -> &'static str
fn allowed_roles(&self) -> Vec<String>
fn allowed_actions(&self) -> Option<Vec<MenuAction>>
Source§fn custom_actions(&self) -> Vec<CustomAction>
fn custom_actions(&self) -> Vec<CustomAction>
Extra id-scoped operations beyond CRUD, exposed at
POST /{base}/{id}/action/{name} and as buttons on the detail page.Source§fn readonly_keys(&self) -> Vec<&'static str>
fn readonly_keys(&self) -> Vec<&'static str>
Columns that must never be client-set.
Source§fn soft_delete(&self) -> bool
fn soft_delete(&self) -> bool
Whether delete should soft-delete (set
deleted = true).Source§fn form_structure(&self) -> Option<Value>
fn form_structure(&self) -> Option<Value>
Custom form layout for create/edit pages. Return
None to derive fields
from permit_keys(). Shape: { "groups": [{ "fields": [...] }] }.Source§fn filterable_fields(&self) -> Vec<FilterField>
fn filterable_fields(&self) -> Vec<FilterField>
Columns exposed as filters on the list page. Empty (the default) means no
filter bar is shown. Build entries with
FilterField::text/select/boolean.Source§fn file_fields(&self) -> Vec<FileField>
fn file_fields(&self) -> Vec<FileField>
File attachments this resource accepts. Empty (the default) means no
upload widgets are shown. Each field renders an
<input type=file> on the
detail page, backed by the attach/serve/detach routes. Requires an
attachment backend (adminx-storage) to be registered; without one the
widgets are hidden.Source§fn search_fields(&self) -> Vec<&'static str>
fn search_fields(&self) -> Vec<&'static str>
Columns included in this resource’s full-text search document. Empty (the
default) means the resource is not searchable — no search box, no
indexing. When non-empty and a search backend (
adminx-search) is
registered, create/update keep the index in sync, delete removes the
record, and the list page grows a ?q= search box.fn list<'life0, 'life1, 'async_trait>(
&'life0 self,
ctx: &'life1 ReqCtx,
) -> Pin<Box<dyn Future<Output = ApiResponse> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
Self: 'async_trait,
fn get<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
ctx: &'life1 ReqCtx,
id: &'life2 str,
) -> Pin<Box<dyn Future<Output = ApiResponse> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Self: 'async_trait,
Source§fn form_fields(&self) -> Vec<Value>
fn form_fields(&self) -> Vec<Value>
The form fields to render on create/edit. Derived from an explicit
form_structure() when present, otherwise from permit_keys().fn list_page<'life0, 'life1, 'async_trait>(
&'life0 self,
ctx: &'life1 ReqCtx,
) -> Pin<Box<dyn Future<Output = ApiResponse> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
Self: 'async_trait,
fn new_page<'life0, 'life1, 'async_trait>(
&'life0 self,
ctx: &'life1 ReqCtx,
) -> Pin<Box<dyn Future<Output = ApiResponse> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
Self: 'async_trait,
fn edit_page<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
ctx: &'life1 ReqCtx,
id: &'life2 str,
) -> Pin<Box<dyn Future<Output = ApiResponse> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Self: 'async_trait,
fn view_page<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
ctx: &'life1 ReqCtx,
id: &'life2 str,
) -> Pin<Box<dyn Future<Output = ApiResponse> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Self: 'async_trait,
Source§fn attach_file<'life0, 'life1, 'life2, 'life3, 'async_trait>(
&'life0 self,
ctx: &'life1 ReqCtx,
id: &'life2 str,
field: &'life3 str,
csrf: Option<String>,
file: UploadedFile,
) -> Pin<Box<dyn Future<Output = ApiResponse> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait,
Self: 'async_trait,
fn attach_file<'life0, 'life1, 'life2, 'life3, 'async_trait>(
&'life0 self,
ctx: &'life1 ReqCtx,
id: &'life2 str,
field: &'life3 str,
csrf: Option<String>,
file: UploadedFile,
) -> Pin<Box<dyn Future<Output = ApiResponse> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait,
Self: 'async_trait,
Store an uploaded file against this record under
field. Called by the
web adapter after it parses the multipart body; redirects back to the
detail page on success. Gated on Update — attaching a file changes the
record.Source§fn serve_file<'life0, 'life1, 'life2, 'life3, 'async_trait>(
&'life0 self,
ctx: &'life1 ReqCtx,
id: &'life2 str,
field: &'life3 str,
) -> Pin<Box<dyn Future<Output = ApiResponse> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait,
Self: 'async_trait,
fn serve_file<'life0, 'life1, 'life2, 'life3, 'async_trait>(
&'life0 self,
ctx: &'life1 ReqCtx,
id: &'life2 str,
field: &'life3 str,
) -> Pin<Box<dyn Future<Output = ApiResponse> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait,
Self: 'async_trait,
Stream a stored attachment back. Gated on
Read — seeing the file is a
read of the record it belongs to. Returns the bytes with the stored
content type and a download-friendly filename.Source§fn detach_file<'life0, 'life1, 'life2, 'life3, 'async_trait>(
&'life0 self,
ctx: &'life1 ReqCtx,
id: &'life2 str,
field: &'life3 str,
csrf: Option<String>,
) -> Pin<Box<dyn Future<Output = ApiResponse> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait,
Self: 'async_trait,
fn detach_file<'life0, 'life1, 'life2, 'life3, 'async_trait>(
&'life0 self,
ctx: &'life1 ReqCtx,
id: &'life2 str,
field: &'life3 str,
csrf: Option<String>,
) -> Pin<Box<dyn Future<Output = ApiResponse> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait,
Self: 'async_trait,
Remove one field’s attachment. Gated on
Update; redirects back to the
detail page.Source§fn history_page<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
ctx: &'life1 ReqCtx,
id: &'life2 str,
) -> Pin<Box<dyn Future<Output = ApiResponse> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Self: 'async_trait,
fn history_page<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
ctx: &'life1 ReqCtx,
id: &'life2 str,
) -> Pin<Box<dyn Future<Output = ApiResponse> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Self: 'async_trait,
The recorded history of one record. Reads through the audit seam, so with
no auditor registered it renders an empty log rather than 404 — the route
exists either way and the page explains itself.
Source§fn create_form<'life0, 'life1, 'async_trait>(
&'life0 self,
ctx: &'life1 ReqCtx,
form: HashMap<String, String>,
) -> Pin<Box<dyn Future<Output = ApiResponse> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
Self: 'async_trait,
fn create_form<'life0, 'life1, 'async_trait>(
&'life0 self,
ctx: &'life1 ReqCtx,
form: HashMap<String, String>,
) -> Pin<Box<dyn Future<Output = ApiResponse> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
Self: 'async_trait,
Handle a submitted create form; redirects to the list on success.
Source§fn update_form<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
ctx: &'life1 ReqCtx,
id: &'life2 str,
form: HashMap<String, String>,
) -> Pin<Box<dyn Future<Output = ApiResponse> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Self: 'async_trait,
fn update_form<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
ctx: &'life1 ReqCtx,
id: &'life2 str,
form: HashMap<String, String>,
) -> Pin<Box<dyn Future<Output = ApiResponse> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Self: 'async_trait,
Handle a submitted edit form; redirects to the item view on success.
Source§fn delete_form<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
ctx: &'life1 ReqCtx,
id: &'life2 str,
csrf: Option<String>,
) -> Pin<Box<dyn Future<Output = ApiResponse> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Self: 'async_trait,
fn delete_form<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
ctx: &'life1 ReqCtx,
id: &'life2 str,
csrf: Option<String>,
) -> Pin<Box<dyn Future<Output = ApiResponse> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Self: 'async_trait,
Handle a delete from the list UI; redirects back to the list.
csrf is
the submitted hidden field, checked against the cookie before anything
is removed.Source§fn run_action<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
ctx: &'life1 ReqCtx,
name: &'life2 str,
id: String,
body: Value,
csrf: Option<String>,
) -> Pin<Box<dyn Future<Output = ApiResponse> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Self: 'async_trait,
fn run_action<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
ctx: &'life1 ReqCtx,
name: &'life2 str,
id: String,
body: Value,
csrf: Option<String>,
) -> Pin<Box<dyn Future<Output = ApiResponse> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Self: 'async_trait,
Look up a custom action by name and run it (after auth + CSRF checks).
csrf is the submitted hidden field; the action button posts a form, so
it’s guarded like the other mutating form handlers.Source§fn export<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
ctx: &'life1 ReqCtx,
format: &'life2 str,
) -> Pin<Box<dyn Future<Output = ApiResponse> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Self: 'async_trait,
fn export<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
ctx: &'life1 ReqCtx,
format: &'life2 str,
) -> Pin<Box<dyn Future<Output = ApiResponse> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Self: 'async_trait,
Export the resource’s rows as
json or csv (used by ?download=).Whether the principal in
ctx may perform action on this resource.
Delegates to the authorization seam: always allowed when auth is not
configured; a registered Authorizer decides
per action; otherwise the principal must hold one of allowed_roles().Source§fn filter_writable(
&self,
body: Value,
) -> Result<Map<String, Value>, ApiResponse>
fn filter_writable( &self, body: Value, ) -> Result<Map<String, Value>, ApiResponse>
Apply the permit/readonly/primary-key rules to an incoming JSON body,
returning the writable column map or a ready-made error response.
Auto Trait Implementations§
impl Freeze for PermissionResource
impl RefUnwindSafe for PermissionResource
impl Send for PermissionResource
impl Sync for PermissionResource
impl Unpin for PermissionResource
impl UnsafeUnpin for PermissionResource
impl UnwindSafe for PermissionResource
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more