import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { VERSION } from "@goauthentik/common/constants"; import { EventContext, EventModel, EventWithContext } from "@goauthentik/common/events"; import { AKElement } from "@goauthentik/elements/Base"; import "@goauthentik/elements/Expand"; import "@goauthentik/elements/Spinner"; import { PFSize } from "@goauthentik/elements/Spinner"; import { t } from "@lingui/macro"; import { CSSResult, TemplateResult, css, html } from "lit"; import { customElement, property } from "lit/decorators.js"; import { until } from "lit/directives/until.js"; import PFButton from "@patternfly/patternfly/components/Button/button.css"; import PFDescriptionList from "@patternfly/patternfly/components/DescriptionList/description-list.css"; import PFList from "@patternfly/patternfly/components/List/list.css"; import PFFlex from "@patternfly/patternfly/layouts/Flex/flex.css"; import PFBase from "@patternfly/patternfly/patternfly-base.css"; import { EventActions, FlowsApi } from "@goauthentik/api"; @customElement("ak-event-info") export class EventInfo extends AKElement { @property({ attribute: false }) event!: EventWithContext; static get styles(): CSSResult[] { return [ PFBase, PFButton, PFFlex, PFList, PFDescriptionList, css` code { display: block; white-space: pre-wrap; word-break: break-all; } .pf-l-flex { justify-content: space-between; } .pf-l-flex__item { min-width: 25%; } iframe { width: 100%; height: 50rem; } `, ]; } getModelInfo(context: EventModel): TemplateResult { if (context === null) { return html`-`; } return html`
${t`UID`}
${context.pk}
${t`Name`}
${context.name}
${t`App`}
${context.app}
${t`Model Name`}
${context.model_name}
`; } getEmailInfo(context: EventContext): TemplateResult { if (context === null) { return html`-`; } return html`
${t`Message`}
${context.message}
${t`Subject`}
${context.subject}
${t`From`}
${context.from_email}
${t`To`}
${(context.to_email as string[]).map((to) => { return html`
  • ${to}
  • `; })}
    `; } defaultResponse(): TemplateResult { return html`

    ${t`Context`}

    ${JSON.stringify(this.event?.context, null, 4)}

    ${t`User`}

    ${JSON.stringify(this.event?.user, null, 4)}
    `; } buildGitHubIssueUrl(context: EventContext): string { const httpRequest = this.event.context.http_request as EventContext; let title = ""; if (httpRequest) { title = `${httpRequest?.method} ${httpRequest?.path}`; } // https://docs.github.com/en/issues/tracking-your-work-with-issues/creating-issues/about-automation-for-issues-and-pull-requests-with-query-parameters const fullBody = ` **Describe the bug** A clear and concise description of what the bug is. **To Reproduce** Steps to reproduce the behavior: 1. Go to '...' 2. Click on '....' 3. Scroll down to '....' 4. See error **Expected behavior** A clear and concise description of what you expected to happen. **Screenshots** If applicable, add screenshots to help explain your problem. **Logs**
    Stacktrace from authentik \`\`\` ${context.message as string} \`\`\`
    **Version and Deployment (please complete the following information):** - authentik version: ${VERSION} - Deployment: [e.g. docker-compose, helm] **Additional context** Add any other context about the problem here. `; return `https://github.com/goauthentik/authentik/issues/ new?labels=bug,from_authentik&title=${encodeURIComponent(title)} &body=${encodeURIComponent(fullBody)}`.trim(); } render(): TemplateResult { if (!this.event) { return html``; } switch (this.event?.action) { case EventActions.ModelCreated: case EventActions.ModelUpdated: case EventActions.ModelDeleted: return html`

    ${t`Affected model:`}

    ${this.getModelInfo(this.event.context?.model as EventModel)} `; case EventActions.AuthorizeApplication: return html`

    ${t`Authorized application:`}

    ${this.getModelInfo( this.event.context.authorized_application as EventModel, )}

    ${t`Using flow`}

    ${until( new FlowsApi(DEFAULT_CONFIG) .flowsInstancesList({ flowUuid: this.event.context.flow as string, }) .then((resp) => { return html`${resp.results[0].name}`; }), html``, )}
    ${this.defaultResponse()}`; case EventActions.EmailSent: return html`

    ${t`Email info:`}

    ${this.getEmailInfo(this.event.context)} `; case EventActions.SecretView: return html`

    ${t`Secret:`}

    ${this.getModelInfo(this.event.context.secret as EventModel)}`; case EventActions.SystemException: return html` ${t`Open issue on GitHub...`}

    ${t`Exception`}

    ${this.event.context.message}
    ${this.defaultResponse()}`; case EventActions.PropertyMappingException: return html`

    ${t`Exception`}

    ${this.event.context.message || this.event.context.error}

    ${t`Expression`}

    ${this.event.context.expression}
    ${this.defaultResponse()}`; case EventActions.PolicyException: return html`

    ${t`Binding`}

    ${this.getModelInfo(this.event.context.binding as EventModel)}

    ${t`Request`}

    ${t`Exception`}

    ${this.event.context.message || this.event.context.error}
    ${this.defaultResponse()}`; case EventActions.PolicyExecution: return html`

    ${t`Binding`}

    ${this.getModelInfo(this.event.context.binding as EventModel)}

    ${t`Request`}

    ${t`Result`}

    ${this.defaultResponse()}`; case EventActions.ConfigurationError: return html`

    ${this.event.context.message}

    ${this.defaultResponse()}`; case EventActions.UpdateAvailable: return html`

    ${t`New version available!`}

    ${this.event.context.new_version} `; // Action types which typically don't record any extra context. // If context is not empty, we fall to the default response. case EventActions.Login: if ("using_source" in this.event.context) { return html`

    ${t`Using source`}

    ${this.getModelInfo(this.event.context.using_source as EventModel)}
    `; } return this.defaultResponse(); case EventActions.LoginFailed: return html`

    ${t`Attempted to log in as ${this.event.context.username}`}

    ${this.defaultResponse()}`; case EventActions.Logout: if (Object.keys(this.event.context).length === 0) { return html`${t`No additional data available.`}`; } return this.defaultResponse(); case EventActions.SystemTaskException: return html`

    ${t`Exception`}

    ${this.event.context.message}
    `; default: return this.defaultResponse(); } } }