Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view

This file was deleted.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 7 additions & 3 deletions crates/defguard_common/src/db/models/mfa_flow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,19 +49,20 @@ pub struct MfaFlowSnapshot {
pub steps: Vec<MfaFlowStep<Id>>,
}

/// Assignment of an MFA flow to a location, enriched for API consumption.
/// MFA flow assignment with location metadata.
#[derive(Clone, Debug, Serialize)]
pub struct LocationMfaFlowItem {
pub id: Id,
pub title: String,
pub step_count: i64,
pub group_ids: Vec<Id>,
pub group_names: Vec<String>,
pub position: i32,
pub is_default: bool,
}

/// Input for a single flow assignment to a location.
#[derive(Clone, Debug)]
#[derive(Clone, Debug, Deserialize, Serialize, ToSchema)]
pub struct LocationMfaFlowAssignment {
pub flow_id: Id,
pub is_default: bool,
Expand Down Expand Up @@ -525,7 +526,10 @@ impl MfaFlow<Id> {
LocationMfaFlowItem,
"SELECT mf.id, mf.title, \
COALESCE(s.step_count, 0) AS \"step_count!: i64\", \
COALESCE(array_agg(g.name ORDER BY g.name) \
COALESCE(array_agg(lmfg.group_id ORDER BY lmfg.group_id) \
FILTER (WHERE lmfg.group_id IS NOT NULL), '{}') \
AS \"group_ids!: Vec<Id>\", \
COALESCE(array_agg(g.name ORDER BY lmfg.group_id) \
FILTER (WHERE g.name IS NOT NULL), '{}') \
AS \"group_names!: Vec<String>\", \
lmf.position, lmf.is_default \
Expand Down
12 changes: 5 additions & 7 deletions crates/defguard_common/src/db/models/wizard.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,15 +122,13 @@ impl Wizard {
.fetch_one(executor)
.await?;

let active_wizard;

if has_auto_adopt_flags {
active_wizard = ActiveWizard::AutoAdoption;
let active_wizard = if has_auto_adopt_flags {
ActiveWizard::AutoAdoption
} else if is_fresh_instance {
active_wizard = ActiveWizard::Initial;
ActiveWizard::Initial
} else {
active_wizard = ActiveWizard::Migration;
}
ActiveWizard::Migration
};

wizard.active_wizard = active_wizard;

Expand Down
72 changes: 0 additions & 72 deletions crates/defguard_core/src/enterprise/handlers/device_posture.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1114,84 +1114,12 @@ pub async fn duplicate_device_posture(
Ok(ApiResponse::json(response, StatusCode::CREATED))
}

/// Request body for assigning posture checks to a VPN location.
#[derive(Clone, Debug, Deserialize, Serialize, ToSchema)]
pub struct AssignPosturesData {
pub postures: Vec<Id>,
}

/// Request body for assigning VPN locations to a posture check.
#[derive(Clone, Debug, Deserialize, Serialize, ToSchema)]
pub struct AssignLocationsData {
pub locations: Vec<Id>,
}

/// Assign device posture check policies to a location
///
/// Replaces the current assignment.
#[utoipa::path(
put,
path = "/api/v1/network/{id}/postures",
tag = "device posture",
params(
("id" = i64, Path, description = "ID of the location.")
),
request_body = AssignPosturesData,
responses(
(status = 200, description = "Device posture check policies assigned to the location.", body = [Id]),
(status = 400, description = "Posture checks cannot be assigned to a service location.", body = ApiErrorResponse, example = json!({"msg": "Posture checks cannot be assigned to service locations"})),
(status = 401, description = "Session is missing or invalid.", body = ApiErrorResponse, example = json!({"msg": "Session is required"})),
(status = 403, description = "Requires admin privileges and an active enterprise license.", body = ApiErrorResponse, example = json!({"msg": "requires privileged access"})),
(status = 404, description = "Location not found.", body = ApiErrorResponse, example = json!({"msg": "Location 1 not found"})),
(status = 500, description = "Unable to assign device posture check policies to the location.", body = ApiErrorResponse, example = json!({"msg": "Internal server error"}))
),
security(
("cookie" = []),
("api_token" = [])
)
)]
pub async fn set_postures_for_location(
_license: LicenseGated<DevicePostureFeature>,
_admin: AdminRole,
session: SessionInfo,
context: ApiRequestContext,
Path(location_id): Path<Id>,
State(appstate): State<AppState>,
Json(data): Json<AssignPosturesData>,
) -> ApiResult {
debug!(
"User {} assigning device posture checks {:?} to location {location_id}",
session.user.username, data.postures
);

let location = WireguardNetwork::find_by_id(&appstate.pool, location_id)
.await?
.ok_or_else(|| WebError::ObjectNotFound(format!("Location {location_id} not found")))?;

let mut tx = appstate.pool.begin().await?;
let old_postures = DevicePostureLocation::find_by_location(&mut *tx, location_id).await?;
let result =
DevicePostureLocation::set_for_location(&mut tx, location_id, &data.postures).await?;
let gateway_commands = if same_id_set(&old_postures, &result) {
Vec::new()
} else {
build_location_peer_refresh_commands(&mut tx, [location_id]).await?
};
tx.commit().await?;

appstate.send_multiple_gateway_commands(gateway_commands);

appstate.emit_event(ApiEvent {
context,
event: Box::new(ApiEventType::LocationPosturesAssigned {
location,
posture_ids: result.clone(),
}),
})?;

Ok(ApiResponse::json(result, StatusCode::OK))
}

/// Assign locations to a device posture check policy
///
/// Replaces the current assignment.
Expand Down
Loading
Loading