Skip to content

Commit e6a9c8f

Browse files
committed
(backend) convert db errors to service errors
1 parent a03a433 commit e6a9c8f

File tree

5 files changed

+63
-53
lines changed

5 files changed

+63
-53
lines changed

backend/services/assets.go

+6-6
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ func (s AssetsService) CreateNoteAsset(
3030
Where("owner_id = ? AND notes.id = ?", userID, noteID).
3131
Limit(1).
3232
Count(&count).Error; err != nil {
33-
return StoredAsset{}, err
33+
return StoredAsset{}, dbErrorToServiceError(err)
3434
}
3535
if count == 0 {
3636
return StoredAsset{}, NotFoundError
@@ -43,7 +43,7 @@ func (s AssetsService) CreateNoteAsset(
4343

4444
if err := db.DB.Transaction(func(tx *gorm.DB) error {
4545
if err := tx.Create(&noteAsset).Error; err != nil {
46-
return err
46+
return dbErrorToServiceError(err)
4747
}
4848
return storage.WriteNoteAsset(noteID, noteAsset.ID, content)
4949
}); err != nil {
@@ -77,7 +77,7 @@ func (s AssetsService) GetNoteAssets(
7777
).
7878
Find(&noteAssets).
7979
Error; err != nil {
80-
return storedAssets, err
80+
return storedAssets, dbErrorToServiceError(err)
8181
}
8282

8383
for _, noteAsset := range noteAssets {
@@ -102,7 +102,7 @@ func (s AssetsService) GetNoteAssetContentByID(
102102
if err := db.DB.
103103
First(&noteAsset, "id = ? AND note_id = ?", assetID, noteID).
104104
Error; err != nil {
105-
return noteAsset, storage.AssetFileInfo{}, nil, err
105+
return noteAsset, storage.AssetFileInfo{}, nil, dbErrorToServiceError(err)
106106
}
107107

108108
assetInfo, err := storage_backend.GetNoteAssetInfo(noteID, assetID)
@@ -130,7 +130,7 @@ func (s AssetsService) DeleteNoteAssetByID(
130130
Where("owner_id = ? AND notes.id = ?", userID, noteID).
131131
Limit(1).
132132
Count(&count).Error; err != nil {
133-
return err
133+
return dbErrorToServiceError(err)
134134
}
135135
if count == 0 {
136136
return NotFoundError
@@ -141,7 +141,7 @@ func (s AssetsService) DeleteNoteAssetByID(
141141
Unscoped().
142142
Delete(&db.NoteAsset{}, "id = ? AND note_id = ?", assetID, noteID).
143143
Error; err != nil {
144-
return err
144+
return dbErrorToServiceError(err)
145145
}
146146
return storage_backend.DeleteNoteAsset(noteID, assetID)
147147
})

backend/services/books.go

+8-8
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,15 @@ type BooksService struct{}
99

1010
func (s BooksService) CreateBook(userID uuid.UUID, toCreate db.CreateBook) (db.Book, error) {
1111
book := toCreate.IntoBook(userID)
12-
return book, db.DB.Create(&book).Error
12+
return book, dbErrorToServiceError(db.DB.Create(&book).Error)
1313
}
1414

1515
func (s BooksService) GetBookByID(currentUserID *uuid.UUID, bookID uuid.UUID) (db.Book, error) {
1616
var book db.Book
17-
return book, db.DB.
17+
return book, dbErrorToServiceError(db.DB.
1818
Where("owner_id = ? OR is_public = ?", currentUserID, true).
1919
First(&book, "id = ?", bookID).
20-
Error
20+
Error)
2121
}
2222

2323
func (s BooksService) GetBookBySlug(
@@ -30,18 +30,18 @@ func (s BooksService) GetBookBySlug(
3030
Select("id").
3131
First(&bookOwner, "username = ?", username).
3232
Error; err != nil {
33-
return db.Book{}, err
33+
return db.Book{}, dbErrorToServiceError(err)
3434
}
3535

3636
query := db.DB
3737
if includeNotes {
3838
query = query.Preload("Notes")
3939
}
4040
var book db.Book
41-
return book, query.
41+
return book, dbErrorToServiceError(query.
4242
Where("owner_id = ? OR is_public = ?", currentUserID, true).
4343
First(&book, "slug = ? AND owner_id = ?", bookSlug, bookOwner.ID).
44-
Error
44+
Error)
4545
}
4646

4747
func (s BooksService) UpdateBookByID(
@@ -53,7 +53,7 @@ func (s BooksService) UpdateBookByID(
5353
Where("id = ? AND owner_id = ?", bookID, currentUserID).
5454
Updates(input)
5555
if err := result.Error; err != nil {
56-
return err
56+
return dbErrorToServiceError(err)
5757
}
5858
if result.RowsAffected == 0 {
5959
return NotFoundError
@@ -66,7 +66,7 @@ func (s BooksService) DeleteBookByID(currentUserID uuid.UUID, bookID uuid.UUID)
6666
Where("id = ? AND owner_id = ?", bookID, currentUserID).
6767
Delete(&db.Book{})
6868
if err := result.Error; err != nil {
69-
return err
69+
return dbErrorToServiceError(err)
7070
}
7171
if result.RowsAffected == 0 {
7272
return NotFoundError

backend/services/notes.go

+22-22
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,13 @@ func (s NotesService) CreateNote(
2424
Where("id = ? AND owner_id = ?", bookID, userID).
2525
Limit(1).
2626
Count(&count).Error; err != nil {
27-
return db.Note{}, err
27+
return db.Note{}, dbErrorToServiceError(err)
2828
}
2929
if count == 0 {
3030
return db.Note{}, NotFoundError
3131
}
3232
note := toCreate.IntoNote(bookID)
33-
return note, db.DB.Create(&note).Error
33+
return note, dbErrorToServiceError(db.DB.Create(&note).Error)
3434
}
3535

3636
func (s NotesService) GetRecentNotes(currentUserID *uuid.UUID) ([]db.ValueWithSlug, error) {
@@ -51,13 +51,13 @@ func (s NotesService) GetRecentNotes(currentUserID *uuid.UUID) ([]db.ValueWithSl
5151
recentNotes := make([]db.ValueWithSlug, 0)
5252

5353
if rows, err := tx.Rows(); err != nil {
54-
return nil, err
54+
return nil, dbErrorToServiceError(err)
5555
} else {
5656
defer rows.Close()
5757
for rows.Next() {
5858
var row db.Note
5959
if err := db.DB.ScanRows(rows, &row); err != nil {
60-
return nil, err
60+
return nil, dbErrorToServiceError(err)
6161
}
6262
recentNotes = append(recentNotes, db.ValueWithSlug{
6363
Value: row,
@@ -84,16 +84,16 @@ func (s NotesService) GetNotesByBookID(currentUserID *uuid.UUID, bookID uuid.UUI
8484
tx = tx.Where("notes.deleted_at IS NOT NULL")
8585
}
8686
var notes []db.Note
87-
return notes, tx.Find(&notes).Error
87+
return notes, dbErrorToServiceError(tx.Find(&notes).Error)
8888
}
8989

9090
func (s NotesService) GetNoteByID(currentUserID *uuid.UUID, noteID uuid.UUID) (db.Note, error) {
9191
var note db.Note
92-
return note, db.DB.
92+
return note, dbErrorToServiceError(db.DB.
9393
Preload("Book").
9494
Joins("JOIN books ON books.id = notes.book_id").
9595
Where("owner_id = ? OR is_public = ?", currentUserID, true).
96-
First(&note, "notes.id = ?", noteID).Error
96+
First(&note, "notes.id = ?", noteID).Error)
9797
}
9898

9999
func (s NotesService) GetNoteBySlug(
@@ -105,15 +105,15 @@ func (s NotesService) GetNoteBySlug(
105105
if err := db.DB.
106106
Select("id").
107107
First(&bookOwner, "username = ?", username).Error; err != nil {
108-
return db.Note{}, err
108+
return db.Note{}, dbErrorToServiceError(err)
109109
}
110110
var note db.Note
111-
return note, db.DB.
111+
return note, dbErrorToServiceError(db.DB.
112112
Preload("Book").
113113
Joins("JOIN books ON books.id = notes.book_id").
114114
Where("books.slug = ? AND books.owner_id = ?", bookSlug, bookOwner.ID).
115115
Where("owner_id = ? OR is_public = ?", currentUserID, true).
116-
First(&note, "notes.slug = ?", noteSlug).Error
116+
First(&note, "notes.slug = ?", noteSlug).Error)
117117
}
118118

119119
func (s NotesService) GetNoteContent(
@@ -129,7 +129,7 @@ func (s NotesService) GetNoteContent(
129129
Where("notes.id = ?", noteID).
130130
Limit(1).
131131
Count(&count).Error; err != nil {
132-
return "", nil, err
132+
return "", nil, dbErrorToServiceError(err)
133133
}
134134
if count == 0 {
135135
return "", nil, NotFoundError
@@ -159,7 +159,7 @@ func (s NotesService) UpdateNoteByID(
159159
Where("owner_id = ? AND notes.id = ?", currentUserID, noteID).
160160
Limit(1).
161161
Count(&count).Error; err != nil {
162-
return err
162+
return dbErrorToServiceError(err)
163163
}
164164
if count == 0 {
165165
return NotFoundError
@@ -170,7 +170,7 @@ func (s NotesService) UpdateNoteByID(
170170
Where("notes.id = ?", noteID).
171171
Updates(input)
172172
if err := result.Error; err != nil {
173-
return err
173+
return dbErrorToServiceError(err)
174174
}
175175
if result.RowsAffected == 0 {
176176
return NotFoundError
@@ -191,7 +191,7 @@ func (s NotesService) UpdateNoteContentByID(
191191
Where("owner_id = ? AND notes.id = ?", currentUserID, noteID).
192192
Limit(1).
193193
Count(&count).Error; err != nil {
194-
return err
194+
return dbErrorToServiceError(err)
195195
}
196196
if count == 0 {
197197
return NotFoundError
@@ -204,7 +204,7 @@ func (s NotesService) UpdateNoteContentByID(
204204
Where("id = ?", noteID).
205205
Update("UpdatedAt", db.DB.NowFunc()).
206206
Error; err != nil {
207-
return err
207+
return dbErrorToServiceError(err)
208208
}
209209
if err := storage_backend.WriteNote(noteID, content); err != nil {
210210
return err
@@ -222,7 +222,7 @@ func (s NotesService) RestoreNoteByID(currentUserID uuid.UUID, noteID uuid.UUID)
222222
Where("owner_id = ?", currentUserID).
223223
Select("notes.id", "book_id").
224224
First(&note, "notes.id = ?", noteID).Error; err != nil {
225-
return err
225+
return dbErrorToServiceError(err)
226226
}
227227

228228
return db.DB.Transaction(func(tx *gorm.DB) error {
@@ -232,15 +232,15 @@ func (s NotesService) RestoreNoteByID(currentUserID uuid.UUID, noteID uuid.UUID)
232232
Where("id = ?", note.ID).
233233
Update("deleted_at", nil).
234234
Error; err != nil {
235-
return err
235+
return dbErrorToServiceError(err)
236236
}
237237
// restore book (ensuring user can visit restored note)
238238
if err := tx.Unscoped().
239239
Model(&db.Book{}).
240240
Where("id = ?", note.BookID).
241241
Update("deleted_at", nil).
242242
Error; err != nil {
243-
return err
243+
return dbErrorToServiceError(err)
244244
}
245245
return nil
246246
})
@@ -261,7 +261,7 @@ func (s NotesService) DeleteNoteByID(
261261
Where("owner_id = ? AND notes.id = ?", currentUserID, noteID).
262262
Limit(1).
263263
Count(&count).Error; err != nil {
264-
return err
264+
return dbErrorToServiceError(err)
265265
}
266266
if count == 0 {
267267
return NotFoundError
@@ -271,10 +271,10 @@ func (s NotesService) DeleteNoteByID(
271271
// performs hard deletion
272272
return db.DB.Transaction(func(tx *gorm.DB) error {
273273
if err := tx.Unscoped().Delete(&db.NoteAsset{}, "note_id = ?", noteID).Error; err != nil {
274-
return err
274+
return dbErrorToServiceError(err)
275275
}
276276
if err := tx.Unscoped().Delete(&db.Note{}, "id = ?", noteID).Error; err != nil {
277-
return err
277+
return dbErrorToServiceError(err)
278278
}
279279
if err := storage_backend.DeleteNote(noteID); err != nil {
280280
return err
@@ -283,6 +283,6 @@ func (s NotesService) DeleteNoteByID(
283283
})
284284
} else {
285285
// performs soft deletion
286-
return db.DB.Delete(&db.Note{}, "id = ?", noteID).Error
286+
return dbErrorToServiceError(db.DB.Delete(&db.Note{}, "id = ?", noteID).Error)
287287
}
288288
}

backend/services/users.go

+9-16
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,12 @@ func (s UsersService) CreateUser(appConfig config.AppConfig, toCreate db.CreateU
1818
return db.User{}, UserSignupDisabledError
1919
}
2020
user := toCreate.IntoUser()
21-
return user, db.DB.Create(&user).Error
21+
return user, dbErrorToServiceError(db.DB.Create(&user).Error)
2222
}
2323

2424
func (s UsersService) GetUserProfileByID(userID uuid.UUID) (db.User, error) {
2525
var user db.User
26-
return user, db.DB.First(&user, "id = ?", userID).Error
26+
return user, dbErrorToServiceError(db.DB.First(&user, "id = ?", userID).Error)
2727
}
2828

2929
func (s UsersService) GetUserByUsername(
@@ -32,25 +32,22 @@ func (s UsersService) GetUserByUsername(
3232
getBooks bool,
3333
getNotes bool) (db.User, error) {
3434
query := db.DB
35-
3635
if getBooks || getNotes {
3736
query = query.Preload("Books", "owner_id = ? OR is_public = ?", currentUserID, true)
3837
}
39-
4038
if getNotes {
4139
query = query.Preload("Books.Notes")
4240
}
43-
4441
var user db.User
45-
return user, query.First(&user, "username = ?", username).Error
42+
return user, dbErrorToServiceError(query.First(&user, "username = ?", username).Error)
4643
}
4744

4845
func (s UsersService) UpdateUserProfile(userID uuid.UUID, input db.UpdateUser) error {
49-
return db.DB.
46+
return dbErrorToServiceError(db.DB.
5047
Model(&db.User{}).
5148
Where("id = ?", userID).
5249
Updates(input).
53-
Error
50+
Error)
5451
}
5552

5653
func (s UsersService) UpdateUserPassword(userID uuid.UUID, input db.UpdateUserPassword) error {
@@ -59,25 +56,21 @@ func (s UsersService) UpdateUserPassword(userID uuid.UUID, input db.UpdateUserPa
5956
First(&user, "id = ?", userID).
6057
Select("password").
6158
Error; err != nil {
62-
return err
59+
return dbErrorToServiceError(err)
6360
}
64-
6561
if !user.IsPasswordMatch(input.ExistingPassword) {
6662
return UserPasswordInvalid
6763
}
68-
6964
user.SetPassword(input.NewPassword)
70-
71-
return db.DB.Save(&user).Error
65+
return dbErrorToServiceError(db.DB.Save(&user).Error)
7266
}
7367

7468
func (s UsersService) GetSearchForUser(username string) ([]string, error) {
75-
7669
var users []string
77-
return users, db.DB.
70+
return users, dbErrorToServiceError(db.DB.
7871
Model(&db.User{}).
7972
Limit(6).
8073
Where("username LIKE ?", username+"%").
8174
Pluck("username", &users).
82-
Error
75+
Error)
8376
}

backend/services/utils.go

+18-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,24 @@
11
package services
22

3-
import "errors"
3+
import (
4+
"errors"
5+
6+
"gorm.io/gorm"
7+
)
48

59
var (
610
NotFoundError = errors.New("not found")
11+
ConflictError = errors.New("conflict, already exists")
712
)
13+
14+
func dbErrorToServiceError(err error) error {
15+
if err == nil {
16+
return nil
17+
} else if errors.Is(err, gorm.ErrRecordNotFound) {
18+
return errors.Join(err, NotFoundError)
19+
} else if errors.Is(err, gorm.ErrDuplicatedKey) {
20+
return errors.Join(err, ConflictError)
21+
} else {
22+
return err
23+
}
24+
}

0 commit comments

Comments
 (0)