@hed-hog/core 0.0.266 → 0.0.273
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/README.md +402 -0
- package/dist/dashboard/dashboard-component-role/dashboard-component-role.controller.d.ts +15 -15
- package/dist/dashboard/dashboard-component-role/dashboard-component-role.service.d.ts +15 -15
- package/dist/dashboard/dashboard-role/dashboard-role.controller.d.ts +7 -7
- package/dist/dashboard/dashboard-role/dashboard-role.service.d.ts +7 -7
- package/dist/file/file.controller.d.ts +2 -2
- package/dist/file/file.service.d.ts +4 -4
- package/dist/install/install.module.d.ts.map +1 -1
- package/dist/install/install.module.js +2 -0
- package/dist/install/install.module.js.map +1 -1
- package/dist/install/install.service.d.ts +3 -2
- package/dist/install/install.service.d.ts.map +1 -1
- package/dist/install/install.service.js +33 -56
- package/dist/install/install.service.js.map +1 -1
- package/dist/setting/setting.service.d.ts.map +1 -1
- package/dist/setting/setting.service.js +2 -1
- package/dist/setting/setting.service.js.map +1 -1
- package/hedhog/data/dashboard_component.yaml +8 -8
- package/hedhog/data/dashboard_item.yaml +18 -18
- package/hedhog/frontend/app/dashboard/[slug]/dashboard-content.tsx.ejs +10 -8
- package/hedhog/frontend/app/dashboard/components/draggable-grid.tsx.ejs +20 -18
- package/hedhog/frontend/app/dashboard/components/widget-wrapper.tsx.ejs +6 -6
- package/hedhog/frontend/app/dashboard/dashboard.css.ejs +92 -184
- package/package.json +11 -4
- package/src/install/install.module.ts +2 -0
- package/src/install/install.service.ts +42 -65
- package/src/setting/setting.service.ts +5 -4
|
@@ -122,12 +122,12 @@ export function WidgetWrapper({
|
|
|
122
122
|
);
|
|
123
123
|
}
|
|
124
124
|
|
|
125
|
-
return (
|
|
126
|
-
<div className="group relative h-full w-full">
|
|
127
|
-
<div
|
|
128
|
-
className="drag-handle absolute left-3 top-3 z-20"
|
|
129
|
-
style={{ cursor: 'grab' }}
|
|
130
|
-
>
|
|
125
|
+
return (
|
|
126
|
+
<div className="dashboard-widget group relative h-full w-full">
|
|
127
|
+
<div
|
|
128
|
+
className="drag-handle absolute left-3 top-3 z-20"
|
|
129
|
+
style={{ cursor: 'grab' }}
|
|
130
|
+
>
|
|
131
131
|
<IconGripVertical className="size-4 shrink-0 text-muted-foreground/30 opacity-0 transition-opacity group-hover:opacity-100" />
|
|
132
132
|
</div>
|
|
133
133
|
{onRemove && (
|
|
@@ -1,157 +1,62 @@
|
|
|
1
|
-
.react-grid-layout {
|
|
2
|
-
position: relative;
|
|
3
|
-
transition: height 200ms ease;
|
|
4
|
-
}
|
|
5
|
-
|
|
6
|
-
.react-grid-item {
|
|
7
|
-
transition: all 200ms ease;
|
|
8
|
-
transition-property: left, top, width, height;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
.react-grid-item img {
|
|
12
|
-
pointer-events: none;
|
|
13
|
-
user-select: none;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
.react-grid-item > .react-resizable-handle {
|
|
17
|
-
position: absolute;
|
|
18
|
-
width:
|
|
19
|
-
height:
|
|
20
|
-
z-index: 10;
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
.react-grid-item
|
|
39
|
-
opacity: 1;
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
right: 0;
|
|
61
|
-
cursor: se-resize;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
.react-grid-item > .react-resizable-handle.react-resizable-handle-se::after {
|
|
65
|
-
right: 2px;
|
|
66
|
-
bottom: 2px;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
.react-grid-item > .react-resizable-handle.react-resizable-handle-nw {
|
|
70
|
-
top: 0;
|
|
71
|
-
left: 0;
|
|
72
|
-
cursor: nw-resize;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
.react-grid-item > .react-resizable-handle.react-resizable-handle-nw::after {
|
|
76
|
-
left: 2px;
|
|
77
|
-
top: 2px;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
.react-grid-item > .react-resizable-handle.react-resizable-handle-ne {
|
|
81
|
-
top: 0;
|
|
82
|
-
right: 0;
|
|
83
|
-
cursor: ne-resize;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
.react-grid-item > .react-resizable-handle.react-resizable-handle-ne::after {
|
|
87
|
-
right: 2px;
|
|
88
|
-
top: 2px;
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
.react-grid-item > .react-resizable-handle.react-resizable-handle-w {
|
|
92
|
-
left: 0;
|
|
93
|
-
top: 50%;
|
|
94
|
-
transform: translateY(-50%);
|
|
95
|
-
cursor: ew-resize;
|
|
96
|
-
width: 20px;
|
|
97
|
-
height: 60px;
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
.react-grid-item > .react-resizable-handle.react-resizable-handle-w::after {
|
|
101
|
-
left: 2px;
|
|
102
|
-
top: 50%;
|
|
103
|
-
transform: translateY(-50%);
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
.react-grid-item > .react-resizable-handle.react-resizable-handle-e {
|
|
107
|
-
right: 0;
|
|
108
|
-
top: 50%;
|
|
109
|
-
transform: translateY(-50%);
|
|
110
|
-
cursor: ew-resize;
|
|
111
|
-
width: 20px;
|
|
112
|
-
height: 60px;
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
.react-grid-item > .react-resizable-handle.react-resizable-handle-e::after {
|
|
116
|
-
right: 2px;
|
|
117
|
-
top: 50%;
|
|
118
|
-
transform: translateY(-50%);
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
.react-grid-item > .react-resizable-handle.react-resizable-handle-n {
|
|
122
|
-
top: 0;
|
|
123
|
-
left: 50%;
|
|
124
|
-
transform: translateX(-50%);
|
|
125
|
-
cursor: ns-resize;
|
|
126
|
-
width: 60px;
|
|
127
|
-
height: 20px;
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
.react-grid-item > .react-resizable-handle.react-resizable-handle-n::after {
|
|
131
|
-
top: 2px;
|
|
132
|
-
left: 50%;
|
|
133
|
-
transform: translateX(-50%);
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
.react-grid-item > .react-resizable-handle.react-resizable-handle-s {
|
|
137
|
-
bottom: 0;
|
|
138
|
-
left: 50%;
|
|
139
|
-
transform: translateX(-50%);
|
|
140
|
-
cursor: ns-resize;
|
|
141
|
-
width: 60px;
|
|
142
|
-
height: 20px;
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
.react-grid-item > .react-resizable-handle.react-resizable-handle-s::after {
|
|
146
|
-
bottom: 2px;
|
|
147
|
-
left: 50%;
|
|
148
|
-
transform: translateX(-50%);
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
/* Drag handle styles */
|
|
152
|
-
.drag-handle {
|
|
153
|
-
cursor: grab !important;
|
|
154
|
-
user-select: none !important;
|
|
1
|
+
.dashboard-grid.react-grid-layout {
|
|
2
|
+
position: relative;
|
|
3
|
+
transition: height 200ms ease;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
.dashboard-grid .react-grid-item {
|
|
7
|
+
transition: all 200ms ease;
|
|
8
|
+
transition-property: left, top, width, height;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
.dashboard-grid .react-grid-item img {
|
|
12
|
+
pointer-events: none;
|
|
13
|
+
user-select: none;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
.dashboard-grid .react-grid-item > .react-resizable-handle {
|
|
17
|
+
position: absolute;
|
|
18
|
+
width: 18px;
|
|
19
|
+
height: 18px;
|
|
20
|
+
z-index: 10;
|
|
21
|
+
opacity: 0;
|
|
22
|
+
transition: opacity 0.15s ease;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
.dashboard-grid .react-grid-item > .react-resizable-handle::after {
|
|
26
|
+
content: '';
|
|
27
|
+
position: absolute;
|
|
28
|
+
right: 3px;
|
|
29
|
+
bottom: 3px;
|
|
30
|
+
width: 6px;
|
|
31
|
+
height: 6px;
|
|
32
|
+
border-right: 2px solid hsl(var(--muted-foreground));
|
|
33
|
+
border-bottom: 2px solid hsl(var(--muted-foreground));
|
|
34
|
+
opacity: 0.45;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
.dashboard-grid .react-grid-item:hover > .react-resizable-handle.react-resizable-handle-se,
|
|
38
|
+
.dashboard-grid .react-grid-item.resizing > .react-resizable-handle.react-resizable-handle-se {
|
|
39
|
+
opacity: 1;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
.dashboard-grid .react-resizable-hide > .react-resizable-handle {
|
|
43
|
+
display: none;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
.dashboard-grid .react-grid-item > .react-resizable-handle:not(.react-resizable-handle-se) {
|
|
47
|
+
display: none;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
.dashboard-grid .react-grid-item > .react-resizable-handle.react-resizable-handle-se {
|
|
51
|
+
bottom: 0;
|
|
52
|
+
right: 0;
|
|
53
|
+
cursor: se-resize;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/* Drag handle styles */
|
|
57
|
+
.drag-handle {
|
|
58
|
+
cursor: grab !important;
|
|
59
|
+
user-select: none !important;
|
|
155
60
|
}
|
|
156
61
|
|
|
157
62
|
.drag-handle:active {
|
|
@@ -159,38 +64,41 @@
|
|
|
159
64
|
}
|
|
160
65
|
|
|
161
66
|
/* Prevent text selection during drag */
|
|
162
|
-
.react-grid-item.react-draggable-dragging {
|
|
163
|
-
transition: none;
|
|
164
|
-
z-index: 100;
|
|
165
|
-
will-change: transform;
|
|
166
|
-
opacity: 0.9;
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
.react-grid-item.resizing {
|
|
170
|
-
transition: none;
|
|
171
|
-
z-index: 100;
|
|
172
|
-
will-change: transform;
|
|
173
|
-
opacity: 0.9;
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
.
|
|
180
|
-
|
|
181
|
-
opacity: 0.5;
|
|
182
|
-
transition-duration: 100ms;
|
|
67
|
+
.dashboard-grid .react-grid-item.react-draggable-dragging {
|
|
68
|
+
transition: none;
|
|
69
|
+
z-index: 100;
|
|
70
|
+
will-change: transform;
|
|
71
|
+
opacity: 0.9;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
.dashboard-grid .react-grid-item.resizing {
|
|
75
|
+
transition: none;
|
|
76
|
+
z-index: 100;
|
|
77
|
+
will-change: transform;
|
|
78
|
+
opacity: 0.9;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/* Placeholder styling */
|
|
82
|
+
.dashboard-grid .react-grid-placeholder {
|
|
83
|
+
background: hsl(var(--primary) / 0.2);
|
|
84
|
+
opacity: 0.5;
|
|
85
|
+
transition-duration: 100ms;
|
|
183
86
|
z-index: 2;
|
|
184
87
|
border-radius: 0.5rem;
|
|
185
88
|
border: 2px dashed hsl(var(--primary));
|
|
186
89
|
}
|
|
187
90
|
|
|
188
|
-
.react-grid-item:hover {
|
|
189
|
-
outline: 1px solid hsl(var(--primary) / 0.
|
|
190
|
-
outline-offset: -1px;
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
.
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
91
|
+
.dashboard-grid .react-grid-item:hover {
|
|
92
|
+
outline: 1px solid hsl(var(--primary) / 0.12);
|
|
93
|
+
outline-offset: -1px;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
.dashboard-widget > [data-slot='card'] {
|
|
97
|
+
gap: 0.75rem;
|
|
98
|
+
padding-top: 0.75rem;
|
|
99
|
+
padding-bottom: 0.75rem;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
.dashboard-widget > [data-slot='card'] > [data-slot='card-header'] {
|
|
103
|
+
padding-top: 0;
|
|
104
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hed-hog/core",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.273",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"types": "dist/index.d.ts",
|
|
6
6
|
"dependencies": {
|
|
@@ -30,12 +30,12 @@
|
|
|
30
30
|
"sharp": "^0.34.2",
|
|
31
31
|
"speakeasy": "^2.0.0",
|
|
32
32
|
"uuid": "^11.1.0",
|
|
33
|
+
"@hed-hog/api-prisma": "0.0.5",
|
|
33
34
|
"@hed-hog/api-pagination": "0.0.6",
|
|
34
|
-
"@hed-hog/api-mail": "0.0.8",
|
|
35
35
|
"@hed-hog/api-locale": "0.0.13",
|
|
36
|
-
"@hed-hog/api
|
|
36
|
+
"@hed-hog/api": "0.0.4",
|
|
37
37
|
"@hed-hog/api-types": "0.0.1",
|
|
38
|
-
"@hed-hog/api": "0.0.
|
|
38
|
+
"@hed-hog/api-mail": "0.0.8"
|
|
39
39
|
},
|
|
40
40
|
"exports": {
|
|
41
41
|
".": {
|
|
@@ -44,11 +44,18 @@
|
|
|
44
44
|
"require": "./dist/index.js",
|
|
45
45
|
"default": "./dist/index.js"
|
|
46
46
|
},
|
|
47
|
+
"./*": {
|
|
48
|
+
"types": "./dist/*.d.ts",
|
|
49
|
+
"import": "./dist/*.js",
|
|
50
|
+
"require": "./dist/*.js",
|
|
51
|
+
"default": "./dist/*.js"
|
|
52
|
+
},
|
|
47
53
|
"./package.json": "./package.json"
|
|
48
54
|
},
|
|
49
55
|
"typesVersions": {
|
|
50
56
|
"*": {
|
|
51
57
|
"*": [
|
|
58
|
+
"./dist/*.d.ts",
|
|
52
59
|
"./dist/index.d.ts"
|
|
53
60
|
]
|
|
54
61
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { PrismaModule } from '@hed-hog/api-prisma';
|
|
2
2
|
import { forwardRef, Module } from '@nestjs/common';
|
|
3
|
+
import { ConfigModule } from '@nestjs/config';
|
|
3
4
|
import { AuthModule } from '../auth/auth.module';
|
|
4
5
|
import { SecurityModule } from '../security/security.module';
|
|
5
6
|
import { SettingModule } from '../setting/setting.module';
|
|
@@ -12,6 +13,7 @@ import { InstallService } from './install.service';
|
|
|
12
13
|
forwardRef(() => SettingModule),
|
|
13
14
|
forwardRef(() => SecurityModule),
|
|
14
15
|
forwardRef(() => AuthModule),
|
|
16
|
+
forwardRef(() => ConfigModule),
|
|
15
17
|
],
|
|
16
18
|
controllers: [InstallController],
|
|
17
19
|
providers: [InstallService],
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { PrismaService } from '@hed-hog/api-prisma';
|
|
2
2
|
import { BadRequestException, Injectable, Logger } from '@nestjs/common';
|
|
3
|
+
import { ConfigService } from '@nestjs/config';
|
|
3
4
|
import { existsSync, readFileSync } from 'fs';
|
|
4
5
|
import { writeFile } from 'fs/promises';
|
|
5
6
|
import { resolve } from 'path';
|
|
@@ -13,80 +14,50 @@ export class InstallService {
|
|
|
13
14
|
|
|
14
15
|
constructor(
|
|
15
16
|
private readonly security: SecurityService,
|
|
16
|
-
private readonly prisma: PrismaService
|
|
17
|
+
private readonly prisma: PrismaService,
|
|
18
|
+
private readonly configService: ConfigService,
|
|
17
19
|
) { }
|
|
18
20
|
|
|
19
21
|
private async forceReset() {
|
|
20
22
|
|
|
21
23
|
await new Promise((resolve) => setTimeout(resolve, 1000));
|
|
22
24
|
|
|
23
|
-
//
|
|
24
|
-
const
|
|
25
|
-
|
|
26
|
-
|
|
25
|
+
// In development, touching main.ts triggers restart; in production only dist exists.
|
|
26
|
+
const candidatePaths = [
|
|
27
|
+
resolve(process.cwd(), 'src', 'main.ts'),
|
|
28
|
+
resolve(process.cwd(), 'dist', 'apps', 'api', 'src', 'main.js'),
|
|
29
|
+
resolve(process.cwd(), 'dist', 'src', 'main.js'),
|
|
30
|
+
];
|
|
31
|
+
const mainFilePath = candidatePaths.find((filePath) => existsSync(filePath));
|
|
32
|
+
if (!mainFilePath) {
|
|
33
|
+
this.logger.warn('Skip force reset: no main entry file found to touch.');
|
|
34
|
+
return;
|
|
27
35
|
}
|
|
36
|
+
|
|
28
37
|
let mainContent: string;
|
|
29
38
|
try {
|
|
30
39
|
mainContent = readFileSync(mainFilePath, 'utf-8');
|
|
31
40
|
} catch (err: any) {
|
|
32
|
-
throw new BadRequestException(
|
|
41
|
+
throw new BadRequestException(
|
|
42
|
+
`Failed to read main entry file: ${err.message}`,
|
|
43
|
+
);
|
|
33
44
|
}
|
|
34
45
|
try {
|
|
35
|
-
this.logger.verbose(
|
|
46
|
+
this.logger.verbose(
|
|
47
|
+
`Forcing application restart by touching ${mainFilePath}...`,
|
|
48
|
+
);
|
|
36
49
|
await writeFile(mainFilePath, mainContent, 'utf-8');
|
|
37
50
|
} catch (err: any) {
|
|
38
|
-
throw new BadRequestException(
|
|
51
|
+
throw new BadRequestException(
|
|
52
|
+
`Failed to write main entry file: ${err.message}`,
|
|
53
|
+
);
|
|
39
54
|
}
|
|
40
55
|
|
|
41
56
|
}
|
|
42
57
|
|
|
43
58
|
private async checkInstallation() {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
let data = {
|
|
48
|
-
installed: false
|
|
49
|
-
};
|
|
50
|
-
|
|
51
|
-
if (existsSync(hedhogFilePath)) {
|
|
52
|
-
try {
|
|
53
|
-
const fileContent = readFileSync(hedhogFilePath, 'utf-8');
|
|
54
|
-
data = JSON.parse(fileContent);
|
|
55
|
-
} catch (err: any) {
|
|
56
|
-
this.logger.warn(`Failed to read hedhog.json: ${err.message}`);
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
return data.installed === true;
|
|
61
|
-
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
private async markAsInstalled() {
|
|
65
|
-
|
|
66
|
-
const hedhogFilePath = resolve(process.cwd(), '..', '..', 'hedhog.json');
|
|
67
|
-
|
|
68
|
-
let content: any = {}
|
|
69
|
-
|
|
70
|
-
if (existsSync(hedhogFilePath)) {
|
|
71
|
-
try {
|
|
72
|
-
const fileContent = readFileSync(hedhogFilePath, 'utf-8');
|
|
73
|
-
content = JSON.parse(fileContent);
|
|
74
|
-
} catch (err: any) {
|
|
75
|
-
this.logger.warn(`Failed to read hedhog.json: ${err.message}`);
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
content.installed = true;
|
|
80
|
-
content.installedAt = new Date().toISOString();
|
|
81
|
-
|
|
82
|
-
try {
|
|
83
|
-
this.logger.verbose('Marking application as installed in hedghog.json...');
|
|
84
|
-
await writeFile(hedhogFilePath, JSON.stringify(content, null, 2), 'utf-8');
|
|
85
|
-
} catch (err: any) {
|
|
86
|
-
throw new BadRequestException(`Failed to write hedhog.json: ${err.message}`);
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
return true;
|
|
59
|
+
const usersCount = await this.prisma.user.count();
|
|
60
|
+
return usersCount > 0;
|
|
90
61
|
}
|
|
91
62
|
|
|
92
63
|
private async updateEnvSecrets(pepper: string) {
|
|
@@ -170,8 +141,6 @@ export class InstallService {
|
|
|
170
141
|
throw new BadRequestException('Application is already installed.');
|
|
171
142
|
}
|
|
172
143
|
|
|
173
|
-
const pepper = this.base64Encode(this.security.randomOpaque(16));
|
|
174
|
-
|
|
175
144
|
await this.prisma.$transaction(async (prisma) => {
|
|
176
145
|
|
|
177
146
|
this.logger.log('Starting installation process...');
|
|
@@ -220,6 +189,13 @@ export class InstallService {
|
|
|
220
189
|
|
|
221
190
|
this.logger.log(`Creating admin user: ${userName} <${email}>`);
|
|
222
191
|
|
|
192
|
+
const pepper = this.configService.get<string>('PEPPER');
|
|
193
|
+
if (!pepper) {
|
|
194
|
+
throw new BadRequestException(
|
|
195
|
+
'PEPPER is not configured. Set PEPPER before installation.',
|
|
196
|
+
);
|
|
197
|
+
}
|
|
198
|
+
|
|
223
199
|
const passwordHash = await this.security.hashArgon2(password, pepper);
|
|
224
200
|
|
|
225
201
|
const user = await prisma.user.create({
|
|
@@ -260,9 +236,15 @@ export class InstallService {
|
|
|
260
236
|
|
|
261
237
|
this.logger.log(`Roles assigned to user ID: ${user.id}`);
|
|
262
238
|
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
239
|
+
const isDevelopment = process.env.NODE_ENV !== 'production';
|
|
240
|
+
if (isDevelopment) {
|
|
241
|
+
await this.updateEnvSecrets(pepper);
|
|
242
|
+
await this.forceReset();
|
|
243
|
+
} else {
|
|
244
|
+
this.logger.log(
|
|
245
|
+
'Skipping env secret update and force reset outside development.',
|
|
246
|
+
);
|
|
247
|
+
}
|
|
266
248
|
|
|
267
249
|
this.logger.log('Installation process completed successfully.');
|
|
268
250
|
|
|
@@ -273,12 +255,7 @@ export class InstallService {
|
|
|
273
255
|
}
|
|
274
256
|
|
|
275
257
|
async check() {
|
|
276
|
-
|
|
277
|
-
return { success: true };
|
|
278
|
-
} else {
|
|
279
|
-
throw new BadRequestException('Application is not installed.');
|
|
280
|
-
}
|
|
281
|
-
|
|
258
|
+
return { success: true };
|
|
282
259
|
}
|
|
283
260
|
|
|
284
261
|
async generateMailMigration({
|
|
@@ -181,10 +181,11 @@ export class SettingService {
|
|
|
181
181
|
'date-format',
|
|
182
182
|
'time-format',
|
|
183
183
|
'timezone',
|
|
184
|
-
'menu-width',
|
|
185
|
-
'providers',
|
|
186
|
-
'disable-authentication-with-email-and-password'
|
|
187
|
-
|
|
184
|
+
'menu-width',
|
|
185
|
+
'providers',
|
|
186
|
+
'disable-authentication-with-email-and-password',
|
|
187
|
+
'contact-allow-company-registration',
|
|
188
|
+
];
|
|
188
189
|
const setting = await this.getSettingValues(slugs);
|
|
189
190
|
return { locales, setting };
|
|
190
191
|
}
|