Skip to content

Commit 6910c43

Browse files
authored
Merge pull request #1533 from RedisInsight/release/2.16.0
Release/2.16.0
2 parents 74fb2eb + 3d1b96f commit 6910c43

File tree

333 files changed

+12286
-3238
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

333 files changed

+12286
-3238
lines changed

.circleci/config.yml

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -511,7 +511,13 @@ jobs:
511511
- run:
512512
name: install dependencies
513513
command: |
514-
sudo apt-get update -y && sudo apt-get install -y rpm
514+
sudo apt-get update -y && sudo apt-get install -y rpm flatpak flatpak-builder ca-certificates
515+
flatpak remote-add --user --if-not-exists flathub https://dl.flathub.org/repo/flathub.flatpakrepo
516+
flatpak install flathub --no-deps --arch x86_64 --assumeyes \
517+
runtime/org.freedesktop.Sdk/x86_64/20.08 \
518+
runtime/org.freedesktop.Platform/x86_64/20.08 \
519+
org.electronjs.Electron2.BaseApp/x86_64/20.08
520+
515521
yarn --cwd redisinsight/api/ install
516522
yarn install
517523
yarn build:statics
@@ -554,6 +560,8 @@ jobs:
554560
- release/RedisInsight*.deb
555561
- release/RedisInsight*.rpm
556562
- release/RedisInsight*.AppImage
563+
- release/RedisInsight*.flatpak
564+
- release/RedisInsight*.snap
557565
- release/*-linux.yml
558566
- release/redisstack
559567
macosx:

electron-builder.json

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,9 +64,17 @@
6464
"target": "deb",
6565
"arch": ["x64"]
6666
},
67+
{
68+
"target": "flatpak",
69+
"arch": ["x64"]
70+
},
6771
{
6872
"target": "rpm",
6973
"arch": ["x64"]
74+
},
75+
{
76+
"target": "snap",
77+
"arch": ["x64"]
7078
}
7179
],
7280
"synopsis": "Redis GUI by Redis Ltd.",
@@ -78,6 +86,49 @@
7886
"Comment": "Redis GUI by Redis Ltd"
7987
}
8088
},
89+
"snap": {
90+
"plugs": [
91+
"default",
92+
"password-manager-service"
93+
],
94+
"confinement": "strict",
95+
"stagePackages": ["default"]
96+
},
97+
"flatpak": {
98+
"runtimeVersion": "20.08",
99+
"modules": [
100+
{
101+
"name": "libsecret",
102+
"buildsystem": "meson",
103+
"config-opts": [
104+
"-Dmanpage=false",
105+
"-Dvapi=false",
106+
"-Dgtk_doc=false",
107+
"-Dintrospection=false"
108+
],
109+
"cleanup": ["/bin", "/include", "/lib/pkgconfig", "/share/man"],
110+
"sources": [
111+
{
112+
"type": "archive",
113+
"url": "https://download.gnome.org/sources/libsecret/0.20/libsecret-0.20.5.tar.xz",
114+
"sha256": "3fb3ce340fcd7db54d87c893e69bfc2b1f6e4d4b279065ffe66dac9f0fd12b4d"
115+
}
116+
]
117+
}
118+
],
119+
"finishArgs": [
120+
"--share=ipc",
121+
"--share=network",
122+
"--filesystem=home",
123+
"--device=dri",
124+
"--talk-name=org.freedesktop.secrets",
125+
"--talk-name=org.freedesktop.Notifications",
126+
"--talk-name=org.freedesktop.Flatpak",
127+
"--socket=fallback-x11",
128+
"--socket=wayland",
129+
"--socket=x11"
130+
]
131+
},
81132
"directories": {
82133
"app": "redisinsight",
83134
"buildResources": "resources",

jest.config.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,10 +54,10 @@ module.exports = {
5454
],
5555
coverageThreshold: {
5656
global: {
57-
statements: 70,
58-
branches: 50,
59-
functions: 60,
60-
lines: 72,
57+
statements: 77,
58+
branches: 55,
59+
functions: 65,
60+
lines: 75,
6161
},
6262
// './redisinsight/ui/src/slices/**/*.ts': {
6363
// statements: 90,
Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,49 @@
1-
import * as React from 'react';
1+
import React, { useEffect } from 'react';
22

