Skip to content
This repository has been archived by the owner on Apr 24, 2024. It is now read-only.

Feature/1168 creation and update times and ids of elements #1175

Open
wants to merge 19 commits into
base: master
Choose a base branch
from
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
3 changes: 2 additions & 1 deletion .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
"name": "Debug",
"program": "${workspaceFolder}/backend/target/debug/backend",
"args": [],
"cwd": "${workspaceFolder}/backend"
"cwd": "${workspaceFolder}/backend",
"envFile": "${workspaceFolder}/backend/.env"
},
{
"type": "chrome",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
-- seeds
ALTER TABLE seeds
RENAME COLUMN created_by TO owner_id;

-- plantings
ALTER TABLE plantings
DROP COLUMN created_at,
DROP COLUMN modified_at,
DROP COLUMN created_by,
DROP COLUMN modified_by;

ALTER TABLE plantings
ALTER COLUMN notes DROP NOT NULL,
ALTER COLUMN notes DROP DEFAULT;

-- maps
ALTER TABLE maps
ADD COLUMN creation_date date;

UPDATE maps
SET
creation_date = created_at;

ALTER TABLE maps
DROP COLUMN created_at,
DROP COLUMN modified_at,
DROP COLUMN modified_by;

ALTER TABLE maps
RENAME COLUMN created_by TO owner_id;

ALTER TABLE maps
ALTER COLUMN creation_date SET NOT NULL;
56 changes: 56 additions & 0 deletions backend/migrations/2024-01-24-184709_plantings_auditability/up.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
-- maps
ALTER TABLE maps
RENAME COLUMN owner_id TO created_by;

ALTER TABLE maps
ADD COLUMN created_at timestamp (0) without time zone,
ADD COLUMN modified_at timestamp (0) without time zone,
ADD COLUMN modified_by uuid;

UPDATE maps
SET
created_at = date_trunc('day', creation_date) + interval '12:00:00',
modified_at = date_trunc('day', creation_date) + interval '12:00:00',
modified_by = created_by;

ALTER TABLE maps
DROP COLUMN creation_date;

ALTER TABLE maps
ALTER COLUMN created_at SET DEFAULT now(),
ALTER COLUMN created_at SET NOT NULL,
ALTER COLUMN modified_at SET DEFAULT now(),
ALTER COLUMN modified_at SET NOT NULL,
ALTER COLUMN created_by SET NOT NULL,
ALTER COLUMN modified_by SET NOT NULL;

-- plantings
ALTER TABLE plantings
ADD COLUMN created_at timestamp (0) without time zone,
ADD COLUMN modified_at timestamp (0) without time zone,
ADD COLUMN created_by uuid,
ADD COLUMN modified_by uuid;

UPDATE plantings
SET
created_at = maps.created_at,
modified_at = maps.modified_at,
created_by = maps.created_by,
modified_by = maps.created_by
FROM layers
INNER JOIN maps ON layers.map_id = maps.id
WHERE plantings.layer_id = layers.id;

ALTER TABLE plantings
ALTER COLUMN created_at SET DEFAULT now(),
ALTER COLUMN created_at SET NOT NULL,
ALTER COLUMN modified_at SET DEFAULT now(),
ALTER COLUMN modified_at SET NOT NULL,
ALTER COLUMN created_by SET NOT NULL,
ALTER COLUMN modified_by SET NOT NULL,
ALTER COLUMN notes SET DEFAULT '',
ALTER COLUMN notes SET NOT NULL;

-- seeds
ALTER TABLE seeds
RENAME COLUMN owner_id TO created_by;
8 changes: 3 additions & 5 deletions backend/src/config/api_doc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,8 @@ use crate::{
TimelinePagePlantingsDto,
},
plantings::{
MovePlantingDto, NewPlantingDto, PlantingDto, TransformPlantingDto,
UpdateAddDatePlantingDto, UpdatePlantingDto, UpdatePlantingNoteDto,
UpdateRemoveDatePlantingDto,
MovePlantingDto, PlantingDto, TransformPlantingDto, UpdateAddDatePlantingDto,
UpdatePlantingDto, UpdatePlantingNoteDto, UpdateRemoveDatePlantingDto,
},
timeline::{TimelineDto, TimelineEntryDto},
BaseLayerImageDto, ConfigDto, Coordinates, GainedBlossomsDto, GuidedToursDto, LayerDto,
Expand Down Expand Up @@ -173,9 +172,8 @@ struct BaseLayerImagesApiDoc;
),
components(
schemas(
PlantingDto,
TimelinePagePlantingsDto,
NewPlantingDto,
PlantingDto,
UpdatePlantingDto,
TransformPlantingDto,
MovePlantingDto,
Expand Down
8 changes: 4 additions & 4 deletions backend/src/controller/plantings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ pub async fn find(
),
request_body = ActionDtoWrapperNewPlantings,
responses(
(status = 201, description = "Create plantings", body = Vec<PlantingDto>)
(status = 201, description = "Create plantings", body = Vec<NewPlantingDto>)
),
security(
("oauth2" = [])
Expand All @@ -75,7 +75,7 @@ pub async fn create(

let ActionDtoWrapper { action_id, dto } = new_plantings.into_inner();

let created_plantings = plantings::create(dto, &app_data).await?;
let created_plantings = plantings::create(dto, map_id, user_info.id, &app_data).await?;

app_data
.broadcaster
Expand Down Expand Up @@ -116,7 +116,7 @@ pub async fn update(

let ActionDtoWrapper { action_id, dto } = update_planting.into_inner();

let updated_plantings = plantings::update(dto.clone(), &app_data).await?;
let updated_plantings = plantings::update(dto.clone(), map_id, user_info.id, &app_data).await?;

let action = match &dto {
UpdatePlantingDto::Transform(dto) => {
Expand Down Expand Up @@ -169,7 +169,7 @@ pub async fn delete(

let ActionDtoWrapper { action_id, dto } = delete_planting.into_inner();

plantings::delete_by_ids(dto.clone(), &app_data).await?;
plantings::delete_by_ids(dto.clone(), map_id, user_info.id, &app_data).await?;

app_data
.broadcaster
Expand Down
24 changes: 13 additions & 11 deletions backend/src/model/dto.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//! DTOs of `PermaplanT`.
#![allow(clippy::module_name_repetitions)] // There needs to be a difference between DTOs and entities otherwise imports will be messy.

use chrono::NaiveDate;
use chrono::{NaiveDate, NaiveDateTime};
use postgis_diesel::types::{Point, Polygon};
use serde::{Deserialize, Serialize};
use typeshare::typeshare;
Expand Down Expand Up @@ -79,8 +79,8 @@ pub struct SeedDto {
pub price: Option<i16>,
/// Notes about the seeds.
pub notes: Option<String>,
/// The id of the owner of the seed.
pub owner_id: Uuid,
/// The id of the creator of the seed.
pub created_by: Uuid,
/// Timestamp indicating when the seed was archived.
/// Empty if the seed was not archived.
pub archived_at: Option<String>,
Expand Down Expand Up @@ -215,8 +215,14 @@ pub struct MapDto {
pub id: i32,
/// The name of the map.
pub name: String,
/// The date the map was created.
pub creation_date: NaiveDate,
/// When the map was created.
pub created_at: NaiveDateTime,
/// When a map was last modified, e.g by modifying plantings.
pub modified_at: NaiveDateTime,
/// The id of the creator of the map.
pub created_by: Uuid,
/// By whom the map was last modified.
pub modified_by: Uuid,
/// The date the map is supposed to be deleted.
pub deletion_date: Option<NaiveDate>,
/// The date the last time the map view was opened by any user.
Expand All @@ -237,8 +243,6 @@ pub struct MapDto {
pub description: Option<String>,
/// The location of the map as a latitude/longitude point.
pub location: Option<Coordinates>,
/// The id of the owner of the map.
pub owner_id: Uuid,
/// The geometry of the map.
///
/// E.g. `{"rings": [[{"x": 0.0,"y": 0.0},{"x": 1000.0,"y": 0.0},{"x": 1000.0,"y": 1000.0},{"x": 0.0,"y": 1000.0},{"x": 0.0,"y": 0.0}]],"srid": 4326}`
Expand All @@ -253,8 +257,6 @@ pub struct MapDto {
pub struct NewMapDto {
/// The name of the map.
pub name: String,
/// The date the map was created.
pub creation_date: NaiveDate,
/// The date the map is supposed to be deleted.
pub deletion_date: Option<NaiveDate>,
/// The date the last time the map view was opened by any user.
Expand Down Expand Up @@ -317,8 +319,8 @@ pub struct MapSearchParameters {
pub name: Option<String>,
/// Whether or not the map is active.
pub is_inactive: Option<bool>,
/// The owner of the map.
pub owner_id: Option<Uuid>,
/// The creator of the map.
pub created_by: Option<Uuid>,
/// The selected privacy of the map.
pub privacy: Option<PrivacyOption>,
}
Expand Down
88 changes: 27 additions & 61 deletions backend/src/model/dto/actions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ use super::{
BaseLayerImageDto, UpdateMapGeometryDto,
};

/// Actions broadcast events to other users viewing the same map,
/// so that they can update the map state appropriately.
/// It keeps all users on the map in sync via [`crate::sse::broadcaster::Broadcaster`]
#[typeshare]
#[derive(Debug, Serialize, Clone)]
#[serde(rename_all = "camelCase")]
Expand All @@ -34,44 +37,46 @@ pub struct Action {

#[typeshare]
#[derive(Debug, Serialize, Clone)]
// Use the name of the enum variant as the type field looking like { "type": "CreatePlanting", ... }.
/// An enum representing all the actions that can be broadcasted via [`crate::sse::broadcaster::Broadcaster`].
// Use the name of the enum variant as the field "type" looking like
/// { "type": "CreatePlanting", "payload": ... }.
#[serde(tag = "type", content = "payload")]
pub enum ActionType {
/// An action used to broadcast creation of a plant.
CreatePlanting(Vec<CreatePlantActionPayload>),
/// An action used to broadcast deletion of a plant.
/// New plantings have been created.
CreatePlanting(Vec<PlantingDto>),
/// Existing plantings have been deleted.
DeletePlanting(Vec<DeletePlantActionPayload>),
/// An action used to broadcast movement of a plant.
/// Plantings have been moved (panned).
MovePlanting(Vec<MovePlantActionPayload>),
/// An action used to broadcast transformation of a plant.
/// Plantings have been transformation.
TransformPlanting(Vec<TransformPlantActionPayload>),
/// An action used to update the `add_date` of a plant.
/// The `add_date` field of plantings has been changed.
UpdatePlantingAddDate(Vec<UpdateAddDateActionPayload>),
/// An action used to update the `remove_date` of a plant.
/// The `remove_date` field of plantings has been changed.
UpdatePlantingRemoveDate(Vec<UpdateRemoveDateActionPayload>),
/// An action used to broadcast updating a Markdown notes of a plant.
/// Note (markdown) of plantings had been changed.
UpdatePlatingNotes(Vec<UpdatePlantingNoteActionPayload>),
/// An action used to broadcast creation of a baseLayerImage.
/// The `additional_name` field of one planting has been changed.
UpdatePlantingAdditionalName(UpdatePlantingAdditionalNamePayload),

/// A new base layer image has been created.
CreateBaseLayerImage(CreateBaseLayerImageActionPayload),
/// An action used to broadcast update of a baseLayerImage.
/// A base layer image has been update.
UpdateBaseLayerImage(UpdateBaseLayerImageActionPayload),
/// An action used to broadcast deletion of a baseLayerImage.
/// A base later image has been deleted.
DeleteBaseLayerImage(DeleteBaseLayerImageActionPayload),
/// An action used to broadcast an update to the map geometry.

/// The map geometry has been changed.
UpdateMapGeometry(UpdateMapGeometryActionPayload),
/// An action used to update the `additional_name` of a plant.
UpdatePlantingAdditionalName(UpdatePlantingAdditionalNamePayload),

/// An action used to broadcast creation of a new drawing shape.
/// New drawings have been created.
CreateDrawing(Vec<DrawingDto>),
/// An action used to broadcast deletion of an existing drawing shape.
/// Existing drawings have been deleted.
DeleteDrawing(Vec<Uuid>),
/// An action used to broadcast the update of an existing drawing shape.
/// Drawings have been updated.
UpdateDrawing(Vec<DrawingDto>),
/// An action used to update the `add_date` of a drawing.
/// The `add_date` field of drawings has been changed.
UpdateDrawingAddDate(Vec<DrawingDto>),
/// An action used to update the `remove_date` of a drawing.
/// The `remove_date` of drawings has changed.
UpdateDrawingRemoveDate(Vec<DrawingDto>),
}

Expand All @@ -85,25 +90,7 @@ impl Action {
Self {
action_id,
user_id,
action: ActionType::CreatePlanting(
dtos.iter()
.map(|dto| CreatePlantActionPayload {
id: dto.id,
layer_id: dto.layer_id,
plant_id: dto.plant_id,
x: dto.x,
y: dto.y,
rotation: dto.rotation,
size_x: dto.size_x,
size_y: dto.size_y,
add_date: dto.add_date,
remove_date: dto.remove_date,
seed_id: dto.seed_id,
additional_name: dto.additional_name.clone(),
is_area: dto.is_area,
})
.collect(),
),
action: ActionType::CreatePlanting(Vec::from(dtos)),
}
}

Expand Down Expand Up @@ -230,27 +217,6 @@ impl Action {
}
}

#[typeshare]
#[derive(Debug, Serialize, Clone)]
/// The payload of the [`ActionType::CreatePlanting`].
/// This struct should always match [`PlantingDto`].
#[serde(rename_all = "camelCase")]
pub struct CreatePlantActionPayload {
id: Uuid,
layer_id: i32,
plant_id: i32,
x: i32,
y: i32,
rotation: f32,
size_x: i32,
size_y: i32,
add_date: Option<NaiveDate>,
remove_date: Option<NaiveDate>,
seed_id: Option<i32>,
additional_name: Option<String>,
is_area: bool,
}

#[typeshare]
#[derive(Debug, Serialize, Clone)]
/// The payload of the [`ActionType::DeletePlanting`].
Expand Down
4 changes: 2 additions & 2 deletions backend/src/model/dto/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@ use typeshare::typeshare;
use utoipa::ToSchema;
use uuid::Uuid;

use super::plantings::{DeletePlantingDto, NewPlantingDto, PlantingDto, UpdatePlantingDto};
use super::plantings::{DeletePlantingDto, PlantingDto, UpdatePlantingDto};

/// A wrapper for a dto that is used to perform an action.
#[typeshare]
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
#[aliases(
ActionDtoWrapperNewPlantings = ActionDtoWrapper<Vec<NewPlantingDto>>,
ActionDtoWrapperNewPlantings = ActionDtoWrapper<Vec<PlantingDto>>,
ActionDtoWrapperUpdatePlantings = ActionDtoWrapper<UpdatePlantingDto>,
ActionDtoWrapperDeletePlantings = ActionDtoWrapper<Vec<DeletePlantingDto>>,
ActionDtoWrapperDeleteDrawings = ActionDtoWrapper<Vec<Uuid>>,
Expand Down
6 changes: 4 additions & 2 deletions backend/src/model/dto/map_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@ impl From<Map> for MapDto {
Self {
id: map.id,
name: map.name,
creation_date: map.creation_date,
created_at: map.created_at,
modified_at: map.modified_at,
created_by: map.created_by,
modified_by: map.modified_by,
deletion_date: map.deletion_date,
last_visit: map.last_visit,
is_inactive: map.is_inactive,
Expand All @@ -20,7 +23,6 @@ impl From<Map> for MapDto {
privacy: map.privacy,
description: map.description,
location: map.location.map(From::from),
owner_id: map.owner_id,
geometry: map.geometry,
}
}
Expand Down
Loading