-
Notifications
You must be signed in to change notification settings - Fork 847
feat: add folder and group permission history tracking #7006
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| -- Add down migration script here | ||
| DROP INDEX IF EXISTS idx_group_perm_history_workspace_group; | ||
| DROP TABLE IF EXISTS group_permission_history; | ||
|
|
||
| DROP INDEX IF EXISTS idx_folder_perm_history_workspace_folder; | ||
| DROP TABLE IF EXISTS folder_permission_history; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| -- Add up migration script here | ||
|
|
||
| -- Folder permission changes history | ||
| CREATE TABLE IF NOT EXISTS folder_permission_history ( | ||
| id BIGSERIAL PRIMARY KEY, | ||
| workspace_id VARCHAR(50) NOT NULL, | ||
| folder_name VARCHAR(255) NOT NULL, | ||
| changed_by VARCHAR(50) NOT NULL, | ||
| changed_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(), | ||
| change_type VARCHAR(50) NOT NULL, | ||
| owner_affected VARCHAR(100), | ||
| FOREIGN KEY (workspace_id, folder_name) REFERENCES folder(workspace_id, name) ON DELETE CASCADE | ||
| ); | ||
|
|
||
| CREATE INDEX IF NOT EXISTS idx_folder_perm_history_workspace_folder | ||
| ON folder_permission_history(workspace_id, folder_name, changed_at DESC); | ||
|
|
||
| -- Group permission changes history | ||
| CREATE TABLE IF NOT EXISTS group_permission_history ( | ||
| id BIGSERIAL PRIMARY KEY, | ||
| workspace_id VARCHAR(50) NOT NULL, | ||
| group_name VARCHAR(255) NOT NULL, | ||
| changed_by VARCHAR(50) NOT NULL, | ||
| changed_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(), | ||
| change_type VARCHAR(50) NOT NULL, | ||
| member_affected VARCHAR(100), | ||
| FOREIGN KEY (workspace_id, group_name) REFERENCES group_(workspace_id, name) ON DELETE CASCADE | ||
| ); | ||
|
|
||
| CREATE INDEX IF NOT EXISTS idx_group_perm_history_workspace_group | ||
| ON group_permission_history(workspace_id, group_name, changed_at DESC); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,68 @@ | ||
| /* | ||
| * Author: Ruben Fiszel | ||
| * Copyright: Windmill Labs, Inc 2022 | ||
| * This file and its contents are licensed under the AGPLv3 License. | ||
| * Please see the included NOTICE for copyright information and | ||
| * LICENSE-AGPL for a copy of the license. | ||
| */ | ||
|
|
||
| use crate::db::ApiAuthed; | ||
| use axum::{ | ||
| extract::{Extension, Path, Query}, | ||
| routing::get, | ||
| Router, | ||
| }; | ||
| use windmill_common::{ | ||
| db::UserDB, | ||
| error::JsonResult, | ||
| utils::{paginate, Pagination}, | ||
| }; | ||
|
|
||
| use serde::Serialize; | ||
| use sqlx::FromRow; | ||
|
|
||
| pub fn workspaced_service() -> Router { | ||
| Router::new().route("/get/:name", get(get_folder_permission_history)) | ||
| } | ||
|
|
||
| #[derive(Serialize, FromRow)] | ||
| pub struct FolderPermissionChange { | ||
| pub id: i64, | ||
| pub changed_by: String, | ||
| pub changed_at: chrono::DateTime<chrono::Utc>, | ||
| pub change_type: String, | ||
| pub owner_affected: Option<String>, | ||
| } | ||
|
|
||
| async fn get_folder_permission_history( | ||
| authed: ApiAuthed, | ||
| Extension(user_db): Extension<UserDB>, | ||
| Path((w_id, name)): Path<(String, String)>, | ||
| Query(pagination): Query<Pagination>, | ||
| ) -> JsonResult<Vec<FolderPermissionChange>> { | ||
| let mut tx = user_db.begin(&authed).await?; | ||
|
|
||
| // Check if user is owner of the folder | ||
| crate::folders::require_is_owner(&authed, &name)?; | ||
|
|
||
| let (per_page, offset) = paginate(pagination); | ||
|
|
||
| let history = sqlx::query_as!( | ||
| FolderPermissionChange, | ||
| "SELECT id, changed_by, changed_at, change_type, owner_affected | ||
| FROM folder_permission_history | ||
| WHERE workspace_id = $1 AND folder_name = $2 | ||
| ORDER BY changed_at DESC | ||
| LIMIT $3 OFFSET $4", | ||
| w_id, | ||
| name, | ||
| per_page as i64, | ||
| offset as i64 | ||
| ) | ||
| .fetch_all(&mut *tx) | ||
| .await?; | ||
|
|
||
| tx.commit().await?; | ||
|
|
||
| Ok(axum::Json(history)) | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Performance: Consider moving the authorization check before starting the transaction to avoid creating unnecessary transactions when authorization fails:
This is a minor optimization but follows the pattern of failing fast before allocating resources.