Перейти к содержимому

Actions

Эта страница переведена с английского. Читать страницу на английском

Action (действие) это серверный код, который могут вызвать экран, таблица, форма, команда, JSON API или агент. #[action] объявляет, кто может его вызывать; фреймворк проверяет это до выполнения кода.

Объявление action

#[action(permission = "stock.product.read")]
pub async fn search_products(q: DataQuery, store: ProductStore) -> Result<Page<Product>> {
    Ok(q.apply(store.all()?))
}

#[action(permission = "stock.product.write", audit)]
pub async fn save_product(product: Valid<Product>, store: ProductStore) -> Result<Product> {
    store.save(product.into_inner())
}
  • Первый аргумент это входные данные. Они приходят от клиента, поэтому фреймворк читает их как недоверенный JSON.
  • Все остальные аргументы внедряются: Ctx или зарегистрированный Service.
  • Возвращаемый тип: Result<T>.

Доступ

Каждый action объявляет ровно одно из:

ПараметрЗначение
permission = "feature.resource.verb"Субъекту нужно это разрешение
publicЛюбой, включая пользователей, которые не вошли в систему

Action без доступа не компилируется. Имена разрешений пишутся строчными буквами через точки, например sales.order.write.

Другие параметры:

ПараметрЗначение
auditЗаписывает запись аудита при каждом вызове
reauthПользователь должен был недавно войти в систему (App::reauth_within)

Ошибки

ОшибкаСтатусПрименение
Error::NotFound404Записи не существует или пользователю не следует знать о её существовании
Error::Forbidden403Доступ запрещён
Error::Denied(t!("..."))403Отказ с причиной, понятной пользователю
Error::Conflict409Версия строки изменилась после загрузки формы
Error::Validation(errors)422Ошибки полей, показываются рядом с полями
Error::Internal("detail")500Подробности попадают только в журнал сервера

Ошибка поля из кода:

let mut errors = ValidationErrors::default();
errors.add(Product::code, t!("stock.code_taken", code = product.code));
return Err(errors.into());

Списки

Списки принимают DataQuery и возвращают Page<M>. Action списка никогда не возвращает все строки; таблица запрашивает страницы, а сервер ограничивает размер страницы независимо от того, что отправит клиент.

Контекст

Ctx это запрос: ctx.identity(), ctx.locale(), ctx.time_zone(), ctx.now(), ctx.today(), ctx.tenant(), ctx.license(), ctx.config(), ctx.theme() и ctx.t(&text). Используйте ctx.now() и ctx.today() вместо системных часов, чтобы тесты могли зафиксировать время через App::fixed_now.

Где используются action

  • DataGrid::of(action) загружает строки; .edit_with(action), .row_action(...) и .bulk_action(...) изменяют их.
  • Form::submit(label, action) сохраняет форму.
  • ActionButton::new(label, action, input) запускает action по кнопке.
  • Command::action(...) запускает его из палитры команд или сочетанием клавиш.
  • Feature::api(action) публикует его как JSON (см. API and OpenAPI).
  • Feature::search(action) добавляет серверный поиск в палитру команд.

Каждый путь выполняет одни и те же проверки: CSRF для вызовов из браузера, guard Feature, доступ action, затем перехватчики (interceptors).