33
export default function MonacoEditor(props) {
4-
return <div {...props} data-testid="monaco"/>;
4+
useEffect(() => {
5+
props.editorDidMount && props.editorDidMount(
6+
// editor
7+
{
8+
addCommand: jest.fn(),
9+
getContribution: jest.fn(),
10+
onKeyDown: jest.fn(),
11+
onMouseDown: jest.fn(),
12+
addAction: jest.fn(),
13+
getAction: jest.fn(),
14+
deltaDecorations: jest.fn(),
15+
createContextKey: jest.fn(),
16+
focus: jest.fn(),
17+
onDidChangeCursorPosition: jest.fn(),
18+
executeEdits: jest.fn()
19+
},
20+
// monaco
21+
{
22+
Range: jest.fn().mockImplementation(() => { return {} }),
23+
languages: {
24+
getLanguages: jest.fn(),
25+
register: jest.fn(),
26+
registerCompletionItemProvider: jest.fn().mockReturnValue({
27+
dispose: jest.fn()
28+
}),
29+
registerSignatureHelpProvider: jest.fn().mockReturnValue({
30+
dispose: jest.fn()
31+
}),
32+
setLanguageConfiguration: jest.fn(),
33+
setMonarchTokensProvider: jest.fn(),
34+
},
35+
KeyMod: {},
36+
KeyCode: {}
37+
})
38+
}, [])
39+
return <input {...props} data-testid="monaco"/>;
40+
}
41+
42+
export const languages = {
43+
CompletionItemKind: {
44+
Function: 1
45+
},
46+
CompletionItemInsertTextRule: {
47+
InsertAsSnippet: 4
48+
}
549
}

