censor_bear 0.1.14 → 0.1.15
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +19 -1
- data/app/controllers/censor_bear/mod_logs_controller.rb +21 -21
- data/app/models/censor_bear/mod_log.rb +39 -16
- data/app/views/censor_bear/mod_logs/_mod_log.html.haml +42 -37
- data/app/views/censor_bear/mod_logs/index.html.haml +12 -2
- data/config/locales/censor_bear.yml +4 -0
- data/config/routes.rb +4 -3
- data/db/migrate/20211209113710_add_aasm_state_to_censor_bear_mod_logs.rb +5 -0
- data/lib/censor_bear/version.rb +1 -1
- data/lib/censor_bear.rb +1 -0
- metadata +16 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 775cd9c238b951f9b9d5ce8564ae76e3e4b5d38fb3e9b71dc599d6a75bc04f5e
|
4
|
+
data.tar.gz: f8daa1001d2682697143aec92e6098d1e291d3c4d8cb7c9d28f60455fee7e6b4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3bd8ea39fb05994a01083fdaf574501657bf085238a1c9a24b883bddadf374a8a441f910a95594f7a42081d981a2800b9b2b02c9b3cc578e200536faa52ed4b8
|
7
|
+
data.tar.gz: 6ee79015b14bf37b4f070e041c91738d906bb3d1f8c39b215a94ccf6fbe89ccc0816a9d919e1436ee3689b3bb62bd9be2df1a025afbe1090e09ee9bf0be1022d
|
data/README.md
CHANGED
@@ -50,10 +50,12 @@ rails censor_bear:install:migrations
|
|
50
50
|
|
51
51
|
## 🦆 Methods
|
52
52
|
```ruby
|
53
|
-
|
53
|
+
censor_remove # 删除内容
|
54
|
+
censor_cancel # 撤销删除
|
54
55
|
censor_approve # 通过审核
|
55
56
|
censor_show_path # 详情路由
|
56
57
|
censor_ban_user # 封禁用户
|
58
|
+
|
57
59
|
```
|
58
60
|
|
59
61
|
## Exceptions
|
@@ -63,6 +65,22 @@ censor_ban_user # 封禁用户
|
|
63
65
|
class NotPassedException < StandardError; end
|
64
66
|
```
|
65
67
|
|
68
|
+
## 初始化配置
|
69
|
+
详细配置项可在`lib/censor_bear/configuration.rb`中查看。
|
70
|
+
|
71
|
+
```ruby
|
72
|
+
CensorBear.configure do |config|
|
73
|
+
config.user_class = 'User'
|
74
|
+
config.user_name_method = 'nickname'
|
75
|
+
|
76
|
+
config.aliyun_green_access_key_id = 'access key id'
|
77
|
+
config.aliyun_green_access_key_secret = 'access key secret'
|
78
|
+
config.aliyun_green_enable_internal = false
|
79
|
+
|
80
|
+
config.main_app_root_path_method = 'root_path'
|
81
|
+
end
|
82
|
+
```
|
83
|
+
|
66
84
|
## 注意事项
|
67
85
|
1. 为 MOD 时,表示需要人工审核,需要被审查对象(UGC内容)支持`is_approved`字段(默认为`true`),此时内容自己能看到,别人暂时看不到,需审核通过后可见。
|
68
86
|
2. 被审查对象可以通过软删实现,隐藏(目的是防止错判,撤销),删除的内容对自己和别人都是不可见的。
|
@@ -1,28 +1,23 @@
|
|
1
|
-
require_dependency
|
1
|
+
require_dependency 'censor_bear/application_controller'
|
2
2
|
|
3
3
|
module CensorBear
|
4
4
|
class ModLogsController < ApplicationController
|
5
|
-
before_action :set_mod_log, only: %i[show edit update destroy
|
5
|
+
before_action :set_mod_log, only: %i[show edit update destroy suspend ban pass undo reject]
|
6
6
|
|
7
|
-
# GET /mod_logs
|
8
7
|
def index
|
9
8
|
load_mod_logs
|
10
9
|
end
|
11
10
|
|
12
|
-
# GET /mod_logs/1
|
13
11
|
def show
|
14
12
|
end
|
15
13
|
|
16
|
-
# GET /mod_logs/new
|
17
14
|
def new
|
18
15
|
@mod_log = ModLog.new
|
19
16
|
end
|
20
17
|
|
21
|
-
# GET /mod_logs/1/edit
|
22
18
|
def edit
|
23
19
|
end
|
24
20
|
|
25
|
-
# POST /mod_logs
|
26
21
|
def create
|
27
22
|
@mod_log = ModLog.new(mod_log_params)
|
28
23
|
|
@@ -33,7 +28,6 @@ module CensorBear
|
|
33
28
|
end
|
34
29
|
end
|
35
30
|
|
36
|
-
# PATCH/PUT /mod_logs/1
|
37
31
|
def update
|
38
32
|
if @mod_log.update(mod_log_params)
|
39
33
|
redirect_to @mod_log, notice: 'Mod log was successfully updated.'
|
@@ -42,7 +36,6 @@ module CensorBear
|
|
42
36
|
end
|
43
37
|
end
|
44
38
|
|
45
|
-
# DELETE /mod_logs/1
|
46
39
|
def destroy
|
47
40
|
@mod_log.destroy
|
48
41
|
|
@@ -53,23 +46,29 @@ module CensorBear
|
|
53
46
|
end
|
54
47
|
|
55
48
|
|
56
|
-
def
|
49
|
+
def suspend
|
57
50
|
@mod_log.suspend!
|
58
51
|
|
59
52
|
redirect_to mod_logs_url, notice: 'Mod log was successfully ignored.'
|
60
53
|
end
|
61
54
|
|
62
|
-
def
|
63
|
-
|
64
|
-
@mod_log.delete(params[:reason])
|
55
|
+
def pass
|
56
|
+
@mod_log.approve
|
65
57
|
|
66
|
-
redirect_to mod_logs_url, notice: 'Mod log was successfully
|
58
|
+
redirect_to mod_logs_url, notice: 'Mod log was successfully ignored.'
|
67
59
|
end
|
68
60
|
|
69
|
-
def
|
70
|
-
|
61
|
+
def undo
|
62
|
+
# TODO: 判断状态,确定是撤销通过呢还是撤销删除
|
63
|
+
@mod_log.cancel
|
64
|
+
|
65
|
+
redirect_to mod_logs_url, notice: 'Mod log was successfully ignored.'
|
66
|
+
end
|
67
|
+
|
68
|
+
def reject
|
69
|
+
@mod_log.remove(params[:reason])
|
71
70
|
|
72
|
-
redirect_to mod_logs_url, notice: 'Mod log was successfully
|
71
|
+
redirect_to mod_logs_url, notice: 'Mod log was successfully ignored.'
|
73
72
|
end
|
74
73
|
|
75
74
|
def ban
|
@@ -80,8 +79,11 @@ module CensorBear
|
|
80
79
|
|
81
80
|
def load_mod_logs
|
82
81
|
builder ||= mod_log_scope.includes(:record)
|
83
|
-
builder = builder.where(
|
84
|
-
|
82
|
+
builder = builder.where('content ilike ?', "%#{params[:q]}%") if params[:q].present?
|
83
|
+
if params[:filter] != 'all'
|
84
|
+
builder = builder.pending
|
85
|
+
builder = builder.unscope(where: :aasm_state).where(aasm_state: params[:state]) if params[:state].present?
|
86
|
+
end
|
85
87
|
builder = builder.order(id: :desc)
|
86
88
|
|
87
89
|
@pagy, @mod_logs = pagy(builder)
|
@@ -89,7 +91,6 @@ module CensorBear
|
|
89
91
|
|
90
92
|
private
|
91
93
|
|
92
|
-
# Use callbacks to share common setup or constraints between actions.
|
93
94
|
def set_mod_log
|
94
95
|
@mod_log = ModLog.find(params[:id] || params[:mod_log_id])
|
95
96
|
end
|
@@ -98,7 +99,6 @@ module CensorBear
|
|
98
99
|
ModLog
|
99
100
|
end
|
100
101
|
|
101
|
-
# Only allow a list of trusted parameters through.
|
102
102
|
def mod_log_params
|
103
103
|
params.require(:mod_log).permit(:record_id, :record_type, :mod_words, :user_id, :reason)
|
104
104
|
end
|
@@ -1,6 +1,8 @@
|
|
1
1
|
module CensorBear
|
2
2
|
class ModLog < ApplicationRecord
|
3
|
-
|
3
|
+
include AASM
|
4
|
+
|
5
|
+
REASONS = %w(无 广告/SPAM 恶意灌水 违规内容 文不对题 重复发布 其它).freeze
|
4
6
|
belongs_to :record, polymorphic: true, required: false
|
5
7
|
|
6
8
|
def record_path
|
@@ -9,14 +11,14 @@ module CensorBear
|
|
9
11
|
record.censor_show_path
|
10
12
|
end
|
11
13
|
|
12
|
-
def
|
14
|
+
def remove(reason)
|
13
15
|
return if record.blank?
|
14
16
|
return if record.discarded?
|
15
17
|
# ugc内容需要开软删,便于撤销&查看统计,可以定时删除统计并删除软删内容,类似回收站机制
|
16
|
-
raise NoMethodError
|
18
|
+
raise NoMethodError, 'undefined censor_remove for record' unless record.respond_to?(:censor_remove)
|
17
19
|
|
18
|
-
ret = record.
|
19
|
-
|
20
|
+
ret = record.censor_remove
|
21
|
+
reject!(reason) if ret
|
20
22
|
end
|
21
23
|
|
22
24
|
def approve
|
@@ -24,7 +26,15 @@ module CensorBear
|
|
24
26
|
raise NoMethodError unless record.respond_to?(:censor_approve)
|
25
27
|
|
26
28
|
ret = record.censor_approve
|
27
|
-
|
29
|
+
pass! if ret
|
30
|
+
end
|
31
|
+
|
32
|
+
def cancel
|
33
|
+
return if record.blank?
|
34
|
+
raise NoMethodError unless record.respond_to?(:censor_cancel)
|
35
|
+
|
36
|
+
ret = record.censor_cancel
|
37
|
+
undo! if ret
|
28
38
|
end
|
29
39
|
|
30
40
|
def ban_user
|
@@ -32,23 +42,36 @@ module CensorBear
|
|
32
42
|
raise NoMethodError unless record.respond_to?(:censor_ban_user)
|
33
43
|
|
34
44
|
ret = record.censor_ban_user
|
35
|
-
|
45
|
+
reject!('已被封禁该用户') if ret
|
36
46
|
end
|
37
47
|
|
38
|
-
|
39
|
-
|
40
|
-
|
48
|
+
aasm do
|
49
|
+
state :pending, initial: true
|
50
|
+
state :rejected, :passed, :suspended
|
51
|
+
|
52
|
+
event :reject do
|
53
|
+
transitions from: %i[pending suspended], to: :rejected, after: Proc.new {|*args| set_reason(*args) }
|
54
|
+
end
|
55
|
+
|
56
|
+
event :pass do
|
57
|
+
transitions from: %i[pending suspended], to: :passed
|
58
|
+
end
|
59
|
+
|
60
|
+
event :suspend do
|
61
|
+
transitions from: :pending, to: :suspended, after: :unset_reason
|
62
|
+
end
|
41
63
|
|
42
|
-
|
43
|
-
|
64
|
+
event :undo do
|
65
|
+
transitions from: %i[passed rejected], to: :pending, after: :unset_reason
|
66
|
+
end
|
44
67
|
end
|
45
68
|
|
46
|
-
def
|
47
|
-
update_columns(
|
69
|
+
def unset_reason
|
70
|
+
update_columns(reason: nil)
|
48
71
|
end
|
49
72
|
|
50
|
-
def
|
51
|
-
update_columns(
|
73
|
+
def set_reason(reason)
|
74
|
+
update_columns(reason: reason)
|
52
75
|
end
|
53
76
|
end
|
54
77
|
end
|
@@ -2,44 +2,49 @@
|
|
2
2
|
%div{class: "flex flex-col"}
|
3
3
|
%div{class: "border rounded-md mb-2 p-2 flex flex-col space-y-1"}
|
4
4
|
%div{class: "flex justify-between"}
|
5
|
-
%div{class: ""}
|
5
|
+
%div{class: "text-sm"}
|
6
6
|
= link_to mod_log.record_path, data: { turbo: false }, target: "_blank" do
|
7
|
-
%span{class: "
|
8
|
-
-
|
9
|
-
|
10
|
-
%span{class: "text-sm bg-red-100 text-red-600 py-1 px-2 rounded-lg"}=t("censor_log.label.#{label}")
|
11
|
-
- unless mod_log.mod_words.blank?
|
12
|
-
- mod_log.mod_words.each do |word|
|
13
|
-
%span{class: "text-sm bg-yellow-100 text-yellow-600 py-1 px-2 rounded-lg"}="##{word}"
|
14
|
-
%span{class: "text-sm bg-gray-100 text-gray-600 py-1 px-2 rounded-lg"}= mod_log.created_at
|
15
|
-
%div{class: "flex space-x-2 items-center"}
|
7
|
+
%span{class: "bg-indigo-100 text-indigo-600 py-1 px-2 rounded-lg"}="#{mod_log.record_type.upcase}##{mod_log.record_id}"
|
8
|
+
%span{class: "bg-yellow-100 text-yellow-600 rounded-md p-1"}=t("censor_log.aasm_state.#{mod_log.aasm_state}")
|
9
|
+
%div{class: "flex space-x-2 items-center text-sm"}
|
16
10
|
- if mod_log.reason
|
17
11
|
%span{class: "bg-red-100 text-red-600 p-1 rounded-lg"}
|
18
12
|
= mod_log.reason
|
19
|
-
%span{class: "bg-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
%
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
13
|
+
%span{class: "bg-gray-100 text-gray-600 py-1 px-2 rounded-lg"}= mod_log.created_at
|
14
|
+
- if current_user.admin?
|
15
|
+
= button_to '删除', mod_log, method: :delete, data: { confirm: 'Are you sure?'}, class: "bg-red-600 text-white rounded-md px-2 py-0.5 cursor-pointer"
|
16
|
+
%div{class: "flex justify-between items-center py-2 w-full"}
|
17
|
+
%div{class: "flex flex-col rounded-lg bg-gray-50 p-3 text-sm space-y-4 w-full"}
|
18
|
+
-unless mod_log.record
|
19
|
+
%h3{class: "text-2xl text-red-600"} 对应条目已被永久删除,当前审核请求已无效,请删除
|
20
|
+
- else
|
21
|
+
%div
|
22
|
+
%span{class: "border border-pink-600 text-pink-600 rounded-lg text-xs p-0.5"}=mod_log.record.is_private ? "隐私" : "公开"
|
23
|
+
%span{class: "border border-blue-600 text-blue-600 rounded-lg text-xs p-0.5"}=mod_log.record.is_approved ? "审核通过" : "审核中..."
|
24
|
+
- if mod_log.record.discarded?
|
25
|
+
%div{class: "text-gray-900 leading-relaxed"}
|
26
|
+
%del= mod_log.record.content
|
27
|
+
- else
|
28
|
+
%div{class: "text-gray-900 leading-relaxed"}= mod_log.record.content
|
29
|
+
%div
|
30
|
+
- mod_log.record.pictures.each do |pic|
|
31
|
+
= image_tag pic.full_url, class: "w-16 rounded-md"
|
32
|
+
%div
|
33
|
+
- unless mod_log.labels.blank?
|
34
|
+
- mod_log.labels.each do |label|
|
35
|
+
%span{class: "text-xs bg-gray-200 text-gray-600 py-0.5 px-1 rounded-lg"}=t("censor_log.label.#{label}")
|
36
|
+
- unless mod_log.mod_words.blank?
|
37
|
+
- mod_log.mod_words.each do |word|
|
38
|
+
%span{class: "text-sm bg-gray-100 text-gray-600 py-0.5 px-1 rounded-lg"}="##{word}"
|
39
|
+
%div{class: "flex space-x-2 items-center justify-end"}
|
40
|
+
- if mod_log.may_suspend?
|
41
|
+
= link_to "忽略", mod_log_suspend_path(mod_log), class: "text-yellow-600 cursor-pointer"
|
42
|
+
- if mod_log.may_pass?
|
43
|
+
= link_to "通过", mod_log_pass_path(mod_log), class: "text-green-600 cursor-pointer"
|
44
|
+
- if mod_log.may_undo?
|
45
|
+
= link_to "撤销", mod_log_undo_path(mod_log), class: "text-red-600 cursor-pointer"
|
46
|
+
- if mod_log.may_reject?
|
47
|
+
= form_with(url: mod_log_reject_path(mod_log), method: :get, class: "space-x-1 flex items-center") do |f|
|
48
|
+
= f.submit "拒绝", class: "text-red-600 bg-transparent cursor-pointer"
|
49
|
+
= f.text_field :reason, value: mod_log.reason, placeholder: "不通过原因", class: "border rounded-md m py-0.5 px-1 text-sm"
|
50
|
+
|
@@ -6,8 +6,18 @@
|
|
6
6
|
= f.text_field :q, value: params[:q], placeholder: "关键词", class: "border rounded-md m py-0.5 px-1"
|
7
7
|
= f.submit "检索", class: "rounded-md px-2 py-1 text-sm bg-black text-white cursor-pointer"
|
8
8
|
= link_to "重置", mod_logs_path, class: "text-sm"
|
9
|
-
|
10
|
-
|
9
|
+
%div{class: "flex items-center space-x-2"}
|
10
|
+
%div{class: "text-sm text-gray-600"}="共 #{@pagy.count} 条"
|
11
|
+
%div{class: "bg-gray-200 rounded-full px-3 py-1 text-xs #{params[:filter] == "all" ? 'font-bold' : ''}"}
|
12
|
+
= link_to "全部", request.params.merge(filter: "all", state: "")
|
13
|
+
%div{class: "bg-gray-200 rounded-full px-3 py-1 text-xs #{params[:state].blank? && params[:filter].blank? ? 'font-bold' : ''}"}
|
14
|
+
= link_to "待处理", request.params.merge(state: "", filter: "")
|
15
|
+
%div{class: "bg-gray-200 rounded-full px-3 py-1 text-xs #{params[:state] == 'rejected' ? 'font-bold' : ''}"}
|
16
|
+
= link_to "被驳回", request.params.merge(state: "rejected", filter: "")
|
17
|
+
%div{class: "bg-gray-200 rounded-full px-3 py-1 text-xs #{params[:state] == 'passed' ? 'font-bold' : ''}"}
|
18
|
+
= link_to "通过", request.params.merge(state: "passed", filter: "")
|
19
|
+
%div{class: "bg-gray-200 rounded-full px-3 py-1 text-xs #{params[:state] == 'suspended' ? 'font-bold' : ''}"}
|
20
|
+
= link_to "暂缓处理", request.params.merge(state: "suspended", filter: "")
|
11
21
|
%div
|
12
22
|
- if @mod_logs.blank?
|
13
23
|
%div{class: "flex justify-center text-gray-500 p-8 border rounded-md"} 空空如也
|
data/config/routes.rb
CHANGED
data/lib/censor_bear/version.rb
CHANGED
data/lib/censor_bear.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: censor_bear
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.15
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- 42up
|
@@ -30,6 +30,20 @@ dependencies:
|
|
30
30
|
- - ">="
|
31
31
|
- !ruby/object:Gem::Version
|
32
32
|
version: 6.0.4.1
|
33
|
+
- !ruby/object:Gem::Dependency
|
34
|
+
name: aasm
|
35
|
+
requirement: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - ">="
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '0'
|
40
|
+
type: :runtime
|
41
|
+
prerelease: false
|
42
|
+
version_requirements: !ruby/object:Gem::Requirement
|
43
|
+
requirements:
|
44
|
+
- - ">="
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '0'
|
33
47
|
- !ruby/object:Gem::Dependency
|
34
48
|
name: aliyun_green
|
35
49
|
requirement: !ruby/object:Gem::Requirement
|
@@ -169,6 +183,7 @@ files:
|
|
169
183
|
- db/migrate/20211206092626_add_ip_to_censor_bear_logs.rb
|
170
184
|
- db/migrate/20211208041114_add_labels_to_censor_bear_logs.rb
|
171
185
|
- db/migrate/20211209093050_add_response_to_censor_bear_logs.rb
|
186
|
+
- db/migrate/20211209113710_add_aasm_state_to_censor_bear_mod_logs.rb
|
172
187
|
- lib/censor_bear.rb
|
173
188
|
- lib/censor_bear/censor.rb
|
174
189
|
- lib/censor_bear/configuration.rb
|