mirror of
				https://git.sr.ht/~tsileo/microblog.pub
				synced 2025-06-05 21:59:23 +02:00 
			
		
		
		
	Allow to delete webmentions
This commit is contained in:
		
							
								
								
									
										37
									
								
								app/admin.py
									
									
									
									
									
								
							
							
						
						
									
										37
									
								
								app/admin.py
									
									
									
									
									
								
							| @@ -11,6 +11,7 @@ from fastapi.exceptions import HTTPException | ||||
| from fastapi.responses import RedirectResponse | ||||
| from loguru import logger | ||||
| from sqlalchemy import and_ | ||||
| from sqlalchemy import delete | ||||
| from sqlalchemy import func | ||||
| from sqlalchemy import or_ | ||||
| from sqlalchemy import select | ||||
| @@ -883,6 +884,42 @@ async def admin_actions_force_delete( | ||||
|     return RedirectResponse(redirect_url, status_code=302) | ||||
|  | ||||
|  | ||||
| @router.post("/actions/force_delete_webmention") | ||||
| async def admin_actions_force_delete_webmention( | ||||
|     request: Request, | ||||
|     webmention_id: int = Form(), | ||||
|     redirect_url: str = Form(), | ||||
|     csrf_check: None = Depends(verify_csrf_token), | ||||
|     db_session: AsyncSession = Depends(get_db_session), | ||||
| ) -> RedirectResponse: | ||||
|     webmention = await boxes.get_webmention_by_id(db_session, webmention_id) | ||||
|     if not webmention: | ||||
|         raise ValueError(f"Cannot find {webmention_id}") | ||||
|     if not webmention.outbox_object: | ||||
|         raise ValueError(f"Missing related outbox object for {webmention_id}") | ||||
|  | ||||
|     # TODO: move this | ||||
|     logger.info(f"Deleting {webmention_id}") | ||||
|     webmention.is_deleted = True | ||||
|     await db_session.flush() | ||||
|     from app.webmentions import _handle_webmention_side_effects | ||||
|  | ||||
|     await _handle_webmention_side_effects( | ||||
|         db_session, webmention, webmention.outbox_object | ||||
|     ) | ||||
|     # Delete related notifications | ||||
|     notif_deletion_result = await db_session.execute( | ||||
|         delete(models.Notification) | ||||
|         .where(models.Notification.webmention_id == webmention.id) | ||||
|         .execution_options(synchronize_session=False) | ||||
|     ) | ||||
|     logger.info( | ||||
|         f"Deleted {notif_deletion_result.rowcount} notifications"  # type: ignore | ||||
|     ) | ||||
|     await db_session.commit() | ||||
|     return RedirectResponse(redirect_url, status_code=302) | ||||
|  | ||||
|  | ||||
| @router.post("/actions/follow") | ||||
| async def admin_actions_follow( | ||||
|     request: Request, | ||||
|   | ||||
							
								
								
									
										14
									
								
								app/boxes.py
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								app/boxes.py
									
									
									
									
									
								
							| @@ -1088,6 +1088,20 @@ async def get_anybox_object_by_ap_id( | ||||
|         return await get_inbox_object_by_ap_id(db_session, ap_id) | ||||
|  | ||||
|  | ||||
| async def get_webmention_by_id( | ||||
|     db_session: AsyncSession, webmention_id: int | ||||
| ) -> models.Webmention | None: | ||||
|     return ( | ||||
|         await db_session.execute( | ||||
|             select(models.Webmention) | ||||
|             .where(models.Webmention.id == webmention_id) | ||||
|             .options( | ||||
|                 joinedload(models.Webmention.outbox_object), | ||||
|             ) | ||||
|         ) | ||||
|     ).scalar_one_or_none()  # type: ignore | ||||
|  | ||||
|  | ||||
| async def _handle_delete_activity( | ||||
|     db_session: AsyncSession, | ||||
|     from_actor: models.Actor, | ||||
|   | ||||
| @@ -142,6 +142,17 @@ | ||||
| {% endblock %} | ||||
| {% endmacro %} | ||||
|  | ||||
| {% macro admin_force_delete_webmention_button(webmention_id, permalink_id=None) %} | ||||
| {% block admin_force_delete_webmention_button scoped %} | ||||
| <form action="{{ request.url_for("admin_actions_force_delete_webmention") }}" class="object-delete-form" method="POST"> | ||||
|     {{ embed_csrf_token() }} | ||||
|     {{ embed_redirect_url(permalink_id) }} | ||||
|     <input type="hidden" name="webmention_id" value="{{ webmention_id }}"> | ||||
|     <input type="submit" value="local delete"> | ||||
| </form> | ||||
| {% endblock %} | ||||
| {% endmacro %} | ||||
|  | ||||
| {% macro admin_announce_button(ap_object_id, permalink_id=None) %} | ||||
| {% block admin_announce_button scoped %} | ||||
| <form action="{{ request.url_for("admin_actions_announce") }}" method="POST"> | ||||
| @@ -473,6 +484,11 @@ | ||||
|         <li> | ||||
|             <time class="dt-published" datetime="{{ wm_reply.published_at.replace(microsecond=0).isoformat() }}" title="{{ wm_reply.published_at.replace(microsecond=0).isoformat() }}">{{ wm_reply.published_at | timeago }}</time> | ||||
|         </li> | ||||
|         {% if is_admin %} | ||||
|             <li> | ||||
|                 {{ admin_force_delete_webmention_button(wm_reply.webmention_id) }} | ||||
|             </li> | ||||
|         {% endif %} | ||||
|     </ul> | ||||
|     </nav> | ||||
| </div> | ||||
|   | ||||
| @@ -125,6 +125,7 @@ class WebmentionReply: | ||||
|     url: str | ||||
|     published_at: datetime.datetime | ||||
|     in_reply_to: str | ||||
|     webmention_id: int | ||||
|  | ||||
|     @classmethod | ||||
|     def from_webmention(cls, webmention: Webmention) -> Optional["WebmentionReply"]: | ||||
| @@ -147,6 +148,7 @@ class WebmentionReply: | ||||
|                             item["properties"]["published"][0] | ||||
|                         ).replace(tzinfo=None), | ||||
|                         in_reply_to=webmention.target,  # type: ignore | ||||
|                         webmention_id=webmention.id,  # type: ignore | ||||
|                     ) | ||||
|                 except Exception: | ||||
|                     logger.exception( | ||||
|   | ||||
| @@ -8,6 +8,7 @@ from fastapi import HTTPException | ||||
| from fastapi import Request | ||||
| from fastapi.responses import JSONResponse | ||||
| from loguru import logger | ||||
| from sqlalchemy import func | ||||
| from sqlalchemy import select | ||||
|  | ||||
| from app import models | ||||
| @@ -204,7 +205,13 @@ async def _handle_webmention_side_effects( | ||||
| ) -> None: | ||||
|     if webmention.webmention_type == models.WebmentionType.UNKNOWN: | ||||
|         # TODO: recount everything | ||||
|         mentioned_object.webmentions_count = mentioned_object.webmentions_count + 1 | ||||
|         mentioned_object.webmentions_count = await db_session.scalar( | ||||
|             select(func.count(models.Webmention.id)).where( | ||||
|                 models.Webmention.is_deleted.is_(False), | ||||
|                 models.Webmention.outbox_object_id == mentioned_object.id, | ||||
|                 models.Webmention.webmention_type == models.WebmentionType.UNKNOWN, | ||||
|             ) | ||||
|         ) | ||||
|     elif webmention.webmention_type == models.WebmentionType.LIKE: | ||||
|         mentioned_object.likes_count = await _get_outbox_likes_count( | ||||
|             db_session, mentioned_object | ||||
|   | ||||
		Reference in New Issue
	
	Block a user