bolt.go 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  1. package kvdb
  2. import (
  3. "encoding/json"
  4. "errors"
  5. "fmt"
  6. "time"
  7. "go.etcd.io/bbolt"
  8. )
  9. var (
  10. usersBucket = []byte("users")
  11. bucketsBucket = []byte("buckets")
  12. )
  13. // Ensure BoltKVDB implements KVDB interface
  14. var _ KVDB = (*BoltKVDB)(nil)
  15. // BucketConfig stores bucket-level configuration
  16. type BucketConfig struct {
  17. BucketID string `json:"bucket_id"`
  18. AccountID string `json:"account_id"`
  19. BucketName string `json:"bucket_name"`
  20. PublicViewing bool `json:"public_viewing"`
  21. CreatedAt string `json:"created_at"`
  22. }
  23. // BoltKVDB is a BoltDB-based key-value database
  24. type BoltKVDB struct {
  25. db *bbolt.DB
  26. }
  27. // NewBoltKVDB creates a new BoltDB-based key-value database
  28. func NewBoltKVDB(path string) (*BoltKVDB, error) {
  29. db, err := bbolt.Open(path, 0600, &bbolt.Options{Timeout: 1 * time.Second})
  30. if err != nil {
  31. return nil, err
  32. }
  33. // Create buckets if they don't exist
  34. err = db.Update(func(tx *bbolt.Tx) error {
  35. _, err := tx.CreateBucketIfNotExists(usersBucket)
  36. if err != nil {
  37. return err
  38. }
  39. _, err = tx.CreateBucketIfNotExists(bucketsBucket)
  40. return err
  41. })
  42. if err != nil {
  43. db.Close()
  44. return nil, err
  45. }
  46. return &BoltKVDB{db: db}, nil
  47. }
  48. // GetUser retrieves a user by access key ID
  49. func (db *BoltKVDB) GetUser(accessKeyID string) (*User, error) {
  50. var user User
  51. err := db.db.View(func(tx *bbolt.Tx) error {
  52. b := tx.Bucket(usersBucket)
  53. data := b.Get([]byte(accessKeyID))
  54. if data == nil {
  55. return ErrUserNotFound
  56. }
  57. return json.Unmarshal(data, &user)
  58. })
  59. if err != nil {
  60. return nil, err
  61. }
  62. return &user, nil
  63. }
  64. // CreateUser creates a new user
  65. func (db *BoltKVDB) CreateUser(user *User) error {
  66. return db.db.Update(func(tx *bbolt.Tx) error {
  67. b := tx.Bucket(usersBucket)
  68. // Check if user already exists
  69. if b.Get([]byte(user.AccessKeyID)) != nil {
  70. return ErrUserAlreadyExists
  71. }
  72. data, err := json.Marshal(user)
  73. if err != nil {
  74. return err
  75. }
  76. return b.Put([]byte(user.AccessKeyID), data)
  77. })
  78. }
  79. // UpdateUser updates an existing user
  80. func (db *BoltKVDB) UpdateUser(user *User) error {
  81. return db.db.Update(func(tx *bbolt.Tx) error {
  82. b := tx.Bucket(usersBucket)
  83. // Check if user exists
  84. if b.Get([]byte(user.AccessKeyID)) == nil {
  85. return ErrUserNotFound
  86. }
  87. data, err := json.Marshal(user)
  88. if err != nil {
  89. return err
  90. }
  91. return b.Put([]byte(user.AccessKeyID), data)
  92. })
  93. }
  94. // DeleteUser deletes a user
  95. func (db *BoltKVDB) DeleteUser(accessKeyID string) error {
  96. return db.db.Update(func(tx *bbolt.Tx) error {
  97. b := tx.Bucket(usersBucket)
  98. // Check if user exists
  99. if b.Get([]byte(accessKeyID)) == nil {
  100. return ErrUserNotFound
  101. }
  102. return b.Delete([]byte(accessKeyID))
  103. })
  104. }
  105. // ListUsers returns all users
  106. func (db *BoltKVDB) ListUsers() ([]*User, error) {
  107. var users []*User
  108. err := db.db.View(func(tx *bbolt.Tx) error {
  109. b := tx.Bucket(usersBucket)
  110. return b.ForEach(func(k, v []byte) error {
  111. var user User
  112. if err := json.Unmarshal(v, &user); err != nil {
  113. return err
  114. }
  115. users = append(users, &user)
  116. return nil
  117. })
  118. })
  119. return users, err
  120. }
  121. // ValidateCredentials validates user credentials
  122. func (db *BoltKVDB) ValidateCredentials(accessKeyID, secretAccessKey string) (*User, error) {
  123. user, err := db.GetUser(accessKeyID)
  124. if err != nil {
  125. return nil, err
  126. }
  127. if user.SecretAccessKey != secretAccessKey {
  128. return nil, errors.New("invalid credentials")
  129. }
  130. return user, nil
  131. }
  132. // Close closes the database
  133. func (db *BoltKVDB) Close() error {
  134. return db.db.Close()
  135. }
  136. // Bucket configuration methods
  137. // SetBucketConfig sets the configuration for a bucket
  138. func (db *BoltKVDB) SetBucketConfig(config *BucketConfig) error {
  139. return db.db.Update(func(tx *bbolt.Tx) error {
  140. b := tx.Bucket(bucketsBucket)
  141. // Key format: accountID:bucketID
  142. key := config.AccountID + ":" + config.BucketID
  143. data, err := json.Marshal(config)
  144. if err != nil {
  145. return err
  146. }
  147. return b.Put([]byte(key), data)
  148. })
  149. }
  150. // GetBucketConfig gets the configuration for a bucket
  151. func (db *BoltKVDB) GetBucketConfig(accountID, bucketID string) (*BucketConfig, error) {
  152. var config BucketConfig
  153. err := db.db.View(func(tx *bbolt.Tx) error {
  154. bucket := tx.Bucket(bucketsBucket)
  155. if bucket == nil {
  156. return fmt.Errorf("buckets bucket not found")
  157. }
  158. key := fmt.Sprintf("%s:%s", accountID, bucketID)
  159. data := bucket.Get([]byte(key))
  160. if data == nil {
  161. return fmt.Errorf("bucket config not found")
  162. }
  163. return json.Unmarshal(data, &config)
  164. })
  165. if err != nil {
  166. return nil, err
  167. }
  168. return &config, nil
  169. }
  170. // DeleteBucketConfig deletes the configuration for a bucket
  171. func (db *BoltKVDB) DeleteBucketConfig(accountID, bucketID string) error {
  172. return db.db.Update(func(tx *bbolt.Tx) error {
  173. b := tx.Bucket(bucketsBucket)
  174. key := accountID + ":" + bucketID
  175. return b.Delete([]byte(key))
  176. })
  177. }
  178. // ListBucketConfigs lists all bucket configurations for an account
  179. func (db *BoltKVDB) ListBucketConfigs(accountID string) ([]*BucketConfig, error) {
  180. var configs []*BucketConfig
  181. prefix := []byte(accountID + ":")
  182. err := db.db.View(func(tx *bbolt.Tx) error {
  183. b := tx.Bucket(bucketsBucket)
  184. c := b.Cursor()
  185. for k, v := c.Seek(prefix); k != nil && len(k) >= len(prefix) && string(k[:len(prefix)]) == string(prefix); k, v = c.Next() {
  186. var config BucketConfig
  187. if err := json.Unmarshal(v, &config); err != nil {
  188. continue
  189. }
  190. configs = append(configs, &config)
  191. }
  192. return nil
  193. })
  194. return configs, err
  195. }
  196. // ResolveBucketName resolves a bucket name to accountID and bucketID
  197. func (db *BoltKVDB) ResolveBucketName(bucketName string) (accountID string, bucketID string, err error) {
  198. err = db.db.View(func(tx *bbolt.Tx) error {
  199. bucket := tx.Bucket(bucketsBucket)
  200. if bucket == nil {
  201. return fmt.Errorf("buckets bucket not found")
  202. }
  203. // Iterate through all bucket configs to find matching bucket name
  204. cursor := bucket.Cursor()
  205. for k, v := cursor.First(); k != nil; k, v = cursor.Next() {
  206. var config BucketConfig
  207. if err := json.Unmarshal(v, &config); err != nil {
  208. continue
  209. }
  210. if config.BucketName == bucketName {
  211. accountID = config.AccountID
  212. bucketID = config.BucketID
  213. return nil
  214. }
  215. }
  216. return fmt.Errorf("bucket not found: %s", bucketName)
  217. })
  218. if err != nil {
  219. return "", "", err
  220. }
  221. return accountID, bucketID, nil
  222. }
  223. // InitializeDefaultUsers initializes hardcoded users
  224. func (db *BoltKVDB) InitializeDefaultUsers() error {
  225. defaultUsers := []*User{
  226. {
  227. AccessKeyID: "AKIAIOSFODNN7EXAMPLE",
  228. SecretAccessKey: "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
  229. AccountID: "123456789012",
  230. Username: "alice",
  231. Email: "[email protected]",
  232. },
  233. {
  234. AccessKeyID: "AKIAJSIE27KKMHXI3BJQ",
  235. SecretAccessKey: "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",
  236. AccountID: "987654321098",
  237. Username: "bob",
  238. Email: "[email protected]",
  239. },
  240. }
  241. for _, user := range defaultUsers {
  242. // Try to create user, ignore if already exists
  243. err := db.CreateUser(user)
  244. if err != nil && err != ErrUserAlreadyExists {
  245. return err
  246. }
  247. }
  248. return nil
  249. }