| 814 | |
| 815 | #[expect(clippy::too_many_lines)] |
| 816 | async fn create_web( |
| 817 | &mut self, |
| 818 | actor: ActorId, |
| 819 | parameter: CreateWebParameter, |
| 820 | ) -> Result<CreateWebResponse, Report<WebCreationError>> { |
| 821 | let policy_components = PolicyComponents::builder(self) |
| 822 | .with_actor(actor) |
| 823 | .with_action(ActionName::CreateWeb, MergePolicies::No) |
| 824 | .await |
| 825 | .change_context(WebCreationError::BuildPolicyComponents)?; |
| 826 | |
| 827 | let web_id = WebId::new(parameter.id.unwrap_or_else(Uuid::new_v4)); |
| 828 | |
| 829 | match policy_components |
| 830 | .build_policy_set([ActionName::CreateWeb]) |
| 831 | .change_context(WebCreationError::PolicySetCreation)? |
| 832 | .evaluate( |
| 833 | &Request { |
| 834 | actor: policy_components.actor_id(), |
| 835 | action: ActionName::CreateWeb, |
| 836 | resource: &ResourceId::Web(web_id), |
| 837 | context: RequestContext::default(), |
| 838 | }, |
| 839 | policy_components.context(), |
| 840 | ) |
| 841 | .change_context(WebCreationError::StoreError)? |
| 842 | { |
| 843 | Authorized::Always => {} |
| 844 | Authorized::Never => { |
| 845 | return Err(Report::new(WebCreationError::NotAuthorized)) |
| 846 | .attach(StatusCode::PermissionDenied); |
| 847 | } |
| 848 | } |
| 849 | |
| 850 | let mut transaction = self |
| 851 | .transaction() |
| 852 | .await |
| 853 | .change_context(WebCreationError::StoreError)?; |
| 854 | |
| 855 | transaction |
| 856 | .as_client() |
| 857 | .execute( |
| 858 | "INSERT INTO web (id, shortname) VALUES ($1, $2)", |
| 859 | &[&web_id, ¶meter.shortname], |
| 860 | ) |
| 861 | .instrument(tracing::info_span!( |
| 862 | "INSERT", |
| 863 | otel.kind = "client", |
| 864 | db.system = "postgresql", |
| 865 | peer.service = "Postgres", |
| 866 | )) |
| 867 | .await |
| 868 | .map_err(|error| match error.code() { |
| 869 | Some(&SqlState::UNIQUE_VIOLATION) => { |
| 870 | Report::new(error).change_context(WebCreationError::AlreadyExists { web_id }) |
| 871 | } |
| 872 | _ => Report::new(error).change_context(WebCreationError::StoreError), |
| 873 | })?; |