Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(collection): new api DeleteSubjectCollection #556

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion dal/query/export_db.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,6 @@ import (
"gorm.io/gorm"
)

func (q *Query) DB() *gorm.DB {
func (q *Query) RawDB() *gorm.DB {
return q.db
}
2 changes: 1 addition & 1 deletion internal/auth/mysql_repository_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ import (
func getRepo(t *testing.T) (auth.Repo, *query.Query) {
t.Helper()
q := query.Use(test.GetGorm(t))
repo := auth.NewMysqlRepo(q, zap.NewNop(), sqlx.NewDb(lo.Must(q.DB().DB()), "mysql"))
repo := auth.NewMysqlRepo(q, zap.NewNop(), sqlx.NewDb(lo.Must(q.RawDB().DB()), "mysql"))

return repo, q
}
Expand Down
4 changes: 4 additions & 0 deletions internal/collections/domain.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,10 @@ type Repo interface { //nolint:interfacebloat
update func(ctx context.Context, s *collection.Subject) (*collection.Subject, error),
) error

DeleteSubjectCollection(
ctx context.Context, userID model.UserID, subjectID model.SubjectID,
) error

UpdateEpisodeCollection(
ctx context.Context,
userID model.UserID, subjectID model.SubjectID,
Expand Down
30 changes: 27 additions & 3 deletions internal/collections/infra/mysql_repo.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,30 @@ func (r mysqlRepo) UpdateOrCreateSubjectCollection(
return r.updateOrCreateSubjectCollection(ctx, userID, subject, at, ip, update, s)
}

func (r mysqlRepo) DeleteSubjectCollection(
ctx context.Context,
userID model.UserID,
subjectID model.SubjectID,
) error {
err := r.q.RawDB().Exec(`
UPDATE chii_subject_interests set interest_type = 0,
interest_rate = 0,
interest_comment = 0,
interest_has_comment = 0,
interest_tag = '',
interest_ep_status = 0,
interest_vol_status = 0,
interest_wish_dateline = 0,
interest_doing_dateline = 0,
interest_collect_dateline = 0,
interest_on_hold_dateline = 0,
interest_dropped_dateline = 0
where interest_uid = ? and interest_subject_id = ?
`, userID, subjectID).Error

return err
}

//nolint:funlen
func (r mysqlRepo) updateOrCreateSubjectCollection(
ctx context.Context,
Expand Down Expand Up @@ -308,7 +332,7 @@ func (r mysqlRepo) reCountSubjectTags(ctx context.Context, tx *query.Query,
return true
})

db := tx.DB().WithContext(ctx)
db := tx.RawDB().WithContext(ctx)

err = db.Exec(`
update chii_tag_neue_index as ti
Expand Down Expand Up @@ -554,7 +578,7 @@ func (r mysqlRepo) reCountSubjectCollection(ctx context.Context, subjectID model
}

return r.q.Transaction(func(tx *query.Query) error {
err := tx.DB().WithContext(ctx).Raw(`
err := tx.RawDB().WithContext(ctx).Raw(`
select interest_type as type, count(interest_type) as total from chii_subject_interests
where interest_subject_id = ?
group by interest_type
Expand Down Expand Up @@ -603,7 +627,7 @@ func (r mysqlRepo) reCountSubjectRate(ctx context.Context, subjectID model.Subje
for _, rate := range []uint8{before, after} {
var count uint32
if rate != 0 {
err := tx.DB().WithContext(ctx).Raw(`
err := tx.RawDB().WithContext(ctx).Raw(`
select count(*) from chii_subject_interests
where interest_subject_id = ? and interest_private = 0 and interest_rate = ?
`, subjectID, rate).Scan(&count).Error
Expand Down
35 changes: 33 additions & 2 deletions internal/collections/infra/mysql_repo_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,7 @@ func TestMysqlRepo_UpdateOrCreateSubjectCollection(t *testing.T) {

now := time.Now()

// DB 里没有数据
// RawDB 里没有数据
_, err = table.WithContext(context.TODO()).Where(table.SubjectID.Eq(sid), table.UserID.Eq(uid)).Take()
require.Error(t, err)

Expand All @@ -253,7 +253,7 @@ func TestMysqlRepo_UpdateOrCreateSubjectCollection(t *testing.T) {
})
require.NoError(t, err)

// DB 里有数据
// RawDB 里有数据
_, err = table.WithContext(context.TODO()).Where(table.SubjectID.Eq(sid), table.UserID.Eq(uid)).Take()
require.NoError(t, err)

Expand Down Expand Up @@ -442,6 +442,37 @@ func TestMysqlRepo_UpdateSubjectCollectionType(t *testing.T) {
require.Zero(t, r.OnHoldTime)
}

func TestMysqlRepo_DeleteSubjectCollection(t *testing.T) {
t.Parallel()
test.RequireEnv(t, test.EnvMysql)

const id model.UserID = 30000
const subjectID model.SubjectID = 10000

repo, q := getRepo(t)

test.RunAndCleanup(t, func() {
_, err := q.WithContext(context.Background()).SubjectCollection.
Where(q.SubjectCollection.SubjectID.Eq(subjectID), q.SubjectCollection.UserID.Eq(id)).Delete()
require.NoError(t, err)
})

err := q.WithContext(context.Background()).SubjectCollection.Create(&dao.SubjectCollection{
UserID: id,
SubjectID: subjectID,
Rate: 2,
})
require.NoError(t, err)

err = repo.DeleteSubjectCollection(context.Background(), id, subjectID)
require.NoError(t, err)

r, err := q.WithContext(context.Background()).SubjectCollection.
Where(q.SubjectCollection.SubjectID.Eq(subjectID), q.SubjectCollection.UserID.Eq(id)).Take()
require.ErrorIs(t, err, gorm.ErrRecordNotFound)
require.Nil(t, r)
}

func TestMysqlRepo_UpdateEpisodeCollection(t *testing.T) {
test.RequireEnv(t, test.EnvMysql)
t.Parallel()
Expand Down
48 changes: 48 additions & 0 deletions internal/mocks/CollectionRepo.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion internal/tag/mysql_repo_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ import (
func getRepo(t *testing.T) tag.Repo {
t.Helper()
q := query.Use(test.GetGorm(t))
repo, err := tag.NewMysqlRepo(q, zap.NewNop(), sqlx.NewDb(lo.Must(q.DB().DB()), "mysql"))
repo, err := tag.NewMysqlRepo(q, zap.NewNop(), sqlx.NewDb(lo.Must(q.RawDB().DB()), "mysql"))
require.NoError(t, err)

return repo
Expand Down
34 changes: 34 additions & 0 deletions openapi/v0.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1233,6 +1233,40 @@ paths:
"$ref": "#/components/schemas/ErrorDetail"
security:
- OptionalHTTPBearer: []
delete:
tags:
- 收藏
summary: 删除用户单个收藏
description: |
删除条目收藏状态

会删除当前填写的评分、tags 和吐槽,不会影响章节进度
operationId: deleteUserCollection
parameters:
- $ref: "#/components/parameters/path_subject_id"
responses:
"204":
description: Successful Response
"400":
description: Validation Error
content:
application/json:
schema:
"$ref": "#/components/schemas/ErrorDetail"
"401":
description: Unauthorized
content:
application/json:
schema:
"$ref": "#/components/schemas/ErrorDetail"
"404":
description: 用户不存在或者条目未收藏
content:
application/json:
schema:
"$ref": "#/components/schemas/ErrorDetail"
security:
- OptionalHTTPBearer: []

"/v0/users/-/collections/{subject_id}/episodes":
get:
Expand Down
53 changes: 53 additions & 0 deletions web/handler/user/delete_subject_collection.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// SPDX-License-Identifier: AGPL-3.0-only
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
// by the Free Software Foundation, version 3.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>

package user

import (
"errors"
"net/http"

"github.com/labstack/echo/v4"

"github.com/bangumi/server/domain/gerr"
"github.com/bangumi/server/internal/model"
"github.com/bangumi/server/web/accessor"
"github.com/bangumi/server/web/req"
"github.com/bangumi/server/web/res"
)

func (h User) DeleteSubjectCollection(c echo.Context) error {
subjectID, err := req.ParseID(c.Param("subject_id"))
if err != nil {
return err
}

return h.deleteSubjectCollection(c, subjectID)
}

func (h User) deleteSubjectCollection(c echo.Context, subjectID model.SubjectID) error {
u := accessor.GetFromCtx(c)

err := h.collect.DeleteSubjectCollection(c.Request().Context(), u.ID, subjectID)
if err != nil {
switch {
case errors.Is(err, gerr.ErrSubjectNotCollected):
return res.JSONError(c, err)
default:
return err
}
}

return c.NoContent(http.StatusNoContent)
}
50 changes: 50 additions & 0 deletions web/handler/user/delete_subject_collection_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// SPDX-License-Identifier: AGPL-3.0-only
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
// by the Free Software Foundation, version 3.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>

package user_test

import (
"fmt"
"net/http"
"testing"

"github.com/labstack/echo/v4"
"github.com/stretchr/testify/mock"
"github.com/trim21/htest"

"github.com/bangumi/server/internal/auth"
"github.com/bangumi/server/internal/mocks"
"github.com/bangumi/server/internal/model"
"github.com/bangumi/server/internal/pkg/test"
)

func TestUser_DeleteSubjectCollection(t *testing.T) {
t.Parallel()
const uid model.UserID = 1
const sid model.SubjectID = 8

a := mocks.NewAuthService(t)
a.EXPECT().GetByToken(mock.Anything, mock.Anything).Return(auth.Auth{ID: uid}, nil)

c := mocks.NewCollectionRepo(t)
c.EXPECT().DeleteSubjectCollection(mock.Anything, uid, sid).
Return(nil)

app := test.GetWebApp(t, test.Mock{CollectionRepo: c, AuthService: a})

htest.New(t, app).
Header(echo.HeaderAuthorization, "Bearer t").
Delete(fmt.Sprintf("/v0/users/-/collections/%d", sid)).
ExpectCode(http.StatusNoContent)
}
1 change: 1 addition & 0 deletions web/routes.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ func AddRouters(
v0.GET("/users/-/collections/:subject_id/episodes", userHandler.GetSubjectEpisodeCollection, mw.NeedLogin)
v0.PATCH("/users/-/collections/:subject_id", userHandler.PatchSubjectCollection, req.JSON, mw.NeedLogin)
v0.POST("/users/-/collections/:subject_id", userHandler.PostSubjectCollection, req.JSON, mw.NeedLogin)
v0.DELETE("/users/-/collections/:subject_id", userHandler.DeleteSubjectCollection, mw.NeedLogin)
v0.PATCH("/users/-/collections/:subject_id/episodes",
userHandler.PatchEpisodeCollectionBatch, req.JSON, mw.NeedLogin)

Expand Down
Loading