dbnexus 0.3.1 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api.js +7922 -686
- package/dist/cli.js +222 -66
- package/dist/web/assets/index-DoAn-9yR.js +517 -0
- package/dist/web/index.html +1 -1
- package/package.json +1 -1
- package/dist/web/assets/index-Cqd98z-J.js +0 -510
package/dist/cli.js
CHANGED
|
@@ -33113,7 +33113,7 @@ var import_dotenv = __toESM(require_main(), 1);
|
|
|
33113
33113
|
import Database from "better-sqlite3";
|
|
33114
33114
|
|
|
33115
33115
|
// packages/metadata/dist/schema.js
|
|
33116
|
-
var SCHEMA_VERSION =
|
|
33116
|
+
var SCHEMA_VERSION = 21;
|
|
33117
33117
|
var MIGRATIONS = [
|
|
33118
33118
|
// Version 1: Initial schema
|
|
33119
33119
|
`
|
|
@@ -33514,6 +33514,90 @@ var MIGRATIONS = [
|
|
|
33514
33514
|
ALTER TABLE servers ADD COLUMN stop_command TEXT;
|
|
33515
33515
|
|
|
33516
33516
|
UPDATE schema_version SET version = 19;
|
|
33517
|
+
`,
|
|
33518
|
+
// Version 20: Add authentication tables (users, api_keys, user_permissions, refresh_tokens)
|
|
33519
|
+
`
|
|
33520
|
+
-- Users table for authentication
|
|
33521
|
+
CREATE TABLE IF NOT EXISTS users (
|
|
33522
|
+
id TEXT PRIMARY KEY,
|
|
33523
|
+
email TEXT UNIQUE NOT NULL,
|
|
33524
|
+
password_hash TEXT NOT NULL,
|
|
33525
|
+
name TEXT,
|
|
33526
|
+
role TEXT NOT NULL DEFAULT 'viewer' CHECK(role IN ('admin', 'editor', 'viewer')),
|
|
33527
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
33528
|
+
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
33529
|
+
);
|
|
33530
|
+
|
|
33531
|
+
-- API Keys for CLI/programmatic access
|
|
33532
|
+
CREATE TABLE IF NOT EXISTS api_keys (
|
|
33533
|
+
id TEXT PRIMARY KEY,
|
|
33534
|
+
user_id TEXT NOT NULL,
|
|
33535
|
+
name TEXT NOT NULL,
|
|
33536
|
+
key_hash TEXT NOT NULL,
|
|
33537
|
+
last_used_at TEXT,
|
|
33538
|
+
expires_at TEXT,
|
|
33539
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
33540
|
+
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
|
|
33541
|
+
);
|
|
33542
|
+
|
|
33543
|
+
-- User permissions for per-database access control
|
|
33544
|
+
CREATE TABLE IF NOT EXISTS user_permissions (
|
|
33545
|
+
id TEXT PRIMARY KEY,
|
|
33546
|
+
user_id TEXT NOT NULL,
|
|
33547
|
+
connection_id TEXT NOT NULL,
|
|
33548
|
+
permission TEXT NOT NULL DEFAULT 'read' CHECK(permission IN ('read', 'write', 'admin')),
|
|
33549
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
33550
|
+
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
|
|
33551
|
+
FOREIGN KEY (connection_id) REFERENCES connections(id) ON DELETE CASCADE,
|
|
33552
|
+
UNIQUE(user_id, connection_id)
|
|
33553
|
+
);
|
|
33554
|
+
|
|
33555
|
+
-- Refresh tokens for JWT authentication
|
|
33556
|
+
CREATE TABLE IF NOT EXISTS refresh_tokens (
|
|
33557
|
+
id TEXT PRIMARY KEY,
|
|
33558
|
+
user_id TEXT NOT NULL,
|
|
33559
|
+
token_hash TEXT NOT NULL,
|
|
33560
|
+
expires_at TEXT NOT NULL,
|
|
33561
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
33562
|
+
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
|
|
33563
|
+
);
|
|
33564
|
+
|
|
33565
|
+
CREATE INDEX IF NOT EXISTS idx_users_email ON users(email);
|
|
33566
|
+
CREATE INDEX IF NOT EXISTS idx_api_keys_user ON api_keys(user_id);
|
|
33567
|
+
CREATE INDEX IF NOT EXISTS idx_user_permissions_user ON user_permissions(user_id);
|
|
33568
|
+
CREATE INDEX IF NOT EXISTS idx_user_permissions_connection ON user_permissions(connection_id);
|
|
33569
|
+
CREATE INDEX IF NOT EXISTS idx_refresh_tokens_user ON refresh_tokens(user_id);
|
|
33570
|
+
CREATE INDEX IF NOT EXISTS idx_refresh_tokens_expires ON refresh_tokens(expires_at);
|
|
33571
|
+
|
|
33572
|
+
UPDATE schema_version SET version = 20;
|
|
33573
|
+
`,
|
|
33574
|
+
// Version 21: Add created_by column to resources for multi-user ownership
|
|
33575
|
+
`
|
|
33576
|
+
-- Add created_by to connections
|
|
33577
|
+
ALTER TABLE connections ADD COLUMN created_by TEXT REFERENCES users(id) ON DELETE SET NULL;
|
|
33578
|
+
CREATE INDEX IF NOT EXISTS idx_connections_created_by ON connections(created_by);
|
|
33579
|
+
|
|
33580
|
+
-- Add created_by to servers
|
|
33581
|
+
ALTER TABLE servers ADD COLUMN created_by TEXT REFERENCES users(id) ON DELETE SET NULL;
|
|
33582
|
+
CREATE INDEX IF NOT EXISTS idx_servers_created_by ON servers(created_by);
|
|
33583
|
+
|
|
33584
|
+
-- Add created_by to projects
|
|
33585
|
+
ALTER TABLE projects ADD COLUMN created_by TEXT REFERENCES users(id) ON DELETE SET NULL;
|
|
33586
|
+
CREATE INDEX IF NOT EXISTS idx_projects_created_by ON projects(created_by);
|
|
33587
|
+
|
|
33588
|
+
-- Add created_by to database_groups
|
|
33589
|
+
ALTER TABLE database_groups ADD COLUMN created_by TEXT REFERENCES users(id) ON DELETE SET NULL;
|
|
33590
|
+
CREATE INDEX IF NOT EXISTS idx_database_groups_created_by ON database_groups(created_by);
|
|
33591
|
+
|
|
33592
|
+
-- Add created_by to saved_queries
|
|
33593
|
+
ALTER TABLE saved_queries ADD COLUMN created_by TEXT REFERENCES users(id) ON DELETE SET NULL;
|
|
33594
|
+
CREATE INDEX IF NOT EXISTS idx_saved_queries_created_by ON saved_queries(created_by);
|
|
33595
|
+
|
|
33596
|
+
-- Add created_by to backups
|
|
33597
|
+
ALTER TABLE backups ADD COLUMN created_by TEXT REFERENCES users(id) ON DELETE SET NULL;
|
|
33598
|
+
CREATE INDEX IF NOT EXISTS idx_backups_created_by ON backups(created_by);
|
|
33599
|
+
|
|
33600
|
+
UPDATE schema_version SET version = 21;
|
|
33517
33601
|
`
|
|
33518
33602
|
];
|
|
33519
33603
|
|
|
@@ -33627,15 +33711,15 @@ var ConnectionRepository = class {
|
|
|
33627
33711
|
/**
|
|
33628
33712
|
* Create a new connection with password
|
|
33629
33713
|
*/
|
|
33630
|
-
create(input) {
|
|
33714
|
+
create(input, userId) {
|
|
33631
33715
|
const id = MetadataDatabase.generateId();
|
|
33632
33716
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
33633
33717
|
const encryptedPwd = input.password ? encryptPassword(input.password) : null;
|
|
33634
33718
|
const connectionType = input.connectionType || this.inferConnectionType(input.host);
|
|
33635
33719
|
this.db.prepare(`
|
|
33636
|
-
INSERT INTO connections (id, name, engine, connection_type, host, port, database, username, encrypted_password, ssl, default_schema, tags, read_only, server_id, project_id, group_id, created_at, updated_at)
|
|
33637
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
33638
|
-
`).run(id, input.name, input.engine, connectionType, input.host, input.port, input.database, input.username, encryptedPwd, input.ssl ? 1 : 0, input.defaultSchema || null, JSON.stringify(input.tags ?? []), input.readOnly ? 1 : 0, input.serverId || null, input.projectId || null, input.groupId || null, now, now);
|
|
33720
|
+
INSERT INTO connections (id, name, engine, connection_type, host, port, database, username, encrypted_password, ssl, default_schema, tags, read_only, server_id, project_id, group_id, created_by, created_at, updated_at)
|
|
33721
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
33722
|
+
`).run(id, input.name, input.engine, connectionType, input.host, input.port, input.database, input.username, encryptedPwd, input.ssl ? 1 : 0, input.defaultSchema || null, JSON.stringify(input.tags ?? []), input.readOnly ? 1 : 0, input.serverId || null, input.projectId || null, input.groupId || null, userId || null, now, now);
|
|
33639
33723
|
return this.findById(id);
|
|
33640
33724
|
}
|
|
33641
33725
|
/**
|
|
@@ -33675,10 +33759,10 @@ var ConnectionRepository = class {
|
|
|
33675
33759
|
return row ? this.rowToConnection(row) : null;
|
|
33676
33760
|
}
|
|
33677
33761
|
/**
|
|
33678
|
-
* Get all connections
|
|
33762
|
+
* Get all connections (filtered by user unless admin)
|
|
33679
33763
|
*/
|
|
33680
|
-
findAll() {
|
|
33681
|
-
|
|
33764
|
+
findAll(userContext) {
|
|
33765
|
+
let query = `
|
|
33682
33766
|
SELECT
|
|
33683
33767
|
c.*,
|
|
33684
33768
|
s.name as server_name,
|
|
@@ -33688,15 +33772,21 @@ var ConnectionRepository = class {
|
|
|
33688
33772
|
LEFT JOIN servers s ON c.server_id = s.id
|
|
33689
33773
|
LEFT JOIN projects p ON c.project_id = p.id
|
|
33690
33774
|
LEFT JOIN database_groups dg ON c.group_id = dg.id
|
|
33691
|
-
|
|
33692
|
-
|
|
33775
|
+
`;
|
|
33776
|
+
const params = [];
|
|
33777
|
+
if (userContext && !userContext.isAdmin && userContext.userId) {
|
|
33778
|
+
query += ` WHERE c.created_by = ? OR c.created_by IS NULL`;
|
|
33779
|
+
params.push(userContext.userId);
|
|
33780
|
+
}
|
|
33781
|
+
query += ` ORDER BY p.name, dg.name, c.name`;
|
|
33782
|
+
const rows = this.db.prepare(query).all(...params);
|
|
33693
33783
|
return rows.map((row) => this.rowToConnection(row));
|
|
33694
33784
|
}
|
|
33695
33785
|
/**
|
|
33696
|
-
* Find connections by project
|
|
33786
|
+
* Find connections by project (filtered by user unless admin)
|
|
33697
33787
|
*/
|
|
33698
|
-
findByProject(projectId) {
|
|
33699
|
-
|
|
33788
|
+
findByProject(projectId, userContext) {
|
|
33789
|
+
let query = `
|
|
33700
33790
|
SELECT
|
|
33701
33791
|
c.*,
|
|
33702
33792
|
s.name as server_name,
|
|
@@ -33707,15 +33797,21 @@ var ConnectionRepository = class {
|
|
|
33707
33797
|
LEFT JOIN projects p ON c.project_id = p.id
|
|
33708
33798
|
LEFT JOIN database_groups dg ON c.group_id = dg.id
|
|
33709
33799
|
WHERE c.project_id = ?
|
|
33710
|
-
|
|
33711
|
-
|
|
33800
|
+
`;
|
|
33801
|
+
const params = [projectId];
|
|
33802
|
+
if (userContext && !userContext.isAdmin && userContext.userId) {
|
|
33803
|
+
query += ` AND (c.created_by = ? OR c.created_by IS NULL)`;
|
|
33804
|
+
params.push(userContext.userId);
|
|
33805
|
+
}
|
|
33806
|
+
query += ` ORDER BY dg.name, c.name`;
|
|
33807
|
+
const rows = this.db.prepare(query).all(...params);
|
|
33712
33808
|
return rows.map((row) => this.rowToConnection(row));
|
|
33713
33809
|
}
|
|
33714
33810
|
/**
|
|
33715
|
-
* Find connections by database group
|
|
33811
|
+
* Find connections by database group (filtered by user unless admin)
|
|
33716
33812
|
*/
|
|
33717
|
-
findByGroup(groupId) {
|
|
33718
|
-
|
|
33813
|
+
findByGroup(groupId, userContext) {
|
|
33814
|
+
let query = `
|
|
33719
33815
|
SELECT
|
|
33720
33816
|
c.*,
|
|
33721
33817
|
s.name as server_name,
|
|
@@ -33726,15 +33822,21 @@ var ConnectionRepository = class {
|
|
|
33726
33822
|
LEFT JOIN projects p ON c.project_id = p.id
|
|
33727
33823
|
LEFT JOIN database_groups dg ON c.group_id = dg.id
|
|
33728
33824
|
WHERE c.group_id = ?
|
|
33729
|
-
|
|
33730
|
-
|
|
33825
|
+
`;
|
|
33826
|
+
const params = [groupId];
|
|
33827
|
+
if (userContext && !userContext.isAdmin && userContext.userId) {
|
|
33828
|
+
query += ` AND (c.created_by = ? OR c.created_by IS NULL)`;
|
|
33829
|
+
params.push(userContext.userId);
|
|
33830
|
+
}
|
|
33831
|
+
query += ` ORDER BY c.name`;
|
|
33832
|
+
const rows = this.db.prepare(query).all(...params);
|
|
33731
33833
|
return rows.map((row) => this.rowToConnection(row));
|
|
33732
33834
|
}
|
|
33733
33835
|
/**
|
|
33734
|
-
* Find ungrouped connections (no project assigned)
|
|
33836
|
+
* Find ungrouped connections (no project assigned, filtered by user unless admin)
|
|
33735
33837
|
*/
|
|
33736
|
-
findUngrouped() {
|
|
33737
|
-
|
|
33838
|
+
findUngrouped(userContext) {
|
|
33839
|
+
let query = `
|
|
33738
33840
|
SELECT
|
|
33739
33841
|
c.*,
|
|
33740
33842
|
s.name as server_name,
|
|
@@ -33745,15 +33847,21 @@ var ConnectionRepository = class {
|
|
|
33745
33847
|
LEFT JOIN projects p ON c.project_id = p.id
|
|
33746
33848
|
LEFT JOIN database_groups dg ON c.group_id = dg.id
|
|
33747
33849
|
WHERE c.project_id IS NULL
|
|
33748
|
-
|
|
33749
|
-
|
|
33850
|
+
`;
|
|
33851
|
+
const params = [];
|
|
33852
|
+
if (userContext && !userContext.isAdmin && userContext.userId) {
|
|
33853
|
+
query += ` AND (c.created_by = ? OR c.created_by IS NULL)`;
|
|
33854
|
+
params.push(userContext.userId);
|
|
33855
|
+
}
|
|
33856
|
+
query += ` ORDER BY c.name`;
|
|
33857
|
+
const rows = this.db.prepare(query).all(...params);
|
|
33750
33858
|
return rows.map((row) => this.rowToConnection(row));
|
|
33751
33859
|
}
|
|
33752
33860
|
/**
|
|
33753
|
-
* Find connections by tag
|
|
33861
|
+
* Find connections by tag (filtered by user unless admin)
|
|
33754
33862
|
*/
|
|
33755
|
-
findByTag(tag) {
|
|
33756
|
-
|
|
33863
|
+
findByTag(tag, userContext) {
|
|
33864
|
+
let query = `
|
|
33757
33865
|
SELECT
|
|
33758
33866
|
c.*,
|
|
33759
33867
|
s.name as server_name,
|
|
@@ -33763,8 +33871,14 @@ var ConnectionRepository = class {
|
|
|
33763
33871
|
LEFT JOIN servers s ON c.server_id = s.id
|
|
33764
33872
|
LEFT JOIN projects p ON c.project_id = p.id
|
|
33765
33873
|
LEFT JOIN database_groups dg ON c.group_id = dg.id
|
|
33766
|
-
|
|
33767
|
-
|
|
33874
|
+
`;
|
|
33875
|
+
const params = [];
|
|
33876
|
+
if (userContext && !userContext.isAdmin && userContext.userId) {
|
|
33877
|
+
query += ` WHERE c.created_by = ? OR c.created_by IS NULL`;
|
|
33878
|
+
params.push(userContext.userId);
|
|
33879
|
+
}
|
|
33880
|
+
query += ` ORDER BY c.name`;
|
|
33881
|
+
const rows = this.db.prepare(query).all(...params);
|
|
33768
33882
|
return rows.filter((row) => {
|
|
33769
33883
|
const tags = JSON.parse(row.tags);
|
|
33770
33884
|
return tags.includes(tag);
|
|
@@ -33905,27 +34019,45 @@ var ConnectionRepository = class {
|
|
|
33905
34019
|
serverId: row.server_id || void 0,
|
|
33906
34020
|
projectId: row.project_id || void 0,
|
|
33907
34021
|
groupId: row.group_id || void 0,
|
|
34022
|
+
createdBy: row.created_by || void 0,
|
|
33908
34023
|
serverName: row.server_name,
|
|
33909
34024
|
projectName: row.project_name,
|
|
33910
34025
|
groupName: row.group_name
|
|
33911
34026
|
};
|
|
33912
34027
|
}
|
|
33913
34028
|
/**
|
|
33914
|
-
*
|
|
34029
|
+
* Check if user can access a connection
|
|
33915
34030
|
*/
|
|
33916
|
-
|
|
33917
|
-
|
|
33918
|
-
|
|
33919
|
-
|
|
33920
|
-
|
|
33921
|
-
|
|
33922
|
-
|
|
33923
|
-
|
|
33924
|
-
|
|
33925
|
-
|
|
33926
|
-
|
|
33927
|
-
|
|
33928
|
-
|
|
34031
|
+
canAccess(connectionId, userContext) {
|
|
34032
|
+
if (userContext.isAdmin)
|
|
34033
|
+
return true;
|
|
34034
|
+
const row = this.db.prepare("SELECT created_by FROM connections WHERE id = ?").get(connectionId);
|
|
34035
|
+
if (!row)
|
|
34036
|
+
return false;
|
|
34037
|
+
return row.created_by === null || row.created_by === userContext.userId;
|
|
34038
|
+
}
|
|
34039
|
+
/**
|
|
34040
|
+
* Find connections by server ID (filtered by user unless admin)
|
|
34041
|
+
*/
|
|
34042
|
+
findByServerId(serverId, userContext) {
|
|
34043
|
+
let query = `
|
|
34044
|
+
SELECT c.*,
|
|
34045
|
+
s.name as server_name,
|
|
34046
|
+
p.name as project_name,
|
|
34047
|
+
g.name as group_name
|
|
34048
|
+
FROM connections c
|
|
34049
|
+
LEFT JOIN servers s ON c.server_id = s.id
|
|
34050
|
+
LEFT JOIN projects p ON c.project_id = p.id
|
|
34051
|
+
LEFT JOIN database_groups g ON c.group_id = g.id
|
|
34052
|
+
WHERE c.server_id = ?
|
|
34053
|
+
`;
|
|
34054
|
+
const params = [serverId];
|
|
34055
|
+
if (userContext && !userContext.isAdmin && userContext.userId) {
|
|
34056
|
+
query += ` AND (c.created_by = ? OR c.created_by IS NULL)`;
|
|
34057
|
+
params.push(userContext.userId);
|
|
34058
|
+
}
|
|
34059
|
+
query += ` ORDER BY c.name`;
|
|
34060
|
+
const rows = this.db.prepare(query).all(...params);
|
|
33929
34061
|
return rows.map((row) => this.rowToConnection(row));
|
|
33930
34062
|
}
|
|
33931
34063
|
};
|
|
@@ -33963,21 +34095,22 @@ var ServerRepository = class {
|
|
|
33963
34095
|
stopCommand: row.stop_command ?? void 0,
|
|
33964
34096
|
createdAt: new Date(row.created_at),
|
|
33965
34097
|
updatedAt: new Date(row.updated_at),
|
|
34098
|
+
createdBy: row.created_by ?? void 0,
|
|
33966
34099
|
databaseCount: row.database_count
|
|
33967
34100
|
};
|
|
33968
34101
|
}
|
|
33969
34102
|
/**
|
|
33970
34103
|
* Create a new server
|
|
33971
34104
|
*/
|
|
33972
|
-
create(input) {
|
|
34105
|
+
create(input, userId) {
|
|
33973
34106
|
const id = MetadataDatabase.generateId();
|
|
33974
34107
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
33975
34108
|
const encryptedPwd = input.password ? encryptPassword(input.password) : null;
|
|
33976
34109
|
const connectionType = input.connectionType || this.inferConnectionType(input.host);
|
|
33977
34110
|
this.db.prepare(`
|
|
33978
|
-
INSERT INTO servers (id, name, engine, connection_type, host, port, username, encrypted_password, ssl, tags, start_command, stop_command, created_at, updated_at)
|
|
33979
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
33980
|
-
`).run(id, input.name, input.engine, connectionType, input.host, input.port, input.username, encryptedPwd, input.ssl ? 1 : 0, JSON.stringify(input.tags ?? []), input.startCommand ?? null, input.stopCommand ?? null, now, now);
|
|
34111
|
+
INSERT INTO servers (id, name, engine, connection_type, host, port, username, encrypted_password, ssl, tags, start_command, stop_command, created_by, created_at, updated_at)
|
|
34112
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
34113
|
+
`).run(id, input.name, input.engine, connectionType, input.host, input.port, input.username, encryptedPwd, input.ssl ? 1 : 0, JSON.stringify(input.tags ?? []), input.startCommand ?? null, input.stopCommand ?? null, userId || null, now, now);
|
|
33981
34114
|
return this.findById(id);
|
|
33982
34115
|
}
|
|
33983
34116
|
/**
|
|
@@ -34005,30 +34138,53 @@ var ServerRepository = class {
|
|
|
34005
34138
|
return row ? this.rowToServer(row) : null;
|
|
34006
34139
|
}
|
|
34007
34140
|
/**
|
|
34008
|
-
* Find all servers
|
|
34141
|
+
* Find all servers (filtered by user unless admin)
|
|
34009
34142
|
*/
|
|
34010
|
-
findAll() {
|
|
34011
|
-
|
|
34012
|
-
|
|
34013
|
-
|
|
34014
|
-
|
|
34015
|
-
|
|
34016
|
-
|
|
34143
|
+
findAll(userContext) {
|
|
34144
|
+
let query = `
|
|
34145
|
+
SELECT s.*,
|
|
34146
|
+
(SELECT COUNT(*) FROM connections c WHERE c.server_id = s.id) as database_count
|
|
34147
|
+
FROM servers s
|
|
34148
|
+
`;
|
|
34149
|
+
const params = [];
|
|
34150
|
+
if (userContext && !userContext.isAdmin && userContext.userId) {
|
|
34151
|
+
query += ` WHERE s.created_by = ? OR s.created_by IS NULL`;
|
|
34152
|
+
params.push(userContext.userId);
|
|
34153
|
+
}
|
|
34154
|
+
query += ` ORDER BY s.name`;
|
|
34155
|
+
const rows = this.db.prepare(query).all(...params);
|
|
34017
34156
|
return rows.map((row) => this.rowToServer(row));
|
|
34018
34157
|
}
|
|
34019
34158
|
/**
|
|
34020
|
-
* Find servers by engine
|
|
34159
|
+
* Find servers by engine (filtered by user unless admin)
|
|
34021
34160
|
*/
|
|
34022
|
-
findByEngine(engine) {
|
|
34023
|
-
|
|
34024
|
-
|
|
34025
|
-
|
|
34026
|
-
|
|
34027
|
-
|
|
34028
|
-
|
|
34029
|
-
|
|
34161
|
+
findByEngine(engine, userContext) {
|
|
34162
|
+
let query = `
|
|
34163
|
+
SELECT s.*,
|
|
34164
|
+
(SELECT COUNT(*) FROM connections c WHERE c.server_id = s.id) as database_count
|
|
34165
|
+
FROM servers s
|
|
34166
|
+
WHERE s.engine = ?
|
|
34167
|
+
`;
|
|
34168
|
+
const params = [engine];
|
|
34169
|
+
if (userContext && !userContext.isAdmin && userContext.userId) {
|
|
34170
|
+
query += ` AND (s.created_by = ? OR s.created_by IS NULL)`;
|
|
34171
|
+
params.push(userContext.userId);
|
|
34172
|
+
}
|
|
34173
|
+
query += ` ORDER BY s.name`;
|
|
34174
|
+
const rows = this.db.prepare(query).all(...params);
|
|
34030
34175
|
return rows.map((row) => this.rowToServer(row));
|
|
34031
34176
|
}
|
|
34177
|
+
/**
|
|
34178
|
+
* Check if user can access a server
|
|
34179
|
+
*/
|
|
34180
|
+
canAccess(serverId, userContext) {
|
|
34181
|
+
if (userContext.isAdmin)
|
|
34182
|
+
return true;
|
|
34183
|
+
const row = this.db.prepare("SELECT created_by FROM servers WHERE id = ?").get(serverId);
|
|
34184
|
+
if (!row)
|
|
34185
|
+
return false;
|
|
34186
|
+
return row.created_by === null || row.created_by === userContext.userId;
|
|
34187
|
+
}
|
|
34032
34188
|
/**
|
|
34033
34189
|
* Update a server
|
|
34034
34190
|
*/
|
|
@@ -34123,7 +34279,7 @@ var ServerRepository = class {
|
|
|
34123
34279
|
};
|
|
34124
34280
|
|
|
34125
34281
|
// apps/cli/dist/version.js
|
|
34126
|
-
var VERSION = true ? "0.
|
|
34282
|
+
var VERSION = true ? "0.4.0" : "0.1.10";
|
|
34127
34283
|
|
|
34128
34284
|
// apps/cli/dist/commands/init.js
|
|
34129
34285
|
function loadEnvFile(cwd) {
|