Skip to content

Commit f67e767

Browse files
committed
feat(collection): new api DeleteSubjectCollection
1 parent d085c24 commit f67e767

File tree

8 files changed

+234
-0
lines changed

8 files changed

+234
-0
lines changed

internal/collections/domain.go

+4
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,10 @@ type Repo interface {
6464
update func(ctx context.Context, s *collection.Subject) (*collection.Subject, error),
6565
) error
6666

67+
DeleteSubjectCollection(
68+
ctx context.Context, userID model.UserID, subjectID model.SubjectID,
69+
) error
70+
6771
UpdateEpisodeCollection(
6872
ctx context.Context,
6973
userID model.UserID, subjectID model.SubjectID,

internal/collections/infra/mysql_repo.go

+11
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,17 @@ func (r mysqlRepo) UpdateOrCreateSubjectCollection(
117117
return r.updateOrCreateSubjectCollection(ctx, userID, subject, at, ip, update, s)
118118
}
119119

120+
func (r mysqlRepo) DeleteSubjectCollection(
121+
ctx context.Context,
122+
userID model.UserID,
123+
subjectID model.SubjectID,
124+
) error {
125+
_, err := r.q.SubjectCollection.WithContext(ctx).
126+
Where(r.q.SubjectCollection.UserID.Eq(userID), r.q.SubjectCollection.SubjectID.Eq(subjectID)).
127+
Delete()
128+
return err
129+
}
130+
120131
func (r mysqlRepo) updateOrCreateSubjectCollection(
121132
ctx context.Context,
122133
userID model.UserID,

internal/collections/infra/mysql_repo_test.go

+33
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323
"github.com/trim21/go-phpserialize"
2424
"go.uber.org/zap"
2525
"gorm.io/gen/field"
26+
"gorm.io/gorm"
2627

2728
"github.com/bangumi/server/dal/dao"
2829
"github.com/bangumi/server/dal/query"
@@ -415,6 +416,38 @@ func TestMysqlRepo_UpdateSubjectCollectionType(t *testing.T) {
415416
require.Zero(t, r.DoneTime)
416417
require.Zero(t, r.OnHoldTime)
417418
}
419+
420+
func TestMysqlRepo_DeleteSubjectCollection(t *testing.T) {
421+
t.Parallel()
422+
test.RequireEnv(t, test.EnvMysql)
423+
424+
const id model.UserID = 30000
425+
const subjectID model.SubjectID = 10000
426+
427+
repo, q := getRepo(t)
428+
429+
test.RunAndCleanup(t, func() {
430+
_, err := q.WithContext(context.Background()).SubjectCollection.
431+
Where(q.SubjectCollection.SubjectID.Eq(subjectID), q.SubjectCollection.UserID.Eq(id)).Delete()
432+
require.NoError(t, err)
433+
})
434+
435+
err := q.WithContext(context.Background()).SubjectCollection.Create(&dao.SubjectCollection{
436+
UserID: id,
437+
SubjectID: subjectID,
438+
Rate: 2,
439+
})
440+
require.NoError(t, err)
441+
442+
err = repo.DeleteSubjectCollection(context.Background(), id, subjectID)
443+
require.NoError(t, err)
444+
445+
r, err := q.WithContext(context.Background()).SubjectCollection.
446+
Where(q.SubjectCollection.SubjectID.Eq(subjectID), q.SubjectCollection.UserID.Eq(id)).Take()
447+
require.ErrorIs(t, err, gorm.ErrRecordNotFound)
448+
require.Nil(t, r)
449+
}
450+
418451
func TestMysqlRepo_UpdateEpisodeCollection(t *testing.T) {
419452
test.RequireEnv(t, test.EnvMysql)
420453
t.Parallel()

internal/mocks/CollectionRepo.go

+48
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

openapi/v0.yaml

+34
Original file line numberDiff line numberDiff line change
@@ -957,6 +957,40 @@ paths:
957957
"$ref": "#/components/schemas/ErrorDetail"
958958
security:
959959
- OptionalHTTPBearer: []
960+
delete:
961+
tags:
962+
- 收藏
963+
summary: 删除用户单个收藏
964+
description: |
965+
删除条目收藏状态
966+
967+
会删除当前填写的评分、tags 和吐槽,不会影响章节进度
968+
operationId: deleteUserCollection
969+
parameters:
970+
- $ref: "#/components/parameters/path_subject_id"
971+
responses:
972+
"204":
973+
description: Successful Response
974+
"400":
975+
description: Validation Error
976+
content:
977+
application/json:
978+
schema:
979+
"$ref": "#/components/schemas/ErrorDetail"
980+
"401":
981+
description: Unauthorized
982+
content:
983+
application/json:
984+
schema:
985+
"$ref": "#/components/schemas/ErrorDetail"
986+
"404":
987+
description: 用户不存在或者条目未收藏
988+
content:
989+
application/json:
990+
schema:
991+
"$ref": "#/components/schemas/ErrorDetail"
992+
security:
993+
- OptionalHTTPBearer: []
960994

961995
"/v0/users/-/collections/{subject_id}/episodes":
962996
get:
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
// SPDX-License-Identifier: AGPL-3.0-only
2+
//
3+
// This program is free software: you can redistribute it and/or modify
4+
// it under the terms of the GNU Affero General Public License as published
5+
// by the Free Software Foundation, version 3.
6+
//
7+
// This program is distributed in the hope that it will be useful,
8+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
9+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
10+
// See the GNU Affero General Public License for more details.
11+
//
12+
// You should have received a copy of the GNU Affero General Public License
13+
// along with this program. If not, see <https://www.gnu.org/licenses/>
14+
15+
package user
16+
17+
import (
18+
"errors"
19+
"net/http"
20+
21+
"github.com/labstack/echo/v4"
22+
23+
"github.com/bangumi/server/domain/gerr"
24+
"github.com/bangumi/server/internal/model"
25+
"github.com/bangumi/server/web/accessor"
26+
"github.com/bangumi/server/web/req"
27+
"github.com/bangumi/server/web/res"
28+
)
29+
30+
func (h User) DeleteSubjectCollection(c echo.Context) error {
31+
subjectID, err := req.ParseID(c.Param("subject_id"))
32+
if err != nil {
33+
return err
34+
}
35+
36+
return h.deleteSubjectCollection(c, subjectID)
37+
}
38+
39+
func (h User) deleteSubjectCollection(c echo.Context, subjectID model.SubjectID) error {
40+
u := accessor.GetFromCtx(c)
41+
42+
err := h.collect.DeleteSubjectCollection(c.Request().Context(), u.ID, subjectID)
43+
if err != nil {
44+
switch {
45+
case errors.Is(err, gerr.ErrSubjectNotCollected):
46+
return res.JSONError(c, err)
47+
default:
48+
return err
49+
}
50+
}
51+
52+
return c.NoContent(http.StatusNoContent)
53+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
// SPDX-License-Identifier: AGPL-3.0-only
2+
//
3+
// This program is free software: you can redistribute it and/or modify
4+
// it under the terms of the GNU Affero General Public License as published
5+
// by the Free Software Foundation, version 3.
6+
//
7+
// This program is distributed in the hope that it will be useful,
8+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
9+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
10+
// See the GNU Affero General Public License for more details.
11+
//
12+
// You should have received a copy of the GNU Affero General Public License
13+
// along with this program. If not, see <https://www.gnu.org/licenses/>
14+
15+
package user_test
16+
17+
import (
18+
"fmt"
19+
"net/http"
20+
"testing"
21+
22+
"github.com/labstack/echo/v4"
23+
"github.com/stretchr/testify/mock"
24+
"github.com/trim21/htest"
25+
26+
"github.com/bangumi/server/internal/auth"
27+
"github.com/bangumi/server/internal/mocks"
28+
"github.com/bangumi/server/internal/model"
29+
"github.com/bangumi/server/internal/pkg/test"
30+
)
31+
32+
func TestUser_DeleteSubjectCollection(t *testing.T) {
33+
t.Parallel()
34+
const uid model.UserID = 1
35+
const sid model.SubjectID = 8
36+
37+
a := mocks.NewAuthService(t)
38+
a.EXPECT().GetByToken(mock.Anything, mock.Anything).Return(auth.Auth{ID: uid}, nil)
39+
40+
c := mocks.NewCollectionRepo(t)
41+
c.EXPECT().DeleteSubjectCollection(mock.Anything, uid, sid).
42+
Return(nil)
43+
44+
app := test.GetWebApp(t, test.Mock{CollectionRepo: c, AuthService: a})
45+
46+
htest.New(t, app).
47+
Header(echo.HeaderAuthorization, "Bearer t").
48+
Delete(fmt.Sprintf("/v0/users/-/collections/%d", sid)).
49+
ExpectCode(http.StatusNoContent)
50+
}

web/routes.go

+1
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ func AddRouters(
8383
v0.GET("/users/-/collections/:subject_id/episodes", userHandler.GetSubjectEpisodeCollection, mw.NeedLogin)
8484
v0.PATCH("/users/-/collections/:subject_id", userHandler.PatchSubjectCollection, req.JSON, mw.NeedLogin)
8585
v0.POST("/users/-/collections/:subject_id", userHandler.PostSubjectCollection, req.JSON, mw.NeedLogin)
86+
v0.DELETE("/users/-/collections/:subject_id", userHandler.DeleteSubjectCollection, mw.NeedLogin)
8687
v0.PATCH("/users/-/collections/:subject_id/episodes",
8788
userHandler.PatchEpisodeCollectionBatch, req.JSON, mw.NeedLogin)
8889

0 commit comments

Comments
 (0)