-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcreate_database.go
More file actions
145 lines (131 loc) · 4.27 KB
/
create_database.go
File metadata and controls
145 lines (131 loc) · 4.27 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
package database
import (
"encoding/json"
"fmt"
"time"
"github.com/google/uuid"
"github.com/labbs/nexo/infrastructure/helpers/apperrors"
"github.com/labbs/nexo/application/database/dto"
permissionDto "github.com/labbs/nexo/application/permission/dto"
spaceDto "github.com/labbs/nexo/application/space/dto"
"github.com/labbs/nexo/domain"
)
func (app *DatabaseApplication) CreateDatabase(input dto.CreateDatabaseInput) (*dto.CreateDatabaseOutput, error) {
// Verify user has access to the space
spaceResult, err := app.SpaceApplication.GetSpaceById(spaceDto.GetSpaceByIdInput{SpaceId: input.SpaceId})
if err != nil {
return nil, fmt.Errorf("space not found: %w", err)
}
if spaceResult.Space.GetUserRole(input.UserId) == nil {
return nil, apperrors.ErrAccessDenied
}
// Determine database type (default to spreadsheet)
dbType := domain.DatabaseTypeSpreadsheet
if input.Type == string(domain.DatabaseTypeDocument) {
dbType = domain.DatabaseTypeDocument
}
// Use default schema if none provided
schemaToUse := input.Schema
if len(schemaToUse) == 0 {
if dbType == domain.DatabaseTypeDocument {
// Document databases only need a title field by default
schemaToUse = []dto.PropertySchema{
{Id: "title", Name: "Title", Type: "title"},
}
} else {
// Spreadsheet databases get name and date
schemaToUse = []dto.PropertySchema{
{Id: "name", Name: "Name", Type: "title"},
{Id: "date", Name: "Date", Type: "date"},
}
}
}
// Build schema JSONBArray
schemaJSON, err := json.Marshal(schemaToUse)
if err != nil {
return nil, fmt.Errorf("failed to marshal schema: %w", err)
}
var schema domain.JSONBArray
json.Unmarshal(schemaJSON, &schema)
// Create default view (always table)
defaultViewType := domain.ViewTypeTable
defaultView := dto.ViewConfig{
Id: uuid.New().String(),
Name: "Default",
Type: string(defaultViewType),
}
viewsJSON, _ := json.Marshal([]dto.ViewConfig{defaultView})
var views domain.JSONBArray
json.Unmarshal(viewsJSON, &views)
database := &domain.Database{
Id: uuid.New().String(),
SpaceId: input.SpaceId,
DocumentId: input.DocumentId,
Name: input.Name,
Description: input.Description,
Icon: input.Icon,
Schema: schema,
Views: views,
DefaultView: string(defaultViewType),
Type: dbType,
CreatedBy: input.UserId,
CreatedAt: time.Now(),
UpdatedAt: time.Now(),
}
if err := app.DatabasePers.Create(database); err != nil {
return nil, fmt.Errorf("failed to create database: %w", err)
}
// Auto-create editor permission for the creator
// This ensures they retain access even if their space role is downgraded
if err := app.PermissionApplication.AssignOwnerPermission(permissionDto.AssignOwnerPermissionInput{
ResourceType: "database",
ResourceId: database.Id,
UserId: input.UserId,
Role: "editor",
}); err != nil {
// Log but don't fail - the database is already created
app.Logger.Warn().Err(err).Str("database_id", database.Id).Str("user_id", input.UserId).Msg("failed to create creator permission")
}
// Create sample rows for new spreadsheet databases only (not for document databases)
if dbType == domain.DatabaseTypeSpreadsheet {
// Find the first "title" type column to use for sample data names
now := time.Now()
var titleColumnId string
for _, prop := range schemaToUse {
if prop.Type == "title" {
titleColumnId = prop.Id
break
}
}
if titleColumnId == "" && len(schemaToUse) > 0 {
titleColumnId = schemaToUse[0].Id // fallback to first column
}
if titleColumnId != "" {
sampleNames := []string{"Data 1", "Data 2", "Data 3"}
for _, name := range sampleNames {
row := &domain.DatabaseRow{
Id: uuid.New().String(),
DatabaseId: database.Id,
Properties: domain.JSONB{
titleColumnId: name,
},
CreatedBy: input.UserId,
CreatedAt: now,
UpdatedAt: now,
}
// Ignore errors for sample data - not critical
app.DatabaseRowPers.Create(row)
}
}
}
return &dto.CreateDatabaseOutput{
Id: database.Id,
Name: database.Name,
Description: database.Description,
Icon: database.Icon,
Schema: schemaToUse,
DefaultView: database.DefaultView,
Type: string(database.Type),
CreatedAt: database.CreatedAt,
}, nil
}