github.com/cs3org/reva/v2@v2.27.7/pkg/cbox/favorite/sql/sql.go (about) 1 // Copyright 2018-2021 CERN 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 // 15 // In applying this license, CERN does not waive the privileges and immunities 16 // granted to it by virtue of its status as an Intergovernmental Organization 17 // or submit itself to any jurisdiction. 18 19 package cbox 20 21 import ( 22 "context" 23 "database/sql" 24 "fmt" 25 26 user "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1" 27 provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" 28 "github.com/cs3org/reva/v2/pkg/cbox/utils" 29 ctxpkg "github.com/cs3org/reva/v2/pkg/ctx" 30 "github.com/cs3org/reva/v2/pkg/storage/favorite" 31 "github.com/cs3org/reva/v2/pkg/storage/favorite/registry" 32 "github.com/mitchellh/mapstructure" 33 ) 34 35 func init() { 36 registry.Register("sql", New) 37 } 38 39 type config struct { 40 DbUsername string `mapstructure:"db_username"` 41 DbPassword string `mapstructure:"db_password"` 42 DbHost string `mapstructure:"db_host"` 43 DbPort int `mapstructure:"db_port"` 44 DbName string `mapstructure:"db_name"` 45 } 46 47 type mgr struct { 48 c *config 49 db *sql.DB 50 } 51 52 // New returns an instance of the cbox sql favorites manager. 53 func New(m map[string]interface{}) (favorite.Manager, error) { 54 c := &config{} 55 if err := mapstructure.Decode(m, c); err != nil { 56 return nil, err 57 } 58 59 db, err := sql.Open("mysql", fmt.Sprintf("%s:%s@tcp(%s:%d)/%s", c.DbUsername, c.DbPassword, c.DbHost, c.DbPort, c.DbName)) 60 if err != nil { 61 return nil, err 62 } 63 64 return &mgr{ 65 c: c, 66 db: db, 67 }, nil 68 } 69 70 func (m *mgr) ListFavorites(ctx context.Context, userID *user.UserId) ([]*provider.ResourceId, error) { 71 user := ctxpkg.ContextMustGetUser(ctx) 72 infos := []*provider.ResourceId{} 73 query := `SELECT fileid_prefix, fileid FROM cbox_metadata WHERE uid=? AND tag_key="fav"` 74 rows, err := m.db.Query(query, user.Id.OpaqueId) 75 if err != nil { 76 return nil, err 77 } 78 defer rows.Close() 79 80 for rows.Next() { 81 var info provider.ResourceId 82 if err := rows.Scan(&info.SpaceId, &info.OpaqueId); err != nil { 83 return nil, err 84 } 85 infos = append(infos, &info) 86 } 87 88 if err = rows.Err(); err != nil { 89 return nil, err 90 } 91 return infos, nil 92 } 93 94 func (m *mgr) SetFavorite(ctx context.Context, userID *user.UserId, resourceInfo *provider.ResourceInfo) error { 95 user := ctxpkg.ContextMustGetUser(ctx) 96 spaceID := resourceInfo.Id.SpaceId 97 98 // The primary key is just the ID in the table, it should ideally be (uid, fileid_prefix, fileid, tag_key) 99 // For the time being, just check if the favorite already exists. If it does, return early 100 var id int 101 query := `SELECT id FROM cbox_metadata WHERE uid=? AND fileid_prefix=? AND fileid=? AND tag_key="fav"` 102 if err := m.db.QueryRow(query, user.Id.OpaqueId, spaceID, resourceInfo.Id.OpaqueId).Scan(&id); err == nil { 103 // Favorite is already set, return 104 return nil 105 } 106 107 query = `INSERT INTO cbox_metadata SET item_type=?, uid=?, fileid_prefix=?, fileid=?, tag_key="fav"` 108 vals := []interface{}{utils.ResourceTypeToItemInt(resourceInfo.Type), user.Id.OpaqueId, spaceID, resourceInfo.Id.OpaqueId} 109 stmt, err := m.db.Prepare(query) 110 if err != nil { 111 return err 112 } 113 114 if _, err = stmt.Exec(vals...); err != nil { 115 return err 116 } 117 return nil 118 } 119 120 func (m *mgr) UnsetFavorite(ctx context.Context, userID *user.UserId, resourceInfo *provider.ResourceInfo) error { 121 user := ctxpkg.ContextMustGetUser(ctx) 122 spaceID := resourceInfo.Id.SpaceId 123 124 stmt, err := m.db.Prepare(`DELETE FROM cbox_metadata WHERE uid=? AND fileid_prefix=? AND fileid=? AND tag_key="fav"`) 125 if err != nil { 126 return err 127 } 128 129 res, err := stmt.Exec(user.Id.OpaqueId, spaceID, resourceInfo.Id.OpaqueId) 130 if err != nil { 131 return err 132 } 133 134 _, err = res.RowsAffected() 135 if err != nil { 136 return err 137 } 138 return nil 139 }