redisinsight/api/config/default.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ export default {
5757
appVersion: process.env.APP_VERSION || '2.0.0',
5858
requestTimeout: parseInt(process.env.REQUEST_TIMEOUT, 10) || 10000,
5959
excludeRoutes: [],
60+
excludeAuthRoutes: [],
6061
},
6162
sockets: {
6263
cors: process.env.SOCKETS_CORS ? process.env.SOCKETS_CORS === 'true' : false,

redisinsight/api/config/stack.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ export default {
55
excludeRoutes: [
66
'redis-enterprise/*',
77
'redis-sentinel/*',
8+
{ path: 'databases/import' },
89
{ path: 'databases', method: RequestMethod.POST },
910
{ path: 'databases', method: RequestMethod.DELETE },
1011
{ path: 'databases/:id', method: RequestMethod.DELETE },
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { MigrationInterface, QueryRunner } from "typeorm";
2+
3+
export class databaseNew1670252337342 implements MigrationInterface {
4+
name = 'databaseNew1670252337342'
5+
6+
public async up(queryRunner: QueryRunner): Promise<void> {
7+
await queryRunner.query(`CREATE TABLE "temporary_database_instance" ("id" varchar PRIMARY KEY NOT NULL, "host" varchar NOT NULL, "port" integer NOT NULL, "name" varchar NOT NULL, "username" varchar, "password" varchar, "tls" boolean, "verifyServerCert" boolean, "lastConnection" datetime, "caCertId" varchar, "clientCertId" varchar, "connectionType" varchar NOT NULL DEFAULT ('STANDALONE'), "nodes" varchar DEFAULT ('[]'), "nameFromProvider" varchar, "sentinelMasterName" varchar, "sentinelMasterUsername" varchar, "sentinelMasterPassword" varchar, "provider" varchar DEFAULT ('UNKNOWN'), "modules" varchar NOT NULL DEFAULT ('[]'), "db" integer, "encryption" varchar, "tlsServername" varchar, "new" boolean, CONSTRAINT "FK_3b9b625266c00feb2d66a9f36e4" FOREIGN KEY ("clientCertId") REFERENCES "client_certificate" ("id") ON DELETE SET NULL ON UPDATE NO ACTION, CONSTRAINT "FK_d1bc747b5938e22b4b708d8e9a5" FOREIGN KEY ("caCertId") REFERENCES "ca_certificate" ("id") ON DELETE SET NULL ON UPDATE NO ACTION)`);
8+
await queryRunner.query(`INSERT INTO "temporary_database_instance"("id", "host", "port", "name", "username", "password", "tls", "verifyServerCert", "lastConnection", "caCertId", "clientCertId", "connectionType", "nodes", "nameFromProvider", "sentinelMasterName", "sentinelMasterUsername", "sentinelMasterPassword", "provider", "modules", "db", "encryption", "tlsServername") SELECT "id", "host", "port", "name", "username", "password", "tls", "verifyServerCert", "lastConnection", "caCertId", "clientCertId", "connectionType", "nodes", "nameFromProvider", "sentinelMasterName", "sentinelMasterUsername", "sentinelMasterPassword", "provider", "modules", "db", "encryption", "tlsServername" FROM "database_instance"`);
9+
await queryRunner.query(`DROP TABLE "database_instance"`);
10+
await queryRunner.query(`ALTER TABLE "temporary_database_instance" RENAME TO "database_instance"`);
11+
}
12+
13+
public async down(queryRunner: QueryRunner): Promise<void> {
14+
await queryRunner.query(`ALTER TABLE "database_instance" RENAME TO "temporary_database_instance"`);
15+
await queryRunner.query(`CREATE TABLE "database_instance" ("id" varchar PRIMARY KEY NOT NULL, "host" varchar NOT NULL, "port" integer NOT NULL, "name" varchar NOT NULL, "username" varchar, "password" varchar, "tls" boolean, "verifyServerCert" boolean, "lastConnection" datetime, "caCertId" varchar, "clientCertId" varchar, "connectionType" varchar NOT NULL DEFAULT ('STANDALONE'), "nodes" varchar DEFAULT ('[]'), "nameFromProvider" varchar, "sentinelMasterName" varchar, "sentinelMasterUsername" varchar, "sentinelMasterPassword" varchar, "provider" varchar DEFAULT ('UNKNOWN'), "modules" varchar NOT NULL DEFAULT ('[]'), "db" integer, "encryption" varchar, "tlsServername" varchar, CONSTRAINT "FK_3b9b625266c00feb2d66a9f36e4" FOREIGN KEY ("clientCertId") REFERENCES "client_certificate" ("id") ON DELETE SET NULL ON UPDATE NO ACTION, CONSTRAINT "FK_d1bc747b5938e22b4b708d8e9a5" FOREIGN KEY ("caCertId") REFERENCES "ca_certificate" ("id") ON DELETE SET NULL ON UPDATE NO ACTION)`);
16+
await queryRunner.query(`INSERT INTO "database_instance"("id", "host", "port", "name", "username", "password", "tls", "verifyServerCert", "lastConnection", "caCertId", "clientCertId", "connectionType", "nodes", "nameFromProvider", "sentinelMasterName", "sentinelMasterUsername", "sentinelMasterPassword", "provider", "modules", "db", "encryption", "tlsServername") SELECT "id", "host", "port", "name", "username", "password", "tls", "verifyServerCert", "lastConnection", "caCertId", "clientCertId", "connectionType", "nodes", "nameFromProvider", "sentinelMasterName", "sentinelMasterUsername", "sentinelMasterPassword", "provider", "modules", "db", "encryption", "tlsServername" FROM "temporary_database_instance"`);
17+
await queryRunner.query(`DROP TABLE "temporary_database_instance"`);
18+
}
19+
20+
}

redisinsight/api/migration/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import { databaseAnalysis1664785208236 } from './1664785208236-database-analysis
2121
import { databaseAnalysisExpirationGroups1664886479051 } from './1664886479051-database-analysis-expiration-groups';
2222
import { workbenchExecutionTime1667368983699 } from './1667368983699-workbench-execution-time';
2323
import { database1667477693934 } from './1667477693934-database';
24+
import { databaseNew1670252337342 } from './1670252337342-database-new';
2425

2526
export default [
2627
initialMigration1614164490968,
@@ -46,4 +47,5 @@ export default [
4647
databaseAnalysisExpirationGroups1664886479051,
4748
workbenchExecutionTime1667368983699,
4849
database1667477693934,
50+
databaseNew1670252337342,
4951
];

redisinsight/api/src/__mocks__/common.ts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
import { ClientContext, ClientMetadata, Session } from 'src/common/models';
2+
import { mockDatabase } from 'src/__mocks__/databases';
3+
import { v4 as uuidv4 } from 'uuid';
4+
15
export type MockType<T> = {
26
[P in keyof T]: jest.Mock<any>;
37
};
@@ -28,6 +32,7 @@ export const mockQueryBuilderExecute = jest.fn();
2832
export const mockCreateQueryBuilder = jest.fn(() => ({
2933
// where: jest.fn().mockReturnThis(),
3034
where: mockQueryBuilderWhere,
35+
orWhere: mockQueryBuilderWhere,
3136
update: jest.fn().mockReturnThis(),
3237
select: jest.fn().mockReturnThis(),
3338
set: jest.fn().mockReturnThis(),
@@ -57,3 +62,33 @@ export const mockRepository = jest.fn(() => ({
5762
remove: jest.fn(),
5863
createQueryBuilder: mockCreateQueryBuilder,
5964
}));
65+
66+
export const mockSession: Session = {
67+
userId: uuidv4(),
68+
sessionId: uuidv4(),
69+
};
70+
71+
export const mockCliClientMetadata: ClientMetadata = {
72+
session: mockSession,
73+
databaseId: mockDatabase.id,
74+
context: ClientContext.CLI,
75+
uniqueId: uuidv4(),
76+
};
77+
78+
export const mockWorkbenchClientMetadata: ClientMetadata = {
79+
session: mockSession,
80+
databaseId: mockDatabase.id,
81+
context: ClientContext.Workbench,
82+
};
83+
84+
export const mockBrowserClientMetadata: ClientMetadata = {
85+
session: mockSession,
86+
databaseId: mockDatabase.id,
87+
context: ClientContext.Browser,
88+
};
89+
90+
export const mockCommonClientMetadata: ClientMetadata = {
91+
session: mockSession,
92+
databaseId: mockDatabase.id,
93+
context: ClientContext.Common,
94+
};
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
import { DatabaseImportResponse, DatabaseImportStatus } from 'src/modules/database-import/dto/database-import.response';
2+
import { BadRequestException, ForbiddenException } from '@nestjs/common';
3+
import { mockDatabase, mockSentinelDatabaseWithTlsAuth } from 'src/__mocks__/databases';
4+
import { ValidationException } from 'src/common/exceptions';
5+
import { mockCaCertificate, mockClientCertificate } from 'src/__mocks__/certificates';
6+
import {
7+
InvalidCaCertificateBodyException, InvalidCertificateNameException,
8+
} from 'src/modules/database-import/exceptions';
9+
10+
export const mockDatabasesToImportArray = new Array(10).fill(mockSentinelDatabaseWithTlsAuth);
11+
12+
export const mockDatabaseImportFile = {
13+
originalname: 'filename.json',
14+
mimetype: 'application/json',
15+
size: 1,
16+
buffer: Buffer.from(JSON.stringify(mockDatabasesToImportArray)),
17+
};
18+
19+
export const mockDatabaseImportResultSuccess = {
20+
index: 0,
21+
status: DatabaseImportStatus.Success,
22+
host: mockDatabase.host,
23+
port: mockDatabase.port,
24+
};
25+
26+
export const mockDatabaseImportResultFail = {
27+
index: 0,
28+
status: DatabaseImportStatus.Fail,
29+
host: mockDatabase.host,
30+
port: mockDatabase.port,
31+
errors: [new BadRequestException()],
32+
};
33+
34+
export const mockDatabaseImportResultPartial = {
35+
index: 0,
36+
status: DatabaseImportStatus.Partial,
37+
host: mockDatabase.host,
38+
port: mockDatabase.port,
39+
errors: [new InvalidCaCertificateBodyException()],
40+
};
41+
42+
export const mockDatabaseImportResponse = Object.assign(new DatabaseImportResponse(), {
43+
total: 10,
44+
success: (new Array(5).fill(mockDatabaseImportResultSuccess)).map((v, index) => ({
45+
...v,
46+
index: index + 5,
47+
})),
48+
partial: [
49+
[new InvalidCaCertificateBodyException(), new InvalidCertificateNameException()],
50+
[new InvalidCertificateNameException()],
51+
].map((errors, index) => ({
52+
...mockDatabaseImportResultPartial,
53+
index: index + 3,
54+
errors,
55+
})),
56+
fail: [
57+
new ValidationException('Bad request'),
58+
new BadRequestException(),
59+
new ForbiddenException(),
60+
].map((error, index) => ({
61+
...mockDatabaseImportResultFail,
62+
index,
63+
errors: [error],
64+
})),
65+
});
66+
67+
export const mockDatabaseImportPartialAnalyticsPayload = {
68+
partially: mockDatabaseImportResponse.partial.length,
69+
errors: ['InvalidCaCertificateBodyException', 'InvalidCertificateNameException'],
70+
};
71+
72+
export const mockDatabaseImportFailedAnalyticsPayload = {
73+
failed: mockDatabaseImportResponse.fail.length,
74+
errors: ['ValidationException', 'BadRequestException', 'ForbiddenException'],
75+
};
76+
77+
export const mockDatabaseImportSucceededAnalyticsPayload = {
78+
succeed: mockDatabaseImportResponse.success.length,
79+
};
80+
81+
export const mockDatabaseImportAnalytics = jest.fn(() => ({
82+
sendImportResults: jest.fn(),
83+
sendImportFailed: jest.fn(),
84+
}));
85+
86+
export const mockCertificateImportService = jest.fn(() => ({
87+
processCaCertificate: jest.fn().mockResolvedValue(mockCaCertificate),
88+
processClientCertificate: jest.fn().mockResolvedValue(mockClientCertificate),
89+
}));

0 commit comments

Comments
 (0)