github.com/e154/smart-home@v0.17.2-0.20240311175135-e530a6e5cd45/db/plugin.go (about) 1 // This file is part of the Smart Home 2 // Program complex distribution https://github.com/e154/smart-home 3 // Copyright (C) 2016-2023, Filippov Alex 4 // 5 // This library is free software: you can redistribute it and/or 6 // modify it under the terms of the GNU Lesser General Public 7 // License as published by the Free Software Foundation; either 8 // version 3 of the License, or (at your option) any later version. 9 // 10 // This library is distributed in the hope that it will be useful, 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 // Library General Public License for more details. 14 // 15 // You should have received a copy of the GNU Lesser General Public 16 // License along with this library. If not, see 17 // <https://www.gnu.org/licenses/>. 18 19 package db 20 21 import ( 22 "context" 23 "encoding/json" 24 "fmt" 25 26 "github.com/pkg/errors" 27 "gorm.io/gorm" 28 "gorm.io/gorm/clause" 29 30 "github.com/e154/smart-home/common/apperr" 31 ) 32 33 // Plugins ... 34 type Plugins struct { 35 Db *gorm.DB 36 } 37 38 // Plugin ... 39 type Plugin struct { 40 Name string `gorm:"primary_key"` 41 Version string 42 Enabled bool 43 System bool 44 Actor bool 45 Settings json.RawMessage `gorm:"type:jsonb;not null"` 46 } 47 48 // TableName ... 49 func (d Plugin) TableName() string { 50 return "plugins" 51 } 52 53 // Add ... 54 func (n Plugins) Add(ctx context.Context, plugin *Plugin) (err error) { 55 if err = n.Db.WithContext(ctx).Create(&plugin).Error; err != nil { 56 err = errors.Wrap(apperr.ErrPluginAdd, err.Error()) 57 return 58 } 59 return 60 } 61 62 // CreateOrUpdate ... 63 func (n Plugins) CreateOrUpdate(ctx context.Context, v *Plugin) (err error) { 64 err = n.Db.WithContext(ctx).Model(&Plugin{}).Clauses(clause.OnConflict{ 65 Columns: []clause.Column{{Name: "name"}}, 66 DoUpdates: clause.Assignments(map[string]interface{}{ 67 "version": v.Version, 68 "enabled": v.Enabled, 69 "system": v.System, 70 "settings": v.Settings, 71 "actor": v.Actor, 72 }), 73 }).Create(&v).Error 74 if err != nil { 75 err = errors.Wrap(apperr.ErrPluginUpdate, err.Error()) 76 } 77 return 78 } 79 80 // Update ... 81 func (n Plugins) Update(ctx context.Context, m *Plugin) (err error) { 82 if err = n.Db.WithContext(ctx).Model(&Plugin{}).Where("name = ?", m.Name).Updates(map[string]interface{}{ 83 "enabled": m.Enabled, 84 "system": m.System, 85 "actor": m.Actor, 86 "settings": m.Settings, 87 }).Error; err != nil { 88 err = errors.Wrap(apperr.ErrPluginUpdate, err.Error()) 89 } 90 return 91 } 92 93 // Delete ... 94 func (n Plugins) Delete(ctx context.Context, name string) (err error) { 95 if err = n.Db.WithContext(ctx).Delete(&Plugin{Name: name}).Error; err != nil { 96 err = errors.Wrap(apperr.ErrPluginDelete, err.Error()) 97 } 98 return 99 } 100 101 // List ... 102 func (n Plugins) List(ctx context.Context, limit, offset int, orderBy, sort string, onlyEnabled bool) (list []*Plugin, total int64, err error) { 103 104 list = make([]*Plugin, 0) 105 q := n.Db.WithContext(ctx).Model(&Plugin{}) 106 107 if onlyEnabled { 108 q = q. 109 Where("enabled is true") 110 } 111 112 if err = q.Count(&total).Error; err != nil { 113 err = errors.Wrap(apperr.ErrPluginList, err.Error()) 114 return 115 } 116 117 if sort != "" && orderBy != "" { 118 q = q. 119 Order(fmt.Sprintf("%s %s", sort, orderBy)) 120 } 121 122 q = q. 123 Limit(limit). 124 Offset(offset) 125 126 if err = q.Find(&list).Error; err != nil { 127 err = errors.Wrap(apperr.ErrPluginList, err.Error()) 128 } 129 130 return 131 } 132 133 // Search ... 134 func (n Plugins) Search(ctx context.Context, query string, limit, offset int) (list []*Plugin, total int64, err error) { 135 136 q := n.Db.WithContext(ctx).Model(&Plugin{}). 137 Where("name LIKE ? and actor=true and enabled=true", "%"+query+"%") 138 139 if err = q.Count(&total).Error; err != nil { 140 err = errors.Wrap(apperr.ErrPluginSearch, err.Error()) 141 return 142 } 143 144 q = q. 145 Limit(limit). 146 Offset(offset). 147 Order("name ASC") 148 149 list = make([]*Plugin, 0) 150 if err = q.Find(&list).Error; err != nil { 151 err = errors.Wrap(apperr.ErrPluginSearch, err.Error()) 152 } 153 154 return 155 } 156 157 // GetByName ... 158 func (n Plugins) GetByName(ctx context.Context, name string) (plugin *Plugin, err error) { 159 160 plugin = &Plugin{} 161 err = n.Db.WithContext(ctx).Model(plugin). 162 Where("name = ?", name). 163 First(&plugin). 164 Error 165 if err != nil { 166 if errors.Is(err, gorm.ErrRecordNotFound) { 167 err = errors.Wrap(apperr.ErrPluginNotFound, fmt.Sprintf("name \"%s\"", name)) 168 return 169 } 170 err = errors.Wrap(apperr.ErrPluginGet, err.Error()) 171 } 172 return 173 }