mirror of
				https://github.com/mealie-recipes/mealie.git
				synced 2025-11-04 03:28:28 -05:00 
			
		
		
		
	* fix webhooks not firing due to missing session * disable webhook test button because it doesnt do anything * fix background task administration not working at all * fix error in test
This commit is contained in:
		
							parent
							
								
									da791ec9c5
								
							
						
					
					
						commit
						84d55eb920
					
				@ -18,6 +18,8 @@
 | 
			
		||||
            icon: $globals.icons.testTube,
 | 
			
		||||
            text: $tc('general.test'),
 | 
			
		||||
            event: 'test',
 | 
			
		||||
            // TODO: There is no functionality hooked up to this. Enable it when there is
 | 
			
		||||
            disabled: true,
 | 
			
		||||
          },
 | 
			
		||||
          {
 | 
			
		||||
            icon: $globals.icons.save,
 | 
			
		||||
 | 
			
		||||
@ -25,7 +25,7 @@
 | 
			
		||||
        content-class="text-caption"
 | 
			
		||||
      >
 | 
			
		||||
        <template #activator="{ on, attrs }">
 | 
			
		||||
          <v-btn tile :large="large" icon v-bind="attrs" @click="$emit(btn.event)" v-on="on">
 | 
			
		||||
          <v-btn tile :large="large" icon v-bind="attrs" @click="$emit(btn.event)" v-on="on" :disabled="btn.disabled">
 | 
			
		||||
            <v-icon> {{ btn.icon }} </v-icon>
 | 
			
		||||
          </v-btn>
 | 
			
		||||
        </template>
 | 
			
		||||
@ -43,6 +43,7 @@ export interface ButtonOption {
 | 
			
		||||
  text: string;
 | 
			
		||||
  event: string;
 | 
			
		||||
  children?: ButtonOption[];
 | 
			
		||||
  disabled?: boolean;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export default defineComponent({
 | 
			
		||||
 | 
			
		||||
@ -1,5 +1,6 @@
 | 
			
		||||
import { BaseAPI } from "../base/base-clients";
 | 
			
		||||
import { ServerTask } from "~/lib/api/types/server";
 | 
			
		||||
import { PaginationData } from "~/lib/api/types/non-generated";
 | 
			
		||||
 | 
			
		||||
const prefix = "/api";
 | 
			
		||||
 | 
			
		||||
@ -13,6 +14,6 @@ export class AdminTaskAPI extends BaseAPI {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  async getAll() {
 | 
			
		||||
    return await this.requests.get<ServerTask[]>(routes.base);
 | 
			
		||||
    return await this.requests.get<PaginationData<ServerTask>>(routes.base);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -57,7 +57,7 @@ export default defineComponent({
 | 
			
		||||
      const { data } = await api.serverTasks.getAll();
 | 
			
		||||
 | 
			
		||||
      if (data) {
 | 
			
		||||
        tasks.value = data;
 | 
			
		||||
        tasks.value = data.items;
 | 
			
		||||
      }
 | 
			
		||||
      loading.value = false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -100,5 +100,5 @@ class GroupEventsNotifierController(BaseUserController):
 | 
			
		||||
            document_data=EventDocumentDataBase(document_type=EventDocumentType.generic, operation=EventOperation.info),
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        test_listener = AppriseEventListener(self.event_bus.session, self.group_id)
 | 
			
		||||
        test_listener = AppriseEventListener(self.group_id)
 | 
			
		||||
        test_listener.publish_to_subscribers(test_event, [item.apprise_url])
 | 
			
		||||
 | 
			
		||||
@ -13,7 +13,6 @@ from sqlalchemy.orm.session import Session
 | 
			
		||||
 | 
			
		||||
from mealie.db.db_setup import session_context
 | 
			
		||||
from mealie.db.models.group.webhooks import GroupWebhooksModel
 | 
			
		||||
from mealie.repos.all_repositories import get_repositories
 | 
			
		||||
from mealie.repos.repository_factory import AllRepositories
 | 
			
		||||
from mealie.schema.group.group_events import GroupEventNotifierPrivate
 | 
			
		||||
from mealie.schema.group.webhook import ReadWebhook
 | 
			
		||||
@ -24,12 +23,14 @@ from .publisher import ApprisePublisher, PublisherLike, WebhookPublisher
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class EventListenerBase(ABC):
 | 
			
		||||
    session: Session | None
 | 
			
		||||
    _session: Session | None
 | 
			
		||||
    _repos: AllRepositories | None
 | 
			
		||||
 | 
			
		||||
    def __init__(self, session: Session, group_id: UUID4, publisher: PublisherLike) -> None:
 | 
			
		||||
        self.session = session
 | 
			
		||||
    def __init__(self, group_id: UUID4, publisher: PublisherLike) -> None:
 | 
			
		||||
        self.group_id = group_id
 | 
			
		||||
        self.publisher = publisher
 | 
			
		||||
        self._session = None
 | 
			
		||||
        self._repos = None
 | 
			
		||||
 | 
			
		||||
    @abstractmethod
 | 
			
		||||
    def get_subscribers(self, event: Event) -> list:
 | 
			
		||||
@ -52,22 +53,29 @@ class EventListenerBase(ABC):
 | 
			
		||||
        may be constructed during a request where the session is provided by the request, but the when
 | 
			
		||||
        run as a scheduled task, the session is not provided and must be created.
 | 
			
		||||
        """
 | 
			
		||||
        if self.session is None:
 | 
			
		||||
        if self._session is None:
 | 
			
		||||
            with session_context() as session:
 | 
			
		||||
                self.session = session
 | 
			
		||||
                yield self.session
 | 
			
		||||
                self._session = session
 | 
			
		||||
                yield self._session
 | 
			
		||||
        else:
 | 
			
		||||
            yield self.session
 | 
			
		||||
            yield self._session
 | 
			
		||||
 | 
			
		||||
    @contextlib.contextmanager
 | 
			
		||||
    def ensure_repos(self) -> Generator[AllRepositories, None, None]:
 | 
			
		||||
        if self._repos is None:
 | 
			
		||||
            with self.ensure_session() as session:
 | 
			
		||||
                self._repos = AllRepositories(session)
 | 
			
		||||
                yield self._repos
 | 
			
		||||
        else:
 | 
			
		||||
            yield self._repos
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class AppriseEventListener(EventListenerBase):
 | 
			
		||||
    def __init__(self, session: Session, group_id: UUID4) -> None:
 | 
			
		||||
        super().__init__(session, group_id, ApprisePublisher())
 | 
			
		||||
    def __init__(self, group_id: UUID4) -> None:
 | 
			
		||||
        super().__init__(group_id, ApprisePublisher())
 | 
			
		||||
 | 
			
		||||
    def get_subscribers(self, event: Event) -> list[str]:
 | 
			
		||||
        with self.ensure_session():
 | 
			
		||||
            repos = AllRepositories(self.session)
 | 
			
		||||
 | 
			
		||||
        with self.ensure_repos() as repos:
 | 
			
		||||
            notifiers: list[GroupEventNotifierPrivate] = repos.group_event_notifier.by_group(  # type: ignore
 | 
			
		||||
                self.group_id
 | 
			
		||||
            ).multi_query({"enabled": True}, override_schema=GroupEventNotifierPrivate)
 | 
			
		||||
@ -115,9 +123,8 @@ class AppriseEventListener(EventListenerBase):
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class WebhookEventListener(EventListenerBase):
 | 
			
		||||
    def __init__(self, session: Session, group_id: UUID4) -> None:
 | 
			
		||||
        super().__init__(session, group_id, WebhookPublisher())
 | 
			
		||||
        self.repos = get_repositories(session)
 | 
			
		||||
    def __init__(self, group_id: UUID4) -> None:
 | 
			
		||||
        super().__init__(group_id, WebhookPublisher())
 | 
			
		||||
 | 
			
		||||
    def get_subscribers(self, event: Event) -> list[ReadWebhook]:
 | 
			
		||||
        # we only care about events that contain webhook information
 | 
			
		||||
@ -127,13 +134,13 @@ class WebhookEventListener(EventListenerBase):
 | 
			
		||||
        scheduled_webhooks = self.get_scheduled_webhooks(
 | 
			
		||||
            event.document_data.webhook_start_dt, event.document_data.webhook_end_dt
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        return scheduled_webhooks
 | 
			
		||||
 | 
			
		||||
    def publish_to_subscribers(self, event: Event, subscribers: list[ReadWebhook]) -> None:
 | 
			
		||||
        with self.ensure_repos() as repos:
 | 
			
		||||
            if event.document_data.document_type == EventDocumentType.mealplan:
 | 
			
		||||
                # TODO: limit mealplan data to a date range instead of returning all mealplans
 | 
			
		||||
            meal_repo = self.repos.meals.by_group(self.group_id)
 | 
			
		||||
                meal_repo = repos.meals.by_group(self.group_id)
 | 
			
		||||
                meal_pagination_data = meal_repo.page_all(pagination=PaginationQuery(page=1, per_page=-1))
 | 
			
		||||
                meal_data = meal_pagination_data.items
 | 
			
		||||
                if meal_data:
 | 
			
		||||
 | 
			
		||||
@ -50,8 +50,8 @@ class EventBusService:
 | 
			
		||||
        self.group_id = group_id
 | 
			
		||||
 | 
			
		||||
        self.listeners: list[EventListenerBase] = [
 | 
			
		||||
            AppriseEventListener(self.session, self.group_id),
 | 
			
		||||
            WebhookEventListener(self.session, self.group_id),
 | 
			
		||||
            AppriseEventListener(self.group_id),
 | 
			
		||||
            WebhookEventListener(self.group_id),
 | 
			
		||||
        ]
 | 
			
		||||
 | 
			
		||||
    def dispatch(
 | 
			
		||||
 | 
			
		||||
@ -51,7 +51,7 @@ def test_get_scheduled_webhooks_filter_query(database: AllRepositories, unique_u
 | 
			
		||||
        if new_item.enabled:
 | 
			
		||||
            expected.append(new_item)
 | 
			
		||||
 | 
			
		||||
    event_bus_listener = WebhookEventListener(database.session, unique_user.group_id)  # type: ignore
 | 
			
		||||
    event_bus_listener = WebhookEventListener(unique_user.group_id)  # type: ignore
 | 
			
		||||
    results = event_bus_listener.get_scheduled_webhooks(start, datetime.now() + timedelta(minutes=5))
 | 
			
		||||
 | 
			
		||||
    assert len(results) == len(expected)
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user