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  }