Compare commits

...

5 Commits

Author SHA1 Message Date
Rostislav Dugin
01911dbf72 FIX (notifiers & storages): Avoid request for workspace_id for storages and notifiers removal 2025-11-11 10:05:45 +03:00
Rostislav Dugin
1a16f27a5d FIX (notifiers): Fix update of existing DB notifiers 2025-11-11 08:10:02 +03:00
Rostislav Dugin
778db71625 FIX (tests): Improve tests stability in CI \ CD 2025-11-09 20:41:36 +03:00
Rostislav Dugin
45fc9a7fff FIX (databases): Verify DB nil on side of DB instead of interface 2025-11-09 20:03:22 +03:00
Rostislav Dugin
7f5e786261 FIX (databases): If some DB missing PostgreSQL db fix nil issue 2025-11-09 18:57:42 +03:00
10 changed files with 15 additions and 42 deletions

View File

@@ -185,7 +185,7 @@ jobs:
- name: Run Go tests
run: |
cd backend
go test ./internal/...
go test -p=1 -count=1 -failfast ./internal/...
- name: Stop test containers
if: always()

View File

@@ -94,7 +94,6 @@ func (c *BackupConfigController) GetBackupConfigByDbID(ctx *gin.Context) {
// @Tags backup-configs
// @Produce json
// @Param id path string true "Storage ID"
// @Param workspace_id query string true "Workspace ID"
// @Success 200 {object} map[string]bool
// @Failure 400
// @Failure 401
@@ -113,19 +112,7 @@ func (c *BackupConfigController) IsStorageUsing(ctx *gin.Context) {
return
}
workspaceIDStr := ctx.Query("workspace_id")
if workspaceIDStr == "" {
ctx.JSON(http.StatusBadRequest, gin.H{"error": "workspace_id query parameter is required"})
return
}
workspaceID, err := uuid.Parse(workspaceIDStr)
if err != nil {
ctx.JSON(http.StatusBadRequest, gin.H{"error": "invalid workspace_id"})
return
}
isUsing, err := c.backupConfigService.IsStorageUsing(user, workspaceID, id)
isUsing, err := c.backupConfigService.IsStorageUsing(user, id)
if err != nil {
ctx.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return

View File

@@ -341,7 +341,7 @@ func Test_IsStorageUsing_PermissionsEnforced(t *testing.T) {
test_utils.MakeGetRequestAndUnmarshal(
t,
router,
"/api/v1/backup-configs/storage/"+storage.ID.String()+"/is-using?workspace_id="+workspace.ID.String(),
"/api/v1/backup-configs/storage/"+storage.ID.String()+"/is-using",
"Bearer "+testUserToken,
tt.expectedStatusCode,
&response,
@@ -354,7 +354,7 @@ func Test_IsStorageUsing_PermissionsEnforced(t *testing.T) {
testResp := test_utils.MakeGetRequest(
t,
router,
"/api/v1/backup-configs/storage/"+storage.ID.String()+"/is-using?workspace_id="+workspace.ID.String(),
"/api/v1/backup-configs/storage/"+storage.ID.String()+"/is-using",
"Bearer "+testUserToken,
tt.expectedStatusCode,
)

View File

@@ -119,7 +119,6 @@ func (s *BackupConfigService) GetBackupConfigByDbId(
func (s *BackupConfigService) IsStorageUsing(
user *users_models.User,
workspaceID uuid.UUID,
storageID uuid.UUID,
) (bool, error) {
_, err := s.storageService.GetStorage(user, storageID)

View File

@@ -271,7 +271,6 @@ func (c *DatabaseController) TestDatabaseConnectionDirect(ctx *gin.Context) {
// @Tags databases
// @Produce json
// @Param id path string true "Notifier ID"
// @Param workspace_id query string true "Workspace ID"
// @Success 200 {object} map[string]bool
// @Failure 400
// @Failure 401
@@ -290,19 +289,7 @@ func (c *DatabaseController) IsNotifierUsing(ctx *gin.Context) {
return
}
workspaceIDStr := ctx.Query("workspace_id")
if workspaceIDStr == "" {
ctx.JSON(http.StatusBadRequest, gin.H{"error": "workspace_id query parameter is required"})
return
}
workspaceID, err := uuid.Parse(workspaceIDStr)
if err != nil {
ctx.JSON(http.StatusBadRequest, gin.H{"error": "invalid workspace_id"})
return
}
isUsing, err := c.databaseService.IsNotifierUsing(user, workspaceID, id)
isUsing, err := c.databaseService.IsNotifierUsing(user, id)
if err != nil {
ctx.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return

View File

@@ -67,6 +67,10 @@ func (p *PostgresqlDatabase) TestConnection(logger *slog.Logger) error {
}
func (p *PostgresqlDatabase) HideSensitiveData() {
if p == nil {
return
}
p.Password = ""
}

View File

@@ -67,6 +67,7 @@ func (d *Database) HideSensitiveData() {
func (d *Database) Update(incoming *Database) {
d.Name = incoming.Name
d.Type = incoming.Type
d.Notifiers = incoming.Notifiers
switch d.Type {
case DatabaseTypePostgres:

View File

@@ -219,7 +219,6 @@ func (s *DatabaseService) GetDatabasesByWorkspace(
func (s *DatabaseService) IsNotifierUsing(
user *users_models.User,
workspaceID uuid.UUID,
notifierID uuid.UUID,
) (bool, error) {
_, err := s.notifierService.GetNotifier(user, notifierID)

View File

@@ -108,6 +108,7 @@ export function EditEmailNotifierComponent({ notifier, setNotifier, setIsUnsaved
<div className="mb-1 flex items-center">
<div className="w-[130px] min-w-[130px]">SMTP password</div>
<Input
type="password"
value={notifier?.emailNotifier?.smtpPassword || ''}
onChange={(e) => {
if (!notifier?.emailNotifier) return;

View File

@@ -212,7 +212,7 @@ export function SettingsComponent({ contentHeight }: Props) {
<div className="mt-3 text-sm text-gray-500">
Read more about settings you can{' '}
<a
href="https://postgresus.com/settings"
href="https://postgresus.com/access-management/#global-settings"
target="_blank"
rel="noreferrer"
className="!text-blue-600"
@@ -230,23 +230,18 @@ export function SettingsComponent({ contentHeight }: Props) {
<code
className="flex-1 cursor-pointer transition-colors select-all hover:text-blue-600"
onClick={() => {
window.open(
`${getApplicationServer()}/api/v1/downdetect/is-available`,
'_blank',
);
window.open(`${getApplicationServer()}/api/v1/system/health`, '_blank');
}}
title="Click to open in new tab"
>
{getApplicationServer()}/api/v1/downdetect/is-available
{getApplicationServer()}/api/v1/system/health
</code>
<Button
type="text"
size="small"
className="ml-2 opacity-0 transition-opacity group-hover:opacity-100"
onClick={() => {
navigator.clipboard.writeText(
`${getApplicationServer()}/api/v1/downdetect/is-available`,
);
navigator.clipboard.writeText(`${getApplicationServer()}/api/v1/system/health`);
message.success('Health-check endpoint copied to clipboard');
}}
>