7
7
use axum:: extract:: Path ;
8
8
use axum:: Json ;
9
9
use crates_io_worker:: BackgroundJob ;
10
- use diesel:: { ExpressionMethods , RunQueryDsl } ;
10
+ use diesel:: { ExpressionMethods , QueryDsl , RunQueryDsl } ;
11
11
use diesel_async:: async_connection_wrapper:: AsyncConnectionWrapper ;
12
12
use http:: request:: Parts ;
13
13
use http:: StatusCode ;
@@ -142,14 +142,52 @@ fn apply_yank_update(
142
142
) -> AppResult < ( ) > {
143
143
// Try to update the yank state first, to avoid unnecessary checks.
144
144
update_version_yank_state ( version, update_data) ?;
145
+ perform_version_yank_update ( state, req, conn, version, krate) ?;
145
146
146
- // Add authentication check
147
+ Ok ( ( ) )
148
+ }
149
+
150
+ fn update_version_yank_state ( version : & mut Version , update_data : & VersionUpdate ) -> AppResult < ( ) > {
151
+ match ( update_data. yanked , & update_data. yank_message ) {
152
+ ( Some ( true ) , Some ( message) ) => {
153
+ version. yanked = true ;
154
+ version. yank_message = Some ( message. clone ( ) ) ;
155
+ }
156
+ ( Some ( yanked) , None ) => {
157
+ version. yanked = yanked;
158
+ version. yank_message = None ;
159
+ }
160
+ ( Some ( false ) , Some ( _) ) => {
161
+ return Err ( bad_request ( "Cannot set yank message when unyanking" ) ) ;
162
+ }
163
+ ( None , Some ( message) ) => {
164
+ if version. yanked {
165
+ version. yank_message = Some ( message. clone ( ) ) ;
166
+ } else {
167
+ return Err ( bad_request (
168
+ "Cannot update yank message for a version that is not yanked" ,
169
+ ) ) ;
170
+ }
171
+ }
172
+ // If both yanked and yank_message are None, do nothing.
173
+ // This function only cares about updating the yanked state and yank message.
174
+ ( None , None ) => { }
175
+ }
176
+ Ok ( ( ) )
177
+ }
178
+
179
+ pub fn perform_version_yank_update (
180
+ state : & AppState ,
181
+ req : & Parts ,
182
+ conn : & mut impl Conn ,
183
+ version : & Version ,
184
+ krate : & Crate ,
185
+ ) -> AppResult < ( ) > {
147
186
let auth = AuthCheck :: default ( )
148
187
. with_endpoint_scope ( EndpointScope :: Yank )
149
188
. for_crate ( & krate. name )
150
189
. check ( req, conn) ?;
151
190
152
- // Add rate limiting check
153
191
state
154
192
. rate_limiter
155
193
. check_rate_limit ( auth. user_id ( ) , LimitedAction :: YankUnyank , conn) ?;
@@ -158,7 +196,6 @@ fn apply_yank_update(
158
196
let user = auth. user ( ) ;
159
197
let owners = krate. owners ( conn) ?;
160
198
161
- // Check user rights
162
199
if Handle :: current ( ) . block_on ( user. rights ( state, & owners) ) ? < Rights :: Publish {
163
200
if user. is_admin {
164
201
warn ! (
@@ -168,58 +205,41 @@ fn apply_yank_update(
168
205
} else {
169
206
return Err ( custom (
170
207
StatusCode :: FORBIDDEN ,
171
- "must already be an owner to update version " ,
208
+ "must already be an owner to yank or unyank " ,
172
209
) ) ;
173
210
}
174
211
}
175
212
176
- diesel:: update ( & * version)
213
+ // Check if the yanked state or yank message has changed
214
+ let ( yanked, yank_message) = crate :: schema:: versions:: table
215
+ . find ( version. id )
216
+ . select ( (
217
+ crate :: schema:: versions:: yanked,
218
+ crate :: schema:: versions:: yank_message,
219
+ ) )
220
+ . first :: < ( bool , Option < String > ) > ( conn) ?;
221
+
222
+ if yanked == version. yanked && yank_message == version. yank_message {
223
+ // No changes, return early
224
+ return Ok ( ( ) ) ;
225
+ }
226
+
227
+ diesel:: update ( version)
177
228
. set ( (
178
229
crate :: schema:: versions:: yanked. eq ( version. yanked ) ,
179
230
crate :: schema:: versions:: yank_message. eq ( & version. yank_message ) ,
180
231
) )
181
232
. execute ( conn) ?;
182
233
183
- // Add version owner action
184
234
let action = if version. yanked {
185
235
VersionAction :: Yank
186
236
} else {
187
237
VersionAction :: Unyank
188
238
} ;
189
239
insert_version_owner_action ( conn, version. id , user. id , api_token_id, action) ?;
190
240
191
- // Enqueue jobs
192
241
jobs:: enqueue_sync_to_index ( & krate. name , conn) ?;
193
242
UpdateDefaultVersion :: new ( krate. id ) . enqueue ( conn) ?;
194
243
195
244
Ok ( ( ) )
196
245
}
197
-
198
- fn update_version_yank_state ( version : & mut Version , update_data : & VersionUpdate ) -> AppResult < ( ) > {
199
- match ( update_data. yanked , & update_data. yank_message ) {
200
- ( Some ( true ) , Some ( message) ) => {
201
- version. yanked = true ;
202
- version. yank_message = Some ( message. clone ( ) ) ;
203
- }
204
- ( Some ( yanked) , None ) => {
205
- version. yanked = yanked;
206
- version. yank_message = None ;
207
- }
208
- ( Some ( false ) , Some ( _) ) => {
209
- return Err ( bad_request ( "Cannot set yank message when unyanking" ) ) ;
210
- }
211
- ( None , Some ( message) ) => {
212
- if version. yanked {
213
- version. yank_message = Some ( message. clone ( ) ) ;
214
- } else {
215
- return Err ( bad_request (
216
- "Cannot update yank message for a version that is not yanked" ,
217
- ) ) ;
218
- }
219
- }
220
- // If both yanked and yank_message are None, do nothing.
221
- // This function only cares about updating the yanked state and yank message.
222
- ( None , None ) => { }
223
- }
224
- Ok ( ( ) )
225
- }
0 commit comments