2 Commits

Author SHA1 Message Date
Mikhail Chusavitin
8f7defdb8a Добавил шаблон для создания пользователя в БД 2026-02-05 10:55:02 +03:00
Mikhail Chusavitin
0c190efda4 Fix sync owner mapping before pushing configurations 2026-02-05 10:43:34 +03:00
2 changed files with 56 additions and 0 deletions

View File

@@ -85,6 +85,30 @@ auth:
go run ./cmd/qfs -migrate
```
### Минимальные права БД для пользователя квотаций
Если нужен пользователь, который может создавать/редактировать квотации, но не может управлять ценами:
```sql
DROP USER IF EXISTS 'quote_user'@'%';
CREATE USER 'quote_user'@'%' IDENTIFIED BY 'StrongPassword!';
-- чтение данных для расчета/просмотра
GRANT SELECT ON RFQ_LOG.lot TO 'quote_user'@'%';
GRANT SELECT ON RFQ_LOG.qt_lot_metadata TO 'quote_user'@'%';
GRANT SELECT ON RFQ_LOG.qt_pricelists TO 'quote_user'@'%';
GRANT SELECT ON RFQ_LOG.qt_pricelist_items TO 'quote_user'@'%';
GRANT SELECT ON RFQ_LOG.qt_users TO 'quote_user'@'%';
-- работа с квотациями
GRANT SELECT, INSERT, UPDATE, DELETE ON RFQ_LOG.qt_configurations TO 'quote_user'@'%';
FLUSH PRIVILEGES;
```
Важно: этот вариант не ограничивает редактирование только своими записями в `qt_configurations`.
Если пересоздавать пользователя нельзя, используйте `SHOW GRANTS FOR 'quote_user'@'%';` и сделайте точечные `REVOKE`.
### 4. Импорт метаданных компонентов
```bash

View File

@@ -484,6 +484,9 @@ func (s *Service) pushConfigurationCreate(change *localdb.PendingChange) error {
// Create repository
configRepo := repository.NewConfigurationRepository(mariaDB)
if err := s.ensureConfigurationOwner(mariaDB, &cfg); err != nil {
return fmt.Errorf("resolve configuration owner: %w", err)
}
// Create on server
if err := configRepo.Create(&cfg); err != nil {
@@ -536,6 +539,9 @@ func (s *Service) pushConfigurationUpdate(change *localdb.PendingChange) error {
// Create repository
configRepo := repository.NewConfigurationRepository(mariaDB)
if err := s.ensureConfigurationOwner(mariaDB, &cfg); err != nil {
return fmt.Errorf("resolve configuration owner: %w", err)
}
// Ensure we have a server ID before updating
// If the payload doesn't have ID, get it from local configuration
@@ -585,6 +591,32 @@ func (s *Service) pushConfigurationUpdate(change *localdb.PendingChange) error {
return nil
}
func (s *Service) ensureConfigurationOwner(mariaDB *gorm.DB, cfg *models.Configuration) error {
if cfg == nil {
return fmt.Errorf("configuration is nil")
}
ownerUsername := cfg.OwnerUsername
if ownerUsername == "" {
ownerUsername = s.localDB.GetDBUser()
cfg.OwnerUsername = ownerUsername
}
if ownerUsername == "" {
return fmt.Errorf("owner username is empty")
}
userID, err := models.EnsureDBUser(mariaDB, ownerUsername)
if err != nil {
return err
}
if userID == 0 {
return fmt.Errorf("resolved user ID is 0 for owner %q", ownerUsername)
}
cfg.UserID = userID
return nil
}
func (s *Service) pushConfigurationRollback(change *localdb.PendingChange) error {
// Last-write-wins for now: rollback is pushed as an update with rollback metadata.
return s.pushConfigurationUpdate(change)