Skip to content

Commit 7bfe570

Browse files
committed
solve issues #10 and #12 and update npm dependencies
1 parent d4b24b1 commit 7bfe570

File tree

14 files changed

+297
-39
lines changed

14 files changed

+297
-39
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
.s3config.toml
55
.DS_Store
66
db_v2.sqlite3-*
7+
_db_v2.sqlite3*
78
test
89
test.rs
910
.vscode/tasks.json

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "sctgdesk-api-server"
3-
version = "0.1.0"
3+
version = "1.1.99-42"
44
edition = "2021"
55
build = "build.rs"
66
# [workspace]

libs/state/src/database.rs

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -460,15 +460,32 @@ impl Database {
460460
Some(user_id.0 as UserId)
461461
}
462462

463-
pub async fn delete_user(&self, user_id: UserId) -> Option<()> {
463+
/// Delete a user and its address book
464+
pub async fn delete_user(&self, uuid: &str) -> Option<()> {
464465
let mut tx = self.pool.begin().await.unwrap();
466+
let user_id = Uuid::parse_str(uuid);
467+
if user_id.is_err() {
468+
log::error!("delete user error: {:?}", uuid);
469+
return None;
470+
}
471+
let user_id = user_id.unwrap().as_bytes().to_vec();
465472
let res = sqlx::query!(
466473
r#"
467474
DELETE FROM
468475
user
469476
WHERE
470-
guid = ?
477+
guid = ?;
478+
DELETE FROM
479+
ab_legacy
480+
WHERE
481+
user_guid = ?;
482+
DELETE FROM
483+
ab
484+
WHERE
485+
owner = ?;
471486
"#,
487+
user_id,
488+
user_id,
472489
user_id
473490
)
474491
.execute(&mut tx)
@@ -1004,6 +1021,8 @@ impl Database {
10041021
) -> Option<()> {
10051022
let mut conn = self.pool.acquire().await.unwrap();
10061023
let user_guid = Uuid::new_v4().as_bytes().to_vec();
1024+
// Create a personal address book name based on the user name
1025+
let ab_name = format!("{}'s Personal Address Book", name);
10071026
// Check if the group exists
10081027
let res = sqlx::query!(
10091028
r#"
@@ -1036,7 +1055,7 @@ impl Database {
10361055
?,
10371056
(SELECT guid FROM team WHERE name = 'Default'), 1, ?, ?, ?, ?);
10381057
INSERT OR IGNORE INTO ab(guid, name, owner, personal, info)
1039-
VALUES (?,"Personal Address Book",?,1,'{}');
1058+
VALUES (?,?,?,1,'{}');
10401059
"#,
10411060
user_guid,
10421061
group_guid,
@@ -1045,6 +1064,7 @@ impl Database {
10451064
password_hashed,
10461065
email,
10471066
ab_guid,
1067+
ab_name,
10481068
user_guid
10491069
)
10501070
.execute(&mut conn)

libs/state/src/state.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -386,7 +386,7 @@ impl ApiState {
386386
self.db.create_user(username, password, admin).await
387387
}
388388

389-
pub async fn ui_delete_user(&self, user_id: UserId) -> Option<()> {
389+
pub async fn user_delete(&self, user_id: &str) -> Option<()> {
390390
self.db.delete_user(user_id).await
391391
}
392392

libs/utils/src/types.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -784,4 +784,9 @@ pub struct AbSharedNameRequest {
784784
pub name: Option<String>,
785785
pub note: Option<String>,
786786
pub guid: String,
787+
}
788+
789+
#[derive(Serialize, Deserialize, Clone, JsonSchema)]
790+
pub struct DeleteUserRequest {
791+
pub rows: Vec<String>,
787792
}

src/lib.rs

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ use rocket::{
6969
pub use state::{ApiState, UserPasswordInfo};
7070
use utils::{
7171
include_png_as_base64, unwrap_or_return, uuid_into_guid, AbTagRenameRequest, AddUserRequest,
72-
AddressBook, EnableUserRequest, GroupsResponse, OidcSettingsResponse, PeersResponse,
72+
AddressBook, EnableUserRequest, DeleteUserRequest, GroupsResponse, OidcSettingsResponse, PeersResponse,
7373
SoftwareResponse, SoftwareVersionResponse, UpdateUserRequest, UserList,
7474
};
7575
use utils::{
@@ -141,6 +141,7 @@ pub async fn build_rocket(figment: Figment) -> Rocket<Build> {
141141
users,
142142
users_client,
143143
user_add,
144+
user_delete,
144145
user_enable,
145146
user_update,
146147
peers,
@@ -1728,6 +1729,45 @@ async fn user_add(
17281729
Ok(Json(response))
17291730
}
17301731

1732+
/// # Delete user
1733+
///
1734+
/// This function is an API endpoint that deletes a user.
1735+
///
1736+
/// ## Parameters
1737+
///
1738+
/// - `request`: A JSON object containing the list of users to delete.
1739+
///
1740+
/// ## Returns
1741+
///
1742+
/// If successful, this function returns a `Json<UsersResponse>` object containing the number of users deleted.
1743+
#[openapi(tag = "user")]
1744+
#[delete("/api/user", format = "application/json", data = "<request>")]
1745+
async fn user_delete(
1746+
state: &State<ApiState>,
1747+
_user: AuthenticatedAdmin,
1748+
request: Json<DeleteUserRequest>,
1749+
) -> Result<Json<UsersResponse>, status::Unauthorized<()>> {
1750+
log::debug!("create_user");
1751+
state.check_maintenance().await;
1752+
1753+
let delete_users = request.0;
1754+
1755+
let mut count = 0;
1756+
for uuid in delete_users.rows {
1757+
let res = state.user_delete(uuid.as_str()).await;
1758+
if res.is_some() {
1759+
count += 1;
1760+
}
1761+
}
1762+
let response = UsersResponse {
1763+
msg: "success".to_string(),
1764+
total: count,
1765+
data: "[{}]".to_string(),
1766+
};
1767+
1768+
Ok(Json(response))
1769+
}
1770+
17311771
/// # Enable users
17321772
///
17331773
/// This function is an API endpoint that enables or disables users.

webconsole/package.json

Lines changed: 27 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,48 @@
11
{
22
"name": "sctgdesk-api-server-webconsole",
33
"private": false,
4-
"license": "AGPL-3.0-only",
5-
"version": "1.1.99-39",
4+
"version": "1.1.99-42",
65
"type": "module",
76
"scripts": {
8-
"dev": "vite",
7+
"create-cert": "openssl req -x509 -newkey rsa:4096 -keyout localhost.key -out localhost.pem -sha256 -nodes -days 365",
98
"devserver": "npx nodemon -V -w ./src -e js,vue,ts,css,html --exec 'npm run build && node devserver.js'",
10-
"preview": "vite preview",
9+
"dev": "vite",
1110
"build": "vite build && gulp licenses",
12-
"create-cert": "openssl req -x509 -newkey rsa:4096 -keyout localhost.key -out localhost.pem -sha256 -nodes -days 365"
11+
"preview": "vite preview"
1312
},
1413
"dependencies": {
15-
"jdenticon": "^3.3.0",
16-
"@headlessui/vue": "^1.7.22",
17-
"clipboard": "^2.0.11",
18-
"@heroicons/vue": "^2.1.5",
1914
"@pqina/flip": "^1.8.3",
20-
"vue": "^3.4.38",
21-
"vue-router": "^4.3.3",
22-
"pinia": "^2.2.2",
23-
"axios": "^1.7.5",
2415
"chart.js": "^4.4.4",
25-
"flowbite": "^2.5.1"
16+
"@headlessui/vue": "^1.7.22",
17+
"vue-router": "^4.4.3",
18+
"flowbite": "^2.5.1",
19+
"jdenticon": "^3.3.0",
20+
"pinia": "^2.2.2",
21+
"@heroicons/vue": "^2.1.5",
22+
"axios": "^1.7.7",
23+
"vue": "^3.5.3",
24+
"clipboard": "^2.0.11"
2625
},
2726
"devDependencies": {
2827
"gulp": "^5.0.0",
28+
"@tailwindcss/forms": "^0.5.9",
29+
"sass": "^1.78.0",
30+
"@tailwindcss/typography": "^0.5.15",
2931
"postcss-purgefonts": "^1.0.2",
30-
"sass": "^1.77.8",
31-
"ts-node": "^10.9.2",
32-
"typescript": "^5.5.4",
33-
"gulp-if": "^3.0.0",
34-
"@tailwindcss/typography": "^0.5.14",
35-
"gulp-append-prepend": "^1.0.9",
32+
"postcss": "^8.4.45",
3633
"tailwindcss": "^3.4.10",
34+
"nodemon": "^3.1.4",
3735
"vite-plugin-static-copy": "^1.0.6",
38-
"vite": "^5.4.2",
39-
"autoprefixer": "^10.4.20",
40-
"glob": "11.0.0",
36+
"@vitejs/plugin-vue": "^5.1.3",
37+
"gulp-append-prepend": "^1.0.9",
4138
"@fullhuman/postcss-purgecss": "^6.0.0",
42-
"nodemon": "^3.1.4",
39+
"vite": "^5.4.3",
40+
"gulp-if": "^3.0.0",
4341
"@types/glob": "^8.1.0",
44-
"postcss": "^8.4.41",
45-
"express": "^4.19.2",
46-
"@vitejs/plugin-vue": "^5.1.2",
47-
"@tailwindcss/forms": "^0.5.7"
42+
"glob": "11.0.0",
43+
"ts-node": "^10.9.2",
44+
"autoprefixer": "^10.4.20",
45+
"typescript": "^5.5.4",
46+
"express": "^4.19.2"
4847
}
4948
}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
3.0.57
1+
3.0.62

webconsole/src/api/apis/user-api.ts

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import { BASE_PATH, COLLECTION_FORMATS, RequestArgs, BaseAPI, RequiredError } fr
2020
import { AddUserRequest } from '../models';
2121
import { CurrentUserRequest } from '../models';
2222
import { CurrentUserResponse } from '../models';
23+
import { DeleteUserRequest } from '../models';
2324
import { EnableUserRequest } from '../models';
2425
import { UpdateUserRequest } from '../models';
2526
import { UserList } from '../models';
@@ -134,6 +135,58 @@ export const UserApiAxiosParamCreator = function (configuration?: Configuration)
134135
options: localVarRequestOptions,
135136
};
136137
},
138+
/**
139+
* This function is an API endpoint that deletes a user. ## Parameters - `request`: A JSON object containing the list of users to delete. ## Returns If successful, this function returns a `Json<UsersResponse>` object containing the number of users deleted.
140+
* @summary Delete user
141+
* @param {DeleteUserRequest} body
142+
* @param {*} [options] Override http request option.
143+
* @throws {RequiredError}
144+
*/
145+
userDelete: async (body: DeleteUserRequest, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
146+
// verify required parameter 'body' is not null or undefined
147+
if (body === null || body === undefined) {
148+
throw new RequiredError('body','Required parameter body was null or undefined when calling userDelete.');
149+
}
150+
const localVarPath = `/api/user`;
151+
// use dummy base URL string because the URL constructor only accepts absolute URLs.
152+
const localVarUrlObj = new URL(localVarPath, 'https://example.com');
153+
let baseOptions;
154+
if (configuration) {
155+
baseOptions = configuration.baseOptions;
156+
}
157+
const localVarRequestOptions :AxiosRequestConfig = { method: 'DELETE', ...baseOptions, ...options};
158+
const localVarHeaderParameter = {} as any;
159+
const localVarQueryParameter = {} as any;
160+
161+
// authentication authorization_admin required
162+
// http bearer authentication required
163+
if (configuration && configuration.accessToken) {
164+
const accessToken = typeof configuration.accessToken === 'function'
165+
? await configuration.accessToken()
166+
: await configuration.accessToken;
167+
localVarHeaderParameter["Authorization"] = "Bearer " + accessToken;
168+
}
169+
170+
localVarHeaderParameter['Content-Type'] = 'application/json';
171+
172+
const query = new URLSearchParams(localVarUrlObj.search);
173+
for (const key in localVarQueryParameter) {
174+
query.set(key, localVarQueryParameter[key]);
175+
}
176+
for (const key in options.params) {
177+
query.set(key, options.params[key]);
178+
}
179+
localVarUrlObj.search = (new URLSearchParams(query)).toString();
180+
let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
181+
localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
182+
const needsSerialization = (typeof body !== "string") || localVarRequestOptions.headers['Content-Type'] === 'application/json';
183+
localVarRequestOptions.data = needsSerialization ? JSON.stringify(body !== undefined ? body : {}) : (body || "");
184+
185+
return {
186+
url: localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash,
187+
options: localVarRequestOptions,
188+
};
189+
},
137190
/**
138191
* This function is an API endpoint that enables or disables users. ## Parameters - `request`: A JSON object containing the list of users to enable or disable. ## Returns If successful, this function returns a `Json<UsersResponse>` object containing the updated user information.
139192
* @summary Enable users
@@ -417,6 +470,20 @@ export const UserApiFp = function(configuration?: Configuration) {
417470
return axios.request(axiosRequestArgs);
418471
};
419472
},
473+
/**
474+
* This function is an API endpoint that deletes a user. ## Parameters - `request`: A JSON object containing the list of users to delete. ## Returns If successful, this function returns a `Json<UsersResponse>` object containing the number of users deleted.
475+
* @summary Delete user
476+
* @param {DeleteUserRequest} body
477+
* @param {*} [options] Override http request option.
478+
* @throws {RequiredError}
479+
*/
480+
async userDelete(body: DeleteUserRequest, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<UsersResponse>>> {
481+
const localVarAxiosArgs = await UserApiAxiosParamCreator(configuration).userDelete(body, options);
482+
return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => {
483+
const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url};
484+
return axios.request(axiosRequestArgs);
485+
};
486+
},
420487
/**
421488
* This function is an API endpoint that enables or disables users. ## Parameters - `request`: A JSON object containing the list of users to enable or disable. ## Returns If successful, this function returns a `Json<UsersResponse>` object containing the updated user information.
422489
* @summary Enable users
@@ -508,6 +575,16 @@ export const UserApiFactory = function (configuration?: Configuration, basePath?
508575
async userAdd(body: AddUserRequest, options?: AxiosRequestConfig): Promise<AxiosResponse<UsersResponse>> {
509576
return UserApiFp(configuration).userAdd(body, options).then((request) => request(axios, basePath));
510577
},
578+
/**
579+
* This function is an API endpoint that deletes a user. ## Parameters - `request`: A JSON object containing the list of users to delete. ## Returns If successful, this function returns a `Json<UsersResponse>` object containing the number of users deleted.
580+
* @summary Delete user
581+
* @param {DeleteUserRequest} body
582+
* @param {*} [options] Override http request option.
583+
* @throws {RequiredError}
584+
*/
585+
async userDelete(body: DeleteUserRequest, options?: AxiosRequestConfig): Promise<AxiosResponse<UsersResponse>> {
586+
return UserApiFp(configuration).userDelete(body, options).then((request) => request(axios, basePath));
587+
},
511588
/**
512589
* This function is an API endpoint that enables or disables users. ## Parameters - `request`: A JSON object containing the list of users to enable or disable. ## Returns If successful, this function returns a `Json<UsersResponse>` object containing the updated user information.
513590
* @summary Enable users
@@ -586,6 +663,17 @@ export class UserApi extends BaseAPI {
586663
public async userAdd(body: AddUserRequest, options?: AxiosRequestConfig) : Promise<AxiosResponse<UsersResponse>> {
587664
return UserApiFp(this.configuration).userAdd(body, options).then((request) => request(this.axios, this.basePath));
588665
}
666+
/**
667+
* This function is an API endpoint that deletes a user. ## Parameters - `request`: A JSON object containing the list of users to delete. ## Returns If successful, this function returns a `Json<UsersResponse>` object containing the number of users deleted.
668+
* @summary Delete user
669+
* @param {DeleteUserRequest} body
670+
* @param {*} [options] Override http request option.
671+
* @throws {RequiredError}
672+
* @memberof UserApi
673+
*/
674+
public async userDelete(body: DeleteUserRequest, options?: AxiosRequestConfig) : Promise<AxiosResponse<UsersResponse>> {
675+
return UserApiFp(this.configuration).userDelete(body, options).then((request) => request(this.axios, this.basePath));
676+
}
589677
/**
590678
* This function is an API endpoint that enables or disables users. ## Parameters - `request`: A JSON object containing the list of users to enable or disable. ## Returns If successful, this function returns a `Json<UsersResponse>` object containing the updated user information.
591679
* @summary Enable users

0 commit comments

Comments
 (0)