| 1 | use sqlx::{PgPool, Row};
|
|---|
| 2 | use tauri::State;
|
|---|
| 3 |
|
|---|
| 4 | use crate::commands::auth::{require_manager_session, ActiveSessions};
|
|---|
| 5 |
|
|---|
| 6 | #[tauri::command]
|
|---|
| 7 | pub async fn get_employees(
|
|---|
| 8 | token: String,
|
|---|
| 9 | pool: State<'_, PgPool>,
|
|---|
| 10 | sessions: State<'_, ActiveSessions>,
|
|---|
| 11 | ) -> Result<Vec<serde_json::Value>, String> {
|
|---|
| 12 | require_manager_session(&token, sessions.inner()).await?;
|
|---|
| 13 |
|
|---|
| 14 | let rows = sqlx::query(
|
|---|
| 15 | "
|
|---|
| 16 | SELECT
|
|---|
| 17 | u.user_id,
|
|---|
| 18 | u.role_id,
|
|---|
| 19 | u.first_name,
|
|---|
| 20 | u.last_name,
|
|---|
| 21 | u.active,
|
|---|
| 22 | r.role_name
|
|---|
| 23 | FROM app_user u
|
|---|
| 24 | JOIN role r ON u.role_id = r.role_id
|
|---|
| 25 | ORDER BY u.user_id
|
|---|
| 26 | "
|
|---|
| 27 | )
|
|---|
| 28 | .fetch_all(pool.inner())
|
|---|
| 29 | .await
|
|---|
| 30 | .map_err(|e| e.to_string())?;
|
|---|
| 31 |
|
|---|
| 32 | let mut result = Vec::new();
|
|---|
| 33 | for row in rows {
|
|---|
| 34 | result.push(serde_json::json!({
|
|---|
| 35 | "id": row.get::<i32, _>("user_id"),
|
|---|
| 36 | "role_id": row.get::<i32, _>("role_id"),
|
|---|
| 37 | "first_name": row.get::<String, _>("first_name"),
|
|---|
| 38 | "last_name": row.get::<String, _>("last_name"),
|
|---|
| 39 | "active": row.get::<bool, _>("active"),
|
|---|
| 40 | "role_name": row.get::<String, _>("role_name"),
|
|---|
| 41 | }));
|
|---|
| 42 | }
|
|---|
| 43 |
|
|---|
| 44 | Ok(result)
|
|---|
| 45 | }
|
|---|
| 46 |
|
|---|
| 47 | #[tauri::command]
|
|---|
| 48 | pub async fn get_roles(
|
|---|
| 49 | pool: State<'_, PgPool>
|
|---|
| 50 | ) -> Result<Vec<serde_json::Value>, String> {
|
|---|
| 51 | let rows = sqlx::query("SELECT role_id, role_name FROM role")
|
|---|
| 52 | .fetch_all(pool.inner())
|
|---|
| 53 | .await
|
|---|
| 54 | .map_err(|e| e.to_string())?;
|
|---|
| 55 |
|
|---|
| 56 | let mut result = Vec::new();
|
|---|
| 57 | for row in rows {
|
|---|
| 58 | result.push(serde_json::json!({
|
|---|
| 59 | "role_id": row.get::<i32, _>("role_id"),
|
|---|
| 60 | "role_name": row.get::<String, _>("role_name")
|
|---|
| 61 | }));
|
|---|
| 62 | }
|
|---|
| 63 | Ok(result)
|
|---|
| 64 | }
|
|---|
| 65 |
|
|---|
| 66 | #[tauri::command]
|
|---|
| 67 | pub async fn add_employee(
|
|---|
| 68 | token: String,
|
|---|
| 69 | first_name: String,
|
|---|
| 70 | last_name: String,
|
|---|
| 71 | pin: String,
|
|---|
| 72 | role_id: i32,
|
|---|
| 73 | pool: State<'_, PgPool>,
|
|---|
| 74 | sessions: State<'_, ActiveSessions>,
|
|---|
| 75 | ) -> Result<(), String> {
|
|---|
| 76 | require_manager_session(&token, sessions.inner()).await?;
|
|---|
| 77 |
|
|---|
| 78 | if first_name.trim().is_empty() || last_name.trim().is_empty() || pin.trim().is_empty() {
|
|---|
| 79 | return Err("Сите полиња се задолжителни".to_string());
|
|---|
| 80 | }
|
|---|
| 81 |
|
|---|
| 82 | sqlx::query(
|
|---|
| 83 | "
|
|---|
| 84 | INSERT INTO app_user (first_name, last_name, password_hash, role_id, active)
|
|---|
| 85 | VALUES ($1, $2, crypt($3, gen_salt('bf')), $4, true)
|
|---|
| 86 | "
|
|---|
| 87 | )
|
|---|
| 88 | .bind(first_name)
|
|---|
| 89 | .bind(last_name)
|
|---|
| 90 | .bind(pin)
|
|---|
| 91 | .bind(role_id)
|
|---|
| 92 | .execute(pool.inner())
|
|---|
| 93 | .await
|
|---|
| 94 | .map_err(|e| e.to_string())?;
|
|---|
| 95 |
|
|---|
| 96 | Ok(())
|
|---|
| 97 | }
|
|---|
| 98 |
|
|---|
| 99 | #[tauri::command]
|
|---|
| 100 | pub async fn update_employee_role(
|
|---|
| 101 | token: String,
|
|---|
| 102 | user_id: i32,
|
|---|
| 103 | role_id: i32,
|
|---|
| 104 | pool: State<'_, PgPool>,
|
|---|
| 105 | sessions: State<'_, ActiveSessions>,
|
|---|
| 106 | ) -> Result<(), String> {
|
|---|
| 107 | require_manager_session(&token, sessions.inner()).await?;
|
|---|
| 108 |
|
|---|
| 109 | sqlx::query(
|
|---|
| 110 | "
|
|---|
| 111 | UPDATE app_user
|
|---|
| 112 | SET role_id = $1
|
|---|
| 113 | WHERE user_id = $2
|
|---|
| 114 | "
|
|---|
| 115 | )
|
|---|
| 116 | .bind(role_id)
|
|---|
| 117 | .bind(user_id)
|
|---|
| 118 | .execute(pool.inner())
|
|---|
| 119 | .await
|
|---|
| 120 | .map_err(|e| e.to_string())?;
|
|---|
| 121 |
|
|---|
| 122 | Ok(())
|
|---|
| 123 | }
|
|---|
| 124 |
|
|---|
| 125 | #[tauri::command]
|
|---|
| 126 | pub async fn reset_employee_pin(
|
|---|
| 127 | token: String,
|
|---|
| 128 | user_id: i32,
|
|---|
| 129 | new_pin: String,
|
|---|
| 130 | pool: State<'_, PgPool>,
|
|---|
| 131 | sessions: State<'_, ActiveSessions>,
|
|---|
| 132 | ) -> Result<(), String> {
|
|---|
| 133 | require_manager_session(&token, sessions.inner()).await?;
|
|---|
| 134 |
|
|---|
| 135 | if new_pin.trim().is_empty() {
|
|---|
| 136 | return Err("PIN не смее да биде празен".to_string());
|
|---|
| 137 | }
|
|---|
| 138 |
|
|---|
| 139 | sqlx::query(
|
|---|
| 140 | "
|
|---|
| 141 | UPDATE app_user
|
|---|
| 142 | SET password_hash = crypt($1, gen_salt('bf'))
|
|---|
| 143 | WHERE user_id = $2
|
|---|
| 144 | "
|
|---|
| 145 | )
|
|---|
| 146 | .bind(new_pin)
|
|---|
| 147 | .bind(user_id)
|
|---|
| 148 | .execute(pool.inner())
|
|---|
| 149 | .await
|
|---|
| 150 | .map_err(|e| e.to_string())?;
|
|---|
| 151 |
|
|---|
| 152 | Ok(())
|
|---|
| 153 | }
|
|---|
| 154 |
|
|---|
| 155 | #[tauri::command]
|
|---|
| 156 | pub async fn toggle_employee(
|
|---|
| 157 | token: String,
|
|---|
| 158 | user_id: i32,
|
|---|
| 159 | pool: State<'_, PgPool>,
|
|---|
| 160 | sessions: State<'_, ActiveSessions>,
|
|---|
| 161 | ) -> Result<(), String> {
|
|---|
| 162 | require_manager_session(&token, sessions.inner()).await?;
|
|---|
| 163 |
|
|---|
| 164 | sqlx::query(
|
|---|
| 165 | "
|
|---|
| 166 | UPDATE app_user
|
|---|
| 167 | SET active = NOT active
|
|---|
| 168 | WHERE user_id = $1
|
|---|
| 169 | "
|
|---|
| 170 | )
|
|---|
| 171 | .bind(user_id)
|
|---|
| 172 | .execute(pool.inner())
|
|---|
| 173 | .await
|
|---|
| 174 | .map_err(|e| e.to_string())?;
|
|---|
| 175 |
|
|---|
| 176 | Ok(())
|
|---|
| 177 | }
|
|---|
| 178 | #[tauri::command]
|
|---|
| 179 | pub async fn delete_employee(
|
|---|
| 180 | token: String,
|
|---|
| 181 | user_id: i32,
|
|---|
| 182 | pool: State<'_, PgPool>,
|
|---|
| 183 | sessions: State<'_, ActiveSessions>,
|
|---|
| 184 | ) -> Result<(), String> {
|
|---|
| 185 | require_manager_session(&token, sessions.inner()).await?;
|
|---|
| 186 |
|
|---|
| 187 | let result = sqlx::query("DELETE FROM app_user WHERE user_id = $1")
|
|---|
| 188 | .bind(user_id)
|
|---|
| 189 | .execute(pool.inner())
|
|---|
| 190 | .await
|
|---|
| 191 | .map_err(|e| e.to_string())?;
|
|---|
| 192 |
|
|---|
| 193 | if result.rows_affected() == 0 {
|
|---|
| 194 | return Err("Вработениот не е пронајден".to_string());
|
|---|
| 195 | }
|
|---|
| 196 |
|
|---|
| 197 | Ok(())
|
|---|
| 198 | } |
|---|