From f62f720c55426547a3d36e66bd292beb3bd4c2e3 Mon Sep 17 00:00:00 2001 From: Tana M Berry Date: Thu, 9 Nov 2023 16:01:27 -0600 Subject: [PATCH 01/24] website/blog:IPv6 blog (#7496) * draft blog on IPv6 * tweak tags * tweak tags more * error message * polishing * marc edits * spacing off * spacing fixes * rerun prettier --------- Co-authored-by: Tana Berry --- .../blog/2023-11-09-IPv6-addresses/item.md | 223 ++++++++++++++++++ 1 file changed, 223 insertions(+) create mode 100644 website/blog/2023-11-09-IPv6-addresses/item.md diff --git a/website/blog/2023-11-09-IPv6-addresses/item.md b/website/blog/2023-11-09-IPv6-addresses/item.md new file mode 100644 index 000000000..d6f2efa1f --- /dev/null +++ b/website/blog/2023-11-09-IPv6-addresses/item.md @@ -0,0 +1,223 @@ +--- +title: "IPv6 addresses and why you need to make the switch now" +description: "IPv6 addresses have been commercially available since 2010. But is there any compelling reason for sysadmins and security engineers to make the switch?" +slug: 2023-11-09-IPv6-addresses +authors: + - name: Jens Langhammer + title: CTO at Authentik Security Inc + url: https://github.com/BeryJu + image_url: https://github.com/BeryJu.png +tags: + - authentik + - IP address + - IPv4 + - IPv6 + - IP address exhaustion + - NAT Gateway + - IETF + - Internet Engineering Task Force + - IANA + - Internet Assigned Numbers Authority + - IPv6 address format + - SSO + - security + - identity provider + - authentication +hide_table_of_contents: false +--- + +> **_authentik is an open source Identity Provider that unifies your identity needs into a single platform, replacing Okta, Active Directory, and auth0. Authentik Security is a [public benefit company](https://github.com/OpenCoreVentures/ocv-public-benefit-company/blob/main/ocv-public-benefit-company-charter.md) building on top of the open source project._** + +--- + +IPv6 addresses have been commercially available since 2010. Yet, after Google’s IPv6 rollout the following year, the adoption by System Administrators and security engineers responsible for an entire organization’s network has been slower than you might expect. Population size and the plethora of work and personal devices that accompany this large number of workers do not accurately predict which countries have deployed this protocol. + +In this blog post, I explain briefly what IP addresses are and how they work; share why at Authentik Security we went full IPv6 in May 2023; and then set out some reasons why you should switch now. + +## What are IP addresses? + +IP Addresses are locations (similar to street addresses) that are assigned to allow system administrators and others to identify and locate every point (often referred to as a node) on a network through which traffic and communication passes via the internet. For example, every server, printer, computer, laptop, and phone in a single workplace network has its own IP address. + +We use domain names for websites, to avoid having to remember IP addresses, though our readers who are sysadmin—used to referencing all sorts of nodes deep within their organization’s networks—will recall them at the drop of a hat. + +But, increasingly, since many devices are online and [96.6% of internet users now use a smartphone](https://www.oberlo.com/statistics/how-many-people-have-smartphones), most Internet of Things (IoT) devices that we have in our workplaces and homes _also_ have their own IP address. This includes: + +- Computers, laptops and smartphones +- Database servers, web servers, mail servers, virtual servers (virtual machines), and servers that store software packages for distribution +- Other devices such as network printers, routers and services running on computer networks +- Domain names for websites, which are mapped to the IP address using Domain Name Servers (DNS) + +IP addresses are centrally overseen by the Internet Assigned Numbers Authority ([IANA](https://www.iana.org/)), with five [Regional Internet Registries](https://www.nro.net/about/rirs/) (RIRs). + +## What is the state of the IP landscape right now? + +Well, it’s all down to numbers. + +The previous version of this network layer communications protocol is known as IPv4. From our informed vantage point—looking over the rapid growth of ecommerce, business, government, educational, and entertainment services across the internet—it’s easy to see how its originator could not possibly have predicted that demand for IPv4 addresses would outstrip supply. + +Add in the ubiquity of connected devices that allow us to access and consume those services and you can see the problem. + +IP address exhaustion was foreseen in the 1980s, which is why the Internet Engineering Task Force ([IETF](https://www.ietf.org/)) started work on IPv6 in the early 1990s. The first RIR to run out of IPv4 addresses was ARIN (North America) in 2015, followed by the RIPE (Europe) in 2019, and LACNIC (South America) in 2020. The very last, free /8 address block of IPv4 addresses was issued by IANA in January 2011. + +The following realities contributed to the depletion of the IPv4 addresses: + +- IPv4 addresses were designed to use 32 bits and are written with decimal numbers +- This allowed for 4.3 billion IP addresses + +The IPv4 address format is written in 4 groups of 4 numbers, each group separated by a period. + +Even though IPv4 addresses still trade hands, it’s actually quite difficult now to buy a completely unused block. What’s more, they’re expensive for smaller organizations (currently around $39 each) and leasing is cheaper. Unless you can acquire them from those sources, you’ll likely now be issued IPv6 ones. + +> Interesting historical fact: IPv5 was developed specifically for streaming video and voice, becoming the basis for VoIP, though it was never widely adopted as a standard protocol. + +### IPv6 addresses, history and adoption + +The development of IPv6 was initiated by IETF in 1994, and was published as a draft standard in December 1998. The use of IPv6, went live in June 2012, and was ratified as an internet standard in July 2017. + +There is an often circulated metaphor from J. Wiljakka’s IEEE paper, [Transition to IPv6 in GPRS and WCDMA Mobile Networks](https://ieeexplore.ieee.org/document/995863), stating that every grain of sand on every seashore could be allocated its own IPv6 address. Let me illustrate. + +- IPv6 addresses were designed to use 128 bits and are written with hexadecimal digits (10 numbers from 1-10 and 6 letters from A-F). +- So, how many IPv6 addresses are there? In short, there are over 340 trillion IP addresses available! + +The IPv6 address format is written in 8 groups of 4 digits (each digit can be made up of 4 bits), each group separated by a colon. + +> Importantly, the hierarchical structure optimizes global IP routing, keeping routing tables small. + +If you plan to make the switch to IPv6, it’s worth noting that you’ll need to ensure that your devices, router, and ISP all support it. + +### Upward trend in the worldwide adoption by country + +Over 42.9% of Google users worldwide are accessing search using the IPv6 protocol. It’s intriguing to note which countries have a larger adoption of the IPv6 protocol than not: + +- France 74.38% +- Germany 71.52% +- India with 70.18% +- Malaysia 62.67% +- Greece 61.43% +- Saudi Arabia 60.93% + +And, yet China, Indonesia, Pakistan, Nigeria, and Russia lag surprisingly far behind many others in terms of adoption (between 5-15%) given their population size. Even many ISPs have been slow to switch. + +You can consult Google’s [per country IPv6 adoption statistics](https://www.google.com/intl/en/ipv6/statistics.html#tab=per-country-ipv6-adoption) to see where your location sits in the league table. + +## Why we decided on a full IPv6 addresses deployment + +The average internet user won’t be aware of anything much beyond what an IP address is, if even that. However for system administrators, IP addresses form a crucial part of an organization’s computer network infrastructure. + +In our case, the impetus to use IPv6 addresses for authentik came from our own, internal Infrastructure Engineer, Marc Schmitt. We initially considered configuring IPv4 for internal traffic and, as an interim measure, provide IPv6 at the edge only (remaining with IPv4 for everything else). However, that would still have required providing IPv6 support for customers who needed it. + +In the end, we determined it would be more efficient to adopt the IPv6 addresses protocol while we still had time to purchase, deploy, and configure it at our leisure across our existing network. We found it to be mostly a straightforward process. However, there are still some applications that did not fully support IPv6, but we were aided by the fact that we use open source software. This means that we were able to contribute back the changes needed to add IPv6 support to the tools we use. We were thrilled to have close access to a responsive community with some (not all!) of the tool vendors and their communities to help with any integration issues. [Plausible](https://plausible.io/), our web analytics tool, was especially helpful and supportive in our shift to IPv6. + +### Future proofing IP addresses on our network and platform + +While it seemed like there was no urgent reason to deploy IPv6 across our network, we knew that one day, it _would_ suddenly become pressing once ISPs and larger organizations had completely run out of still-circulating IPv4 addresses. + +For those customers who have not yet shifted to IPv6, we still provide IPv4 support at the edge, configuring our load balancers to receive requests over IPv4 and IPv6, and forwarding them internally over IPv6 to our services (such as our customer portal, for example). + +### Limiting ongoing spend + +Deployment of IPv6 can be less expensive as time goes on. If we’d opted to remain with IPv4 even temporarily, we knew we would have needed to buy more IPv4 addresses. + +In addition, we were paying our cloud-provider for using the NAT Gateway to convert our IPv4 addresses—all of which are private—to public IP addresses. On top of that, we were also charged a few cents per GB based on users. The costs can mount up, particularly when we pull Docker images multiple times per day. These costs were ongoing and on top of our existing cloud provider subscription. With IPv6, however, since IP addresses are already public—and there is no need to pay for the cost of translating them from private to public—the costs are limited to paying for the amount of data (incoming and outgoing traffic) passing through the network. + +### Unlimited pods + +Specifically when using the IPv4 protocol, there’s a limitation with our cloud provider if pulling IP addresses from the same subnet for both nodes and Kubernetes pods. You are limited by the number of pods (21) you can attach to a single node. With IPv6, the limit is so much higher that it's insignificant. + +### Clusters setup + +All original clusters were only configured for IPv4. It seemed like a good time to build in the IPv6 protocol while we were already investing time in renewing a cluster. + +We’d already been planning to switch out a cluster for several reasons: + +- We wanted to build a new cluster using ArgoCD (to replace the existing FluxCD one) for better GitOps, since ArgoCD comes with a built-in UI and provides a test deployment of the changes made in PRs to the application. +- We wanted to change the Container Network Interface (CNI) to select an IP from the same subnet as further future-proofing for when more clusters are added (a sandbox for Authentik Security and another sandbox for customers, for example). We enhanced our AWS-VPC-CNI with [Cilium](https://cilium.io/) to handle the interconnections between clusters and currently still use it to grab IPs. + +## IPv6 ensures everything works out-of-the-box + +If you’re a system administrator with limited time and resources, you’ll be concerned with ensuring that all devices, software, or connections are working across your network, and that traffic can flow securely without bottlenecks. So, it’s reassuring to know that IPv6 works out of the box—reducing the onboarding, expense, and maintenance feared by already overburdened sysadmins. + +### Stateless address auto-configuration (SLAAC) + +When it comes to devices, each device on which IPv6 has been enabled will independently assign IP addresses by default. With IPv6, there is no need for static or manual DHCP IP address configuration (though manual configuration is still supported). This is how it works: + +1. When a device is switched on, it requests a network prefix. +2. A router or routers on the link will provide the network prefix to the host. +3. Previously, the subnet prefix was combined with an interface ID generated from an interface's MAC address. However, having a common IP based on the MAC address raises privacy concerns, so now most devices just generate a random one. + +### No need to maintain both protocols across your network or convert IPv4 to IPv6 + +Unless you already have IPv6 deployed right across your network, if your traffic comes in via IPv4 or legacy networks, you’ll have to: + +- Maintain both protocols +- Route traffic differently, depending on what it is + +### No IP addresses sharing + +Typically, public IP addresses, particularly in Europe, are shared by multiple individual units in a single apartment building, or by multiple homes on the same street. This is not really a problem for private individuals, because most people have private IP addresses assigned to them by their routers. + +However, those in charge of the system administration for  organizations and workplaces want to avoid sharing IP addresses. We are almost all subject to various country, state, and territory-based data protection and other compliance legislation. This makes it important to reduce the risks posed by improperly configured static IP addresses. And, given the virtually unlimited number of IP addresses now available with the IPv6 protocol, configuring unique IP addresses for every node on a network is possible. + +## OK but are there any compelling reasons for _me_ to adopt IPv6 addresses _now_? + +If our positive experience and outcomes, as well as the out-of-the-box nature of IPv6 have not yet persuaded you, these reasons might pique your interest. + +### Ubiquitous support for the IPv6 addresses protocol + +Consider how off-putting it is for users that some online services still do not offer otherwise ubiquitous identity protection mechanisms, such as sign-on Single Sign-on ([SSO](https://goauthentik.io/blog/2023-06-21-demystifying-security)) and Multi-factor Authentication (MFA). And, think of systems that do not allow you to switch off or otherwise configure pesky tracking settings that contradict data protection legislation. + +Increasingly and in the same way, professionals will all simply assume that our online platforms, network services, smart devices, and tools support the IPv6 protocol—or they might go elsewhere. While IPv6 does not support all apps, and migration can be risky, putting this off indefinitely could deter buyers from purchasing your software solution. + +### Man-in-the-Middle hack reduction + +Man-in-the-Middle (MITM) attacks rely on redirecting or otherwise changing the communication between two parties using Address Resolution Protocol (ARP) poisoning and other naming-type interceptions. This is how many malicious ecommerce hacks target consumers, via spoofed ecommerce, banking, password reset, or MFA links sent by email or SMS. Experiencing this attack is less likely when you deploy and correctly configure the IPv6 protocol, and connect to other networks and nodes on which it is similarly configured. For example, you should enable IPv6 routing, but also include DNS information and network security policies + +## Are there any challenges with IPv6 that I should be aware of before starting to make the switch? + +Great question! Let’s address each of the stumbling blocks in turn. + +### Long, multipart hexadecimal numbers + +Since they are very long, IPv6 addresses are less memorable than IPv4 ones. + +However, this has been alleviated using a built-in abbreviation standard. Here are the general principles: + +- Dropping any leadings zeros in a group +- Replacing a group of all zeros with a single zero +- Replacing continuous zeros with a double colon + +Though this might take a moment to memorize, familiarity comes through use. + +### Handling firewalls in IPv6 + +With IPv4, the deployment of Network Address Translation (NAT) enables system administrators in larger enterprises, with hundreds or thousands of connected and online devices, to provide a sense of security. Devices with private IP addresses are displayed to the public internet via NAT firewalls and routers that mask those private addresses behind a single, public one. + +- This helps to keep organizations’ IP addresses, devices, and networks hidden and secure. +- Hiding the private IP address discourages malicious attacks that would attempt to target an individual IP address. + +This lack of the need for a huge number of public IPv4 addresses offered by NAT has additional benefits for sysadmins: + +- Helping to manage the central problem of the limited number of available IPv4 addresses +- Allowing for flexibility in how you build and configure your network, without having to change IP addresses of internal nodes +- Limiting the admin burden of assigning and managing IP addresses, particularly if you manage a large number of devices across networks + +### Firewall filter rules + +It is difficult for some to move away from this secure and familiar setup. When it comes to IPv6 however, NAT is not deployed. This might prove to be a concern, if you are used to relying on NAT to provide a layer of security across your network. + +Instead, while a firewall is still one of the default protective mechanisms, system administrators must deploy filter rules in place of NAT. + +- In your router, you’ll be able to add both IPv4 and IPv6 values—with many device vendors now enabling it by default. +- Then, if you’ve also configured filtering rules, when packets encounter the router, they’ll meet any firewall filter rules. The filter rule will check if the packet header matches the rule’s filtering condition, including IP information. + - If it does, the Filter Action will be deployed + - If not, the packet simply proceeds to the next rule + +If you configure filtering on your router, don’t forget to also enable IPv6 there, on your other devices, and on your ISP. + +## Have you deployed IPv6 addresses to tackle address exhaustion? + +Yes, it is true that there is still a way to go before IPv6 is adopted worldwide, as we discussed above. However, as the pace of innovative technologies, solutions, and platforms continues, we predict this will simply become one more common instrument in our tool bag. + +We’d be very interested to know what you think of the IPv6 protocol, whether you’ve already converted and how you found the process. Do you have any ongoing challenges? + +Join the Authentik Security community on [Github](https://github.com/goauthentik/authentik) or [Discord](https://discord.com/invite/jg33eMhnj6), or send us an email at hello@goauthentik.io. We look forward to hearing from you. From 467a149c0632c12fb66897e2ce0130f7339b8bd7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 10 Nov 2023 12:39:55 +0100 Subject: [PATCH 02/24] web: bump the babel group in /web with 7 updates (#7517) Bumps the babel group in /web with 7 updates: | Package | From | To | | --- | --- | --- | | [@babel/core](https://github.com/babel/babel/tree/HEAD/packages/babel-core) | `7.23.2` | `7.23.3` | | [@babel/plugin-proposal-decorators](https://github.com/babel/babel/tree/HEAD/packages/babel-plugin-proposal-decorators) | `7.23.2` | `7.23.3` | | [@babel/plugin-transform-private-methods](https://github.com/babel/babel/tree/HEAD/packages/babel-plugin-transform-private-methods) | `7.22.5` | `7.23.3` | | [@babel/plugin-transform-private-property-in-object](https://github.com/babel/babel/tree/HEAD/packages/babel-plugin-transform-private-property-in-object) | `7.22.11` | `7.23.3` | | [@babel/plugin-transform-runtime](https://github.com/babel/babel/tree/HEAD/packages/babel-plugin-transform-runtime) | `7.23.2` | `7.23.3` | | [@babel/preset-env](https://github.com/babel/babel/tree/HEAD/packages/babel-preset-env) | `7.23.2` | `7.23.3` | | [@babel/preset-typescript](https://github.com/babel/babel/tree/HEAD/packages/babel-preset-typescript) | `7.23.2` | `7.23.3` | Updates `@babel/core` from 7.23.2 to 7.23.3 - [Release notes](https://github.com/babel/babel/releases) - [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md) - [Commits](https://github.com/babel/babel/commits/v7.23.3/packages/babel-core) Updates `@babel/plugin-proposal-decorators` from 7.23.2 to 7.23.3 - [Release notes](https://github.com/babel/babel/releases) - [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md) - [Commits](https://github.com/babel/babel/commits/v7.23.3/packages/babel-plugin-proposal-decorators) Updates `@babel/plugin-transform-private-methods` from 7.22.5 to 7.23.3 - [Release notes](https://github.com/babel/babel/releases) - [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md) - [Commits](https://github.com/babel/babel/commits/v7.23.3/packages/babel-plugin-transform-private-methods) Updates `@babel/plugin-transform-private-property-in-object` from 7.22.11 to 7.23.3 - [Release notes](https://github.com/babel/babel/releases) - [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md) - [Commits](https://github.com/babel/babel/commits/v7.23.3/packages/babel-plugin-transform-private-property-in-object) Updates `@babel/plugin-transform-runtime` from 7.23.2 to 7.23.3 - [Release notes](https://github.com/babel/babel/releases) - [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md) - [Commits](https://github.com/babel/babel/commits/v7.23.3/packages/babel-plugin-transform-runtime) Updates `@babel/preset-env` from 7.23.2 to 7.23.3 - [Release notes](https://github.com/babel/babel/releases) - [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md) - [Commits](https://github.com/babel/babel/commits/v7.23.3/packages/babel-preset-env) Updates `@babel/preset-typescript` from 7.23.2 to 7.23.3 - [Release notes](https://github.com/babel/babel/releases) - [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md) - [Commits](https://github.com/babel/babel/commits/v7.23.3/packages/babel-preset-typescript) --- updated-dependencies: - dependency-name: "@babel/core" dependency-type: direct:development update-type: version-update:semver-patch dependency-group: babel - dependency-name: "@babel/plugin-proposal-decorators" dependency-type: direct:development update-type: version-update:semver-patch dependency-group: babel - dependency-name: "@babel/plugin-transform-private-methods" dependency-type: direct:development update-type: version-update:semver-minor dependency-group: babel - dependency-name: "@babel/plugin-transform-private-property-in-object" dependency-type: direct:development update-type: version-update:semver-minor dependency-group: babel - dependency-name: "@babel/plugin-transform-runtime" dependency-type: direct:development update-type: version-update:semver-patch dependency-group: babel - dependency-name: "@babel/preset-env" dependency-type: direct:development update-type: version-update:semver-patch dependency-group: babel - dependency-name: "@babel/preset-typescript" dependency-type: direct:development update-type: version-update:semver-patch dependency-group: babel ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- web/package-lock.json | 619 ++++++++++++++++++++++-------------------- web/package.json | 14 +- 2 files changed, 335 insertions(+), 298 deletions(-) diff --git a/web/package-lock.json b/web/package-lock.json index 08c618258..aa671a23e 100644 --- a/web/package-lock.json +++ b/web/package-lock.json @@ -43,14 +43,14 @@ "yaml": "^2.3.4" }, "devDependencies": { - "@babel/core": "^7.23.2", + "@babel/core": "^7.23.3", "@babel/plugin-proposal-class-properties": "^7.18.6", - "@babel/plugin-proposal-decorators": "^7.23.2", - "@babel/plugin-transform-private-methods": "^7.22.5", - "@babel/plugin-transform-private-property-in-object": "^7.22.11", - "@babel/plugin-transform-runtime": "^7.23.2", - "@babel/preset-env": "^7.23.2", - "@babel/preset-typescript": "^7.23.2", + "@babel/plugin-proposal-decorators": "^7.23.3", + "@babel/plugin-transform-private-methods": "^7.23.3", + "@babel/plugin-transform-private-property-in-object": "^7.23.3", + "@babel/plugin-transform-runtime": "^7.23.3", + "@babel/preset-env": "^7.23.3", + "@babel/preset-typescript": "^7.23.3", "@hcaptcha/types": "^1.0.3", "@jackfranklin/rollup-plugin-markdown": "^0.4.0", "@jeysal/storybook-addon-css-user-preferences": "^0.2.0", @@ -162,30 +162,30 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.23.2", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.2.tgz", - "integrity": "sha512-0S9TQMmDHlqAZ2ITT95irXKfxN9bncq8ZCoJhun3nHL/lLUxd2NKBJYoNGWH7S0hz6fRQwWlAWn/ILM0C70KZQ==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.3.tgz", + "integrity": "sha512-BmR4bWbDIoFJmJ9z2cZ8Gmm2MXgEDgjdWgpKmKWUt54UGFJdlj31ECtbaDvCG/qVdG3AQ1SfpZEs01lUFbzLOQ==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { - "version": "7.23.2", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.2.tgz", - "integrity": "sha512-n7s51eWdaWZ3vGT2tD4T7J6eJs3QoBXydv7vkUM06Bf1cbVD2Kc2UrkzhiQwobfV7NwOnQXYL7UBJ5VPU+RGoQ==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.3.tgz", + "integrity": "sha512-Jg+msLuNuCJDyBvFv5+OKOUjWMZgd85bKjbICd3zWrKAo+bJ49HJufi7CQE0q0uR8NGyO6xkCACScNqyjHSZew==", "dev": true, "dependencies": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.22.13", - "@babel/generator": "^7.23.0", + "@babel/generator": "^7.23.3", "@babel/helper-compilation-targets": "^7.22.15", - "@babel/helper-module-transforms": "^7.23.0", + "@babel/helper-module-transforms": "^7.23.3", "@babel/helpers": "^7.23.2", - "@babel/parser": "^7.23.0", + "@babel/parser": "^7.23.3", "@babel/template": "^7.22.15", - "@babel/traverse": "^7.23.2", - "@babel/types": "^7.23.0", + "@babel/traverse": "^7.23.3", + "@babel/types": "^7.23.3", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -200,6 +200,27 @@ "url": "https://opencollective.com/babel" } }, + "node_modules/@babel/core/node_modules/@babel/traverse": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.3.tgz", + "integrity": "sha512-+K0yF1/9yR0oHdE0StHuEj3uTPzwwbrLGfNOndVJVV2TqA5+j3oljJUb4nmB954FLGjNem976+B+eDuLIjesiQ==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.22.13", + "@babel/generator": "^7.23.3", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-hoist-variables": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/parser": "^7.23.3", + "@babel/types": "^7.23.3", + "debug": "^4.1.0", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/core/node_modules/convert-source-map": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", @@ -207,12 +228,12 @@ "dev": true }, "node_modules/@babel/generator": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.0.tgz", - "integrity": "sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.3.tgz", + "integrity": "sha512-keeZWAV4LU3tW0qRi19HRpabC/ilM0HRBBzf9/k8FFiG4KVpiv0FIy4hHfLfFQZNhziCTPTmd59zoyv6DNISzg==", "dev": true, "dependencies": { - "@babel/types": "^7.23.0", + "@babel/types": "^7.23.3", "@jridgewell/gen-mapping": "^0.3.2", "@jridgewell/trace-mapping": "^0.3.17", "jsesc": "^2.5.1" @@ -376,9 +397,9 @@ } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.0.tgz", - "integrity": "sha512-WhDWw1tdrlT0gMgUJSlX0IQvoO1eN279zrAUbVB+KpV2c3Tylz8+GnKOLllCS6Z/iZQEyVYxhZVUdPTqs2YYPw==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz", + "integrity": "sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==", "dev": true, "dependencies": { "@babel/helper-environment-visitor": "^7.22.20", @@ -555,9 +576,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.0.tgz", - "integrity": "sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.3.tgz", + "integrity": "sha512-uVsWNvlVsIninV2prNz/3lHCb+5CJ+e+IUBfbjToAHODtfGYLfCFuY4AU7TskI+dAKk+njsPiBjq1gKTvZOBaw==", "dev": true, "bin": { "parser": "bin/babel-parser.js" @@ -567,9 +588,9 @@ } }, "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.22.15.tgz", - "integrity": "sha512-FB9iYlz7rURmRJyXRKEnalYPPdn87H5no108cyuQQyMwlpJ2SJtpIUBI27kdTin956pz+LPypkPVPUTlxOmrsg==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.23.3.tgz", + "integrity": "sha512-iRkKcCqb7iGnq9+3G6rZ+Ciz5VywC4XNRHe57lKM+jOeYAoR0lVqdeeDRfh0tQcTfw/+vBhHn926FmQhLtlFLQ==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" @@ -582,14 +603,14 @@ } }, "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.22.15.tgz", - "integrity": "sha512-Hyph9LseGvAeeXzikV88bczhsrLrIZqDPxO+sSmAunMPaGrBGhfMWzCPYTtiW9t+HzSE2wtV8e5cc5P6r1xMDQ==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.23.3.tgz", + "integrity": "sha512-WwlxbfMNdVEpQjZmK5mhm7oSwD3dS6eU+Iwsi4Knl9wAletWem7kaRsGOG+8UEbRyqxY4SS5zvtfXwX+jMxUwQ==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5", "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", - "@babel/plugin-transform-optional-chaining": "^7.22.15" + "@babel/plugin-transform-optional-chaining": "^7.23.3" }, "engines": { "node": ">=6.9.0" @@ -598,6 +619,22 @@ "@babel/core": "^7.13.0" } }, + "node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.23.3.tgz", + "integrity": "sha512-XaJak1qcityzrX0/IU5nKHb34VaibwP3saKqG6a/tppelgllOH13LUann4ZCIBcVOeE6H18K4Vx9QKkVww3z/w==", + "dev": true, + "dependencies": { + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, "node_modules/@babel/plugin-proposal-class-properties": { "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz", @@ -616,16 +653,16 @@ } }, "node_modules/@babel/plugin-proposal-decorators": { - "version": "7.23.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.23.2.tgz", - "integrity": "sha512-eR0gJQc830fJVGz37oKLvt9W9uUIQSAovUl0e9sJ3YeO09dlcoBVYD3CLrjCj4qHdXmfiyTyFt8yeQYSN5fxLg==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.23.3.tgz", + "integrity": "sha512-u8SwzOcP0DYSsa++nHd/9exlHb0NAlHCb890qtZZbSwPX2bFv8LBEztxwN7Xg/dS8oAFFidhrI9PBcLBJSkGRQ==", "dev": true, "dependencies": { "@babel/helper-create-class-features-plugin": "^7.22.15", "@babel/helper-plugin-utils": "^7.22.5", "@babel/helper-replace-supers": "^7.22.20", "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/plugin-syntax-decorators": "^7.22.10" + "@babel/plugin-syntax-decorators": "^7.23.3" }, "engines": { "node": ">=6.9.0" @@ -721,9 +758,9 @@ } }, "node_modules/@babel/plugin-syntax-decorators": { - "version": "7.22.10", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.22.10.tgz", - "integrity": "sha512-z1KTVemBjnz+kSEilAsI4lbkPOl5TvJH7YDSY1CTIzvLWJ+KHXp+mRe8VPmfnyvqOPqar1V2gid2PleKzRUstQ==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.23.3.tgz", + "integrity": "sha512-cf7Niq4/+/juY67E0PbgH0TDhLQ5J7zS8C/Q5FFx+DWyrRa9sUQdTXkjqKu8zGvuqr7vw1muKiukseihU+PJDA==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" @@ -775,9 +812,9 @@ } }, "node_modules/@babel/plugin-syntax-import-assertions": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.22.5.tgz", - "integrity": "sha512-rdV97N7KqsRzeNGoWUOK6yUsWarLjE5Su/Snk9IYPU9CwkWHs4t+rTGOvffTR8XGkJMTAdLfO0xVnXm8wugIJg==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.23.3.tgz", + "integrity": "sha512-lPgDSU+SJLK3xmFDTV2ZRQAiM7UuUjGidwBywFavObCiZc1BeAAcMtHJKUya92hPHO+at63JJPLygilZard8jw==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" @@ -790,9 +827,9 @@ } }, "node_modules/@babel/plugin-syntax-import-attributes": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.22.5.tgz", - "integrity": "sha512-KwvoWDeNKPETmozyFE0P2rOLqh39EoQHNjqizrI5B8Vt0ZNS7M56s7dAiAqbYfiAYOuIzIh96z3iR2ktgu3tEg==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.23.3.tgz", + "integrity": "sha512-pawnE0P9g10xgoP7yKr6CK63K2FMsTE+FZidZO/1PwRdzmAPVs+HS1mAURUsgaoxammTJvULUdIkEK0gOcU2tA==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" @@ -829,9 +866,9 @@ } }, "node_modules/@babel/plugin-syntax-jsx": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.22.5.tgz", - "integrity": "sha512-gvyP4hZrgrs/wWMaocvxZ44Hw0b3W8Pe+cMxc8V1ULQ07oh8VNbIRaoD1LRZVTvD+0nieDKjfgKg89sD7rrKrg==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.23.3.tgz", + "integrity": "sha512-EB2MELswq55OHUoRZLGg/zC7QWUKfNLpE57m/S2yr1uEneIgsTgrSzXP3NXEsMkVn76OlaVVnzN+ugObuYGwhg==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" @@ -946,9 +983,9 @@ } }, "node_modules/@babel/plugin-syntax-typescript": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.22.5.tgz", - "integrity": "sha512-1mS2o03i7t1c6VzH6fdQ3OA8tcEIxwG18zIPRp+UY1Ihv6W+XZzBCVxExF9upussPXJ0xE9XRHwMoNs1ep/nRQ==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.23.3.tgz", + "integrity": "sha512-9EiNjVJOMwCO+43TqoTrgQ8jMwcAd0sWyXi9RPfIsLTj4R2MADDDQXELhffaUx/uJv2AYcxBgPwH6j4TIA4ytQ==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" @@ -977,9 +1014,9 @@ } }, "node_modules/@babel/plugin-transform-arrow-functions": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.22.5.tgz", - "integrity": "sha512-26lTNXoVRdAnsaDXPpvCNUq+OVWEVC6bx7Vvz9rC53F2bagUWW4u4ii2+h8Fejfh7RYqPxn+libeFBBck9muEw==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.23.3.tgz", + "integrity": "sha512-NzQcQrzaQPkaEwoTm4Mhyl8jI1huEL/WWIEvudjTCMJ9aBZNpsJbMASx7EQECtQQPS/DcnFpo0FIh3LvEO9cxQ==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" @@ -992,9 +1029,9 @@ } }, "node_modules/@babel/plugin-transform-async-generator-functions": { - "version": "7.23.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.23.2.tgz", - "integrity": "sha512-BBYVGxbDVHfoeXbOwcagAkOQAm9NxoTdMGfTqghu1GrvadSaw6iW3Je6IcL5PNOw8VwjxqBECXy50/iCQSY/lQ==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.23.3.tgz", + "integrity": "sha512-59GsVNavGxAXCDDbakWSMJhajASb4kBCqDjqJsv+p5nKdbz7istmZ3HrX3L2LuiI80+zsOADCvooqQH3qGCucQ==", "dev": true, "dependencies": { "@babel/helper-environment-visitor": "^7.22.20", @@ -1010,14 +1047,14 @@ } }, "node_modules/@babel/plugin-transform-async-to-generator": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.22.5.tgz", - "integrity": "sha512-b1A8D8ZzE/VhNDoV1MSJTnpKkCG5bJo+19R4o4oy03zM7ws8yEMK755j61Dc3EyvdysbqH5BOOTquJ7ZX9C6vQ==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.23.3.tgz", + "integrity": "sha512-A7LFsKi4U4fomjqXJlZg/u0ft/n8/7n7lpffUP/ZULx/DtV9SGlNKZolHH6PE8Xl1ngCc0M11OaeZptXVkfKSw==", "dev": true, "dependencies": { - "@babel/helper-module-imports": "^7.22.5", + "@babel/helper-module-imports": "^7.22.15", "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-remap-async-to-generator": "^7.22.5" + "@babel/helper-remap-async-to-generator": "^7.22.20" }, "engines": { "node": ">=6.9.0" @@ -1027,9 +1064,9 @@ } }, "node_modules/@babel/plugin-transform-block-scoped-functions": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.22.5.tgz", - "integrity": "sha512-tdXZ2UdknEKQWKJP1KMNmuF5Lx3MymtMN/pvA+p/VEkhK8jVcQ1fzSy8KM9qRYhAf2/lV33hoMPKI/xaI9sADA==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.23.3.tgz", + "integrity": "sha512-vI+0sIaPIO6CNuM9Kk5VmXcMVRiOpDh7w2zZt9GXzmE/9KD70CUEVhvPR/etAeNK/FAEkhxQtXOzVF3EuRL41A==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" @@ -1042,9 +1079,9 @@ } }, "node_modules/@babel/plugin-transform-block-scoping": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.23.0.tgz", - "integrity": "sha512-cOsrbmIOXmf+5YbL99/S49Y3j46k/T16b9ml8bm9lP6N9US5iQ2yBK7gpui1pg0V/WMcXdkfKbTb7HXq9u+v4g==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.23.3.tgz", + "integrity": "sha512-QPZxHrThbQia7UdvfpaRRlq/J9ciz1J4go0k+lPBXbgaNeY7IQrBj/9ceWjvMMI07/ZBzHl/F0R/2K0qH7jCVw==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" @@ -1057,12 +1094,12 @@ } }, "node_modules/@babel/plugin-transform-class-properties": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.22.5.tgz", - "integrity": "sha512-nDkQ0NfkOhPTq8YCLiWNxp1+f9fCobEjCb0n8WdbNUBc4IB5V7P1QnX9IjpSoquKrXF5SKojHleVNs2vGeHCHQ==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.23.3.tgz", + "integrity": "sha512-uM+AN8yCIjDPccsKGlw271xjJtGii+xQIF/uMPS8H15L12jZTsLfF4o5vNO7d/oUguOyfdikHGc/yi9ge4SGIg==", "dev": true, "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.22.5", + "@babel/helper-create-class-features-plugin": "^7.22.15", "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { @@ -1073,12 +1110,12 @@ } }, "node_modules/@babel/plugin-transform-class-static-block": { - "version": "7.22.11", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.22.11.tgz", - "integrity": "sha512-GMM8gGmqI7guS/llMFk1bJDkKfn3v3C4KHK9Yg1ey5qcHcOlKb0QvcMrgzvxo+T03/4szNh5lghY+fEC98Kq9g==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.23.3.tgz", + "integrity": "sha512-PENDVxdr7ZxKPyi5Ffc0LjXdnJyrJxyqF5T5YjlVg4a0VFfQHW0r8iAtRiDXkfHlu1wwcvdtnndGYIeJLSuRMQ==", "dev": true, "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.22.11", + "@babel/helper-create-class-features-plugin": "^7.22.15", "@babel/helper-plugin-utils": "^7.22.5", "@babel/plugin-syntax-class-static-block": "^7.14.5" }, @@ -1090,18 +1127,18 @@ } }, "node_modules/@babel/plugin-transform-classes": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.22.15.tgz", - "integrity": "sha512-VbbC3PGjBdE0wAWDdHM9G8Gm977pnYI0XpqMd6LrKISj8/DJXEsWqgRuTYaNE9Bv0JGhTZUzHDlMk18IpOuoqw==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.23.3.tgz", + "integrity": "sha512-FGEQmugvAEu2QtgtU0uTASXevfLMFfBeVCIIdcQhn/uBQsMTjBajdnAtanQlOcuihWh10PZ7+HWvc7NtBwP74w==", "dev": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.22.5", "@babel/helper-compilation-targets": "^7.22.15", - "@babel/helper-environment-visitor": "^7.22.5", - "@babel/helper-function-name": "^7.22.5", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", "@babel/helper-optimise-call-expression": "^7.22.5", "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-replace-supers": "^7.22.9", + "@babel/helper-replace-supers": "^7.22.20", "@babel/helper-split-export-declaration": "^7.22.6", "globals": "^11.1.0" }, @@ -1113,13 +1150,13 @@ } }, "node_modules/@babel/plugin-transform-computed-properties": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.22.5.tgz", - "integrity": "sha512-4GHWBgRf0krxPX+AaPtgBAlTgTeZmqDynokHOX7aqqAB4tHs3U2Y02zH6ETFdLZGcg9UQSD1WCmkVrE9ErHeOg==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.23.3.tgz", + "integrity": "sha512-dTj83UVTLw/+nbiHqQSFdwO9CbTtwq1DsDqm3CUEtDrZNET5rT5E6bIdTlOftDTDLMYxvxHNEYO4B9SLl8SLZw==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5", - "@babel/template": "^7.22.5" + "@babel/template": "^7.22.15" }, "engines": { "node": ">=6.9.0" @@ -1129,9 +1166,9 @@ } }, "node_modules/@babel/plugin-transform-destructuring": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.23.0.tgz", - "integrity": "sha512-vaMdgNXFkYrB+8lbgniSYWHsgqK5gjaMNcc84bMIOMRLH0L9AqYq3hwMdvnyqj1OPqea8UtjPEuS/DCenah1wg==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.23.3.tgz", + "integrity": "sha512-n225npDqjDIr967cMScVKHXJs7rout1q+tt50inyBCPkyZ8KxeI6d+GIbSBTT/w/9WdlWDOej3V9HE5Lgk57gw==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" @@ -1144,12 +1181,12 @@ } }, "node_modules/@babel/plugin-transform-dotall-regex": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.22.5.tgz", - "integrity": "sha512-5/Yk9QxCQCl+sOIB1WelKnVRxTJDSAIxtJLL2/pqL14ZVlbH0fUQUZa/T5/UnQtBNgghR7mfB8ERBKyKPCi7Vw==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.23.3.tgz", + "integrity": "sha512-vgnFYDHAKzFaTVp+mneDsIEbnJ2Np/9ng9iviHw3P/KVcgONxpNULEW/51Z/BaFojG2GI2GwwXck5uV1+1NOYQ==", "dev": true, "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.22.5", + "@babel/helper-create-regexp-features-plugin": "^7.22.15", "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { @@ -1160,9 +1197,9 @@ } }, "node_modules/@babel/plugin-transform-duplicate-keys": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.22.5.tgz", - "integrity": "sha512-dEnYD+9BBgld5VBXHnF/DbYGp3fqGMsyxKbtD1mDyIA7AkTSpKXFhCVuj/oQVOoALfBs77DudA0BE4d5mcpmqw==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.23.3.tgz", + "integrity": "sha512-RrqQ+BQmU3Oyav3J+7/myfvRCq7Tbz+kKLLshUmMwNlDHExbGL7ARhajvoBJEvc+fCguPPu887N+3RRXBVKZUA==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" @@ -1175,9 +1212,9 @@ } }, "node_modules/@babel/plugin-transform-dynamic-import": { - "version": "7.22.11", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.22.11.tgz", - "integrity": "sha512-g/21plo58sfteWjaO0ZNVb+uEOkJNjAaHhbejrnBmu011l/eNDScmkbjCC3l4FKb10ViaGU4aOkFznSu2zRHgA==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.23.3.tgz", + "integrity": "sha512-vTG+cTGxPFou12Rj7ll+eD5yWeNl5/8xvQvF08y5Gv3v4mZQoyFf8/n9zg4q5vvCWt5jmgymfzMAldO7orBn7A==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5", @@ -1191,12 +1228,12 @@ } }, "node_modules/@babel/plugin-transform-exponentiation-operator": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.22.5.tgz", - "integrity": "sha512-vIpJFNM/FjZ4rh1myqIya9jXwrwwgFRHPjT3DkUA9ZLHuzox8jiXkOLvwm1H+PQIP3CqfC++WPKeuDi0Sjdj1g==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.23.3.tgz", + "integrity": "sha512-5fhCsl1odX96u7ILKHBj4/Y8vipoqwsJMh4csSA8qFfxrZDEA4Ssku2DyNvMJSmZNOEBT750LfFPbtrnTP90BQ==", "dev": true, "dependencies": { - "@babel/helper-builder-binary-assignment-operator-visitor": "^7.22.5", + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.22.15", "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { @@ -1207,9 +1244,9 @@ } }, "node_modules/@babel/plugin-transform-export-namespace-from": { - "version": "7.22.11", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.22.11.tgz", - "integrity": "sha512-xa7aad7q7OiT8oNZ1mU7NrISjlSkVdMbNxn9IuLZyL9AJEhs1Apba3I+u5riX1dIkdptP5EKDG5XDPByWxtehw==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.23.3.tgz", + "integrity": "sha512-yCLhW34wpJWRdTxxWtFZASJisihrfyMOTOQexhVzA78jlU+dH7Dw+zQgcPepQ5F3C6bAIiblZZ+qBggJdHiBAg==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5", @@ -1239,9 +1276,9 @@ } }, "node_modules/@babel/plugin-transform-for-of": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.22.15.tgz", - "integrity": "sha512-me6VGeHsx30+xh9fbDLLPi0J1HzmeIIyenoOQHuw2D4m2SAU3NrspX5XxJLBpqn5yrLzrlw2Iy3RA//Bx27iOA==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.23.3.tgz", + "integrity": "sha512-X8jSm8X1CMwxmK878qsUGJRmbysKNbdpTv/O1/v0LuY/ZkZrng5WYiekYSdg9m09OTmDDUWeEDsTE+17WYbAZw==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" @@ -1254,13 +1291,13 @@ } }, "node_modules/@babel/plugin-transform-function-name": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.22.5.tgz", - "integrity": "sha512-UIzQNMS0p0HHiQm3oelztj+ECwFnj+ZRV4KnguvlsD2of1whUeM6o7wGNj6oLwcDoAXQ8gEqfgC24D+VdIcevg==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.23.3.tgz", + "integrity": "sha512-I1QXp1LxIvt8yLaib49dRW5Okt7Q4oaxao6tFVKS/anCdEOMtYwWVKoiOA1p34GOWIZjUK0E+zCp7+l1pfQyiw==", "dev": true, "dependencies": { - "@babel/helper-compilation-targets": "^7.22.5", - "@babel/helper-function-name": "^7.22.5", + "@babel/helper-compilation-targets": "^7.22.15", + "@babel/helper-function-name": "^7.23.0", "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { @@ -1271,9 +1308,9 @@ } }, "node_modules/@babel/plugin-transform-json-strings": { - "version": "7.22.11", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.22.11.tgz", - "integrity": "sha512-CxT5tCqpA9/jXFlme9xIBCc5RPtdDq3JpkkhgHQqtDdiTnTI0jtZ0QzXhr5DILeYifDPp2wvY2ad+7+hLMW5Pw==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.23.3.tgz", + "integrity": "sha512-H9Ej2OiISIZowZHaBwF0tsJOih1PftXJtE8EWqlEIwpc7LMTGq0rPOrywKLQ4nefzx8/HMR0D3JGXoMHYvhi0A==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5", @@ -1287,9 +1324,9 @@ } }, "node_modules/@babel/plugin-transform-literals": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.22.5.tgz", - "integrity": "sha512-fTLj4D79M+mepcw3dgFBTIDYpbcB9Sm0bpm4ppXPaO+U+PKFFyV9MGRvS0gvGw62sd10kT5lRMKXAADb9pWy8g==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.23.3.tgz", + "integrity": "sha512-wZ0PIXRxnwZvl9AYpqNUxpZ5BiTGrYt7kueGQ+N5FiQ7RCOD4cm8iShd6S6ggfVIWaJf2EMk8eRzAh52RfP4rQ==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" @@ -1302,9 +1339,9 @@ } }, "node_modules/@babel/plugin-transform-logical-assignment-operators": { - "version": "7.22.11", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.22.11.tgz", - "integrity": "sha512-qQwRTP4+6xFCDV5k7gZBF3C31K34ut0tbEcTKxlX/0KXxm9GLcO14p570aWxFvVzx6QAfPgq7gaeIHXJC8LswQ==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.23.3.tgz", + "integrity": "sha512-+pD5ZbxofyOygEp+zZAfujY2ShNCXRpDRIPOiBmTO693hhyOEteZgl876Xs9SAHPQpcV0vz8LvA/T+w8AzyX8A==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5", @@ -1318,9 +1355,9 @@ } }, "node_modules/@babel/plugin-transform-member-expression-literals": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.22.5.tgz", - "integrity": "sha512-RZEdkNtzzYCFl9SE9ATaUMTj2hqMb4StarOJLrZRbqqU4HSBE7UlBw9WBWQiDzrJZJdUWiMTVDI6Gv/8DPvfew==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.23.3.tgz", + "integrity": "sha512-sC3LdDBDi5x96LA+Ytekz2ZPk8i/Ck+DEuDbRAll5rknJ5XRTSaPKEYwomLcs1AA8wg9b3KjIQRsnApj+q51Ag==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" @@ -1333,12 +1370,12 @@ } }, "node_modules/@babel/plugin-transform-modules-amd": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.23.0.tgz", - "integrity": "sha512-xWT5gefv2HGSm4QHtgc1sYPbseOyf+FFDo2JbpE25GWl5BqTGO9IMwTYJRoIdjsF85GE+VegHxSCUt5EvoYTAw==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.23.3.tgz", + "integrity": "sha512-vJYQGxeKM4t8hYCKVBlZX/gtIY2I7mRGFNcm85sgXGMTBcoV3QdVtdpbcWEbzbfUIUZKwvgFT82mRvaQIebZzw==", "dev": true, "dependencies": { - "@babel/helper-module-transforms": "^7.23.0", + "@babel/helper-module-transforms": "^7.23.3", "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { @@ -1349,12 +1386,12 @@ } }, "node_modules/@babel/plugin-transform-modules-commonjs": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.23.0.tgz", - "integrity": "sha512-32Xzss14/UVc7k9g775yMIvkVK8xwKE0DPdP5JTapr3+Z9w4tzeOuLNY6BXDQR6BdnzIlXnCGAzsk/ICHBLVWQ==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.23.3.tgz", + "integrity": "sha512-aVS0F65LKsdNOtcz6FRCpE4OgsP2OFnW46qNxNIX9h3wuzaNcSQsJysuMwqSibC98HPrf2vCgtxKNwS0DAlgcA==", "dev": true, "dependencies": { - "@babel/helper-module-transforms": "^7.23.0", + "@babel/helper-module-transforms": "^7.23.3", "@babel/helper-plugin-utils": "^7.22.5", "@babel/helper-simple-access": "^7.22.5" }, @@ -1366,13 +1403,13 @@ } }, "node_modules/@babel/plugin-transform-modules-systemjs": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.23.0.tgz", - "integrity": "sha512-qBej6ctXZD2f+DhlOC9yO47yEYgUh5CZNz/aBoH4j/3NOlRfJXJbY7xDQCqQVf9KbrqGzIWER1f23doHGrIHFg==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.23.3.tgz", + "integrity": "sha512-ZxyKGTkF9xT9YJuKQRo19ewf3pXpopuYQd8cDXqNzc3mUNbOME0RKMoZxviQk74hwzfQsEe66dE92MaZbdHKNQ==", "dev": true, "dependencies": { "@babel/helper-hoist-variables": "^7.22.5", - "@babel/helper-module-transforms": "^7.23.0", + "@babel/helper-module-transforms": "^7.23.3", "@babel/helper-plugin-utils": "^7.22.5", "@babel/helper-validator-identifier": "^7.22.20" }, @@ -1384,12 +1421,12 @@ } }, "node_modules/@babel/plugin-transform-modules-umd": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.22.5.tgz", - "integrity": "sha512-+S6kzefN/E1vkSsKx8kmQuqeQsvCKCd1fraCM7zXm4SFoggI099Tr4G8U81+5gtMdUeMQ4ipdQffbKLX0/7dBQ==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.23.3.tgz", + "integrity": "sha512-zHsy9iXX2nIsCBFPud3jKn1IRPWg3Ing1qOZgeKV39m1ZgIdpJqvlWVeiHBZC6ITRG0MfskhYe9cLgntfSFPIg==", "dev": true, "dependencies": { - "@babel/helper-module-transforms": "^7.22.5", + "@babel/helper-module-transforms": "^7.23.3", "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { @@ -1416,9 +1453,9 @@ } }, "node_modules/@babel/plugin-transform-new-target": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.22.5.tgz", - "integrity": "sha512-AsF7K0Fx/cNKVyk3a+DW0JLo+Ua598/NxMRvxDnkpCIGFh43+h/v2xyhRUYf6oD8gE4QtL83C7zZVghMjHd+iw==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.23.3.tgz", + "integrity": "sha512-YJ3xKqtJMAT5/TIZnpAR3I+K+WaDowYbN3xyxI8zxx/Gsypwf9B9h0VB+1Nh6ACAAPRS5NSRje0uVv5i79HYGQ==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" @@ -1431,9 +1468,9 @@ } }, "node_modules/@babel/plugin-transform-nullish-coalescing-operator": { - "version": "7.22.11", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.22.11.tgz", - "integrity": "sha512-YZWOw4HxXrotb5xsjMJUDlLgcDXSfO9eCmdl1bgW4+/lAGdkjaEvOnQ4p5WKKdUgSzO39dgPl0pTnfxm0OAXcg==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.23.3.tgz", + "integrity": "sha512-xzg24Lnld4DYIdysyf07zJ1P+iIfJpxtVFOzX4g+bsJ3Ng5Le7rXx9KwqKzuyaUeRnt+I1EICwQITqc0E2PmpA==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5", @@ -1447,9 +1484,9 @@ } }, "node_modules/@babel/plugin-transform-numeric-separator": { - "version": "7.22.11", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.22.11.tgz", - "integrity": "sha512-3dzU4QGPsILdJbASKhF/V2TVP+gJya1PsueQCxIPCEcerqF21oEcrob4mzjsp2Py/1nLfF5m+xYNMDpmA8vffg==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.23.3.tgz", + "integrity": "sha512-s9GO7fIBi/BLsZ0v3Rftr6Oe4t0ctJ8h4CCXfPoEJwmvAPMyNrfkOOJzm6b9PX9YXcCJWWQd/sBF/N26eBiMVw==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5", @@ -1463,16 +1500,16 @@ } }, "node_modules/@babel/plugin-transform-object-rest-spread": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.22.15.tgz", - "integrity": "sha512-fEB+I1+gAmfAyxZcX1+ZUwLeAuuf8VIg67CTznZE0MqVFumWkh8xWtn58I4dxdVf080wn7gzWoF8vndOViJe9Q==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.23.3.tgz", + "integrity": "sha512-VxHt0ANkDmu8TANdE9Kc0rndo/ccsmfe2Cx2y5sI4hu3AukHQ5wAu4cM7j3ba8B9548ijVyclBU+nuDQftZsog==", "dev": true, "dependencies": { - "@babel/compat-data": "^7.22.9", + "@babel/compat-data": "^7.23.3", "@babel/helper-compilation-targets": "^7.22.15", "@babel/helper-plugin-utils": "^7.22.5", "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-transform-parameters": "^7.22.15" + "@babel/plugin-transform-parameters": "^7.23.3" }, "engines": { "node": ">=6.9.0" @@ -1482,13 +1519,13 @@ } }, "node_modules/@babel/plugin-transform-object-super": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.22.5.tgz", - "integrity": "sha512-klXqyaT9trSjIUrcsYIfETAzmOEZL3cBYqOYLJxBHfMFFggmXOv+NYSX/Jbs9mzMVESw/WycLFPRx8ba/b2Ipw==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.23.3.tgz", + "integrity": "sha512-BwQ8q0x2JG+3lxCVFohg+KbQM7plfpBwThdW9A6TMtWwLsbDA01Ek2Zb/AgDN39BiZsExm4qrXxjk+P1/fzGrA==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-replace-supers": "^7.22.5" + "@babel/helper-replace-supers": "^7.22.20" }, "engines": { "node": ">=6.9.0" @@ -1498,9 +1535,9 @@ } }, "node_modules/@babel/plugin-transform-optional-catch-binding": { - "version": "7.22.11", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.22.11.tgz", - "integrity": "sha512-rli0WxesXUeCJnMYhzAglEjLWVDF6ahb45HuprcmQuLidBJFWjNnOzssk2kuc6e33FlLaiZhG/kUIzUMWdBKaQ==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.23.3.tgz", + "integrity": "sha512-LxYSb0iLjUamfm7f1D7GpiS4j0UAC8AOiehnsGAP8BEsIX8EOi3qV6bbctw8M7ZvLtcoZfZX5Z7rN9PlWk0m5A==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5", @@ -1514,9 +1551,9 @@ } }, "node_modules/@babel/plugin-transform-optional-chaining": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.23.0.tgz", - "integrity": "sha512-sBBGXbLJjxTzLBF5rFWaikMnOGOk/BmK6vVByIdEggZ7Vn6CvWXZyRkkLFK6WE0IF8jSliyOkUN6SScFgzCM0g==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.23.3.tgz", + "integrity": "sha512-zvL8vIfIUgMccIAK1lxjvNv572JHFJIKb4MWBz5OGdBQA0fB0Xluix5rmOby48exiJc987neOmP/m9Fnpkz3Tg==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5", @@ -1531,9 +1568,9 @@ } }, "node_modules/@babel/plugin-transform-parameters": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.22.15.tgz", - "integrity": "sha512-hjk7qKIqhyzhhUvRT683TYQOFa/4cQKwQy7ALvTpODswN40MljzNDa0YldevS6tGbxwaEKVn502JmY0dP7qEtQ==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.23.3.tgz", + "integrity": "sha512-09lMt6UsUb3/34BbECKVbVwrT9bO6lILWln237z7sLaWnMsTi7Yc9fhX5DLpkJzAGfaReXI22wP41SZmnAA3Vw==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" @@ -1546,12 +1583,12 @@ } }, "node_modules/@babel/plugin-transform-private-methods": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.22.5.tgz", - "integrity": "sha512-PPjh4gyrQnGe97JTalgRGMuU4icsZFnWkzicB/fUtzlKUqvsWBKEpPPfr5a2JiyirZkHxnAqkQMO5Z5B2kK3fA==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.23.3.tgz", + "integrity": "sha512-UzqRcRtWsDMTLrRWFvUBDwmw06tCQH9Rl1uAjfh6ijMSmGYQ+fpdB+cnqRC8EMh5tuuxSv0/TejGL+7vyj+50g==", "dev": true, "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.22.5", + "@babel/helper-create-class-features-plugin": "^7.22.15", "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { @@ -1562,13 +1599,13 @@ } }, "node_modules/@babel/plugin-transform-private-property-in-object": { - "version": "7.22.11", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.22.11.tgz", - "integrity": "sha512-sSCbqZDBKHetvjSwpyWzhuHkmW5RummxJBVbYLkGkaiTOWGxml7SXt0iWa03bzxFIx7wOj3g/ILRd0RcJKBeSQ==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.23.3.tgz", + "integrity": "sha512-a5m2oLNFyje2e/rGKjVfAELTVI5mbA0FeZpBnkOWWV7eSmKQ+T/XW0Vf+29ScLzSxX+rnsarvU0oie/4m6hkxA==", "dev": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.22.5", - "@babel/helper-create-class-features-plugin": "^7.22.11", + "@babel/helper-create-class-features-plugin": "^7.22.15", "@babel/helper-plugin-utils": "^7.22.5", "@babel/plugin-syntax-private-property-in-object": "^7.14.5" }, @@ -1580,9 +1617,9 @@ } }, "node_modules/@babel/plugin-transform-property-literals": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.22.5.tgz", - "integrity": "sha512-TiOArgddK3mK/x1Qwf5hay2pxI6wCZnvQqrFSqbtg1GLl2JcNMitVH/YnqjP+M31pLUeTfzY1HAXFDnUBV30rQ==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.23.3.tgz", + "integrity": "sha512-jR3Jn3y7cZp4oEWPFAlRsSWjxKe4PZILGBSd4nis1TsC5qeSpb+nrtihJuDhNI7QHiVbUaiXa0X2RZY3/TI6Nw==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" @@ -1595,9 +1632,9 @@ } }, "node_modules/@babel/plugin-transform-regenerator": { - "version": "7.22.10", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.22.10.tgz", - "integrity": "sha512-F28b1mDt8KcT5bUyJc/U9nwzw6cV+UmTeRlXYIl2TNqMMJif0Jeey9/RQ3C4NOd2zp0/TRsDns9ttj2L523rsw==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.23.3.tgz", + "integrity": "sha512-KP+75h0KghBMcVpuKisx3XTu9Ncut8Q8TuvGO4IhY+9D5DFEckQefOuIsB/gQ2tG71lCke4NMrtIPS8pOj18BQ==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5", @@ -1611,9 +1648,9 @@ } }, "node_modules/@babel/plugin-transform-reserved-words": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.22.5.tgz", - "integrity": "sha512-DTtGKFRQUDm8svigJzZHzb/2xatPc6TzNvAIJ5GqOKDsGFYgAskjRulbR/vGsPKq3OPqtexnz327qYpP57RFyA==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.23.3.tgz", + "integrity": "sha512-QnNTazY54YqgGxwIexMZva9gqbPa15t/x9VS+0fsEFWplwVpXYZivtgl43Z1vMpc1bdPP2PP8siFeVcnFvA3Cg==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" @@ -1626,9 +1663,9 @@ } }, "node_modules/@babel/plugin-transform-runtime": { - "version": "7.23.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.23.2.tgz", - "integrity": "sha512-XOntj6icgzMS58jPVtQpiuF6ZFWxQiJavISGx5KGjRj+3gqZr8+N6Kx+N9BApWzgS+DOjIZfXXj0ZesenOWDyA==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.23.3.tgz", + "integrity": "sha512-XcQ3X58CKBdBnnZpPaQjgVMePsXtSZzHoku70q9tUAQp02ggPQNM04BF3RvlW1GSM/McbSOQAzEK4MXbS7/JFg==", "dev": true, "dependencies": { "@babel/helper-module-imports": "^7.22.15", @@ -1646,9 +1683,9 @@ } }, "node_modules/@babel/plugin-transform-shorthand-properties": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.22.5.tgz", - "integrity": "sha512-vM4fq9IXHscXVKzDv5itkO1X52SmdFBFcMIBZ2FRn2nqVYqw6dBexUgMvAjHW+KXpPPViD/Yo3GrDEBaRC0QYA==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.23.3.tgz", + "integrity": "sha512-ED2fgqZLmexWiN+YNFX26fx4gh5qHDhn1O2gvEhreLW2iI63Sqm4llRLCXALKrCnbN4Jy0VcMQZl/SAzqug/jg==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" @@ -1661,9 +1698,9 @@ } }, "node_modules/@babel/plugin-transform-spread": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.22.5.tgz", - "integrity": "sha512-5ZzDQIGyvN4w8+dMmpohL6MBo+l2G7tfC/O2Dg7/hjpgeWvUx8FzfeOKxGog9IimPa4YekaQ9PlDqTLOljkcxg==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.23.3.tgz", + "integrity": "sha512-VvfVYlrlBVu+77xVTOAoxQ6mZbnIq5FM0aGBSFEcIh03qHf+zNqA4DC/3XMUozTg7bZV3e3mZQ0i13VB6v5yUg==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5", @@ -1677,9 +1714,9 @@ } }, "node_modules/@babel/plugin-transform-sticky-regex": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.22.5.tgz", - "integrity": "sha512-zf7LuNpHG0iEeiyCNwX4j3gDg1jgt1k3ZdXBKbZSoA3BbGQGvMiSvfbZRR3Dr3aeJe3ooWFZxOOG3IRStYp2Bw==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.23.3.tgz", + "integrity": "sha512-HZOyN9g+rtvnOU3Yh7kSxXrKbzgrm5X4GncPY1QOquu7epga5MxKHVpYu2hvQnry/H+JjckSYRb93iNfsioAGg==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" @@ -1692,9 +1729,9 @@ } }, "node_modules/@babel/plugin-transform-template-literals": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.22.5.tgz", - "integrity": "sha512-5ciOehRNf+EyUeewo8NkbQiUs4d6ZxiHo6BcBcnFlgiJfu16q0bQUw9Jvo0b0gBKFG1SMhDSjeKXSYuJLeFSMA==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.23.3.tgz", + "integrity": "sha512-Flok06AYNp7GV2oJPZZcP9vZdszev6vPBkHLwxwSpaIqx75wn6mUd3UFWsSsA0l8nXAKkyCmL/sR02m8RYGeHg==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" @@ -1707,9 +1744,9 @@ } }, "node_modules/@babel/plugin-transform-typeof-symbol": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.22.5.tgz", - "integrity": "sha512-bYkI5lMzL4kPii4HHEEChkD0rkc+nvnlR6+o/qdqR6zrm0Sv/nodmyLhlq2DO0YKLUNd2VePmPRjJXSBh9OIdA==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.23.3.tgz", + "integrity": "sha512-4t15ViVnaFdrPC74be1gXBSMzXk3B4Us9lP7uLRQHTFpV5Dvt33pn+2MyyNxmN3VTTm3oTrZVMUmuw3oBnQ2oQ==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" @@ -1722,15 +1759,15 @@ } }, "node_modules/@babel/plugin-transform-typescript": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.22.15.tgz", - "integrity": "sha512-1uirS0TnijxvQLnlv5wQBwOX3E1wCFX7ITv+9pBV2wKEk4K+M5tqDaoNXnTH8tjEIYHLO98MwiTWO04Ggz4XuA==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.23.3.tgz", + "integrity": "sha512-ogV0yWnq38CFwH20l2Afz0dfKuZBx9o/Y2Rmh5vuSS0YD1hswgEgTfyTzuSrT2q9btmHRSqYoSfwFUVaC1M1Jw==", "dev": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.22.5", "@babel/helper-create-class-features-plugin": "^7.22.15", "@babel/helper-plugin-utils": "^7.22.5", - "@babel/plugin-syntax-typescript": "^7.22.5" + "@babel/plugin-syntax-typescript": "^7.23.3" }, "engines": { "node": ">=6.9.0" @@ -1740,9 +1777,9 @@ } }, "node_modules/@babel/plugin-transform-unicode-escapes": { - "version": "7.22.10", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.22.10.tgz", - "integrity": "sha512-lRfaRKGZCBqDlRU3UIFovdp9c9mEvlylmpod0/OatICsSfuQ9YFthRo1tpTkGsklEefZdqlEFdY4A2dwTb6ohg==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.23.3.tgz", + "integrity": "sha512-OMCUx/bU6ChE3r4+ZdylEqAjaQgHAgipgW8nsCfu5pGqDcFytVd91AwRvUJSBZDz0exPGgnjoqhgRYLRjFZc9Q==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" @@ -1755,12 +1792,12 @@ } }, "node_modules/@babel/plugin-transform-unicode-property-regex": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.22.5.tgz", - "integrity": "sha512-HCCIb+CbJIAE6sXn5CjFQXMwkCClcOfPCzTlilJ8cUatfzwHlWQkbtV0zD338u9dZskwvuOYTuuaMaA8J5EI5A==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.23.3.tgz", + "integrity": "sha512-KcLIm+pDZkWZQAFJ9pdfmh89EwVfmNovFBcXko8szpBeF8z68kWIPeKlmSOkT9BXJxs2C0uk+5LxoxIv62MROA==", "dev": true, "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.22.5", + "@babel/helper-create-regexp-features-plugin": "^7.22.15", "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { @@ -1771,12 +1808,12 @@ } }, "node_modules/@babel/plugin-transform-unicode-regex": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.22.5.tgz", - "integrity": "sha512-028laaOKptN5vHJf9/Arr/HiJekMd41hOEZYvNsrsXqJ7YPYuX2bQxh31fkZzGmq3YqHRJzYFFAVYvKfMPKqyg==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.23.3.tgz", + "integrity": "sha512-wMHpNA4x2cIA32b/ci3AfwNgheiva2W0WUKWTK7vBHBhDKfPsc5cFGNWm69WBqpwd86u1qwZ9PWevKqm1A3yAw==", "dev": true, "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.22.5", + "@babel/helper-create-regexp-features-plugin": "^7.22.15", "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { @@ -1787,12 +1824,12 @@ } }, "node_modules/@babel/plugin-transform-unicode-sets-regex": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.22.5.tgz", - "integrity": "sha512-lhMfi4FC15j13eKrh3DnYHjpGj6UKQHtNKTbtc1igvAhRy4+kLhV07OpLcsN0VgDEw/MjAvJO4BdMJsHwMhzCg==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.23.3.tgz", + "integrity": "sha512-W7lliA/v9bNR83Qc3q1ip9CQMZ09CcHDbHfbLRDNuAhn1Mvkr1ZNF7hPmztMQvtTGVLJ9m8IZqWsTkXOml8dbw==", "dev": true, "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.22.5", + "@babel/helper-create-regexp-features-plugin": "^7.22.15", "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { @@ -1803,25 +1840,26 @@ } }, "node_modules/@babel/preset-env": { - "version": "7.23.2", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.23.2.tgz", - "integrity": "sha512-BW3gsuDD+rvHL2VO2SjAUNTBe5YrjsTiDyqamPDWY723na3/yPQ65X5oQkFVJZ0o50/2d+svm1rkPoJeR1KxVQ==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.23.3.tgz", + "integrity": "sha512-ovzGc2uuyNfNAs/jyjIGxS8arOHS5FENZaNn4rtE7UdKMMkqHCvboHfcuhWLZNX5cB44QfcGNWjaevxMzzMf+Q==", "dev": true, "dependencies": { - "@babel/compat-data": "^7.23.2", + "@babel/compat-data": "^7.23.3", "@babel/helper-compilation-targets": "^7.22.15", "@babel/helper-plugin-utils": "^7.22.5", "@babel/helper-validator-option": "^7.22.15", - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.22.15", - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.22.15", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.23.3", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.23.3", + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.23.3", "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", "@babel/plugin-syntax-async-generators": "^7.8.4", "@babel/plugin-syntax-class-properties": "^7.12.13", "@babel/plugin-syntax-class-static-block": "^7.14.5", "@babel/plugin-syntax-dynamic-import": "^7.8.3", "@babel/plugin-syntax-export-namespace-from": "^7.8.3", - "@babel/plugin-syntax-import-assertions": "^7.22.5", - "@babel/plugin-syntax-import-attributes": "^7.22.5", + "@babel/plugin-syntax-import-assertions": "^7.23.3", + "@babel/plugin-syntax-import-attributes": "^7.23.3", "@babel/plugin-syntax-import-meta": "^7.10.4", "@babel/plugin-syntax-json-strings": "^7.8.3", "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", @@ -1833,56 +1871,55 @@ "@babel/plugin-syntax-private-property-in-object": "^7.14.5", "@babel/plugin-syntax-top-level-await": "^7.14.5", "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", - "@babel/plugin-transform-arrow-functions": "^7.22.5", - "@babel/plugin-transform-async-generator-functions": "^7.23.2", - "@babel/plugin-transform-async-to-generator": "^7.22.5", - "@babel/plugin-transform-block-scoped-functions": "^7.22.5", - "@babel/plugin-transform-block-scoping": "^7.23.0", - "@babel/plugin-transform-class-properties": "^7.22.5", - "@babel/plugin-transform-class-static-block": "^7.22.11", - "@babel/plugin-transform-classes": "^7.22.15", - "@babel/plugin-transform-computed-properties": "^7.22.5", - "@babel/plugin-transform-destructuring": "^7.23.0", - "@babel/plugin-transform-dotall-regex": "^7.22.5", - "@babel/plugin-transform-duplicate-keys": "^7.22.5", - "@babel/plugin-transform-dynamic-import": "^7.22.11", - "@babel/plugin-transform-exponentiation-operator": "^7.22.5", - "@babel/plugin-transform-export-namespace-from": "^7.22.11", - "@babel/plugin-transform-for-of": "^7.22.15", - "@babel/plugin-transform-function-name": "^7.22.5", - "@babel/plugin-transform-json-strings": "^7.22.11", - "@babel/plugin-transform-literals": "^7.22.5", - "@babel/plugin-transform-logical-assignment-operators": "^7.22.11", - "@babel/plugin-transform-member-expression-literals": "^7.22.5", - "@babel/plugin-transform-modules-amd": "^7.23.0", - "@babel/plugin-transform-modules-commonjs": "^7.23.0", - "@babel/plugin-transform-modules-systemjs": "^7.23.0", - "@babel/plugin-transform-modules-umd": "^7.22.5", + "@babel/plugin-transform-arrow-functions": "^7.23.3", + "@babel/plugin-transform-async-generator-functions": "^7.23.3", + "@babel/plugin-transform-async-to-generator": "^7.23.3", + "@babel/plugin-transform-block-scoped-functions": "^7.23.3", + "@babel/plugin-transform-block-scoping": "^7.23.3", + "@babel/plugin-transform-class-properties": "^7.23.3", + "@babel/plugin-transform-class-static-block": "^7.23.3", + "@babel/plugin-transform-classes": "^7.23.3", + "@babel/plugin-transform-computed-properties": "^7.23.3", + "@babel/plugin-transform-destructuring": "^7.23.3", + "@babel/plugin-transform-dotall-regex": "^7.23.3", + "@babel/plugin-transform-duplicate-keys": "^7.23.3", + "@babel/plugin-transform-dynamic-import": "^7.23.3", + "@babel/plugin-transform-exponentiation-operator": "^7.23.3", + "@babel/plugin-transform-export-namespace-from": "^7.23.3", + "@babel/plugin-transform-for-of": "^7.23.3", + "@babel/plugin-transform-function-name": "^7.23.3", + "@babel/plugin-transform-json-strings": "^7.23.3", + "@babel/plugin-transform-literals": "^7.23.3", + "@babel/plugin-transform-logical-assignment-operators": "^7.23.3", + "@babel/plugin-transform-member-expression-literals": "^7.23.3", + "@babel/plugin-transform-modules-amd": "^7.23.3", + "@babel/plugin-transform-modules-commonjs": "^7.23.3", + "@babel/plugin-transform-modules-systemjs": "^7.23.3", + "@babel/plugin-transform-modules-umd": "^7.23.3", "@babel/plugin-transform-named-capturing-groups-regex": "^7.22.5", - "@babel/plugin-transform-new-target": "^7.22.5", - "@babel/plugin-transform-nullish-coalescing-operator": "^7.22.11", - "@babel/plugin-transform-numeric-separator": "^7.22.11", - "@babel/plugin-transform-object-rest-spread": "^7.22.15", - "@babel/plugin-transform-object-super": "^7.22.5", - "@babel/plugin-transform-optional-catch-binding": "^7.22.11", - "@babel/plugin-transform-optional-chaining": "^7.23.0", - "@babel/plugin-transform-parameters": "^7.22.15", - "@babel/plugin-transform-private-methods": "^7.22.5", - "@babel/plugin-transform-private-property-in-object": "^7.22.11", - "@babel/plugin-transform-property-literals": "^7.22.5", - "@babel/plugin-transform-regenerator": "^7.22.10", - "@babel/plugin-transform-reserved-words": "^7.22.5", - "@babel/plugin-transform-shorthand-properties": "^7.22.5", - "@babel/plugin-transform-spread": "^7.22.5", - "@babel/plugin-transform-sticky-regex": "^7.22.5", - "@babel/plugin-transform-template-literals": "^7.22.5", - "@babel/plugin-transform-typeof-symbol": "^7.22.5", - "@babel/plugin-transform-unicode-escapes": "^7.22.10", - "@babel/plugin-transform-unicode-property-regex": "^7.22.5", - "@babel/plugin-transform-unicode-regex": "^7.22.5", - "@babel/plugin-transform-unicode-sets-regex": "^7.22.5", + "@babel/plugin-transform-new-target": "^7.23.3", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.23.3", + "@babel/plugin-transform-numeric-separator": "^7.23.3", + "@babel/plugin-transform-object-rest-spread": "^7.23.3", + "@babel/plugin-transform-object-super": "^7.23.3", + "@babel/plugin-transform-optional-catch-binding": "^7.23.3", + "@babel/plugin-transform-optional-chaining": "^7.23.3", + "@babel/plugin-transform-parameters": "^7.23.3", + "@babel/plugin-transform-private-methods": "^7.23.3", + "@babel/plugin-transform-private-property-in-object": "^7.23.3", + "@babel/plugin-transform-property-literals": "^7.23.3", + "@babel/plugin-transform-regenerator": "^7.23.3", + "@babel/plugin-transform-reserved-words": "^7.23.3", + "@babel/plugin-transform-shorthand-properties": "^7.23.3", + "@babel/plugin-transform-spread": "^7.23.3", + "@babel/plugin-transform-sticky-regex": "^7.23.3", + "@babel/plugin-transform-template-literals": "^7.23.3", + "@babel/plugin-transform-typeof-symbol": "^7.23.3", + "@babel/plugin-transform-unicode-escapes": "^7.23.3", + "@babel/plugin-transform-unicode-property-regex": "^7.23.3", + "@babel/plugin-transform-unicode-regex": "^7.23.3", + "@babel/plugin-transform-unicode-sets-regex": "^7.23.3", "@babel/preset-modules": "0.1.6-no-external-plugins", - "@babel/types": "^7.23.0", "babel-plugin-polyfill-corejs2": "^0.4.6", "babel-plugin-polyfill-corejs3": "^0.8.5", "babel-plugin-polyfill-regenerator": "^0.5.3", @@ -1928,16 +1965,16 @@ } }, "node_modules/@babel/preset-typescript": { - "version": "7.23.2", - "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.23.2.tgz", - "integrity": "sha512-u4UJc1XsS1GhIGteM8rnGiIvf9rJpiVgMEeCnwlLA7WJPC+jcXWJAGxYmeqs5hOZD8BbAfnV5ezBOxQbb4OUxA==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.23.3.tgz", + "integrity": "sha512-17oIGVlqz6CchO9RFYn5U6ZpWRZIngayYCtrPRSgANSwC2V1Jb+iP74nVxzzXJte8b8BYxrL1yY96xfhTBrNNQ==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5", "@babel/helper-validator-option": "^7.22.15", - "@babel/plugin-syntax-jsx": "^7.22.5", - "@babel/plugin-transform-modules-commonjs": "^7.23.0", - "@babel/plugin-transform-typescript": "^7.22.15" + "@babel/plugin-syntax-jsx": "^7.23.3", + "@babel/plugin-transform-modules-commonjs": "^7.23.3", + "@babel/plugin-transform-typescript": "^7.23.3" }, "engines": { "node": ">=6.9.0" @@ -2149,9 +2186,9 @@ } }, "node_modules/@babel/types": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.0.tgz", - "integrity": "sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.3.tgz", + "integrity": "sha512-OZnvoH2l8PK5eUvEcUyCt/sXgr/h+UWpVuBbOljwcrAgUl6lpchoQ++PHGyQy1AtYnVA6CEq3y5xeEI10brpXw==", "dev": true, "dependencies": { "@babel/helper-string-parser": "^7.22.5", diff --git a/web/package.json b/web/package.json index 7a6e4cef5..e0961139c 100644 --- a/web/package.json +++ b/web/package.json @@ -64,14 +64,14 @@ "yaml": "^2.3.4" }, "devDependencies": { - "@babel/core": "^7.23.2", + "@babel/core": "^7.23.3", "@babel/plugin-proposal-class-properties": "^7.18.6", - "@babel/plugin-proposal-decorators": "^7.23.2", - "@babel/plugin-transform-private-methods": "^7.22.5", - "@babel/plugin-transform-private-property-in-object": "^7.22.11", - "@babel/plugin-transform-runtime": "^7.23.2", - "@babel/preset-env": "^7.23.2", - "@babel/preset-typescript": "^7.23.2", + "@babel/plugin-proposal-decorators": "^7.23.3", + "@babel/plugin-transform-private-methods": "^7.23.3", + "@babel/plugin-transform-private-property-in-object": "^7.23.3", + "@babel/plugin-transform-runtime": "^7.23.3", + "@babel/preset-env": "^7.23.3", + "@babel/preset-typescript": "^7.23.3", "@hcaptcha/types": "^1.0.3", "@jackfranklin/rollup-plugin-markdown": "^0.4.0", "@jeysal/storybook-addon-css-user-preferences": "^0.2.0", From 939631c94e3c352dbb4dcdf21dfc85ddb44243dd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 10 Nov 2023 12:40:05 +0100 Subject: [PATCH 03/24] web: bump the sentry group in /web with 2 updates (#7516) Bumps the sentry group in /web with 2 updates: [@sentry/browser](https://github.com/getsentry/sentry-javascript) and [@sentry/tracing](https://github.com/getsentry/sentry-javascript). Updates `@sentry/browser` from 7.79.0 to 7.80.0 - [Release notes](https://github.com/getsentry/sentry-javascript/releases) - [Changelog](https://github.com/getsentry/sentry-javascript/blob/develop/CHANGELOG.md) - [Commits](https://github.com/getsentry/sentry-javascript/compare/7.79.0...7.80.0) Updates `@sentry/tracing` from 7.79.0 to 7.80.0 - [Release notes](https://github.com/getsentry/sentry-javascript/releases) - [Changelog](https://github.com/getsentry/sentry-javascript/blob/develop/CHANGELOG.md) - [Commits](https://github.com/getsentry/sentry-javascript/compare/7.79.0...7.80.0) --- updated-dependencies: - dependency-name: "@sentry/browser" dependency-type: direct:production update-type: version-update:semver-minor dependency-group: sentry - dependency-name: "@sentry/tracing" dependency-type: direct:production update-type: version-update:semver-minor dependency-group: sentry ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- web/package-lock.json | 78 +++++++++++++++++++++---------------------- web/package.json | 4 +-- 2 files changed, 41 insertions(+), 41 deletions(-) diff --git a/web/package-lock.json b/web/package-lock.json index aa671a23e..98296fca4 100644 --- a/web/package-lock.json +++ b/web/package-lock.json @@ -24,8 +24,8 @@ "@open-wc/lit-helpers": "^0.6.0", "@patternfly/elements": "^2.4.0", "@patternfly/patternfly": "^4.224.2", - "@sentry/browser": "^7.79.0", - "@sentry/tracing": "^7.79.0", + "@sentry/browser": "^7.80.0", + "@sentry/tracing": "^7.80.0", "@webcomponents/webcomponentsjs": "^2.8.0", "base64-js": "^1.5.1", "chart.js": "^4.4.0", @@ -4732,84 +4732,84 @@ ] }, "node_modules/@sentry-internal/tracing": { - "version": "7.79.0", - "resolved": "https://registry.npmjs.org/@sentry-internal/tracing/-/tracing-7.79.0.tgz", - "integrity": "sha512-Mf9Bd0OrZ24h1qZpvmz9IRnfORMGYNYC1xWBBFpIR1AauEDX89x+mJwIOrUc4KKAAAwt73shrJv1QA8QOm4E3g==", + "version": "7.80.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/tracing/-/tracing-7.80.0.tgz", + "integrity": "sha512-P1Ab9gamHLsbH9D82i1HY8xfq9dP8runvc4g50AAd6OXRKaJ45f2KGRZUmnMEVqBQ7YoPYp2LFMkrhNYbcZEoQ==", "dependencies": { - "@sentry/core": "7.79.0", - "@sentry/types": "7.79.0", - "@sentry/utils": "7.79.0" + "@sentry/core": "7.80.0", + "@sentry/types": "7.80.0", + "@sentry/utils": "7.80.0" }, "engines": { "node": ">=8" } }, "node_modules/@sentry/browser": { - "version": "7.79.0", - "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-7.79.0.tgz", - "integrity": "sha512-gWbWEElF61uZeTFLIZz3NMyCkAzBDOpMAogEbVu2GX91SHKB7GXlE//INnS/R5wfE5j/CFaZc53mzzoIuMy1sA==", + "version": "7.80.0", + "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-7.80.0.tgz", + "integrity": "sha512-Ngwjc+yyf/aH5q7iQM1LeDNlhM1Ilt4ZLUogTghZR/guwNWmCtk3OHcjOLz7fxBBj9wGFUc2pHPyeYM6bQhrEw==", "dependencies": { - "@sentry-internal/tracing": "7.79.0", - "@sentry/core": "7.79.0", - "@sentry/replay": "7.79.0", - "@sentry/types": "7.79.0", - "@sentry/utils": "7.79.0" + "@sentry-internal/tracing": "7.80.0", + "@sentry/core": "7.80.0", + "@sentry/replay": "7.80.0", + "@sentry/types": "7.80.0", + "@sentry/utils": "7.80.0" }, "engines": { "node": ">=8" } }, "node_modules/@sentry/core": { - "version": "7.79.0", - "resolved": "https://registry.npmjs.org/@sentry/core/-/core-7.79.0.tgz", - "integrity": "sha512-9vG7SfOcJNJNiqlqg4MuHDUCaSf2ZXpv3eZYRPbBkgPGr8X1ekrSABpOK+6kBNvbtKxfWVTWbLpAA6xU+cwnVw==", + "version": "7.80.0", + "resolved": "https://registry.npmjs.org/@sentry/core/-/core-7.80.0.tgz", + "integrity": "sha512-nJiiymdTSEyI035/rdD3VOq6FlOZ2wWLR5bit9LK8a3rzHU3UXkwScvEo6zYgs0Xp1sC0yu1S9+0BEiYkmi29A==", "dependencies": { - "@sentry/types": "7.79.0", - "@sentry/utils": "7.79.0" + "@sentry/types": "7.80.0", + "@sentry/utils": "7.80.0" }, "engines": { "node": ">=8" } }, "node_modules/@sentry/replay": { - "version": "7.79.0", - "resolved": "https://registry.npmjs.org/@sentry/replay/-/replay-7.79.0.tgz", - "integrity": "sha512-vF79NxWGYfoD0hnIkdgUQqedoMcRHHp5UAfZlxhpQzJf4TnbOjollp63AvOrfd38osSG2d3E5kTUU9xs/zKhBQ==", + "version": "7.80.0", + "resolved": "https://registry.npmjs.org/@sentry/replay/-/replay-7.80.0.tgz", + "integrity": "sha512-wWnpuJq3OaDLp1LutE4oxWXnau04fvwuzBjuaFvOXOV+pB/kn+pDPuVOC5+FH/RMRZ5ftwX5+dF6fojfcLVGCg==", "dependencies": { - "@sentry-internal/tracing": "7.79.0", - "@sentry/core": "7.79.0", - "@sentry/types": "7.79.0", - "@sentry/utils": "7.79.0" + "@sentry-internal/tracing": "7.80.0", + "@sentry/core": "7.80.0", + "@sentry/types": "7.80.0", + "@sentry/utils": "7.80.0" }, "engines": { "node": ">=12" } }, "node_modules/@sentry/tracing": { - "version": "7.79.0", - "resolved": "https://registry.npmjs.org/@sentry/tracing/-/tracing-7.79.0.tgz", - "integrity": "sha512-Y1awpIcMKCsTpC3wS+SaEJTcOMd6OugZZXCV2r9ozBIRKE7wG//ntDX3ApcRf4kbDzQMJY2Ylu0QKDIyNEAr0g==", + "version": "7.80.0", + "resolved": "https://registry.npmjs.org/@sentry/tracing/-/tracing-7.80.0.tgz", + "integrity": "sha512-y9zBVMpCgY5Y6dBZrnKKHf6K9YWjGo3S35tPwDV1mQLml64bi6bNr6Fc6OBzXyrl9OTJAO71A1Z7DlAu6BQY9w==", "dependencies": { - "@sentry-internal/tracing": "7.79.0" + "@sentry-internal/tracing": "7.80.0" }, "engines": { "node": ">=8" } }, "node_modules/@sentry/types": { - "version": "7.79.0", - "resolved": "https://registry.npmjs.org/@sentry/types/-/types-7.79.0.tgz", - "integrity": "sha512-3tV32+v/DF8w7kD0p3kLWtgVTVdFL39oGY02+vz//rjWg/vzeqSE95mCYKm5pUfd6cPETX/8dunCiuTBQIkTHQ==", + "version": "7.80.0", + "resolved": "https://registry.npmjs.org/@sentry/types/-/types-7.80.0.tgz", + "integrity": "sha512-4bpMO+2jWiWLDa8zbTASWWNLWe6yhjfPsa7/6VH5y9x1NGtL8oRbqUsTgsvjF3nmeHEMkHQsC8NHPaQ/ibFmZQ==", "engines": { "node": ">=8" } }, "node_modules/@sentry/utils": { - "version": "7.79.0", - "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-7.79.0.tgz", - "integrity": "sha512-tUTlb6PvfZawqBmBK9CPXflqrZDXHKWoX3fve2zLK6W0FSpIMOO4TH8PBqkHBFs0ZgF/bnv/bsM4z7uEAlAtzg==", + "version": "7.80.0", + "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-7.80.0.tgz", + "integrity": "sha512-XbBCEl6uLvE50ftKwrEo6XWdDaZXHXu+kkHXTPWQEcnbvfZKLuG9V0Hxtxxq3xQgyWmuF05OH1GcqYqiO+v5Yg==", "dependencies": { - "@sentry/types": "7.79.0" + "@sentry/types": "7.80.0" }, "engines": { "node": ">=8" diff --git a/web/package.json b/web/package.json index e0961139c..33f9a41bd 100644 --- a/web/package.json +++ b/web/package.json @@ -45,8 +45,8 @@ "@open-wc/lit-helpers": "^0.6.0", "@patternfly/elements": "^2.4.0", "@patternfly/patternfly": "^4.224.2", - "@sentry/browser": "^7.79.0", - "@sentry/tracing": "^7.79.0", + "@sentry/browser": "^7.80.0", + "@sentry/tracing": "^7.80.0", "@webcomponents/webcomponentsjs": "^2.8.0", "base64-js": "^1.5.1", "chart.js": "^4.4.0", From 8b4f66e457716b43be464a8ca99b690d1218b4d7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 10 Nov 2023 12:40:16 +0100 Subject: [PATCH 04/24] core: bump goauthentik.io/api/v3 from 3.2023102.1 to 3.2023103.1 (#7515) Bumps [goauthentik.io/api/v3](https://github.com/goauthentik/client-go) from 3.2023102.1 to 3.2023103.1. - [Release notes](https://github.com/goauthentik/client-go/releases) - [Commits](https://github.com/goauthentik/client-go/compare/v3.2023102.1...v3.2023103.1) --- updated-dependencies: - dependency-name: goauthentik.io/api/v3 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 381bc58f1..348fe36d9 100644 --- a/go.mod +++ b/go.mod @@ -27,7 +27,7 @@ require ( github.com/sirupsen/logrus v1.9.3 github.com/spf13/cobra v1.8.0 github.com/stretchr/testify v1.8.4 - goauthentik.io/api/v3 v3.2023102.1 + goauthentik.io/api/v3 v3.2023103.1 golang.org/x/exp v0.0.0-20230210204819-062eb4c674ab golang.org/x/oauth2 v0.14.0 golang.org/x/sync v0.5.0 diff --git a/go.sum b/go.sum index 3271b54ef..c2ad62fd3 100644 --- a/go.sum +++ b/go.sum @@ -358,8 +358,8 @@ go.opentelemetry.io/otel/trace v1.14.0 h1:wp2Mmvj41tDsyAJXiWDWpfNsOiIyd38fy85pyK go.opentelemetry.io/otel/trace v1.14.0/go.mod h1:8avnQLK+CG77yNLUae4ea2JDQ6iT+gozhnZjy/rw9G8= go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A= go.uber.org/goleak v1.2.1/go.mod h1:qlT2yGI9QafXHhZZLxlSuNsMw3FFLxBr+tBRlmO1xH4= -goauthentik.io/api/v3 v3.2023102.1 h1:TinB3fzh17iw92Mak0pxVdVSMJbL2CxZkQSvd98C4+U= -goauthentik.io/api/v3 v3.2023102.1/go.mod h1:zz+mEZg8rY/7eEjkMGWJ2DnGqk+zqxuybGCGrR2O4Kw= +goauthentik.io/api/v3 v3.2023103.1 h1:KqZny4BPDEQ6cIDuZ9pn6/kpvyu+o6o/EekAfujffow= +goauthentik.io/api/v3 v3.2023103.1/go.mod h1:zz+mEZg8rY/7eEjkMGWJ2DnGqk+zqxuybGCGrR2O4Kw= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190422162423-af44ce270edf/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= From f8e2cd56398bbd7522c1ee14acabe26e17aaa4ae Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 10 Nov 2023 12:40:26 +0100 Subject: [PATCH 05/24] web: bump wdio-wait-for from 3.0.7 to 3.0.8 in /tests/wdio (#7514) Bumps [wdio-wait-for](https://github.com/webdriverio/wdio-wait-for) from 3.0.7 to 3.0.8. - [Release notes](https://github.com/webdriverio/wdio-wait-for/releases) - [Commits](https://github.com/webdriverio/wdio-wait-for/compare/3.0.7...3.0.8) --- updated-dependencies: - dependency-name: wdio-wait-for dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- tests/wdio/package-lock.json | 8 ++++---- tests/wdio/package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/wdio/package-lock.json b/tests/wdio/package-lock.json index 26eb03402..0ffd4fc50 100644 --- a/tests/wdio/package-lock.json +++ b/tests/wdio/package-lock.json @@ -20,7 +20,7 @@ "prettier": "^3.0.3", "ts-node": "^10.9.1", "typescript": "^5.2.2", - "wdio-wait-for": "^3.0.7" + "wdio-wait-for": "^3.0.8" } }, "node_modules/@aashutoshrathi/word-wrap": { @@ -8571,9 +8571,9 @@ } }, "node_modules/wdio-wait-for": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/wdio-wait-for/-/wdio-wait-for-3.0.7.tgz", - "integrity": "sha512-NLxEg57+DAQvsEgsAcuF0zM2XDAQTfbKn2mN4nw9hDzz3RfgsZbCxvp93Nm/3609QuxpikC+MxgQ5ORLSoptvA==", + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/wdio-wait-for/-/wdio-wait-for-3.0.8.tgz", + "integrity": "sha512-Lptqzqso57sia7q6BRG2M+4S0YysXobcj9gchZxJBqYewgoH4e6Rime6i4WseIW85zmDMJu8pMSWNK4efong8A==", "dev": true, "engines": { "node": "^16.13 || >=18" diff --git a/tests/wdio/package.json b/tests/wdio/package.json index 0de4a622b..cf64248c4 100644 --- a/tests/wdio/package.json +++ b/tests/wdio/package.json @@ -17,7 +17,7 @@ "prettier": "^3.0.3", "ts-node": "^10.9.1", "typescript": "^5.2.2", - "wdio-wait-for": "^3.0.7" + "wdio-wait-for": "^3.0.8" }, "scripts": { "wdio": "wdio run ./wdio.conf.ts", From 4ce5f0931b5404899d59d5b79b02f966b6ea7141 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 10 Nov 2023 12:41:04 +0100 Subject: [PATCH 06/24] web: bump axios from 1.5.0 to 1.6.1 in /web (#7518) Bumps [axios](https://github.com/axios/axios) from 1.5.0 to 1.6.1. - [Release notes](https://github.com/axios/axios/releases) - [Changelog](https://github.com/axios/axios/blob/v1.x/CHANGELOG.md) - [Commits](https://github.com/axios/axios/compare/v1.5.0...v1.6.1) --- updated-dependencies: - dependency-name: axios dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- web/package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/web/package-lock.json b/web/package-lock.json index 98296fca4..b24ceccc3 100644 --- a/web/package-lock.json +++ b/web/package-lock.json @@ -11151,9 +11151,9 @@ } }, "node_modules/axios": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.5.0.tgz", - "integrity": "sha512-D4DdjDo5CY50Qms0qGQTTw6Q44jl7zRwY7bthds06pUGfChBCTcQs+N743eFWGEd6pRTMd6A+I87aWyFV5wiZQ==", + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.1.tgz", + "integrity": "sha512-vfBmhDpKafglh0EldBEbVuoe7DyAavGSLWhuSm5ZSEKQnHhBf0xAAwybbNH1IkrJNGnS/VG4I5yxig1pCEXE4g==", "dependencies": { "follow-redirects": "^1.15.0", "form-data": "^4.0.0", From 11dcda77faa2f2b463abdaea5edad9dd66863183 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 10 Nov 2023 12:41:59 +0100 Subject: [PATCH 07/24] core: bump twilio from 8.10.0 to 8.10.1 (#7474) Bumps [twilio](https://github.com/twilio/twilio-python) from 8.10.0 to 8.10.1. - [Release notes](https://github.com/twilio/twilio-python/releases) - [Changelog](https://github.com/twilio/twilio-python/blob/main/CHANGES.md) - [Commits](https://github.com/twilio/twilio-python/compare/8.10.0...8.10.1) --- updated-dependencies: - dependency-name: twilio dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- poetry.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/poetry.lock b/poetry.lock index 9886f5ac7..059215106 100644 --- a/poetry.lock +++ b/poetry.lock @@ -3675,13 +3675,13 @@ wsproto = ">=0.14" [[package]] name = "twilio" -version = "8.10.0" +version = "8.10.1" description = "Twilio API client and TwiML generator" optional = false python-versions = ">=3.7.0" files = [ - {file = "twilio-8.10.0-py2.py3-none-any.whl", hash = "sha256:1eb04af92f3e70fcc87a2fd30617f53784e34045d054e4ae3dc9cfe7bdf1e692"}, - {file = "twilio-8.10.0.tar.gz", hash = "sha256:3bf2def228ceaa7519f4d6e58b2e3c9cb5d865af02b4618239e52c9d9e75e29d"}, + {file = "twilio-8.10.1-py2.py3-none-any.whl", hash = "sha256:eb08ac17c8eb4f6176907b4e7dea984102488fb86ad146ecd47e8a8dfcf3cfa3"}, + {file = "twilio-8.10.1.tar.gz", hash = "sha256:902267856d09cf1f59b7fa4af594edae0225fdd8b473a6ef8e5799e823e0a611"}, ] [package.dependencies] From 9db9ad3d66046b114a62b30604d0cf58a5d16075 Mon Sep 17 00:00:00 2001 From: Philipp Kolberg <39984529+PKizzle@users.noreply.github.com> Date: Fri, 10 Nov 2023 15:44:37 +0100 Subject: [PATCH 08/24] root: Restructure broker / cache / channel / result configuration (#7097) * Initial commit * Remove any remaining mentions of Redis URL This is handled in https://github.com/goauthentik/authentik/pull/5395 * Allow setting broker transport options This enables usage of other brokers that require additional settings * Remove remaining reference to Redis URL This functionality is not part of this PR * Reset default TLS requirements to none * Fix linter errors * Move dict from base64 encoded json to config.py Additionally add tests * Replace ast.literal_eval with json.loads * Use default channel and cache backend configuration If more customization is desired users shall look at goauthentik.io/docs/installation/configuration#custom-python-settings * Send config deprecation notification to all superusers * Remove duplicate method * Add configuration explanation For channel layer settings * Use Event for deprecation warning * Fix remove duplicated method * Add missing comma * Update authentik/lib/config.py Signed-off-by: Jens L. * Fix Event deprecation handling --------- Signed-off-by: Jens L. Co-authored-by: Jens L --- authentik/api/v3/config.py | 8 +- authentik/flows/planner.py | 2 +- authentik/lib/config.py | 90 +++++++++++++++++++-- authentik/lib/default.yml | 24 ++++-- authentik/lib/tests/test_config.py | 87 ++++++++++++++++++-- authentik/outposts/consumer.py | 2 +- authentik/policies/process.py | 2 +- authentik/policies/reputation/signals.py | 2 +- authentik/root/settings.py | 14 ++-- internal/config/struct.go | 7 +- website/docs/installation/configuration.mdx | 42 +++++++--- 11 files changed, 233 insertions(+), 47 deletions(-) diff --git a/authentik/api/v3/config.py b/authentik/api/v3/config.py index bbc676647..0defd1a5b 100644 --- a/authentik/api/v3/config.py +++ b/authentik/api/v3/config.py @@ -93,10 +93,10 @@ class ConfigView(APIView): "traces_sample_rate": float(CONFIG.get("error_reporting.sample_rate", 0.4)), }, "capabilities": self.get_capabilities(), - "cache_timeout": CONFIG.get_int("redis.cache_timeout"), - "cache_timeout_flows": CONFIG.get_int("redis.cache_timeout_flows"), - "cache_timeout_policies": CONFIG.get_int("redis.cache_timeout_policies"), - "cache_timeout_reputation": CONFIG.get_int("redis.cache_timeout_reputation"), + "cache_timeout": CONFIG.get_int("cache.timeout"), + "cache_timeout_flows": CONFIG.get_int("cache.timeout_flows"), + "cache_timeout_policies": CONFIG.get_int("cache.timeout_policies"), + "cache_timeout_reputation": CONFIG.get_int("cache.timeout_reputation"), } ) diff --git a/authentik/flows/planner.py b/authentik/flows/planner.py index 4cf3c6aad..f80461490 100644 --- a/authentik/flows/planner.py +++ b/authentik/flows/planner.py @@ -33,7 +33,7 @@ PLAN_CONTEXT_SOURCE = "source" # Is set by the Flow Planner when a FlowToken was used, and the currently active flow plan # was restored. PLAN_CONTEXT_IS_RESTORED = "is_restored" -CACHE_TIMEOUT = CONFIG.get_int("redis.cache_timeout_flows") +CACHE_TIMEOUT = CONFIG.get_int("cache.timeout_flows") CACHE_PREFIX = "goauthentik.io/flows/planner/" diff --git a/authentik/lib/config.py b/authentik/lib/config.py index 63aa3493a..dd5500f8e 100644 --- a/authentik/lib/config.py +++ b/authentik/lib/config.py @@ -1,4 +1,6 @@ """authentik core config loader""" +import base64 +import json import os from collections.abc import Mapping from contextlib import contextmanager @@ -22,6 +24,25 @@ SEARCH_PATHS = ["authentik/lib/default.yml", "/etc/authentik/config.yml", ""] + ENV_PREFIX = "AUTHENTIK" ENVIRONMENT = os.getenv(f"{ENV_PREFIX}_ENV", "local") +REDIS_ENV_KEYS = [ + f"{ENV_PREFIX}_REDIS__HOST", + f"{ENV_PREFIX}_REDIS__PORT", + f"{ENV_PREFIX}_REDIS__DB", + f"{ENV_PREFIX}_REDIS__USERNAME", + f"{ENV_PREFIX}_REDIS__PASSWORD", + f"{ENV_PREFIX}_REDIS__TLS", + f"{ENV_PREFIX}_REDIS__TLS_REQS", +] + +DEPRECATIONS = { + "redis.broker_url": "broker.url", + "redis.broker_transport_options": "broker.transport_options", + "redis.cache_timeout": "cache.timeout", + "redis.cache_timeout_flows": "cache.timeout_flows", + "redis.cache_timeout_policies": "cache.timeout_policies", + "redis.cache_timeout_reputation": "cache.timeout_reputation", +} + def get_path_from_dict(root: dict, path: str, sep=".", default=None) -> Any: """Recursively walk through `root`, checking each part of `path` separated by `sep`. @@ -81,6 +102,10 @@ class AttrEncoder(JSONEncoder): return super().default(o) +class UNSET: + """Used to test whether configuration key has not been set.""" + + class ConfigLoader: """Search through SEARCH_PATHS and load configuration. Environment variables starting with `ENV_PREFIX` are also applied. @@ -113,6 +138,40 @@ class ConfigLoader: self.update_from_file(env_file) self.update_from_env() self.update(self.__config, kwargs) + self.check_deprecations() + + def check_deprecations(self): + """Warn if any deprecated configuration options are used""" + + def _pop_deprecated_key(current_obj, dot_parts, index): + """Recursive function to remove deprecated keys in configuration""" + dot_part = dot_parts[index] + if index == len(dot_parts) - 1: + return current_obj.pop(dot_part) + value = _pop_deprecated_key(current_obj[dot_part], dot_parts, index + 1) + if not current_obj[dot_part]: + current_obj.pop(dot_part) + return value + + for deprecation, replacement in DEPRECATIONS.items(): + if self.get(deprecation, default=UNSET) is not UNSET: + message = ( + f"'{deprecation}' has been deprecated in favor of '{replacement}'! " + + "Please update your configuration." + ) + self.log( + "warning", + message, + ) + try: + from authentik.events.models import Event, EventAction + + Event.new(EventAction.CONFIGURATION_ERROR, message=message).save() + except ImportError: + continue + + deprecated_attr = _pop_deprecated_key(self.__config, deprecation.split("."), 0) + self.set(replacement, deprecated_attr.value) def log(self, level: str, message: str, **kwargs): """Custom Log method, we want to ensure ConfigLoader always logs JSON even when @@ -180,6 +239,10 @@ class ConfigLoader: error=str(exc), ) + def update_from_dict(self, update: dict): + """Update config from dict""" + self.__config.update(update) + def update_from_env(self): """Check environment variables""" outer = {} @@ -188,19 +251,13 @@ class ConfigLoader: if not key.startswith(ENV_PREFIX): continue relative_key = key.replace(f"{ENV_PREFIX}_", "", 1).replace("__", ".").lower() - # Recursively convert path from a.b.c into outer[a][b][c] - current_obj = outer - dot_parts = relative_key.split(".") - for dot_part in dot_parts[:-1]: - if dot_part not in current_obj: - current_obj[dot_part] = {} - current_obj = current_obj[dot_part] # Check if the value is json, and try to load it try: value = loads(value) except JSONDecodeError: pass - current_obj[dot_parts[-1]] = Attr(value, Attr.Source.ENV, key) + attr_value = Attr(value, Attr.Source.ENV, relative_key) + set_path_in_dict(outer, relative_key, attr_value) idx += 1 if idx > 0: self.log("debug", "Loaded environment variables", count=idx) @@ -241,6 +298,23 @@ class ConfigLoader: """Wrapper for get that converts value into boolean""" return str(self.get(path, default)).lower() == "true" + def get_dict_from_b64_json(self, path: str, default=None) -> dict: + """Wrapper for get that converts value from Base64 encoded string into dictionary""" + config_value = self.get(path) + if config_value is None: + return {} + try: + b64decoded_str = base64.b64decode(config_value).decode("utf-8") + b64decoded_str = b64decoded_str.strip().lstrip("{").rstrip("}") + b64decoded_str = "{" + b64decoded_str + "}" + return json.loads(b64decoded_str) + except (JSONDecodeError, TypeError, ValueError) as exc: + self.log( + "warning", + f"Ignored invalid configuration for '{path}' due to exception: {str(exc)}", + ) + return default if isinstance(default, dict) else {} + def set(self, path: str, value: Any, sep="."): """Set value using same syntax as get()""" set_path_in_dict(self.raw, path, Attr(value), sep=sep) diff --git a/authentik/lib/default.yml b/authentik/lib/default.yml index 793bece13..83bd3c7c9 100644 --- a/authentik/lib/default.yml +++ b/authentik/lib/default.yml @@ -28,14 +28,28 @@ listen: redis: host: localhost port: 6379 + db: 0 + username: "" password: "" tls: false tls_reqs: "none" - db: 0 - cache_timeout: 300 - cache_timeout_flows: 300 - cache_timeout_policies: 300 - cache_timeout_reputation: 300 + +# broker: + # url: "" + # transport_options: "" + +cache: + # url: "" + timeout: 300 + timeout_flows: 300 + timeout_policies: 300 + timeout_reputation: 300 + +# channel: + # url: "" + +# result_backend: + # url: "" paths: media: ./media diff --git a/authentik/lib/tests/test_config.py b/authentik/lib/tests/test_config.py index d95ff8fb8..3c253663f 100644 --- a/authentik/lib/tests/test_config.py +++ b/authentik/lib/tests/test_config.py @@ -1,20 +1,32 @@ """Test config loader""" +import base64 +from json import dumps from os import chmod, environ, unlink, write from tempfile import mkstemp +from unittest import mock from django.conf import ImproperlyConfigured from django.test import TestCase -from authentik.lib.config import ENV_PREFIX, ConfigLoader +from authentik.lib.config import ENV_PREFIX, UNSET, Attr, AttrEncoder, ConfigLoader class TestConfig(TestCase): """Test config loader""" + check_deprecations_env_vars = { + ENV_PREFIX + "_REDIS__BROKER_URL": "redis://myredis:8327/43", + ENV_PREFIX + "_REDIS__BROKER_TRANSPORT_OPTIONS": "bWFzdGVybmFtZT1teW1hc3Rlcg==", + ENV_PREFIX + "_REDIS__CACHE_TIMEOUT": "124s", + ENV_PREFIX + "_REDIS__CACHE_TIMEOUT_FLOWS": "32m", + ENV_PREFIX + "_REDIS__CACHE_TIMEOUT_POLICIES": "3920ns", + ENV_PREFIX + "_REDIS__CACHE_TIMEOUT_REPUTATION": "298382us", + } + + @mock.patch.dict(environ, {ENV_PREFIX + "_test__test": "bar"}) def test_env(self): """Test simple instance""" config = ConfigLoader() - environ[ENV_PREFIX + "_test__test"] = "bar" config.update_from_env() self.assertEqual(config.get("test.test"), "bar") @@ -27,12 +39,20 @@ class TestConfig(TestCase): self.assertEqual(config.get("foo.bar"), "baz") self.assertEqual(config.get("foo.bar"), "bar") + @mock.patch.dict(environ, {"foo": "bar"}) def test_uri_env(self): """Test URI parsing (environment)""" config = ConfigLoader() - environ["foo"] = "bar" - self.assertEqual(config.parse_uri("env://foo").value, "bar") - self.assertEqual(config.parse_uri("env://foo?bar").value, "bar") + foo_uri = "env://foo" + foo_parsed = config.parse_uri(foo_uri) + self.assertEqual(foo_parsed.value, "bar") + self.assertEqual(foo_parsed.source_type, Attr.Source.URI) + self.assertEqual(foo_parsed.source, foo_uri) + foo_bar_uri = "env://foo?bar" + foo_bar_parsed = config.parse_uri(foo_bar_uri) + self.assertEqual(foo_bar_parsed.value, "bar") + self.assertEqual(foo_bar_parsed.source_type, Attr.Source.URI) + self.assertEqual(foo_bar_parsed.source, foo_bar_uri) def test_uri_file(self): """Test URI parsing (file load)""" @@ -91,3 +111,60 @@ class TestConfig(TestCase): config = ConfigLoader() config.set("foo", "bar") self.assertEqual(config.get_int("foo", 1234), 1234) + + def test_get_dict_from_b64_json(self): + """Test get_dict_from_b64_json""" + config = ConfigLoader() + test_value = ' { "foo": "bar" } '.encode("utf-8") + b64_value = base64.b64encode(test_value) + config.set("foo", b64_value) + self.assertEqual(config.get_dict_from_b64_json("foo"), {"foo": "bar"}) + + def test_get_dict_from_b64_json_missing_brackets(self): + """Test get_dict_from_b64_json with missing brackets""" + config = ConfigLoader() + test_value = ' "foo": "bar" '.encode("utf-8") + b64_value = base64.b64encode(test_value) + config.set("foo", b64_value) + self.assertEqual(config.get_dict_from_b64_json("foo"), {"foo": "bar"}) + + def test_get_dict_from_b64_json_invalid(self): + """Test get_dict_from_b64_json with invalid value""" + config = ConfigLoader() + config.set("foo", "bar") + self.assertEqual(config.get_dict_from_b64_json("foo"), {}) + + def test_attr_json_encoder(self): + """Test AttrEncoder""" + test_attr = Attr("foo", Attr.Source.ENV, "AUTHENTIK_REDIS__USERNAME") + json_attr = dumps(test_attr, indent=4, cls=AttrEncoder) + self.assertEqual(json_attr, '"foo"') + + def test_attr_json_encoder_no_attr(self): + """Test AttrEncoder if no Attr is passed""" + + class Test: + """Non Attr class""" + + with self.assertRaises(TypeError): + test_obj = Test() + dumps(test_obj, indent=4, cls=AttrEncoder) + + @mock.patch.dict(environ, check_deprecations_env_vars) + def test_check_deprecations(self): + """Test config key re-write for deprecated env vars""" + config = ConfigLoader() + config.update_from_env() + config.check_deprecations() + self.assertEqual(config.get("redis.broker_url", UNSET), UNSET) + self.assertEqual(config.get("redis.broker_transport_options", UNSET), UNSET) + self.assertEqual(config.get("redis.cache_timeout", UNSET), UNSET) + self.assertEqual(config.get("redis.cache_timeout_flows", UNSET), UNSET) + self.assertEqual(config.get("redis.cache_timeout_policies", UNSET), UNSET) + self.assertEqual(config.get("redis.cache_timeout_reputation", UNSET), UNSET) + self.assertEqual(config.get("broker.url"), "redis://myredis:8327/43") + self.assertEqual(config.get("broker.transport_options"), "bWFzdGVybmFtZT1teW1hc3Rlcg==") + self.assertEqual(config.get("cache.timeout"), "124s") + self.assertEqual(config.get("cache.timeout_flows"), "32m") + self.assertEqual(config.get("cache.timeout_policies"), "3920ns") + self.assertEqual(config.get("cache.timeout_reputation"), "298382us") diff --git a/authentik/outposts/consumer.py b/authentik/outposts/consumer.py index e8c2ee127..dda3feed0 100644 --- a/authentik/outposts/consumer.py +++ b/authentik/outposts/consumer.py @@ -93,7 +93,7 @@ class OutpostConsumer(AuthJsonConsumer): expected=self.outpost.config.kubernetes_replicas, ).dec() - def receive_json(self, content: Data): + def receive_json(self, content: Data, **kwargs): msg = from_dict(WebsocketMessage, content) uid = msg.args.get("uuid", self.channel_name) self.last_uid = uid diff --git a/authentik/policies/process.py b/authentik/policies/process.py index aa3ed9ff5..61ada16b7 100644 --- a/authentik/policies/process.py +++ b/authentik/policies/process.py @@ -20,7 +20,7 @@ from authentik.policies.types import CACHE_PREFIX, PolicyRequest, PolicyResult LOGGER = get_logger() FORK_CTX = get_context("fork") -CACHE_TIMEOUT = CONFIG.get_int("redis.cache_timeout_policies") +CACHE_TIMEOUT = CONFIG.get_int("cache.timeout_policies") PROCESS_CLASS = FORK_CTX.Process diff --git a/authentik/policies/reputation/signals.py b/authentik/policies/reputation/signals.py index 2ee6045df..49b8cf011 100644 --- a/authentik/policies/reputation/signals.py +++ b/authentik/policies/reputation/signals.py @@ -13,7 +13,7 @@ from authentik.policies.reputation.tasks import save_reputation from authentik.stages.identification.signals import identification_failed LOGGER = get_logger() -CACHE_TIMEOUT = CONFIG.get_int("redis.cache_timeout_reputation") +CACHE_TIMEOUT = CONFIG.get_int("cache.timeout_reputation") def update_score(request: HttpRequest, identifier: str, amount: int): diff --git a/authentik/root/settings.py b/authentik/root/settings.py index ee31f2cc6..5c9e5bf45 100644 --- a/authentik/root/settings.py +++ b/authentik/root/settings.py @@ -1,5 +1,4 @@ """root settings for authentik""" - import importlib import os from hashlib import sha512 @@ -195,8 +194,8 @@ _redis_url = ( CACHES = { "default": { "BACKEND": "django_redis.cache.RedisCache", - "LOCATION": f"{_redis_url}/{CONFIG.get('redis.db')}", - "TIMEOUT": CONFIG.get_int("redis.cache_timeout", 300), + "LOCATION": CONFIG.get("cache.url") or f"{_redis_url}/{CONFIG.get('redis.db')}", + "TIMEOUT": CONFIG.get_int("cache.timeout", 300), "OPTIONS": {"CLIENT_CLASS": "django_redis.client.DefaultClient"}, "KEY_PREFIX": "authentik_cache", } @@ -256,7 +255,7 @@ CHANNEL_LAYERS = { "default": { "BACKEND": "channels_redis.pubsub.RedisPubSubChannelLayer", "CONFIG": { - "hosts": [f"{_redis_url}/{CONFIG.get('redis.db')}"], + "hosts": [CONFIG.get("channel.url", f"{_redis_url}/{CONFIG.get('redis.db')}")], "prefix": "authentik_channels_", }, }, @@ -349,8 +348,11 @@ CELERY = { }, "task_create_missing_queues": True, "task_default_queue": "authentik", - "broker_url": f"{_redis_url}/{CONFIG.get('redis.db')}{_redis_celery_tls_requirements}", - "result_backend": f"{_redis_url}/{CONFIG.get('redis.db')}{_redis_celery_tls_requirements}", + "broker_url": CONFIG.get("broker.url") + or f"{_redis_url}/{CONFIG.get('redis.db')}{_redis_celery_tls_requirements}", + "broker_transport_options": CONFIG.get_dict_from_b64_json("broker.transport_options"), + "result_backend": CONFIG.get("result_backend.url") + or f"{_redis_url}/{CONFIG.get('redis.db')}{_redis_celery_tls_requirements}", } # Sentry integration diff --git a/internal/config/struct.go b/internal/config/struct.go index 27ad926b0..c42fb2c7a 100644 --- a/internal/config/struct.go +++ b/internal/config/struct.go @@ -27,14 +27,11 @@ type Config struct { type RedisConfig struct { Host string `yaml:"host" env:"AUTHENTIK_REDIS__HOST"` Port int `yaml:"port" env:"AUTHENTIK_REDIS__PORT"` + DB int `yaml:"db" env:"AUTHENTIK_REDIS__DB"` + Username string `yaml:"username" env:"AUTHENTIK_REDIS__USERNAME"` Password string `yaml:"password" env:"AUTHENTIK_REDIS__PASSWORD"` TLS bool `yaml:"tls" env:"AUTHENTIK_REDIS__TLS"` TLSReqs string `yaml:"tls_reqs" env:"AUTHENTIK_REDIS__TLS_REQS"` - DB int `yaml:"cache_db" env:"AUTHENTIK_REDIS__DB"` - CacheTimeout int `yaml:"cache_timeout" env:"AUTHENTIK_REDIS__CACHE_TIMEOUT"` - CacheTimeoutFlows int `yaml:"cache_timeout_flows" env:"AUTHENTIK_REDIS__CACHE_TIMEOUT_FLOWS"` - CacheTimeoutPolicies int `yaml:"cache_timeout_policies" env:"AUTHENTIK_REDIS__CACHE_TIMEOUT_POLICIES"` - CacheTimeoutReputation int `yaml:"cache_timeout_reputation" env:"AUTHENTIK_REDIS__CACHE_TIMEOUT_REPUTATION"` } type ListenConfig struct { diff --git a/website/docs/installation/configuration.mdx b/website/docs/installation/configuration.mdx index 9f90666d2..f2004d316 100644 --- a/website/docs/installation/configuration.mdx +++ b/website/docs/installation/configuration.mdx @@ -71,16 +71,38 @@ To check if your config has been applied correctly, you can run the following co ## Redis Settings -- `AUTHENTIK_REDIS__HOST`: Hostname of your Redis Server -- `AUTHENTIK_REDIS__PORT`: Redis port, defaults to 6379 -- `AUTHENTIK_REDIS__PASSWORD`: Password for your Redis Server -- `AUTHENTIK_REDIS__TLS`: Use TLS to connect to Redis, defaults to false -- `AUTHENTIK_REDIS__TLS_REQS`: Redis TLS requirements, defaults to "none" -- `AUTHENTIK_REDIS__DB`: Database, defaults to 0 -- `AUTHENTIK_REDIS__CACHE_TIMEOUT`: Timeout for cached data until it expires in seconds, defaults to 300 -- `AUTHENTIK_REDIS__CACHE_TIMEOUT_FLOWS`: Timeout for cached flow plans until they expire in seconds, defaults to 300 -- `AUTHENTIK_REDIS__CACHE_TIMEOUT_POLICIES`: Timeout for cached policies until they expire in seconds, defaults to 300 -- `AUTHENTIK_REDIS__CACHE_TIMEOUT_REPUTATION`: Timeout for cached reputation until they expire in seconds, defaults to 300 +- `AUTHENTIK_REDIS__HOST`: Redis server host when not using configuration URL +- `AUTHENTIK_REDIS__PORT`: Redis server port when not using configuration URL +- `AUTHENTIK_REDIS__DB`: Redis server database when not using configuration URL +- `AUTHENTIK_REDIS__USERNAME`: Redis server username when not using configuration URL +- `AUTHENTIK_REDIS__PASSWORD`: Redis server password when not using configuration URL +- `AUTHENTIK_REDIS__TLS`: Redis server connection using TLS when not using configuration URL +- `AUTHENTIK_REDIS__TLS_REQS`: Redis server TLS connection requirements when not using configuration URL + +## Result Backend Settings + +- `AUTHENTIK_RESULT_BACKEND__URL`: Result backend configuration URL, uses [the Redis Settings](#redis-settings) by default + +## Cache Settings + +- `AUTHENTIK_CACHE__URL`: Cache configuration URL, uses [the Redis Settings](#redis-settings) by default +- `AUTHENTIK_CACHE__TIMEOUT`: Timeout for cached data until it expires in seconds, defaults to 300 +- `AUTHENTIK_CACHE__TIMEOUT_FLOWS`: Timeout for cached flow plans until they expire in seconds, defaults to 300 +- `AUTHENTIK_CACHE__TIMEOUT_POLICIES`: Timeout for cached policies until they expire in seconds, defaults to 300 +- `AUTHENTIK_CACHE__TIMEOUT_REPUTATION`: Timeout for cached reputation until they expire in seconds, defaults to 300 + + :::info + `AUTHENTIK_CACHE__TIMEOUT_REPUTATION` only applies to the cache expiry, see [`AUTHENTIK_REPUTATION__EXPIRY`](#authentik_reputation__expiry) to control how long reputation is persisted for. + ::: + +## Channel Layer Settings (inter-instance communication) + +- `AUTHENTIK_CHANNEL__URL`: Channel layers configuration URL, uses [the Redis Settings](#redis-settings) by default + +## Broker Settings + +- `AUTHENTIK_BROKER__URL`: Broker configuration URL, defaults to Redis using [the respective settings](#redis-settings) +- `AUTHENTIK_BROKER__TRANSPORT_OPTIONS`: Base64 encoded broker transport options :::info `AUTHENTIK_REDIS__CACHE_TIMEOUT_REPUTATION` only applies to the cache expiry, see [`AUTHENTIK_REPUTATION__EXPIRY`](#authentik_reputation__expiry) to control how long reputation is persisted for. From a9fdacc60b1ede4494ef2017f6ed80528a912f27 Mon Sep 17 00:00:00 2001 From: "transifex-integration[bot]" <43880903+transifex-integration[bot]@users.noreply.github.com> Date: Mon, 13 Nov 2023 11:16:00 +0100 Subject: [PATCH 09/24] translate: Updates for file locale/en/LC_MESSAGES/django.po in zh_TW (#7537) Translate locale/en/LC_MESSAGES/django.po in zh_TW 100% translated source file: 'locale/en/LC_MESSAGES/django.po' on 'zh_TW'. Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com> --- locale/zh_TW/LC_MESSAGES/django.po | 2543 ++++++++++++++++++---------- 1 file changed, 1674 insertions(+), 869 deletions(-) diff --git a/locale/zh_TW/LC_MESSAGES/django.po b/locale/zh_TW/LC_MESSAGES/django.po index b89dbd140..3f66e1e82 100644 --- a/locale/zh_TW/LC_MESSAGES/django.po +++ b/locale/zh_TW/LC_MESSAGES/django.po @@ -4,172 +4,258 @@ # FIRST AUTHOR , YEAR. # # Translators: -# Chen Zhikai, 2022 # 刘松, 2022 +# Chen Zhikai, 2022 +# Passerby Dreamer, 2023 # #, fuzzy msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-01-03 12:29+0000\n" -"PO-Revision-Date: 2021-10-09 18:10+0000\n" -"Last-Translator: 刘松, 2022\n" -"Language-Team: Chinese (Taiwan) (https://www.transifex.com/authentik/teams/119923/zh_TW/)\n" +"POT-Creation-Date: 2023-10-02 12:46+0000\n" +"PO-Revision-Date: 2022-09-26 16:47+0000\n" +"Last-Translator: Passerby Dreamer, 2023\n" +"Language-Team: Chinese (Taiwan) (https://app.transifex.com/authentik/teams/119923/zh_TW/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: zh_TW\n" "Plural-Forms: nplurals=1; plural=0;\n" -#: authentik/admin/api/tasks.py:95 +#: authentik/admin/api/tasks.py:125 #, python-format msgid "Successfully re-scheduled Task %(name)s!" -msgstr "已成功重新安排任务%(name)s!" +msgstr "已成功重新安排任務%(name)s!" -#: authentik/api/schema.py:21 +#: authentik/api/schema.py:25 msgid "Generic API Error" -msgstr "通用 API 错误" +msgstr "通用 API 錯誤" -#: authentik/api/schema.py:29 +#: authentik/api/schema.py:33 msgid "Validation Error" -msgstr "校验错误" +msgstr "驗證錯誤" -#: authentik/core/api/providers.py:89 +#: authentik/blueprints/api.py:44 +msgid "Blueprint file does not exist" +msgstr "藍圖檔案不存在" + +#: authentik/blueprints/api.py:55 +#, python-format +msgid "Failed to validate blueprint: %(logs)s" +msgstr "無法驗證以下藍圖:%(logs)s" + +#: authentik/blueprints/api.py:60 +msgid "Either path or content must be set." +msgstr "必須設定路徑或內容其一。" + +#: authentik/blueprints/models.py:30 +msgid "Managed by authentik" +msgstr "由 authentik 管理" + +#: authentik/blueprints/models.py:32 +msgid "" +"Objects that are managed by authentik. These objects are created and updated" +" automatically. This flag only indicates that an object can be overwritten " +"by migrations. You can still modify the objects via the API, but expect " +"changes to be overwritten in a later update." +msgstr "" +"由 authentik 管理的物件。這些物件會自動地被建立和更新。這個旗標僅表示物件可以因遷移而被改寫。您仍然可以透過 API " +"修改物件,但預期在後續的更新中變更會被改寫。" + +#: authentik/blueprints/models.py:112 +msgid "Blueprint Instance" +msgstr "藍圖執行個體" + +#: authentik/blueprints/models.py:113 +msgid "Blueprint Instances" +msgstr "藍圖執行個體" + +#: authentik/blueprints/v1/exporter.py:62 +#, python-format +msgid "authentik Export - %(date)s" +msgstr "authentik 匯出 - %(date)s" + +#: authentik/blueprints/v1/tasks.py:150 authentik/crypto/tasks.py:93 +#, python-format +msgid "Successfully imported %(count)d files." +msgstr "已成功导入 %(count)d 个文件。" + +#: authentik/core/api/providers.py:120 msgid "SAML Provider from Metadata" -msgstr "基于Metadata的SAML请求发起端" +msgstr "從中繼資料取得 SAML 供應商" -#: authentik/core/api/providers.py:90 +#: authentik/core/api/providers.py:121 msgid "Create a SAML Provider by importing its Metadata." -msgstr "通过导入SAML请求发起端的Metadata来创建SAML请求发起端。" +msgstr "透過匯入中繼資料來建立 SAML 供應商。" -#: authentik/core/models.py:69 +#: authentik/core/api/users.py:158 +msgid "No leading or trailing slashes allowed." +msgstr "不允許使用前導或尾隨的斜線。" + +#: authentik/core/api/users.py:161 +msgid "No empty segments in user path allowed." +msgstr "使用者路徑中不允許有空字串。" + +#: authentik/core/models.py:86 msgid "name" -msgstr "名称" +msgstr "名稱" -#: authentik/core/models.py:71 +#: authentik/core/models.py:88 msgid "Users added to this group will be superusers." -msgstr "添加到该组的用户均为超级用户。" +msgstr "加入到該群組的使用者將會成為超級使用者。" -#: authentik/core/models.py:129 +#: authentik/core/models.py:142 msgid "User's display name." -msgstr "用户的显示名称。" +msgstr "使用者的顯示名稱。" -#: authentik/core/models.py:212 authentik/providers/oauth2/models.py:299 +#: authentik/core/models.py:268 authentik/providers/oauth2/models.py:295 msgid "User" -msgstr "用户" +msgstr "使用者" -#: authentik/core/models.py:213 +#: authentik/core/models.py:269 msgid "Users" -msgstr "用户" +msgstr "使用者" -#: authentik/core/models.py:224 +#: authentik/core/models.py:282 +msgid "" +"Flow used for authentication when the associated application is accessed by " +"an un-authenticated user." +msgstr "當未經認證的使用者存取相關應用程式時,用於認證的流程。" + +#: authentik/core/models.py:292 msgid "Flow used when authorizing this provider." -msgstr "授权此请求发起端时使用的Flow。" +msgstr "授權此供應商時所使用的流程。" -#: authentik/core/models.py:257 +#: authentik/core/models.py:304 +msgid "" +"Accessed from applications; optional backchannel providers for protocols " +"like LDAP and SCIM." +msgstr "從應用程式存取;對於像是 LDAP 和 SCIM 這類協定,提供可選的後端通道供應商。" + +#: authentik/core/models.py:359 msgid "Application's display Name." -msgstr "应用的显示名称。" +msgstr "應用程式的顯示名稱。" -#: authentik/core/models.py:258 +#: authentik/core/models.py:360 msgid "Internal application name, used in URLs." -msgstr "应用的内部名称,在URL中使用。" +msgstr "應用程式的內部名稱,將會用在網址中。" -#: authentik/core/models.py:311 +#: authentik/core/models.py:372 +msgid "Open launch URL in a new browser tab or window." +msgstr "從新瀏覽器分頁或視窗開啟網址。" + +#: authentik/core/models.py:436 msgid "Application" -msgstr "应用程序" +msgstr "應用程式" -#: authentik/core/models.py:312 +#: authentik/core/models.py:437 msgid "Applications" -msgstr "应用程序" +msgstr "應用程式" -#: authentik/core/models.py:318 +#: authentik/core/models.py:443 msgid "Use the source-specific identifier" -msgstr "使用源特定的标识符" +msgstr "使用基於來源的識別碼" -#: authentik/core/models.py:326 +#: authentik/core/models.py:445 +msgid "" +"Link to a user with identical email address. Can have security implications " +"when a source doesn't validate email addresses." +msgstr "連接到具有相同電子郵件地址的使用者。當來源不驗證電子郵件地址時,可能會有安全風險。" + +#: authentik/core/models.py:449 msgid "" "Use the user's email address, but deny enrollment when the email address " "already exists." -msgstr "使用用户的电子邮件地址,但在电子邮件地址已存在时拒绝注册。" +msgstr "使用使用者的電子郵件地址,但在電子郵件地址已存在時拒絕註冊。" -#: authentik/core/models.py:335 +#: authentik/core/models.py:452 +msgid "" +"Link to a user with identical username. Can have security implications when " +"a username is used with another source." +msgstr "連接到具有相同使用者名稱的使用者。當使用者名稱與其他來源一同使用時,可能會有安全風險。" + +#: authentik/core/models.py:456 msgid "" "Use the user's username, but deny enrollment when the username already " "exists." -msgstr "使用用户的用户名,但在用户名已存在时拒绝注册。" +msgstr "使用使用者的使用者名稱,但在使用者名稱已存在時拒絕註冊。" -#: authentik/core/models.py:342 +#: authentik/core/models.py:463 msgid "Source's display Name." -msgstr "源的显示名称。" +msgstr "來源的顯示名稱。" -#: authentik/core/models.py:343 +#: authentik/core/models.py:464 msgid "Internal source name, used in URLs." -msgstr "用于 URL的内部源名称。" +msgstr "用於網址的內部來源名稱。" -#: authentik/core/models.py:354 +#: authentik/core/models.py:483 msgid "Flow to use when authenticating existing users." -msgstr "认证已存在用户时所使用的流程。" +msgstr "認證已存在使用者時所使用的流程。" -#: authentik/core/models.py:363 +#: authentik/core/models.py:492 msgid "Flow to use when enrolling new users." -msgstr "新用户注册时所使用的流程。" +msgstr "新使用者註冊時所使用的流程。" -#: authentik/core/models.py:501 +#: authentik/core/models.py:500 +msgid "" +"How the source determines if an existing user should be authenticated or a " +"new user enrolled." +msgstr "來源如何確定應對現有使用者進行身份驗證,還是註冊新使用者。" + +#: authentik/core/models.py:672 msgid "Token" -msgstr "令牌" +msgstr "權杖" -#: authentik/core/models.py:502 +#: authentik/core/models.py:673 msgid "Tokens" -msgstr "令牌" +msgstr "權杖" -#: authentik/core/models.py:545 +#: authentik/core/models.py:714 msgid "Property Mapping" -msgstr "属性映射" +msgstr "屬性對應" -#: authentik/core/models.py:546 +#: authentik/core/models.py:715 msgid "Property Mappings" -msgstr "属性映射" +msgstr "屬性對應" -#: authentik/core/models.py:582 +#: authentik/core/models.py:750 msgid "Authenticated Session" -msgstr "已认证会话" +msgstr "已認證會談" -#: authentik/core/models.py:583 +#: authentik/core/models.py:751 msgid "Authenticated Sessions" -msgstr "已认证会话" +msgstr "已認證會談" -#: authentik/core/sources/flow_manager.py:166 -msgid "source" -msgstr "来源" +#: authentik/core/sources/flow_manager.py:189 +#, python-format +msgid "" +"Request to authenticate with %(source)s has been denied. Please authenticate" +" with the source you've previously signed up with." +msgstr "使用來自 %(source)s 的身份驗證請求已被拒絕。請使用您之前註冊過的來源進行身份驗證。" -#: authentik/core/sources/flow_manager.py:220 -#: authentik/core/sources/flow_manager.py:258 +#: authentik/core/sources/flow_manager.py:241 +msgid "Configured flow does not exist." +msgstr "已設定的流程不存在。" + +#: authentik/core/sources/flow_manager.py:271 +#: authentik/core/sources/flow_manager.py:323 #, python-format msgid "Successfully authenticated with %(source)s!" -msgstr "成功认证 %(source)s !" +msgstr "成功認證 %(source)s !" -#: authentik/core/sources/flow_manager.py:239 +#: authentik/core/sources/flow_manager.py:295 #, python-format msgid "Successfully linked %(source)s!" -msgstr "成功链接 %(source)s!" +msgstr "成功連結 %(source)s!" -#: authentik/core/templates/error/generic.html:27 -msgid "Go to home" -msgstr "返回主页" - -#: authentik/core/templates/if/admin.html:18 -#: authentik/core/templates/if/admin.html:24 -#: authentik/core/templates/if/flow.html:28 -#: authentik/core/templates/if/flow.html:34 -#: authentik/core/templates/if/user.html:18 -#: authentik/core/templates/if/user.html:24 -msgid "Loading..." -msgstr "载入中……" +#: authentik/core/sources/flow_manager.py:314 +msgid "Source is not configured for enrollment." +msgstr "來源未設定為用於註冊。" #: authentik/core/templates/if/end_session.html:7 msgid "End session" -msgstr "结束会话" +msgstr "結束會談" #: authentik/core/templates/if/end_session.html:11 #, python-format @@ -188,17 +274,23 @@ msgid "" " " msgstr "" "\n" -"您已成功登出 %(application)s 。 现在你可以返回总览并运行其他程序,或者登出的你的 authentik 账户。" +"您已成功登出 %(application)s 。 現在您可以返回總覽並啟動其他應用程式,或者登出您的 authentik 帳戶。" -#: authentik/core/templates/if/end_session.html:24 +#: authentik/core/templates/if/end_session.html:25 msgid "Go back to overview" -msgstr "返回总览" +msgstr "返回總覽" -#: authentik/core/templates/if/end_session.html:26 -msgid "Log out of authentik" -msgstr "登出 authentik" +#: authentik/core/templates/if/end_session.html:29 +#, python-format +msgid "" +"\n" +" Log out of %(branding_title)s\n" +" " +msgstr "" +"\n" +" 從 %(branding_title)s 登出" -#: authentik/core/templates/if/end_session.html:30 +#: authentik/core/templates/if/end_session.html:36 #, python-format msgid "" "\n" @@ -209,381 +301,585 @@ msgstr "" " 重新登入 %(application)s\n" " " -#: authentik/core/templates/login/base_full.html:65 +#: authentik/core/templates/if/error.html:18 +msgid "Go home" +msgstr "回到首頁" + +#: authentik/core/templates/login/base_full.html:89 msgid "Powered by authentik" -msgstr "由 authentik 强力驱动" +msgstr "由 authentik 技術支援" -#: authentik/crypto/api.py:132 +#: authentik/core/views/apps.py:53 +#: authentik/providers/oauth2/views/authorize.py:393 +#: authentik/providers/oauth2/views/device_init.py:70 +#: authentik/providers/saml/views/sso.py:70 +#, python-format +msgid "You're about to sign into %(application)s." +msgstr "您即將登入 %(application)s。" + +#: authentik/crypto/api.py:179 msgid "Subject-alt name" -msgstr "替代名称" +msgstr "替代名稱" -#: authentik/crypto/models.py:34 +#: authentik/crypto/models.py:30 msgid "PEM-encoded Certificate data" -msgstr "PEM 编码的证书数据" +msgstr "PEM 編碼的憑證資料" -#: authentik/crypto/models.py:37 +#: authentik/crypto/models.py:33 msgid "" "Optional Private Key. If this is set, you can use this keypair for " "encryption." -msgstr "可选私钥。如果设置了此设置,则可以使用此密钥对进行加密。" - -#: authentik/crypto/models.py:100 -msgid "Certificate-Key Pair" -msgstr "证书密钥对" +msgstr "可選:私鑰。如果設定了此選項,則可以使用此金鑰對進行加密。" #: authentik/crypto/models.py:101 +msgid "Certificate-Key Pair" +msgstr "憑證金鑰對" + +#: authentik/crypto/models.py:102 msgid "Certificate-Key Pairs" -msgstr "证书密钥对" +msgstr "憑證金鑰對" -#: authentik/crypto/tasks.py:93 -#, python-format -msgid "Successfully imported %(count)d files." -msgstr "已成功导入 %(count)d 个文件。" +#: authentik/enterprise/models.py:193 +msgid "License Usage" +msgstr "授權使用情況" -#: authentik/events/models.py:285 +#: authentik/enterprise/models.py:194 +msgid "License Usage Records" +msgstr "授權使用紀錄" + +#: authentik/events/models.py:290 msgid "Event" msgstr "事件" -#: authentik/events/models.py:286 +#: authentik/events/models.py:291 msgid "Events" msgstr "事件" -#: authentik/events/models.py:292 +#: authentik/events/models.py:297 +msgid "authentik inbuilt notifications" +msgstr "authentik 內建通知功能" + +#: authentik/events/models.py:298 msgid "Generic Webhook" msgstr "通用 Webhook" -#: authentik/events/models.py:293 +#: authentik/events/models.py:299 msgid "Slack Webhook (Slack/Discord)" msgstr "Slack Webhook(Slack/Discord)" -#: authentik/events/models.py:294 +#: authentik/events/models.py:300 msgid "Email" -msgstr "电子邮箱" +msgstr "電子郵件" -#: authentik/events/models.py:312 +#: authentik/events/models.py:318 msgid "" "Only send notification once, for example when sending a webhook into a chat " "channel." -msgstr "仅发送一次通知,例如在向聊天频道发送 Webhook 时。" +msgstr "僅發送一次通知,例如在向聊天頻道發送 Webhook 時。" -#: authentik/events/models.py:357 +#: authentik/events/models.py:383 msgid "Severity" -msgstr "严重程度" +msgstr "嚴重程度" -#: authentik/events/models.py:362 +#: authentik/events/models.py:388 msgid "Dispatched for user" -msgstr "为用户分派" +msgstr "為使用者分派" -#: authentik/events/models.py:439 +#: authentik/events/models.py:397 +msgid "Event user" +msgstr "事件使用者" + +#: authentik/events/models.py:491 msgid "Notification Transport" -msgstr "通知传输" +msgstr "通知通道" -#: authentik/events/models.py:440 +#: authentik/events/models.py:492 msgid "Notification Transports" -msgstr "通知传输" +msgstr "通知通道" -#: authentik/events/models.py:446 +#: authentik/events/models.py:498 msgid "Notice" msgstr "注意" -#: authentik/events/models.py:447 +#: authentik/events/models.py:499 msgid "Warning" msgstr "警告" -#: authentik/events/models.py:448 +#: authentik/events/models.py:500 msgid "Alert" -msgstr "注意" +msgstr "警報" -#: authentik/events/models.py:468 +#: authentik/events/models.py:525 msgid "Notification" msgstr "通知" -#: authentik/events/models.py:469 +#: authentik/events/models.py:526 msgid "Notifications" msgstr "通知" -#: authentik/events/models.py:488 +#: authentik/events/models.py:536 +msgid "" +"Select which transports should be used to notify the user. If none are " +"selected, the notification will only be shown in the authentik UI." +msgstr "選擇使用哪些傳輸通道來通知使用者。如果沒有選擇任何方式,通知將僅在 authentik 使用者介面中顯示。" + +#: authentik/events/models.py:544 msgid "Controls which severity level the created notifications will have." -msgstr "控制被创建的通知的严重性级别。" +msgstr "控制已建立通知的嚴重性等級。" -#: authentik/events/models.py:508 +#: authentik/events/models.py:549 +msgid "" +"Define which group of users this notification should be sent and shown to. " +"If left empty, Notification won't ben sent." +msgstr "定義應該向哪個群組的使用者發送和顯示此通知。如果未設定則不會發送通知。" + +#: authentik/events/models.py:567 msgid "Notification Rule" -msgstr "通知规则" +msgstr "通知規則" -#: authentik/events/models.py:509 +#: authentik/events/models.py:568 msgid "Notification Rules" -msgstr "通知规则" +msgstr "通知規則" -#: authentik/events/models.py:530 -msgid "Notification Webhook Mapping" -msgstr "通知 Webhook 映射" +#: authentik/events/models.py:588 +msgid "Webhook Mapping" +msgstr "Webhook 對應" -#: authentik/events/models.py:531 -msgid "Notification Webhook Mappings" -msgstr "通知 Webhook 映射" +#: authentik/events/models.py:589 +msgid "Webhook Mappings" +msgstr "Webhook 對應" -#: authentik/events/monitored_tasks.py:197 +#: authentik/events/monitored_tasks.py:205 msgid "Task has not been run yet." -msgstr "任务尚未运行。" +msgstr "任務尚未執行。" -#: authentik/flows/api/flows.py:350 +#: authentik/flows/api/flows.py:295 #, python-format msgid "Flow not applicable to current user/request: %(messages)s" -msgstr "Flow不适用于当前用户/请求: %(messages)s" +msgstr "流程不適用於當前使用者或請求: %(messages)s" -#: authentik/flows/models.py:107 -msgid "Visible in the URL." -msgstr "在 URL 中可见。" +#: authentik/flows/api/flows_diagram.py:68 +#: authentik/flows/api/flows_diagram.py:94 +#, python-format +msgid "Policy (%(type)s)" +msgstr "政策(%(type)s)" -#: authentik/flows/models.py:109 -msgid "Shown as the Title in Flow pages." -msgstr "显示为 “Flow” 页面中的标题。" +#: authentik/flows/api/flows_diagram.py:71 +#, python-format +msgid "Binding %(order)d" +msgstr "附加%(order)d" -#: authentik/flows/models.py:126 -msgid "Background shown during execution" -msgstr "执行时的背景" +#: authentik/flows/api/flows_diagram.py:118 +msgid "Policy passed" +msgstr "政策已通過" -#: authentik/flows/models.py:133 -msgid "" -"Enable compatibility mode, increases compatibility with password managers on" -" mobile devices." -msgstr "启用兼容模式,增加与移动设备上密码管理器的兼容性。" +#: authentik/flows/api/flows_diagram.py:122 +#, python-format +msgid "Stage (%(type)s)" +msgstr "階段(%(type)s)" -#: authentik/flows/models.py:178 +#: authentik/flows/api/flows_diagram.py:146 +#: authentik/flows/api/flows_diagram.py:206 +msgid "Policy denied" +msgstr "政策被拒" + +#: authentik/flows/api/flows_diagram.py:156 +#: authentik/flows/api/flows_diagram.py:168 +#: authentik/flows/api/flows_diagram.py:205 +#: authentik/flows/api/flows_diagram.py:227 +msgid "End of the flow" +msgstr "流程的結束點" + +#: authentik/flows/api/flows_diagram.py:169 +msgid "Requirement not fulfilled" +msgstr "需求未滿足" + +#: authentik/flows/api/flows_diagram.py:177 +msgid "Flow authentication requirement" +msgstr "流程身份驗證要求" + +#: authentik/flows/api/flows_diagram.py:183 +msgid "Requirement fulfilled" +msgstr "需求已滿足" + +#: authentik/flows/api/flows_diagram.py:196 +msgid "Pre-flow policies" +msgstr "在流程之前的政策" + +#: authentik/flows/api/flows_diagram.py:214 authentik/flows/models.py:193 msgid "Flow" msgstr "流程" -#: authentik/flows/models.py:179 +#: authentik/flows/exceptions.py:19 +msgid "Flow does not apply to current user." +msgstr "流程並未套用到目前的使用者。" + +#: authentik/flows/models.py:114 +#, python-format +msgid "Dynamic In-memory stage: %(doc)s" +msgstr "動態記憶體內儲存階段:%(doc)s" + +#: authentik/flows/models.py:129 +msgid "Visible in the URL." +msgstr "在網址列中可見。" + +#: authentik/flows/models.py:131 +msgid "Shown as the Title in Flow pages." +msgstr "做為在「流程」分頁中的標題。" + +#: authentik/flows/models.py:138 +msgid "" +"Decides what this Flow is used for. For example, the Authentication flow is " +"redirect to when an un-authenticated user visits authentik." +msgstr "決定此流程用於何種目的。例如,當未經驗證的使用者存取 authentik 時,會重新導向到身份驗證流程。" + +#: authentik/flows/models.py:147 +msgid "Background shown during execution" +msgstr "執行時顯示的背景" + +#: authentik/flows/models.py:154 +msgid "" +"Enable compatibility mode, increases compatibility with password managers on" +" mobile devices." +msgstr "啟用相容模式,增加與行動裝置上密碼管理器的相容性。" + +#: authentik/flows/models.py:162 +msgid "Configure what should happen when a flow denies access to a user." +msgstr "設定當流程拒絕某個使用者存取時,應該發生什麼事情。" + +#: authentik/flows/models.py:168 +msgid "Required level of authentication and authorization to access a flow." +msgstr "存取流程時所需的身份驗證和授權等級。" + +#: authentik/flows/models.py:194 msgid "Flows" msgstr "流程" -#: authentik/flows/models.py:209 -msgid "Evaluate policies when the Stage is present to the user." -msgstr "当阶段出现在用户面前时,评估策略。" +#: authentik/flows/models.py:215 +msgid "Evaluate policies during the Flow planning process." +msgstr "在流程規劃過程中的評估政策。" -#: authentik/flows/models.py:216 +#: authentik/flows/models.py:219 +msgid "Evaluate policies when the Stage is present to the user." +msgstr "當階段出現在使用者面前時的評估政策。" + +#: authentik/flows/models.py:226 msgid "" "Configure how the flow executor should handle an invalid response to a " "challenge. RETRY returns the error message and a similar challenge to the " "executor. RESTART restarts the flow from the beginning, and " "RESTART_WITH_CONTEXT restarts the flow while keeping the current context." msgstr "" -"配置流程执行器应如何处理对质询的无效响应。RETRY 向执行器返回错误消息和类似的质询。RESTART 从头开始重新启动流程。 " -"RESTART_WITH_CONTEXT 在保留当前上下文的同时重新启动流程。" +"設定流程執行器應如何處理對挑戰的無效回應。RETRY 向執行器回應錯誤訊息和類似的挑戰。RESTART " +"從頭開始重新啟動流程,RESTART_WITH_CONTEXT 在保留當前上下文的同時重新啟動流程。" -#: authentik/flows/models.py:240 +#: authentik/flows/models.py:249 msgid "Flow Stage Binding" -msgstr "流阶段绑定" +msgstr "流程階段附加" -#: authentik/flows/models.py:241 +#: authentik/flows/models.py:250 msgid "Flow Stage Bindings" -msgstr "流阶段绑定" +msgstr "流程階段附加" -#: authentik/flows/models.py:291 +#: authentik/flows/models.py:265 +msgid "" +"Flow used by an authenticated user to configure this Stage. If empty, user " +"will not be able to configure this stage." +msgstr "由已認證的使用者用來設定此階段的流程。如果未設定則使用者將無法設定此階段。" + +#: authentik/flows/models.py:305 msgid "Flow Token" -msgstr "流程令牌" +msgstr "流程權杖" -#: authentik/flows/models.py:292 +#: authentik/flows/models.py:306 msgid "Flow Tokens" -msgstr "流程令牌" +msgstr "流程權杖" -#: authentik/flows/templates/flows/error.html:12 -msgid "Whoops!" -msgstr "噢!" - -#: authentik/flows/templates/flows/error.html:17 -msgid "Something went wrong! Please try again later." -msgstr "发生错误,请稍后重试。" - -#: authentik/lib/utils/time.py:24 +#: authentik/lib/utils/time.py:27 #, python-format msgid "%(value)s is not in the correct format of 'hours=3;minutes=1'." -msgstr "%(value)s 的格式不正确,应为 'hours=3;minutes=1'。" +msgstr "%(value)s 不符合 'hours=3;minutes=1' 的正確格式。" -#: authentik/managed/models.py:12 -msgid "Managed by authentik" -msgstr "由 authentik 管理" - -#: authentik/outposts/api/service_connections.py:131 +#: authentik/outposts/api/service_connections.py:127 msgid "" "You can only use an empty kubeconfig when connecting to a local cluster." -msgstr "你只能在连接到本地集群时使用空的 kubeconfig。" +msgstr "您只能在連接到本機叢集時使用空的 kubeconfig。" -#: authentik/outposts/api/service_connections.py:139 +#: authentik/outposts/api/service_connections.py:135 msgid "Invalid kubeconfig" -msgstr "无效 Kubeconfig " +msgstr "無效的 kubeconfig" -#: authentik/outposts/models.py:151 -msgid "Outpost Service-Connection" -msgstr "Outpost Service-连接" +#: authentik/outposts/models.py:122 +msgid "" +"If enabled, use the local connection. Required Docker socket/Kubernetes " +"Integration" +msgstr "如果啟用將使用本機連線。需要 Docker socket / Kubernetes 整合。" #: authentik/outposts/models.py:152 -msgid "Outpost Service-Connections" -msgstr "Outpost Service-连接" +msgid "Outpost Service-Connection" +msgstr "Outpost 服務連線" -#: authentik/outposts/models.py:188 +#: authentik/outposts/models.py:153 +msgid "Outpost Service-Connections" +msgstr "Outpost 服務連線" + +#: authentik/outposts/models.py:161 +msgid "" +"Can be in the format of 'unix://' when connecting to a local docker " +"daemon, or 'https://:2376' when connecting to a remote system." +msgstr "" +"當連接到本地 Docker 常駐程式時,將會是 'unix://' 的格式,當連接到遠端系統時,將會是 " +"'https://:2376' 的格式。" + +#: authentik/outposts/models.py:173 +msgid "" +"CA which the endpoint's Certificate is verified against. Can be left empty " +"for no validation." +msgstr "用於驗證端點憑證的 CA(數位憑證認證機構)。若不需要驗證,可以留空。" + +#: authentik/outposts/models.py:185 msgid "" "Certificate/Key used for authentication. Can be left empty for no " "authentication." -msgstr "用于身份验证的证书/密钥。可以留空,留空表示不进行身份验证。" +msgstr "用於身份驗證的憑證/金鑰。可以留空表示不進行身份驗證。" -#: authentik/outposts/models.py:201 +#: authentik/outposts/models.py:203 msgid "Docker Service-Connection" -msgstr "Docker服务连接" +msgstr "Docker 服務連線" -#: authentik/outposts/models.py:202 +#: authentik/outposts/models.py:204 msgid "Docker Service-Connections" -msgstr "Docker服务连接" +msgstr "Docker 服務連線" -#: authentik/outposts/models.py:227 +#: authentik/outposts/models.py:212 +msgid "" +"Paste your kubeconfig here. authentik will automatically use the currently " +"selected context." +msgstr "在這裡貼上您的 kubeconfig。authentik 將自動使用當前選定的上下文。" + +#: authentik/outposts/models.py:218 +msgid "Verify SSL Certificates of the Kubernetes API endpoint" +msgstr "驗證 Kubernetes API 端點的 SSL 憑證" + +#: authentik/outposts/models.py:235 msgid "Kubernetes Service-Connection" -msgstr "Kubernetes 服务连接" +msgstr "Kubernetes 服務連線" -#: authentik/outposts/models.py:228 +#: authentik/outposts/models.py:236 msgid "Kubernetes Service-Connections" -msgstr "Kubernetes 服务连接" +msgstr "Kubernetes 服務連線" + +#: authentik/outposts/models.py:252 +msgid "" +"Select Service-Connection authentik should use to manage this outpost. Leave" +" empty if authentik should not handle the deployment." +msgstr "選擇 authentik 用於管理此前哨站的服務連線。請留空如果 authentik 不應處理此部署。" #: authentik/policies/denied.py:24 msgid "Access denied" -msgstr "访问被拒绝" +msgstr "存取被拒" + +#: authentik/policies/dummy/models.py:44 +msgid "Dummy Policy" +msgstr "假政策" #: authentik/policies/dummy/models.py:45 -msgid "Dummy Policy" -msgstr "虚拟策略" - -#: authentik/policies/dummy/models.py:46 msgid "Dummy Policies" -msgstr "虚拟策略" +msgstr "假政策" -#: authentik/policies/event_matcher/models.py:80 +#: authentik/policies/event_matcher/api.py:20 +#: authentik/policies/event_matcher/models.py:56 +msgid "" +"Match events created by selected application. When left empty, all " +"applications are matched." +msgstr "匹配由所選應用程式產生的事件。如果未設定則所有應用程式都將符合。" + +#: authentik/policies/event_matcher/api.py:29 +#: authentik/policies/event_matcher/models.py:64 +msgid "" +"Match events created by selected model. When left empty, all models are " +"matched. When an app is selected, all the application's models are matched." +msgstr "當未選擇任何模型時,會匹配所有模型產生的事件。如果選擇了某一個應用程式,則會匹配該應用程式下所有模型產生的事件。" + +#: authentik/policies/event_matcher/api.py:42 +msgid "At least one criteria must be set." +msgstr "必須設定至少一個條件。" + +#: authentik/policies/event_matcher/models.py:48 +msgid "" +"Match created events with this action type. When left empty, all action " +"types will be matched." +msgstr "匹配由此動作類型產生的事件。如果未設定則所有動作類型都將符合。" + +#: authentik/policies/event_matcher/models.py:73 +msgid "" +"Matches Event's Client IP (strict matching, for network matching use an " +"Expression Policy)" +msgstr "匹配事件的客戶端 IP(嚴格配對,若需進行網路層級配對,請使用表達式政策)" + +#: authentik/policies/event_matcher/models.py:143 msgid "Event Matcher Policy" -msgstr "事件匹配策略" +msgstr "事件配對政策" -#: authentik/policies/event_matcher/models.py:81 +#: authentik/policies/event_matcher/models.py:144 msgid "Event Matcher Policies" -msgstr "事件匹配策略" +msgstr "事件配對政策" -#: authentik/policies/expiry/models.py:46 -msgid "days" -msgstr "天" +#: authentik/policies/expiry/models.py:45 +#, python-format +msgid "Password expired %(days)d days ago. Please update your password." +msgstr "您的密碼在%(days)d天前已過期。請更新您的密碼。" #: authentik/policies/expiry/models.py:49 msgid "Password has expired." -msgstr "密码已过期。" +msgstr "密碼已過期。" + +#: authentik/policies/expiry/models.py:53 +msgid "Password Expiry Policy" +msgstr "密碼到期政策" #: authentik/policies/expiry/models.py:54 -msgid "Password Expiry Policy" -msgstr "密码过期策略" - -#: authentik/policies/expiry/models.py:55 msgid "Password Expiry Policies" -msgstr "密码过期策略" +msgstr "密碼到期政策" + +#: authentik/policies/expression/models.py:40 +msgid "Expression Policy" +msgstr "表達式政策" #: authentik/policies/expression/models.py:41 -msgid "Expression Policy" -msgstr "表达策略" - -#: authentik/policies/expression/models.py:42 msgid "Expression Policies" -msgstr "表达策略" +msgstr "表達式政策" -#: authentik/policies/hibp/models.py:22 -#: authentik/policies/password/models.py:24 -msgid "Field key to check, field keys defined in Prompt stages are available." -msgstr "要检查的字段键,提示阶段中定义的字段键可用。" - -#: authentik/policies/hibp/models.py:47 -#: authentik/policies/password/models.py:57 -msgid "Password not set in context" -msgstr "未在上下文中设置密码" - -#: authentik/policies/hibp/models.py:60 -#, python-format -msgid "Password exists on %(count)d online lists." -msgstr "在线列表%(count)d 中存在密码。" - -#: authentik/policies/hibp/models.py:66 -msgid "Have I Been Pwned Policy" -msgstr "我被控制了吗政策" - -#: authentik/policies/hibp/models.py:67 -msgid "Have I Been Pwned Policies" -msgstr "我被控制了吗政策" +#: authentik/policies/models.py:22 +msgid "all, all policies must pass" +msgstr "all, all 政策必須通過" #: authentik/policies/models.py:23 -msgid "ALL, all policies must pass" -msgstr "全部,必须通过所有策略" - -#: authentik/policies/models.py:25 -msgid "ANY, any policy must pass" -msgstr "任意,任一策略通过" - -#: authentik/policies/models.py:45 -msgid "Policy Binding Model" -msgstr "策略绑定模型" +msgid "any, any policy must pass" +msgstr "any, any 政策必須通過" #: authentik/policies/models.py:46 +msgid "Policy Binding Model" +msgstr "政策附加模型" + +#: authentik/policies/models.py:47 msgid "Policy Binding Models" -msgstr "策略绑定模型" +msgstr "政策附加模型" -#: authentik/policies/models.py:85 +#: authentik/policies/models.py:86 msgid "Negates the outcome of the policy. Messages are unaffected." -msgstr "否定政策的结果。消息不受影响。" +msgstr "否定政策的結果。訊息不受影響。" -#: authentik/policies/models.py:88 +#: authentik/policies/models.py:89 msgid "Timeout after which Policy execution is terminated." -msgstr "超时后,策略执行将终止。" +msgstr "逾時後,政策的執行將終止。" -#: authentik/policies/models.py:141 +#: authentik/policies/models.py:92 +msgid "Result if the Policy execution fails." +msgstr "如果政策執行失敗的結果。" + +#: authentik/policies/models.py:145 msgid "Policy Binding" -msgstr "策略绑定" +msgstr "政策附加" -#: authentik/policies/models.py:142 +#: authentik/policies/models.py:146 msgid "Policy Bindings" -msgstr "策略绑定" +msgstr "政策附加" -#: authentik/policies/models.py:181 +#: authentik/policies/models.py:167 +msgid "" +"When this option is enabled, all executions of this policy will be logged. " +"By default, only execution errors are logged." +msgstr "當啟用此選項時,將記錄此政策的所有執行操作。預設情況下,僅記錄執行錯誤。" + +#: authentik/policies/models.py:189 msgid "Policy" -msgstr "策略" +msgstr "政策" -#: authentik/policies/models.py:182 +#: authentik/policies/models.py:190 msgid "Policies" -msgstr "策略" +msgstr "政策" -#: authentik/policies/password/models.py:89 +#: authentik/policies/password/models.py:27 +msgid "Field key to check, field keys defined in Prompt stages are available." +msgstr "要檢查的欄位鍵,在提示階段中有可用的已定義欄位鍵。" + +#: authentik/policies/password/models.py:44 +msgid "How many times the password hash is allowed to be on haveibeenpwned" +msgstr "密碼雜湊在 haveibeenpwned 上允許出現的次數" + +#: authentik/policies/password/models.py:49 +msgid "" +"If the zxcvbn score is equal or less than this value, the policy will fail." +msgstr "如果 zxcvbn 分數等於或小於此值,則該政策將失敗。" + +#: authentik/policies/password/models.py:72 +msgid "Password not set in context" +msgstr "未在上下文中設定密碼" + +#: authentik/policies/password/models.py:134 +#, python-format +msgid "Password exists on %(count)d online lists." +msgstr "密碼存在於線上清單%(count)d 中。" + +#: authentik/policies/password/models.py:154 +msgid "Password is too weak." +msgstr "密碼強度太弱。" + +#: authentik/policies/password/models.py:162 msgid "Password Policy" -msgstr "密码策略" +msgstr "密碼政策" -#: authentik/policies/password/models.py:90 +#: authentik/policies/password/models.py:163 msgid "Password Policies" -msgstr "密码策略" +msgstr "密碼政策" -#: authentik/policies/reputation/models.py:54 +#: authentik/policies/reputation/api.py:18 +msgid "Either IP or Username must be checked" +msgstr "至少選取IP或使用者名稱其一" + +#: authentik/policies/reputation/models.py:67 msgid "Reputation Policy" -msgstr "信誉政策" +msgstr "信譽政策" -#: authentik/policies/reputation/models.py:55 +#: authentik/policies/reputation/models.py:68 msgid "Reputation Policies" -msgstr "信誉政策" +msgstr "信譽政策" + +#: authentik/policies/reputation/models.py:95 +msgid "Reputation Score" +msgstr "信譽分數" + +#: authentik/policies/reputation/models.py:96 +msgid "Reputation Scores" +msgstr "信譽分數" #: authentik/policies/templates/policies/denied.html:7 #: authentik/policies/templates/policies/denied.html:11 msgid "Permission denied" -msgstr "没有权限。" +msgstr "權限不足。" -#: authentik/policies/templates/policies/denied.html:20 +#: authentik/policies/templates/policies/denied.html:21 +msgid "User's avatar" +msgstr "個人檔案圖片" + +#: authentik/policies/templates/policies/denied.html:25 +msgid "Not you?" +msgstr "不是您嗎?" + +#: authentik/policies/templates/policies/denied.html:33 msgid "Request has been denied." -msgstr "请求被拒绝。" +msgstr "請求被拒。" -#: authentik/policies/templates/policies/denied.html:31 +#: authentik/policies/templates/policies/denied.html:44 msgid "Messages:" -msgstr "消息:" +msgstr "訊息:" -#: authentik/policies/templates/policies/denied.html:41 +#: authentik/policies/templates/policies/denied.html:54 msgid "Explanation:" -msgstr "解释:" +msgstr "解釋:" -#: authentik/policies/templates/policies/denied.html:45 +#: authentik/policies/templates/policies/denied.html:58 #, python-format msgid "" "\n" @@ -591,879 +887,1267 @@ msgid "" " " msgstr "" "\n" -" 策略绑定 '%(name)s' 返回结果 '%(result)s'\n" +" 附加政策 '%(name)s' 的回傳結果為 '%(result)s'\n" " " #: authentik/policies/views.py:68 msgid "Failed to resolve application" -msgstr "解析应用程序失败" +msgstr "解析應用程式失敗" #: authentik/providers/ldap/models.py:25 msgid "DN under which objects are accessible." -msgstr "在其下可以访问对象的 DN。" +msgstr "可連接到物件的 DN 位置。" #: authentik/providers/ldap/models.py:34 msgid "" "Users in this group can do search queries. If not set, every user can " "execute search queries." -msgstr "该组中的用户可以执行搜索查询。如果未设置,则每个用户都可以执行搜索查询。" +msgstr "該群組中的使用者可以執行搜尋查詢。如果未設定則每個使用者都可以執行搜尋查詢。" #: authentik/providers/ldap/models.py:53 msgid "" -"The start for uidNumbers, this number is added to the user.Pk to make sure " +"The start for uidNumbers, this number is added to the user.pk to make sure " "that the numbers aren't too low for POSIX users. Default is 2000 to ensure " "that we don't collide with local users uidNumber" msgstr "" -"对于UIDNumbers来说,这个数字被添加到User.pk中,以确保对于POSIX用户来说,这个数字不会太低。默认值为 " -"2000,以确保我们不会与本地用户 uidNumber 发生冲突" +"uidNumbers 的起始值,這個數值會和 user.pk 產生的數值相加,以確保 POSIX 使用者編號起始值不會太低。預設值為 " +"2000,以避免與本機使用者編號 uidNumber 發生衝突。" #: authentik/providers/ldap/models.py:62 msgid "" "The start for gidNumbers, this number is added to a number generated from " -"the group.Pk to make sure that the numbers aren't too low for POSIX groups. " +"the group.pk to make sure that the numbers aren't too low for POSIX groups. " "Default is 4000 to ensure that we don't collide with local groups or users " "primary groups gidNumber" msgstr "" -"对于 GIDNumbers 来说,这个数字被添加到从 group.pk 生成的数字中,以确保对于 POSIX 组来说,这个数字不会太低。默认值为 " -"4000,以确保我们不会与本地组或用户主组 GIDNumber 发生冲突" +"gidNumbers 的起始值,這個數值會和 group.pk 產生的數值相加,以確保 POSIX 群組編號起始值不會太低。預設值為 " +"4000,以避免與本機群組或使用者的主要群組編號 gidNumber 發生衝突。" -#: authentik/providers/ldap/models.py:97 +#: authentik/providers/ldap/models.py:76 +msgid "" +"When enabled, code-based multi-factor authentication can be used by " +"appending a semicolon and the TOTP code to the password. This should only be" +" enabled if all users that will bind to this provider have a TOTP device " +"configured, as otherwise a password may incorrectly be rejected if it " +"contains a semicolon." +msgstr "" +"當啟用此功能時,可以透過在密碼後加上分號及TOTP授權碼(範例:password:totp授權碼)來使用多重要素驗證。您應只有在所有要連線到此服務的使用者都已設定TOTP裝置的情況下,才啟用此功能。如果用戶的密碼中恰好包含分號,可能會因誤判而被拒絕存取。" + +#: authentik/providers/ldap/models.py:108 msgid "LDAP Provider" -msgstr "LDAP 提供商" +msgstr "LDAP 供應商" -#: authentik/providers/ldap/models.py:98 +#: authentik/providers/ldap/models.py:109 msgid "LDAP Providers" -msgstr "LDAP 提供商" +msgstr "LDAP 供應商" -#: authentik/providers/oauth2/models.py:36 -msgid "Confidential" -msgstr "机密" - -#: authentik/providers/oauth2/models.py:37 -msgid "Public" -msgstr "公开" - -#: authentik/providers/oauth2/models.py:51 +#: authentik/providers/oauth2/id_token.py:27 msgid "Based on the Hashed User ID" -msgstr "基于经过哈希处理的用户 ID" +msgstr "基於經過雜湊處理的使用者 ID" -#: authentik/providers/oauth2/models.py:52 +#: authentik/providers/oauth2/id_token.py:28 +msgid "Based on user ID" +msgstr "基於使用者 ID" + +#: authentik/providers/oauth2/id_token.py:29 +msgid "Based on user UUID" +msgstr "基於使用者 UUID" + +#: authentik/providers/oauth2/id_token.py:30 msgid "Based on the username" -msgstr "基于用户名" +msgstr "基於使用者名稱" -#: authentik/providers/oauth2/models.py:55 +#: authentik/providers/oauth2/id_token.py:33 msgid "Based on the User's Email. This is recommended over the UPN method." -msgstr "基于用户的电子邮件。 建议在 UPN 方法上使用此方法。" +msgstr "基於使用者的電子郵件。比起使用 UPN 更推薦此方法。" -#: authentik/providers/oauth2/models.py:71 +#: authentik/providers/oauth2/id_token.py:38 +msgid "" +"Based on the User's UPN, only works if user has a 'upn' attribute set. Use " +"this method only if you have different UPN and Mail domains." +msgstr "基於使用者的 UPN,只有當使用者設定了 「upn」 屬性時才有效。只有在您的 UPN 和 Mail 有不同網域時才使用這個方法。" + +#: authentik/providers/oauth2/models.py:43 +msgid "Confidential" +msgstr "機密" + +#: authentik/providers/oauth2/models.py:44 +msgid "Public" +msgstr "公開" + +#: authentik/providers/oauth2/models.py:66 msgid "Same identifier is used for all providers" -msgstr "所有提供商都使用相同的标识符" +msgstr "所有供應商都使用相同的識別碼" -#: authentik/providers/oauth2/models.py:73 +#: authentik/providers/oauth2/models.py:68 msgid "Each provider has a different issuer, based on the application slug." -msgstr "根据应用程序 slug,每个提供商都有不同的颁发者。" +msgstr "每個供應商都有一個不同的發行者,基於應用程式的縮寫(Slug)。" + +#: authentik/providers/oauth2/models.py:75 +msgid "code (Authorization Code Flow)" +msgstr "code(授權碼流程)" + +#: authentik/providers/oauth2/models.py:76 +msgid "id_token (Implicit Flow)" +msgstr "id_token(隱式流程)" + +#: authentik/providers/oauth2/models.py:77 +msgid "id_token token (Implicit Flow)" +msgstr "id_token 權杖(隱式流程)" + +#: authentik/providers/oauth2/models.py:78 +msgid "code token (Hybrid Flow)" +msgstr "授權碼權杖(混合流程)" + +#: authentik/providers/oauth2/models.py:79 +msgid "code id_token (Hybrid Flow)" +msgstr "授權碼 id_token(混合流程)" #: authentik/providers/oauth2/models.py:80 -msgid "code (Authorization Code Flow)" -msgstr "code(授权码流)" - -#: authentik/providers/oauth2/models.py:81 -msgid "id_token (Implicit Flow)" -msgstr "id_token(隐式流)" - -#: authentik/providers/oauth2/models.py:82 -msgid "id_token token (Implicit Flow)" -msgstr "id_token 令牌(隐式流)" - -#: authentik/providers/oauth2/models.py:83 -msgid "code token (Hybrid Flow)" -msgstr "代码令牌(混合流)" - -#: authentik/providers/oauth2/models.py:84 -msgid "code id_token (Hybrid Flow)" -msgstr "code id_token(混合流)" - -#: authentik/providers/oauth2/models.py:85 msgid "code id_token token (Hybrid Flow)" -msgstr "code id_token 令牌(混合流)" +msgstr "授權碼 id_token 權杖(混合流程)" -#: authentik/providers/oauth2/models.py:91 +#: authentik/providers/oauth2/models.py:86 msgid "HS256 (Symmetric Encryption)" -msgstr "HS256(对称加密)" +msgstr "HS256(對稱加密)" -#: authentik/providers/oauth2/models.py:92 +#: authentik/providers/oauth2/models.py:87 msgid "RS256 (Asymmetric Encryption)" -msgstr "RS256(非对称加密)" +msgstr "RS256(非對稱加密)" -#: authentik/providers/oauth2/models.py:93 +#: authentik/providers/oauth2/models.py:88 msgid "ES256 (Asymmetric Encryption)" -msgstr "" +msgstr "ES256(非對稱加密)" -#: authentik/providers/oauth2/models.py:99 +#: authentik/providers/oauth2/models.py:94 msgid "Scope used by the client" -msgstr "客户端使用的作用域(Scope)" +msgstr "用戶端使用的範疇" -#: authentik/providers/oauth2/models.py:125 +#: authentik/providers/oauth2/models.py:98 +msgid "" +"Description shown to the user when consenting. If left empty, the user won't" +" be informed." +msgstr "當需要使用者同意時顯示的說明。如果未設定將不會顯示。" + +#: authentik/providers/oauth2/models.py:117 msgid "Scope Mapping" -msgstr "作用域映射" +msgstr "範疇對應" -#: authentik/providers/oauth2/models.py:126 +#: authentik/providers/oauth2/models.py:118 msgid "Scope Mappings" -msgstr "作用域映射" +msgstr "範疇對應" -#: authentik/providers/oauth2/models.py:136 +#: authentik/providers/oauth2/models.py:128 msgid "Client Type" -msgstr "客户端类型" +msgstr "用戶端類型" -#: authentik/providers/oauth2/models.py:142 +#: authentik/providers/oauth2/models.py:130 +msgid "" +"Confidential clients are capable of maintaining the confidentiality of their" +" credentials. Public clients are incapable" +msgstr "機密用戶端能夠維護其憑證的機密性。公開用戶端則無法做到這一點。" + +#: authentik/providers/oauth2/models.py:137 msgid "Client ID" -msgstr "客户端 ID" +msgstr "用戶端 ID" -#: authentik/providers/oauth2/models.py:148 +#: authentik/providers/oauth2/models.py:143 msgid "Client Secret" -msgstr "客户端密钥" +msgstr "用戶端金鑰" -#: authentik/providers/oauth2/models.py:154 +#: authentik/providers/oauth2/models.py:149 msgid "Redirect URIs" -msgstr "重定向 URI" +msgstr "重新導向 URI" + +#: authentik/providers/oauth2/models.py:150 +msgid "Enter each URI on a new line." +msgstr "每行輸入一個網址。" #: authentik/providers/oauth2/models.py:155 -msgid "Enter each URI on a new line." -msgstr "每行输入一个URL。" - -#: authentik/providers/oauth2/models.py:160 msgid "Include claims in id_token" -msgstr "在 id_token 中包含声明" +msgstr "在 id_token 中包含聲明" -#: authentik/providers/oauth2/models.py:208 -msgid "RSA Key" -msgstr "RSA 密钥" +#: authentik/providers/oauth2/models.py:157 +msgid "" +"Include User claims from scopes in the id_token, for applications that don't" +" access the userinfo endpoint." +msgstr "在 id_token 中包含來自範疇的使用者聲明,適用於那些不存取 userinfo 端點的應用程式。" -#: authentik/providers/oauth2/models.py:212 +#: authentik/providers/oauth2/models.py:166 +msgid "" +"Access codes not valid on or after current time + this value (Format: " +"hours=1;minutes=2;seconds=3)." +msgstr "存取授權碼在當前時間加上此值後並非有效(格式:hours=1;minutes=2;seconds=3)。" + +#: authentik/providers/oauth2/models.py:174 +#: authentik/providers/oauth2/models.py:182 +msgid "" +"Tokens not valid on or after current time + this value (Format: " +"hours=1;minutes=2;seconds=3)." +msgstr "權杖在當前時間加上此值後並非有效(格式:hours=1;minutes=2;seconds=3)。" + +#: authentik/providers/oauth2/models.py:191 +msgid "" +"Configure what data should be used as unique User Identifier. For most " +"cases, the default should be fine." +msgstr "設定應該使用哪些資料作為唯一的使用者識別碼。在大多數情況下使用預設值即可。 " + +#: authentik/providers/oauth2/models.py:198 +msgid "Configure how the issuer field of the ID Token should be filled." +msgstr "設定該如何填寫 ID 權杖的發行者欄位。" + +#: authentik/providers/oauth2/models.py:203 +msgid "Signing Key" +msgstr "簽署金鑰" + +#: authentik/providers/oauth2/models.py:207 msgid "" "Key used to sign the tokens. Only required when JWT Algorithm is set to " "RS256." -msgstr "用于对令牌进行签名的密钥。仅当JWT算法设置为 RS256 时才需要。" +msgstr "用於對權杖進行簽署的金鑰。僅當 JWT 雜湊演算法設定為 RS256 時才需要。" -#: authentik/providers/oauth2/models.py:291 +#: authentik/providers/oauth2/models.py:214 +msgid "" +"Any JWT signed by the JWK of the selected source can be used to " +"authenticate." +msgstr "任何由選擇的 JWK 來源所簽署的 JWT 都可以用來進行身份驗證。" + +#: authentik/providers/oauth2/models.py:287 msgid "OAuth2/OpenID Provider" -msgstr "OAuth2/OpenID 提供商" +msgstr "OAuth2/OpenID 供應商" -#: authentik/providers/oauth2/models.py:292 +#: authentik/providers/oauth2/models.py:288 msgid "OAuth2/OpenID Providers" -msgstr "OAuth2/OpenID 提供商" +msgstr "OAuth2/OpenID 供應商" -#: authentik/providers/oauth2/models.py:300 +#: authentik/providers/oauth2/models.py:297 +#: authentik/providers/oauth2/models.py:429 msgid "Scopes" -msgstr "范围" +msgstr "範疇" -#: authentik/providers/oauth2/models.py:319 +#: authentik/providers/oauth2/models.py:316 msgid "Code" -msgstr "代码" +msgstr "授權碼" + +#: authentik/providers/oauth2/models.py:317 +msgid "Nonce" +msgstr "Nonce(單次使用隨機亂數)" + +#: authentik/providers/oauth2/models.py:318 +msgid "Code Challenge" +msgstr "授權碼驗證挑戰" #: authentik/providers/oauth2/models.py:320 -msgid "Nonce" -msgstr "Nonce" - -#: authentik/providers/oauth2/models.py:321 -msgid "Is Authentication?" -msgstr "是身份验证吗?" - -#: authentik/providers/oauth2/models.py:322 -msgid "Code Challenge" -msgstr "代码质询" - -#: authentik/providers/oauth2/models.py:324 msgid "Code Challenge Method" -msgstr "代码质询方法" +msgstr "授權碼驗證挑戰方法" -#: authentik/providers/oauth2/models.py:338 +#: authentik/providers/oauth2/models.py:340 msgid "Authorization Code" -msgstr "授权码" +msgstr "授權碼" -#: authentik/providers/oauth2/models.py:339 +#: authentik/providers/oauth2/models.py:341 msgid "Authorization Codes" -msgstr "授权码" - -#: authentik/providers/oauth2/models.py:382 -msgid "Access Token" -msgstr "访问令牌" +msgstr "授權碼" #: authentik/providers/oauth2/models.py:383 -msgid "Refresh Token" -msgstr "刷新令牌" +msgid "OAuth2 Access Token" +msgstr "OAuth2 存取權杖" #: authentik/providers/oauth2/models.py:384 +msgid "OAuth2 Access Tokens" +msgstr "OAuth2 存取權杖" + +#: authentik/providers/oauth2/models.py:394 msgid "ID Token" -msgstr "ID 令牌" +msgstr "ID 權杖" -#: authentik/providers/oauth2/models.py:387 -msgid "OAuth2 Token" -msgstr "OAuth2 令牌" +#: authentik/providers/oauth2/models.py:413 +msgid "OAuth2 Refresh Token" +msgstr "OAuth2 更新權杖" -#: authentik/providers/oauth2/models.py:388 -msgid "OAuth2 Tokens" -msgstr "OAuth2 令牌" +#: authentik/providers/oauth2/models.py:414 +msgid "OAuth2 Refresh Tokens" +msgstr "OAuth2 更新權杖" -#: authentik/providers/oauth2/views/authorize.py:458 -#: authentik/providers/saml/views/sso.py:69 +#: authentik/providers/oauth2/models.py:441 +msgid "Device Token" +msgstr "裝置權杖" + +#: authentik/providers/oauth2/models.py:442 +msgid "Device Tokens" +msgstr "裝置權杖" + +#: authentik/providers/oauth2/views/authorize.py:448 +#: authentik/providers/saml/views/flows.py:87 #, python-format -msgid "You're about to sign into %(application)s." -msgstr "你即将登入 %(application)s。" +msgid "Redirecting to %(app)s..." +msgstr "重新導向到%(app)s..." -#: authentik/providers/proxy/models.py:52 +#: authentik/providers/oauth2/views/device_init.py:151 +msgid "Invalid code" +msgstr "無效的授權碼" + +#: authentik/providers/oauth2/views/userinfo.py:55 +#: authentik/providers/oauth2/views/userinfo.py:56 +msgid "GitHub Compatibility: Access your User Information" +msgstr "GitHub 相容性:存取您的使用者資訊" + +#: authentik/providers/oauth2/views/userinfo.py:57 +msgid "GitHub Compatibility: Access you Email addresses" +msgstr "GitHub 相容性:存取您的電子郵件地址" + +#: authentik/providers/oauth2/views/userinfo.py:58 +msgid "GitHub Compatibility: Access your Groups" +msgstr "GitHub 相容性:存取您的群組" + +#: authentik/providers/oauth2/views/userinfo.py:59 +msgid "authentik API Access on behalf of your user" +msgstr "代表您的使用者存取 authentik API" + +#: authentik/providers/proxy/api.py:52 +msgid "User and password attributes must be set when basic auth is enabled." +msgstr "啟用基本認證時必須設定使用者和密碼屬性。" + +#: authentik/providers/proxy/api.py:63 +msgid "Internal host cannot be empty when forward auth is disabled." +msgstr "當禁用轉發認證時,內部主機不能為空。" + +#: authentik/providers/proxy/models.py:54 msgid "Validate SSL Certificates of upstream servers" -msgstr "验证上游服务器的 SSL 证书" +msgstr "驗證上游伺服器的 SSL 憑證" -#: authentik/providers/proxy/models.py:53 +#: authentik/providers/proxy/models.py:55 msgid "Internal host SSL Validation" -msgstr "内部主机 SSL 验证" +msgstr "內部主機 SSL 驗證" -#: authentik/providers/proxy/models.py:59 +#: authentik/providers/proxy/models.py:61 msgid "" "Enable support for forwardAuth in traefik and nginx auth_request. Exclusive " "with internal_host." -msgstr "在 traefik 和 nginx auth_request 中启用对 ForwardAuth 的支持。internal_host 独有。" +msgstr "" +"啟用在 traefik 和 nginx auth_request 中對 ForwardAuth 的支援。只在 internal_host 可使用。" -#: authentik/providers/proxy/models.py:77 +#: authentik/providers/proxy/models.py:70 +msgid "" +"Regular expressions for which authentication is not required. Each new line " +"is interpreted as a new Regular Expression." +msgstr "不需要身份驗證的正規表示式。每一行各都被解釋為一個正規表示式。" + +#: authentik/providers/proxy/models.py:78 +msgid "" +"When enabled, this provider will intercept the authorization header and " +"authenticate requests based on its value." +msgstr "當啟用時,此供應商將攔截授權標頭並根據其值對請求進行身份驗證。" + +#: authentik/providers/proxy/models.py:84 msgid "Set HTTP-Basic Authentication" -msgstr "设置 HTTP 基本身份验证" +msgstr "設定 HTTP 基本身份認證" -#: authentik/providers/proxy/models.py:79 +#: authentik/providers/proxy/models.py:86 msgid "" "Set a custom HTTP-Basic Authentication header based on values from " "authentik." -msgstr "根据来自 authentik 的值设置自定义 HTTP-Basic 身份验证标头。" +msgstr "透過 authentik 設定的值客製化 HTTP 基本身份驗證的標頭。" -#: authentik/providers/proxy/models.py:84 +#: authentik/providers/proxy/models.py:91 msgid "HTTP-Basic Username Key" -msgstr "HTTP-Basic 用户名密钥" +msgstr "HTTP 基本身份驗證的使用者名鍵值" -#: authentik/providers/proxy/models.py:94 +#: authentik/providers/proxy/models.py:93 +msgid "" +"User/Group Attribute used for the user part of the HTTP-Basic Header. If not" +" set, the user's Email address is used." +msgstr "用於 HTTP 基本身份驗證標頭中,使用者區塊中的使用者/群組屬性。如果未設定則套用使用者的電子郵件地址。" + +#: authentik/providers/proxy/models.py:99 msgid "HTTP-Basic Password Key" -msgstr "HTTP-Basic 密码密钥" +msgstr "HTTP 基本身份驗證的密碼鍵值" -#: authentik/providers/proxy/models.py:149 +#: authentik/providers/proxy/models.py:100 +msgid "" +"User/Group Attribute used for the password part of the HTTP-Basic Header." +msgstr "用於 HTTP 基本身份驗證標頭中,密碼區塊中的用戶/群組屬性。" + +#: authentik/providers/proxy/models.py:154 msgid "Proxy Provider" -msgstr "代理提供商" +msgstr "代理伺服器供應商" -#: authentik/providers/proxy/models.py:150 +#: authentik/providers/proxy/models.py:155 msgid "Proxy Providers" -msgstr "代理提供商" +msgstr "代理伺服器供應商" -#: authentik/providers/saml/api.py:176 +#: authentik/providers/radius/models.py:18 +msgid "Shared secret between clients and server to hash packets." +msgstr "用於用戶端與伺服器之間封包雜湊處理的共享金鑰。" + +#: authentik/providers/radius/models.py:24 +msgid "" +"List of CIDRs (comma-separated) that clients can connect from. A more " +"specific CIDR will match before a looser one. Clients connecting from a non-" +"specified CIDR will be dropped." +msgstr "用戶端可以從中連線的CIDR列表(以逗號分隔)。較窄的CIDR會在較寬的CIDR之前優先套用。來自未指定CIDR的用戶端連線將被拒絕。" + +#: authentik/providers/radius/models.py:49 +msgid "Radius Provider" +msgstr "Radius 供應商" + +#: authentik/providers/radius/models.py:50 +msgid "Radius Providers" +msgstr "Radius 供應商" + +#: authentik/providers/saml/api/providers.py:257 msgid "Invalid XML Syntax" -msgstr "XML 语法无效" +msgstr "無效的 XML 語法" -#: authentik/providers/saml/api.py:186 +#: authentik/providers/saml/api/providers.py:267 #, python-format msgid "Failed to import Metadata: %(message)s" -msgstr "导入元数据失败:%(message)s" +msgstr "匯入中繼資料失敗:%(message)s" #: authentik/providers/saml/models.py:38 msgid "ACS URL" -msgstr "ACS URL" +msgstr "ACS 網址" -#: authentik/providers/saml/models.py:49 +#: authentik/providers/saml/models.py:43 +msgid "" +"Value of the audience restriction field of the assertion. When left empty, " +"no audience restriction will be added." +msgstr "斷言的目標對象來源限制欄位的值。當未設定時將不會對任何目標對象進行限制。" + +#: authentik/providers/saml/models.py:47 msgid "Also known as EntityID" -msgstr "也称为 EntityID" +msgstr "也稱為 EntityID" + +#: authentik/providers/saml/models.py:51 +msgid "Service Provider Binding" +msgstr "服務供應商附加" #: authentik/providers/saml/models.py:53 -msgid "Service Provider Binding" -msgstr "服务提供商绑定" +msgid "" +"This determines how authentik sends the response back to the Service " +"Provider." +msgstr "這決定了 authentik 如何將回應發送回服務供應商。" + +#: authentik/providers/saml/models.py:63 +msgid "NameID Property Mapping" +msgstr "NameID 屬性對應" #: authentik/providers/saml/models.py:65 -msgid "NameID Property Mapping" -msgstr "nameID 属性映射" +msgid "" +"Configure how the NameID value will be created. When left empty, the " +"NameIDPolicy of the incoming request will be considered" +msgstr "設定 NameID 值建立的方式。如果未設定則會使用傳入請求中的 NameIDPolicy。" -#: authentik/providers/saml/models.py:109 authentik/sources/saml/models.py:128 +#: authentik/providers/saml/models.py:74 +msgid "" +"Assertion valid not before current time + this value (Format: " +"hours=-1;minutes=-2;seconds=-3)." +msgstr "斷言的有效起始時間是當前時間加上此值(格式:hours=-1;minutes=-2;seconds=-3)。" + +#: authentik/providers/saml/models.py:82 +msgid "" +"Assertion not valid on or after current time + this value (Format: " +"hours=1;minutes=2;seconds=3)." +msgstr "斷言的有效期限為當前時間加上此值(格式:hours=1;minutes=2;seconds=3)。" + +#: authentik/providers/saml/models.py:91 +msgid "" +"Session not valid on or after current time + this value (Format: " +"hours=1;minutes=2;seconds=3)." +msgstr "會談的有效期限是當前時間加上此值(格式:hours=1;minutes=2;seconds=3)。" + +#: authentik/providers/saml/models.py:99 authentik/sources/saml/models.py:150 msgid "SHA1" msgstr "SHA1" -#: authentik/providers/saml/models.py:110 authentik/sources/saml/models.py:129 +#: authentik/providers/saml/models.py:100 authentik/sources/saml/models.py:151 msgid "SHA256" msgstr "SHA256" -#: authentik/providers/saml/models.py:111 authentik/sources/saml/models.py:130 +#: authentik/providers/saml/models.py:101 authentik/sources/saml/models.py:152 msgid "SHA384" msgstr "SHA384" -#: authentik/providers/saml/models.py:112 authentik/sources/saml/models.py:131 +#: authentik/providers/saml/models.py:102 authentik/sources/saml/models.py:153 msgid "SHA512" msgstr "SHA512" -#: authentik/providers/saml/models.py:119 authentik/sources/saml/models.py:138 +#: authentik/providers/saml/models.py:109 authentik/sources/saml/models.py:160 msgid "RSA-SHA1" msgstr "RSA-SHA1" -#: authentik/providers/saml/models.py:120 authentik/sources/saml/models.py:139 +#: authentik/providers/saml/models.py:110 authentik/sources/saml/models.py:161 msgid "RSA-SHA256" msgstr "RSA-SHA256" -#: authentik/providers/saml/models.py:121 authentik/sources/saml/models.py:140 +#: authentik/providers/saml/models.py:111 authentik/sources/saml/models.py:162 msgid "RSA-SHA384" msgstr "RSA-SHA384" -#: authentik/providers/saml/models.py:122 authentik/sources/saml/models.py:141 +#: authentik/providers/saml/models.py:112 authentik/sources/saml/models.py:163 msgid "RSA-SHA512" msgstr "RSA-SHA512" -#: authentik/providers/saml/models.py:123 authentik/sources/saml/models.py:142 +#: authentik/providers/saml/models.py:113 authentik/sources/saml/models.py:164 msgid "DSA-SHA1" msgstr "DSA-SHA1" -#: authentik/providers/saml/models.py:140 +#: authentik/providers/saml/models.py:124 authentik/sources/saml/models.py:130 +msgid "" +"When selected, incoming assertion's Signatures will be validated against " +"this certificate. To allow unsigned Requests, leave on default." +msgstr "當選擇後,傳入的斷言簽章將會根據這個憑證進行驗證。若要允許未簽屬的請求,請保留為預設值。" + +#: authentik/providers/saml/models.py:128 authentik/sources/saml/models.py:134 msgid "Verification Certificate" -msgstr "验证证书" +msgstr "驗證憑證" -#: authentik/providers/saml/models.py:148 +#: authentik/providers/saml/models.py:136 msgid "Keypair used to sign outgoing Responses going to the Service Provider." -msgstr "密钥对用于签署发送给服务提供商的外发响应。" +msgstr "用於簽署傳給服務供應商回應的金鑰對。" -#: authentik/providers/saml/models.py:150 authentik/sources/saml/models.py:118 +#: authentik/providers/saml/models.py:138 authentik/sources/saml/models.py:144 msgid "Signing Keypair" -msgstr "签名密钥对" +msgstr "簽署金鑰對" -#: authentik/providers/saml/models.py:180 +#: authentik/providers/saml/models.py:167 msgid "SAML Provider" -msgstr "SAML 提供商" +msgstr "SAML 供應商" -#: authentik/providers/saml/models.py:181 +#: authentik/providers/saml/models.py:168 msgid "SAML Providers" -msgstr "SAML 提供商" +msgstr "SAML 供應商" -#: authentik/providers/saml/models.py:206 +#: authentik/providers/saml/models.py:192 msgid "SAML Property Mapping" -msgstr "SAML 属性映射" +msgstr "SAML 屬性對應" -#: authentik/providers/saml/models.py:207 +#: authentik/providers/saml/models.py:193 msgid "SAML Property Mappings" -msgstr "SAML 属性映射" +msgstr "SAML 屬性對應" + +#: authentik/providers/scim/models.py:20 +msgid "Base URL to SCIM requests, usually ends in /v2" +msgstr "SCIM 要求中的基礎網址,通常以 /v2 結尾。" + +#: authentik/providers/scim/models.py:21 +msgid "Authentication token" +msgstr "認證權杖" + +#: authentik/providers/scim/models.py:27 authentik/sources/ldap/models.py:94 +msgid "Property mappings used for group creation/updating." +msgstr "用於建立或更新群組的屬性對應。" + +#: authentik/providers/scim/models.py:60 +msgid "SCIM Provider" +msgstr "SCIM 供應商" + +#: authentik/providers/scim/models.py:61 +msgid "SCIM Providers" +msgstr "SCIM 供應商" + +#: authentik/providers/scim/models.py:81 +msgid "SCIM Mapping" +msgstr "SCIM 對應" + +#: authentik/providers/scim/models.py:82 +msgid "SCIM Mappings" +msgstr "SCIM 對應" + +#: authentik/providers/scim/tasks.py:52 +msgid "Starting full SCIM sync" +msgstr "開始完全同步 SCIM" + +#: authentik/providers/scim/tasks.py:59 +#, python-format +msgid "Syncing page %(page)d of users" +msgstr "同步第 %(page)d 頁中的使用者" + +#: authentik/providers/scim/tasks.py:63 +#, python-format +msgid "Syncing page %(page)d of groups" +msgstr "同步第 %(page)d 頁中的群組" + +#: authentik/providers/scim/tasks.py:92 +#, python-format +msgid "Failed to sync user %(user_name)s due to remote error: %(error)s" +msgstr "無法同步使用者 %(user_name)s因發生遠端錯誤:%(error)s" + +#: authentik/providers/scim/tasks.py:103 authentik/providers/scim/tasks.py:144 +#, python-format +msgid "Stopping sync due to error: %(error)s" +msgstr "停止同步因發生以下錯誤:%(error)s" + +#: authentik/providers/scim/tasks.py:133 +#, python-format +msgid "Failed to sync group %(group_name)s due to remote error: %(error)s" +msgstr "無法同步群組 %(group_name)s 因發生遠端錯誤:%(error)s" #: authentik/recovery/management/commands/create_admin_group.py:11 msgid "Create admin group if the default group gets deleted." -msgstr "如果默认群组被删除,则创建管理员群组。" +msgstr "如果預設群組被刪除,則建立管理員群組。" #: authentik/recovery/management/commands/create_recovery_key.py:17 msgid "Create a Key which can be used to restore access to authentik." -msgstr "创建一个密钥,该密钥可用于恢复对 authentik 的访问权限。" +msgstr "建立一個金鑰用於恢復對 authentik 的存取權限。" #: authentik/recovery/views.py:24 msgid "Used recovery-link to authenticate." -msgstr "已使用恢复链接进行身份验证。" +msgstr "已使用救援連結進行認證。" -#: authentik/sources/ldap/models.py:32 +#: authentik/sources/ldap/models.py:37 msgid "Server URI" -msgstr "服务器 URI" +msgstr "伺服器 URI" -#: authentik/sources/ldap/models.py:40 +#: authentik/sources/ldap/models.py:46 msgid "" "Optionally verify the LDAP Server's Certificate against the CA Chain in this" " keypair." -msgstr "可选,根据此密钥对中的 CA 链验证 LDAP 服务器的证书。" +msgstr "可選:根據此金鑰對中的 CA 鏈來驗證 LDAP 伺服器的憑證。" -#: authentik/sources/ldap/models.py:45 +#: authentik/sources/ldap/models.py:55 +msgid "" +"Client certificate to authenticate against the LDAP Server's Certificate." +msgstr "對 LDAP 伺服器的憑證進行認證的用戶端憑證。" + +#: authentik/sources/ldap/models.py:58 msgid "Bind CN" msgstr "Bind CN" -#: authentik/sources/ldap/models.py:47 +#: authentik/sources/ldap/models.py:60 msgid "Enable Start TLS" -msgstr "启用 “启动 TLS”" +msgstr "啟用 STARTTLS" -#: authentik/sources/ldap/models.py:49 +#: authentik/sources/ldap/models.py:61 +msgid "Use Server URI for SNI verification" +msgstr "使用伺服器 URI 進行 SNI 驗證" + +#: authentik/sources/ldap/models.py:63 msgid "Base DN" msgstr "Base DN" -#: authentik/sources/ldap/models.py:51 +#: authentik/sources/ldap/models.py:65 msgid "Prepended to Base DN for User-queries." -msgstr "预先添加到用户查询的Base DN 中。" - -#: authentik/sources/ldap/models.py:52 -msgid "Addition User DN" -msgstr "额外的用户 DN" - -#: authentik/sources/ldap/models.py:56 -msgid "Prepended to Base DN for Group-queries." -msgstr "在组查询的基本 Base DN 前面加上。" - -#: authentik/sources/ldap/models.py:57 -msgid "Addition Group DN" -msgstr "额外的 Group DN" - -#: authentik/sources/ldap/models.py:63 -msgid "Consider Objects matching this filter to be Users." -msgstr "将与此筛选器匹配的对象视为用户。" +msgstr "預先附加到使用者查詢的 Base DN 之前。" #: authentik/sources/ldap/models.py:66 -msgid "Field which contains members of a group." -msgstr "包含组成员的字段。" +msgid "Addition User DN" +msgstr "額外的使用者 DN" #: authentik/sources/ldap/models.py:70 -msgid "Consider Objects matching this filter to be Groups." -msgstr "将与此过滤器匹配的对象视为组。" +msgid "Prepended to Base DN for Group-queries." +msgstr "預先附加到群組查詢的 Base DN 之前。" -#: authentik/sources/ldap/models.py:73 -msgid "Field which contains a unique Identifier." -msgstr "包含唯一标识符的字段。" +#: authentik/sources/ldap/models.py:71 +msgid "Addition Group DN" +msgstr "額外的群組 DN" + +#: authentik/sources/ldap/models.py:77 +msgid "Consider Objects matching this filter to be Users." +msgstr "將符合此過濾條件的物件視為使用者。" #: authentik/sources/ldap/models.py:80 -msgid "Property mappings used for group creation/updating." -msgstr "用于创建/更新组的属性映射。" +msgid "Field which contains members of a group." +msgstr "包含群組成員的欄位。" -#: authentik/sources/ldap/models.py:145 +#: authentik/sources/ldap/models.py:84 +msgid "Consider Objects matching this filter to be Groups." +msgstr "將符合此過濾條件的物件視為群組。" + +#: authentik/sources/ldap/models.py:87 +msgid "Field which contains a unique Identifier." +msgstr "包含唯一識別碼的欄位。" + +#: authentik/sources/ldap/models.py:101 +msgid "" +"When a user changes their password, sync it back to LDAP. This can only be " +"enabled on a single LDAP source." +msgstr "當使用者更改密碼時,將其同步回 LDAP。這只能在只有單一 LDAP 來源上啟用。" + +#: authentik/sources/ldap/models.py:190 msgid "LDAP Source" -msgstr "LDAP 源" +msgstr "LDAP 來源" -#: authentik/sources/ldap/models.py:146 +#: authentik/sources/ldap/models.py:191 msgid "LDAP Sources" -msgstr "LDAP 源" +msgstr "LDAP 來源" -#: authentik/sources/ldap/models.py:169 +#: authentik/sources/ldap/models.py:213 msgid "LDAP Property Mapping" -msgstr "LDAP 属性映射" +msgstr "LDAP 屬性對應" -#: authentik/sources/ldap/models.py:170 +#: authentik/sources/ldap/models.py:214 msgid "LDAP Property Mappings" -msgstr "LDAP 属性映射" +msgstr "LDAP 屬性對應" -#: authentik/sources/ldap/signals.py:58 +#: authentik/sources/ldap/signals.py:50 msgid "Password does not match Active Directory Complexity." -msgstr "密码与活动目录复杂度不匹配。" +msgstr "密碼不符合 Active Directory 的複雜性要求。" + +#: authentik/sources/oauth/clients/oauth2.py:68 +msgid "No token received." +msgstr "未收到權杖。" #: authentik/sources/oauth/models.py:24 msgid "Request Token URL" -msgstr "请求令牌网址" +msgstr "請求權杖的網址" #: authentik/sources/oauth/models.py:26 msgid "" "URL used to request the initial token. This URL is only required for OAuth " "1." -msgstr "用于请求初始令牌的 URL。只有 OAuth 1 才需要此网址。" +msgstr "用於請求初始權杖的網址,僅用於 OAuth 1。" #: authentik/sources/oauth/models.py:32 msgid "Authorization URL" -msgstr "授权网址" +msgstr "授權網址" #: authentik/sources/oauth/models.py:33 msgid "URL the user is redirect to to conest the flow." -msgstr "用户被重定向到的URL,以控制流程。" +msgstr "使用者被重新導向到此網址以連接流程。" #: authentik/sources/oauth/models.py:38 msgid "Access Token URL" -msgstr "访问令牌 URL" +msgstr "存取權杖網址" #: authentik/sources/oauth/models.py:39 msgid "URL used by authentik to retrieve tokens." -msgstr "authentik 用来检索令牌的 URL。" +msgstr "authentik 用來擷取權杖的網址。" #: authentik/sources/oauth/models.py:44 msgid "Profile URL" -msgstr "个人资料网址" +msgstr "個人檔案網址" #: authentik/sources/oauth/models.py:45 msgid "URL used by authentik to get user information." -msgstr "authentik 用来获取用户信息的 URL。" +msgstr "authentik 用來擷取使用者資訊的網址。" -#: authentik/sources/oauth/models.py:97 -msgid "OAuth Source" -msgstr "OAuth 源" - -#: authentik/sources/oauth/models.py:98 -msgid "OAuth Sources" -msgstr "OAuth 源" - -#: authentik/sources/oauth/models.py:107 -msgid "GitHub OAuth Source" -msgstr "GitHub OAuth 来" +#: authentik/sources/oauth/models.py:48 +msgid "Additional Scopes" +msgstr "額外的範疇" #: authentik/sources/oauth/models.py:108 -msgid "GitHub OAuth Sources" -msgstr "GitHub OAuth 源" +msgid "OAuth Source" +msgstr "OAuth 來源" + +#: authentik/sources/oauth/models.py:109 +msgid "OAuth Sources" +msgstr "OAuth 來源" #: authentik/sources/oauth/models.py:117 -msgid "Twitter OAuth Source" -msgstr "Twitter OAuth 源" +msgid "GitHub OAuth Source" +msgstr "GitHub OAuth 來源" #: authentik/sources/oauth/models.py:118 -msgid "Twitter OAuth Sources" -msgstr "Twitter OAuth 源" +msgid "GitHub OAuth Sources" +msgstr "GitHub OAuth 來源" + +#: authentik/sources/oauth/models.py:126 +msgid "Twitch OAuth Source" +msgstr "Twitch OAuth 來源" #: authentik/sources/oauth/models.py:127 +msgid "Twitch OAuth Sources" +msgstr "Twitch OAuth 來源" + +#: authentik/sources/oauth/models.py:135 +msgid "Mailcow OAuth Source" +msgstr "Mailcow OAuth 來源" + +#: authentik/sources/oauth/models.py:136 +msgid "Mailcow OAuth Sources" +msgstr "Mailcow OAuth 來源" + +#: authentik/sources/oauth/models.py:144 +msgid "Twitter OAuth Source" +msgstr "X(Twitter) OAuth 來源" + +#: authentik/sources/oauth/models.py:145 +msgid "Twitter OAuth Sources" +msgstr "X(Twitter) OAuth 來源" + +#: authentik/sources/oauth/models.py:153 msgid "Facebook OAuth Source" -msgstr "Facebook OAuth 源" +msgstr "Facebook OAuth 來源" -#: authentik/sources/oauth/models.py:128 +#: authentik/sources/oauth/models.py:154 msgid "Facebook OAuth Sources" -msgstr "Facebook OAuth 源" +msgstr "Facebook OAuth 來源" -#: authentik/sources/oauth/models.py:137 +#: authentik/sources/oauth/models.py:162 msgid "Discord OAuth Source" -msgstr "Discord OAuth 源" +msgstr "Discord OAuth 來源" -#: authentik/sources/oauth/models.py:138 +#: authentik/sources/oauth/models.py:163 msgid "Discord OAuth Sources" -msgstr "Discord OAuth 源" +msgstr "Discord OAuth 來源" -#: authentik/sources/oauth/models.py:147 +#: authentik/sources/oauth/models.py:171 +msgid "Patreon OAuth Source" +msgstr "Patreon OAuth 來源" + +#: authentik/sources/oauth/models.py:172 +msgid "Patreon OAuth Sources" +msgstr "Patreon OAuth 來源" + +#: authentik/sources/oauth/models.py:180 msgid "Google OAuth Source" -msgstr "谷歌 OAuth 源" +msgstr "Google OAuth 來源" -#: authentik/sources/oauth/models.py:148 +#: authentik/sources/oauth/models.py:181 msgid "Google OAuth Sources" -msgstr "谷歌 OAuth 源" +msgstr "Google OAuth 來源" -#: authentik/sources/oauth/models.py:157 +#: authentik/sources/oauth/models.py:189 msgid "Azure AD OAuth Source" -msgstr "Azure AD OAuth 源" +msgstr "Azure AD OAuth 來源" -#: authentik/sources/oauth/models.py:158 +#: authentik/sources/oauth/models.py:190 msgid "Azure AD OAuth Sources" -msgstr "Azure AD OAuth 来源" +msgstr "Azure AD OAuth 來源" -#: authentik/sources/oauth/models.py:167 +#: authentik/sources/oauth/models.py:198 msgid "OpenID OAuth Source" -msgstr "OpenID OAuth 源" +msgstr "OpenID OAuth 來源" -#: authentik/sources/oauth/models.py:168 +#: authentik/sources/oauth/models.py:199 msgid "OpenID OAuth Sources" -msgstr "OpenID OAuth 源" +msgstr "OpenID OAuth 來源" -#: authentik/sources/oauth/models.py:177 +#: authentik/sources/oauth/models.py:207 msgid "Apple OAuth Source" -msgstr "Apple OAuth 源" +msgstr "Apple OAuth 來源" -#: authentik/sources/oauth/models.py:178 +#: authentik/sources/oauth/models.py:208 msgid "Apple OAuth Sources" -msgstr "Apple OAuth 源" +msgstr "Apple OAuth 來源" -#: authentik/sources/oauth/models.py:187 +#: authentik/sources/oauth/models.py:216 msgid "Okta OAuth Source" -msgstr "Okta OAuth 源" +msgstr "Okta OAuth 來源" -#: authentik/sources/oauth/models.py:188 +#: authentik/sources/oauth/models.py:217 msgid "Okta OAuth Sources" -msgstr "Okta OAuth 源" +msgstr "Okta OAuth 來源" -#: authentik/sources/oauth/models.py:203 +#: authentik/sources/oauth/models.py:225 +msgid "Reddit OAuth Source" +msgstr "Reddit OAuth 來源" + +#: authentik/sources/oauth/models.py:226 +msgid "Reddit OAuth Sources" +msgstr "Reddit OAuth 來源" + +#: authentik/sources/oauth/models.py:248 msgid "User OAuth Source Connection" -msgstr "用户 OAuth 源连接" +msgstr "使用者 OAuth 來源連線" -#: authentik/sources/oauth/models.py:204 +#: authentik/sources/oauth/models.py:249 msgid "User OAuth Source Connections" -msgstr "用户 OAuth 源连接" +msgstr "使用者 OAuth 來源連線" -#: authentik/sources/oauth/views/callback.py:98 -msgid "Authentication Failed." -msgstr "身份验证失败。" +#: authentik/sources/oauth/views/callback.py:100 +#, python-format +msgid "Authentication failed: %(reason)s" +msgstr "認證失敗:%(reason)s" #: authentik/sources/plex/models.py:37 msgid "Client identifier used to talk to Plex." -msgstr "用于与Plex通话的客户端标识符。" +msgstr "用於與 Plex 通話的用戶端識別碼。" + +#: authentik/sources/plex/models.py:44 +msgid "" +"Which servers a user has to be a member of to be granted access. Empty list " +"allows every server." +msgstr "使用者必須是其成員才能獲得存取權限的伺服器列表。留空則允許所有伺服器。" + +#: authentik/sources/plex/models.py:50 +msgid "Allow friends to authenticate, even if you don't share a server." +msgstr "允許朋友進行認證,即使你們沒有共用伺服器。" #: authentik/sources/plex/models.py:52 -msgid "Allow friends to authenticate, even if you don't share a server." -msgstr "允许朋友进行身份验证,即使您不共享服务器。" - -#: authentik/sources/plex/models.py:54 msgid "Plex token used to check friends" -msgstr "用于检查朋友的 Plex 令牌" +msgstr "用於檢查朋友的 Plex 權杖" -#: authentik/sources/plex/models.py:92 +#: authentik/sources/plex/models.py:95 msgid "Plex Source" -msgstr "Plex 源" +msgstr "Plex 來源" -#: authentik/sources/plex/models.py:93 +#: authentik/sources/plex/models.py:96 msgid "Plex Sources" -msgstr "Plex 源" +msgstr "Plex 來源" -#: authentik/sources/plex/models.py:104 +#: authentik/sources/plex/models.py:112 msgid "User Plex Source Connection" -msgstr "用户 Plex 源连接" +msgstr "使用者 Plex 來源連線" -#: authentik/sources/plex/models.py:105 +#: authentik/sources/plex/models.py:113 msgid "User Plex Source Connections" -msgstr "用户 Plex 源连接" +msgstr "使用者 Plex 來源連線" -#: authentik/sources/saml/models.py:36 +#: authentik/sources/saml/models.py:40 msgid "Redirect Binding" -msgstr "重定向绑定" +msgstr "重新導向附加" -#: authentik/sources/saml/models.py:37 +#: authentik/sources/saml/models.py:41 msgid "POST Binding" -msgstr "POST 绑定" +msgstr "POST 附加" -#: authentik/sources/saml/models.py:38 +#: authentik/sources/saml/models.py:42 msgid "POST Binding with auto-confirmation" -msgstr "带有自动确认功能的 POST 绑定" - -#: authentik/sources/saml/models.py:57 -msgid "Flow used before authentication." -msgstr "身份验证之前使用的流程。" - -#: authentik/sources/saml/models.py:64 -msgid "Issuer" -msgstr "Issuer" - -#: authentik/sources/saml/models.py:65 -msgid "Also known as Entity ID. Defaults the Metadata URL." -msgstr "也称为实体 ID。 默认为 Metadata URL。" - -#: authentik/sources/saml/models.py:69 -msgid "SSO URL" -msgstr "SSO 网址" +msgstr "使用自動確認的 POST 附加" #: authentik/sources/saml/models.py:70 -msgid "URL that the initial Login request is sent to." -msgstr "初始登录请求发送到的URL。" - -#: authentik/sources/saml/models.py:76 -msgid "SLO URL" -msgstr "SLO URL" +msgid "Flow used before authentication." +msgstr "在身分驗證之前所使用的流程。" #: authentik/sources/saml/models.py:77 -msgid "Optional URL if your IDP supports Single-Logout." -msgstr "如果您的 IDP 支持单点注销,则为可选 URL。" +msgid "Issuer" +msgstr "發行者" + +#: authentik/sources/saml/models.py:78 +msgid "Also known as Entity ID. Defaults the Metadata URL." +msgstr "亦稱為實體 ID。預設為中繼資料的網址。" + +#: authentik/sources/saml/models.py:82 +msgid "SSO URL" +msgstr "SSO 網址" #: authentik/sources/saml/models.py:83 +msgid "URL that the initial Login request is sent to." +msgstr "初始化登入要求時發送到的網址。" + +#: authentik/sources/saml/models.py:89 +msgid "SLO URL" +msgstr "SLO 網址" + +#: authentik/sources/saml/models.py:90 +msgid "Optional URL if your IDP supports Single-Logout." +msgstr "可選:如果您的身份提供者支援單一登出時使用的網址。" + +#: authentik/sources/saml/models.py:96 msgid "" "Allows authentication flows initiated by the IdP. This can be a security " "risk, as no validation of the request ID is done." -msgstr "允许由 IdP 启动的身份验证流。这可能存在安全风险,因为未对请求 ID 进行验证。" +msgstr "允許由身份提供者發起的認證流程。這可能是一個安全風險,因為不會驗證要求的 ID。" -#: authentik/sources/saml/models.py:91 +#: authentik/sources/saml/models.py:104 msgid "" "NameID Policy sent to the IdP. Can be unset, in which case no Policy is " "sent." -msgstr "已向 IdP 发送了 NameID 策略。可以取消设置,在这种情况下,不会发送任何策略。" +msgstr "發送給身份提供者的 NameID 政策。可以為空,在這種情況下則不會發送任何政策。" -#: authentik/sources/saml/models.py:102 +#: authentik/sources/saml/models.py:115 msgid "Delete temporary users after" -msgstr "之后删除临时用户" +msgstr "在以下狀況後刪除臨時使用者:" -#: authentik/sources/saml/models.py:120 +#: authentik/sources/saml/models.py:118 msgid "" -"Keypair which is used to sign outgoing requests. Leave empty to disable " -"signing." -msgstr "用于签署传出请求的密钥对。留空则禁用签名。" +"Time offset when temporary users should be deleted. This only applies if " +"your IDP uses the NameID Format 'transient', and the user doesn't log out " +"manually. (Format: hours=1;minutes=2;seconds=3)." +msgstr "" +"刪除臨時使用者的時間偏移量。這僅適用於您的身份提供者使用 NameID " +"格式「transient」,且用戶沒有手動登出的情況。(格式:hours=1;minutes=2;seconds=3)。" -#: authentik/sources/saml/models.py:188 +#: authentik/sources/saml/models.py:142 +msgid "" +"Keypair used to sign outgoing Responses going to the Identity Provider." +msgstr "用於簽署發往身份提供者的外送回應的金鑰對。" + +#: authentik/sources/saml/models.py:226 msgid "SAML Source" -msgstr "SAML 源" +msgstr "SAML 來源" -#: authentik/sources/saml/models.py:189 +#: authentik/sources/saml/models.py:227 msgid "SAML Sources" -msgstr "SAML 源" +msgstr "SAML 來源" -#: authentik/stages/authenticator_duo/models.py:64 +#: authentik/sources/saml/models.py:242 +msgid "User SAML Source Connection" +msgstr "使用者 SAML 來源連線" + +#: authentik/sources/saml/models.py:243 +msgid "User SAML Source Connections" +msgstr "使用者 SAML 來源連線" + +#: authentik/stages/authenticator_duo/models.py:79 msgid "Duo Authenticator Setup Stage" -msgstr "Duo 身份验证器设置阶段" +msgstr "Duo 身份驗證器設定階段" -#: authentik/stages/authenticator_duo/models.py:65 +#: authentik/stages/authenticator_duo/models.py:80 msgid "Duo Authenticator Setup Stages" -msgstr "Duo 身份验证器设置阶段" +msgstr "Duo 身份驗證器設定階段" -#: authentik/stages/authenticator_duo/models.py:82 +#: authentik/stages/authenticator_duo/models.py:103 msgid "Duo Device" -msgstr "Duo 设备" +msgstr "Duo 設備" -#: authentik/stages/authenticator_duo/models.py:83 +#: authentik/stages/authenticator_duo/models.py:104 msgid "Duo Devices" -msgstr "Duo 设备" +msgstr "Duo 設備" -#: authentik/stages/authenticator_sms/models.py:157 +#: authentik/stages/authenticator_sms/models.py:57 +msgid "" +"When enabled, the Phone number is only used during enrollment to verify the " +"users authenticity. Only a hash of the phone number is saved to ensure it is" +" not reused in the future." +msgstr "啟用時,手機號碼僅在註冊期間用於驗證使用者的真實性。只保存手機號碼的雜湊以確保未來不會重複使用。" + +#: authentik/stages/authenticator_sms/models.py:68 +msgid "Optionally modify the payload being sent to custom providers." +msgstr "可選:修改發送給自訂供應商的酬載。" + +#: authentik/stages/authenticator_sms/models.py:81 +#, python-format +msgid "Use this code to authenticate in authentik: %(token)s" +msgstr "使用此認證碼在 authentik 中進行認證:%(token)s" + +#: authentik/stages/authenticator_sms/models.py:180 msgid "SMS Authenticator Setup Stage" -msgstr "SMS 身份验证器设置阶段" +msgstr "簡訊身份驗證器設定階段" -#: authentik/stages/authenticator_sms/models.py:158 +#: authentik/stages/authenticator_sms/models.py:181 msgid "SMS Authenticator Setup Stages" -msgstr "SMS 身份验证器设置阶段" +msgstr "簡訊身份驗證器設定階段" -#: authentik/stages/authenticator_sms/models.py:175 +#: authentik/stages/authenticator_sms/models.py:226 msgid "SMS Device" -msgstr "短信设备" +msgstr "簡訊設備" -#: authentik/stages/authenticator_sms/models.py:176 +#: authentik/stages/authenticator_sms/models.py:227 msgid "SMS Devices" -msgstr "短信设备" +msgstr "簡訊設備" -#: authentik/stages/authenticator_sms/stage.py:54 -#: authentik/stages/authenticator_totp/stage.py:45 +#: authentik/stages/authenticator_sms/stage.py:55 +#: authentik/stages/authenticator_totp/stage.py:41 +#: authentik/stages/authenticator_totp/stage.py:44 msgid "Code does not match" -msgstr "代码不匹配" +msgstr "授權碼不符" -#: authentik/stages/authenticator_static/models.py:47 +#: authentik/stages/authenticator_sms/stage.py:71 +msgid "Invalid phone number" +msgstr "無效的電話號碼" + +#: authentik/stages/authenticator_static/models.py:52 msgid "Static Authenticator Stage" -msgstr "静态身份验证器阶段" +msgstr "靜態身份驗證器設定階段" -#: authentik/stages/authenticator_static/models.py:48 +#: authentik/stages/authenticator_static/models.py:53 msgid "Static Authenticator Stages" -msgstr "静态身份验证器阶段" +msgstr "靜態身份驗證器設定階段" -#: authentik/stages/authenticator_totp/models.py:16 +#: authentik/stages/authenticator_static/models.py:98 +msgid "Static device" +msgstr "靜態設備" + +#: authentik/stages/authenticator_static/models.py:99 +msgid "Static devices" +msgstr "靜態設備" + +#: authentik/stages/authenticator_totp/models.py:25 msgid "6 digits, widely compatible" -msgstr "6位数字,广泛兼容" +msgstr "6位數字,廣泛相容各類驗證器" -#: authentik/stages/authenticator_totp/models.py:17 +#: authentik/stages/authenticator_totp/models.py:26 msgid "8 digits, not compatible with apps like Google Authenticator" -msgstr "8位数字,与谷歌身份验证器等应用不兼容" +msgstr "8位數字,不相容於類似 Google Authenticator 等驗證器" -#: authentik/stages/authenticator_totp/models.py:54 +#: authentik/stages/authenticator_totp/models.py:62 msgid "TOTP Authenticator Setup Stage" -msgstr "TOTP 身份验证器设置阶段" +msgstr "TOTP 身份驗證器設定階段" -#: authentik/stages/authenticator_totp/models.py:55 +#: authentik/stages/authenticator_totp/models.py:63 msgid "TOTP Authenticator Setup Stages" -msgstr "TOTP 身份验证器设置阶段" +msgstr "TOTP 身份驗證器設定階段" -#: authentik/stages/authenticator_validate/challenge.py:99 +#: authentik/stages/authenticator_totp/models.py:244 +msgid "TOTP device" +msgstr "TOTP 裝置" + +#: authentik/stages/authenticator_totp/models.py:245 +msgid "TOTP devices" +msgstr "TOTP 裝置" + +#: authentik/stages/authenticator_validate/challenge.py:131 msgid "Invalid Token" -msgstr "无效令牌" +msgstr "無效權杖" -#: authentik/stages/authenticator_validate/models.py:17 +#: authentik/stages/authenticator_validate/models.py:18 +msgid "Static" +msgstr "靜態" + +#: authentik/stages/authenticator_validate/models.py:19 msgid "TOTP" msgstr "TOTP" -#: authentik/stages/authenticator_validate/models.py:18 +#: authentik/stages/authenticator_validate/models.py:20 msgid "WebAuthn" msgstr "WebAuthn" -#: authentik/stages/authenticator_validate/models.py:19 +#: authentik/stages/authenticator_validate/models.py:21 msgid "Duo" msgstr "Duo" -#: authentik/stages/authenticator_validate/models.py:20 +#: authentik/stages/authenticator_validate/models.py:22 msgid "SMS" -msgstr "短信" +msgstr "簡訊" -#: authentik/stages/authenticator_validate/models.py:58 +#: authentik/stages/authenticator_validate/models.py:49 +msgid "" +"Stages used to configure Authenticator when user doesn't have any compatible" +" devices. After this configuration Stage passes, the user is not prompted " +"again." +msgstr "在使用者沒有任何相容設備時用於設定身份驗證器的階段。在通過此設定階段後,使用者將不再收到提示。" + +#: authentik/stages/authenticator_validate/models.py:56 msgid "Device classes which can be used to authenticate" -msgstr "可用于进行身份验证的设备类别" +msgstr "可用於身分驗證的裝置類別" -#: authentik/stages/authenticator_validate/models.py:80 +#: authentik/stages/authenticator_validate/models.py:64 +msgid "" +"If any of the user's device has been used within this threshold, this stage " +"will be skipped" +msgstr "如果在此閾值內的使用者任何設備被使用過,則將跳過此階段。" + +#: authentik/stages/authenticator_validate/models.py:70 +msgid "Enforce user verification for WebAuthn devices." +msgstr "強制使用者使用 WebAuthn 裝置進行驗證。" + +#: authentik/stages/authenticator_validate/models.py:92 msgid "Authenticator Validation Stage" -msgstr "身份验证器验证阶段" +msgstr "身份驗證器驗證階段" -#: authentik/stages/authenticator_validate/models.py:81 +#: authentik/stages/authenticator_validate/models.py:93 msgid "Authenticator Validation Stages" -msgstr "身份验证器验证阶段" +msgstr "身份驗證器驗證階段" -#: authentik/stages/authenticator_webauthn/models.py:71 +#: authentik/stages/authenticator_webauthn/models.py:112 msgid "WebAuthn Authenticator Setup Stage" -msgstr "WebAuthn 身份验证器设置阶段" +msgstr "WebAuthn 身份驗證器設定階段" -#: authentik/stages/authenticator_webauthn/models.py:72 +#: authentik/stages/authenticator_webauthn/models.py:113 msgid "WebAuthn Authenticator Setup Stages" -msgstr "WebAuthn 身份验证器设置阶段" +msgstr "WebAuthn 身份驗證器設定階段" -#: authentik/stages/authenticator_webauthn/models.py:105 +#: authentik/stages/authenticator_webauthn/models.py:151 msgid "WebAuthn Device" -msgstr "WebAuthn 设备" +msgstr "WebAuthn 設備" -#: authentik/stages/authenticator_webauthn/models.py:106 +#: authentik/stages/authenticator_webauthn/models.py:152 msgid "WebAuthn Devices" -msgstr "WebAuthn 设备" +msgstr "WebAuthn 設備" + +#: authentik/stages/captcha/models.py:14 +msgid "Public key, acquired your captcha Provider." +msgstr "公鑰,由您的驗證碼供應商中取得" #: authentik/stages/captcha/models.py:15 -msgid "" -"Public key, acquired from https://www.google.com/recaptcha/intro/v3.html" -msgstr "公钥,从 https://www.google.com/recaptcha/intro/v3.html 获取" +msgid "Private key, acquired your captcha Provider." +msgstr "私鑰,由您的驗證碼供應商中取得" -#: authentik/stages/captcha/models.py:18 -msgid "" -"Private key, acquired from https://www.google.com/recaptcha/intro/v3.html" -msgstr "私钥,从 https://www.google.com/recaptcha/intro/v3.html 获取" - -#: authentik/stages/captcha/models.py:39 +#: authentik/stages/captcha/models.py:37 msgid "Captcha Stage" -msgstr "验证码阶段" +msgstr "驗證碼階段" -#: authentik/stages/captcha/models.py:40 +#: authentik/stages/captcha/models.py:38 msgid "Captcha Stages" -msgstr "验证码阶段" +msgstr "驗證碼階段" -#: authentik/stages/consent/models.py:52 +#: authentik/stages/consent/models.py:30 +msgid "" +"Offset after which consent expires. (Format: hours=1;minutes=2;seconds=3)." +msgstr "同意在此之後過期的時間偏移量。(格式:hours=1;minutes=2;seconds=3)。" + +#: authentik/stages/consent/models.py:50 msgid "Consent Stage" -msgstr "同意阶段" +msgstr "同意階段" -#: authentik/stages/consent/models.py:53 +#: authentik/stages/consent/models.py:51 msgid "Consent Stages" -msgstr "Consent Stages" +msgstr "同意階段" -#: authentik/stages/consent/models.py:68 +#: authentik/stages/consent/models.py:72 msgid "User Consent" -msgstr "用户同意" +msgstr "使用者同意" -#: authentik/stages/consent/models.py:69 +#: authentik/stages/consent/models.py:73 msgid "User Consents" -msgstr "用户同意" +msgstr "使用者同意" + +#: authentik/stages/deny/models.py:30 +msgid "Deny Stage" +msgstr "拒絕階段" #: authentik/stages/deny/models.py:31 -msgid "Deny Stage" -msgstr "拒绝舞台" - -#: authentik/stages/deny/models.py:32 msgid "Deny Stages" -msgstr "拒绝阶段" - -#: authentik/stages/dummy/models.py:33 -msgid "Dummy Stage" -msgstr "虚拟阶段" +msgstr "拒絕階段" #: authentik/stages/dummy/models.py:34 +msgid "Dummy Stage" +msgstr "假階段" + +#: authentik/stages/dummy/models.py:35 msgid "Dummy Stages" -msgstr "虚拟阶段" +msgstr "假階段" -#: authentik/stages/email/models.py:25 +#: authentik/stages/email/models.py:26 msgid "Password Reset" -msgstr "密码重置" +msgstr "重設密碼" -#: authentik/stages/email/models.py:29 +#: authentik/stages/email/models.py:30 msgid "Account Confirmation" -msgstr "账户确认" +msgstr "帳戶認證" -#: authentik/stages/email/models.py:75 +#: authentik/stages/email/models.py:59 +msgid "" +"When enabled, global Email connection settings will be used and connection " +"settings below will be ignored." +msgstr "啟用時,將使用全域電子郵件連線設定,在此之下的連線設定將被忽略。" + +#: authentik/stages/email/models.py:74 msgid "Activate users upon completion of stage." -msgstr "完成阶段后激活用户。" +msgstr "完成階段後啟用使用者。" -#: authentik/stages/email/models.py:79 +#: authentik/stages/email/models.py:78 msgid "Time in minutes the token sent is valid." -msgstr "发送的令牌的有效时间(以分钟为单位)。" +msgstr "發送權杖的有效時間(以分鐘為單位)。" -#: authentik/stages/email/models.py:125 +#: authentik/stages/email/models.py:132 msgid "Email Stage" -msgstr "电子邮件阶段" +msgstr "電子郵件階段" -#: authentik/stages/email/models.py:126 +#: authentik/stages/email/models.py:133 msgid "Email Stages" -msgstr "电子邮件阶段" +msgstr "電子郵件階段" -#: authentik/stages/email/stage.py:106 +#: authentik/stages/email/stage.py:117 msgid "Successfully verified Email." -msgstr "已成功验证电子邮件。" +msgstr "已成功認證電子郵件。" -#: authentik/stages/email/stage.py:113 authentik/stages/email/stage.py:135 +#: authentik/stages/email/stage.py:124 authentik/stages/email/stage.py:146 msgid "No pending user." -msgstr "没有待处理的用户。" +msgstr "沒有待處理的使用者。" -#: authentik/stages/email/stage.py:125 +#: authentik/stages/email/stage.py:136 msgid "Email sent." -msgstr "邮件已发出。" +msgstr "已發送電子郵件。" -#: authentik/stages/email/templates/email/account_confirmation.html:9 +#: authentik/stages/email/templates/email/account_confirmation.html:10 msgid "Welcome!" -msgstr "欢迎!" +msgstr "歡迎!" -#: authentik/stages/email/templates/email/account_confirmation.html:12 +#: authentik/stages/email/templates/email/account_confirmation.html:19 msgid "" "We're excited to have you get started. First, you need to confirm your " "account. Just press the button below." -msgstr "我们很高兴你能开始使用。首先,您需要确认您的帐户。只需按下下面的按钮即可。" +msgstr "我們很高興您能開始使用。首先,您需要驗證您的帳戶。只需按下方的按鈕即可。" -#: authentik/stages/email/templates/email/account_confirmation.html:21 +#: authentik/stages/email/templates/email/account_confirmation.html:24 msgid "Confirm Account" -msgstr "确认账户" +msgstr "驗證帳戶" -#: authentik/stages/email/templates/email/account_confirmation.html:30 +#: authentik/stages/email/templates/email/account_confirmation.html:36 #, python-format msgid "" "\n" @@ -1471,58 +2155,59 @@ msgid "" " " msgstr "" "\n" -" 如果这不起作用,请在浏览器中复制并粘贴以下链接:%(url)s\n" +" 如果這不起作用,請在瀏覽器中複製並貼上以下連結:%(url)s\n" " " -#: authentik/stages/email/templates/email/account_confirmation.html:35 -msgid "" -"If you have any questions, just reply to this email—we're always happy to " -"help out." -msgstr "如果您有任何疑问,请回复此电子邮件——我们很乐意为您提供帮助。" - -#: authentik/stages/email/templates/email/generic.html:24 -msgid "Additional Information" -msgstr "其他信息" - -#: authentik/stages/email/templates/email/password_reset.html:9 +#: authentik/stages/email/templates/email/event_notification.html:46 #, python-format msgid "" "\n" -" Hi %(username)s,\n" -" " +" This email was sent from the notification transport %(name)s.\n" +" " msgstr "" "\n" -" 你好 %(username)s,\n" -" " +" 這封信件來自通知通道:%(name)s。\n" +" " -#: authentik/stages/email/templates/email/password_reset.html:19 +#: authentik/stages/email/templates/email/password_reset.html:10 +#, python-format msgid "" "\n" -" You recently requested to change your password for you authentik account. Use the button below to set a new password.\n" -" " +" Hi %(username)s,\n" +" " msgstr "" "\n" -" 您最近请求更改您的 authentik 账户的密码。使用下面的按钮设置新密码。\n" -" " +" 嗨!%(username)s。\n" +" " -#: authentik/stages/email/templates/email/password_reset.html:33 +#: authentik/stages/email/templates/email/password_reset.html:21 +msgid "" +"\n" +" You recently requested to change your password for your authentik account. Use the button below to set a new password.\n" +" " +msgstr "" +"\n" +" 您最近要求重設您的 authentik 帳戶的密碼。請使用下方的按鈕來設定新密碼。\n" +" " + +#: authentik/stages/email/templates/email/password_reset.html:28 msgid "Reset Password" -msgstr "重置密码" +msgstr "重設密碼" -#: authentik/stages/email/templates/email/password_reset.html:45 +#: authentik/stages/email/templates/email/password_reset.html:39 #, python-format msgid "" "\n" -" If you did not request a password change, please ignore this Email. The link above is valid for %(expires)s.\n" -" " +" If you did not request a password change, please ignore this Email. The link above is valid for %(expires)s.\n" +" " msgstr "" "\n" -" 如果您没有请求更改密码,请忽略此电子邮件。上面的链接对 %(expires)s 有效。\n" -" " +" 如果您沒有要求重設密碼,請忽略本信件。以下連結將在%(expires)s 後過期。\n" +" " #: authentik/stages/email/templates/email/setup.html:9 msgid "authentik Test-Email" -msgstr "authentik 测试电子邮件" +msgstr "authentik 測試電子郵件" #: authentik/stages/email/templates/email/setup.html:17 msgid "" @@ -1531,219 +2216,339 @@ msgid "" " " msgstr "" "\n" -" 这是一封测试电子邮件,用于通知您,您已成功配置身份验证电子邮件。\n" +" 這是一封測試電子郵件用於通知您,您已成功設定了 authentik 電子郵件。\n" " " -#: authentik/stages/identification/models.py:42 +#: authentik/stages/identification/api.py:20 +msgid "When no user fields are selected, at least one source must be selected" +msgstr "當沒有使用者欄位被選擇時,至少要選擇一個來源" + +#: authentik/stages/identification/models.py:29 msgid "" -"When set, shows a password field, instead of showing the password field as " -"seaprate step." -msgstr "设置后,将显示密码字段,而不是将密码字段显示为单独的步骤。" +"Fields of the user object to match against. (Hold shift to select multiple " +"options)" +msgstr "用於配對使用者物件的欄位。(可按住 Shift 選擇多個選項)" -#: authentik/stages/identification/models.py:48 +#: authentik/stages/identification/models.py:47 msgid "When enabled, user fields are matched regardless of their casing." -msgstr "启用后,无论用户字段大小写如何,都将匹配用户字段。" +msgstr "啟用時,配對將無視使用者欄位的大小寫差異。" -#: authentik/stages/identification/models.py:68 +#: authentik/stages/identification/models.py:52 +msgid "" +"When a valid username/email has been entered, and this option is enabled, " +"the user's username and avatar will be shown. Otherwise, the text that the " +"user entered will be shown" +msgstr "當啟用了此選項,且輸入了有效的使用者名稱/電子郵件時,將顯示用戶的用戶名稱和頭像。否則,將顯示使用者輸入的文字。" + +#: authentik/stages/identification/models.py:65 msgid "Optional enrollment flow, which is linked at the bottom of the page." -msgstr "可选注册流程,链接在页面底部。" +msgstr "可選的註冊流程,連結在頁面的底部。" -#: authentik/stages/identification/models.py:77 +#: authentik/stages/identification/models.py:74 msgid "Optional recovery flow, which is linked at the bottom of the page." -msgstr "可选的恢复流程,链接在页面底部。" +msgstr "可選的救援流程,連結在頁面底部。" -#: authentik/stages/identification/models.py:86 +#: authentik/stages/identification/models.py:83 msgid "Optional passwordless flow, which is linked at the bottom of the page." -msgstr "可选的无密码流程,链接在页面底部。" +msgstr "可選的無密碼流程,連結在頁面底部。" -#: authentik/stages/identification/models.py:90 +#: authentik/stages/identification/models.py:87 msgid "Specify which sources should be shown." -msgstr "指定应显示哪些来源。" +msgstr "指定應顯示那些來源。" -#: authentik/stages/identification/models.py:112 +#: authentik/stages/identification/models.py:108 msgid "Identification Stage" -msgstr "识别阶段" +msgstr "識別階段" -#: authentik/stages/identification/models.py:113 +#: authentik/stages/identification/models.py:109 msgid "Identification Stages" -msgstr "识别阶段" +msgstr "識別階段" -#: authentik/stages/identification/stage.py:175 +#: authentik/stages/identification/stage.py:188 msgid "Log in" msgstr "登入" -#: authentik/stages/invitation/models.py:46 +#: authentik/stages/identification/stage.py:189 +msgid "Continue" +msgstr "繼續" + +#: authentik/stages/invitation/models.py:21 +msgid "" +"If this flag is set, this Stage will jump to the next Stage when no " +"Invitation is given. By default this Stage will cancel the Flow when no " +"invitation is given." +msgstr "如果設定了此旗標,在沒有給予邀請的情況下將跳轉到下一階段。預設情況下,當沒有給予邀請時,階段將取消流程。" + +#: authentik/stages/invitation/models.py:44 msgid "Invitation Stage" -msgstr "邀请阶段" +msgstr "邀請階段" -#: authentik/stages/invitation/models.py:47 +#: authentik/stages/invitation/models.py:45 msgid "Invitation Stages" -msgstr "邀请阶段" +msgstr "邀請階段" -#: authentik/stages/invitation/models.py:57 -msgid "When enabled, the invitation will be deleted after usage." -msgstr "启用后,邀请将在使用后被删除。" +#: authentik/stages/invitation/models.py:60 +msgid "When set, only the configured flow can use this invitation." +msgstr "如果設定此項,只有已設定的流程才能夠使用這個邀請。" #: authentik/stages/invitation/models.py:64 +msgid "When enabled, the invitation will be deleted after usage." +msgstr "啟用時,邀請將在使用後被刪除。" + +#: authentik/stages/invitation/models.py:71 msgid "Optional fixed data to enforce on user enrollment." -msgstr "在用户注册时强制执行的可选固定数据。" +msgstr "可選的固定資料,在使用者註冊中強制加入的固定資料。" -#: authentik/stages/invitation/models.py:72 +#: authentik/stages/invitation/models.py:84 msgid "Invitation" -msgstr "邀请" +msgstr "邀請" -#: authentik/stages/invitation/models.py:73 +#: authentik/stages/invitation/models.py:85 msgid "Invitations" -msgstr "邀请" +msgstr "邀請" + +#: authentik/stages/invitation/stage.py:62 +msgid "Invalid invite/invite not found" +msgstr "無效的邀請或找不到該邀請" #: authentik/stages/password/models.py:20 msgid "User database + standard password" -msgstr "用户数据库+标准密码" +msgstr "使用者資料庫 + 標準密碼" #: authentik/stages/password/models.py:24 msgid "User database + app passwords" -msgstr "用户数据库+应用程序密码" +msgstr "使用者資料庫 + 應用程式密碼" #: authentik/stages/password/models.py:28 msgid "User database + LDAP password" -msgstr "用户数据库 + LDAP 密码" +msgstr "使用者資料庫 + LDAP 密碼" #: authentik/stages/password/models.py:38 msgid "Selection of backends to test the password against." -msgstr "选择用于测试密码的后端。" +msgstr "選擇要對照測試密碼的後端。" -#: authentik/stages/password/models.py:78 +#: authentik/stages/password/models.py:43 +msgid "" +"How many attempts a user has before the flow is canceled. To lock the user " +"out, use a reputation policy and a user_write stage." +msgstr "在取消流程前使用者嘗試的次數。要鎖定使用者請使用融域政策和 user_write 階段。" + +#: authentik/stages/password/models.py:75 msgid "Password Stage" -msgstr "密码阶段" +msgstr "密碼階段" -#: authentik/stages/password/models.py:79 +#: authentik/stages/password/models.py:76 msgid "Password Stages" -msgstr "密码阶段" +msgstr "密碼階段" -#: authentik/stages/password/stage.py:152 +#: authentik/stages/password/stage.py:124 msgid "Invalid password" -msgstr "密码无效" +msgstr "無效的密碼" -#: authentik/stages/prompt/models.py:29 +#: authentik/stages/prompt/models.py:43 msgid "Text: Simple Text input" -msgstr "文本:简单文本输入" +msgstr "文字:簡單文字輸入" -#: authentik/stages/prompt/models.py:32 +#: authentik/stages/prompt/models.py:45 +msgid "Text area: Multiline Text Input." +msgstr "文字區塊:多行文字輸入。" + +#: authentik/stages/prompt/models.py:48 msgid "Text (read-only): Simple Text input, but cannot be edited." -msgstr "文本(只读):简单文本输入,但无法编辑。" +msgstr "文字(唯讀):簡單文字輸入,但無法編輯。" -#: authentik/stages/prompt/models.py:39 +#: authentik/stages/prompt/models.py:52 +msgid "Text area (read-only): Multiline Text input, but cannot be edited." +msgstr "文字區塊(唯讀):多行文字輸入。但無法編輯。" + +#: authentik/stages/prompt/models.py:58 +msgid "" +"Username: Same as Text input, but checks for and prevents duplicate " +"usernames." +msgstr "使用者名稱:與文字輸入相同,但檢查是否與現存有重複。" + +#: authentik/stages/prompt/models.py:60 msgid "Email: Text field with Email type." -msgstr "电子邮件:具有电子邮件类型的文本字段。" +msgstr "電子郵件:具有電子郵件類型的文字欄位。" -#: authentik/stages/prompt/models.py:55 +#: authentik/stages/prompt/models.py:64 +msgid "" +"Password: Masked input, multiple inputs of this type on the same prompt need" +" to be identical." +msgstr "密碼:遮罩輸入,同一提示上的多個此類輸入需要相同。" + +#: authentik/stages/prompt/models.py:71 +msgid "Fixed choice field rendered as a group of radio buttons." +msgstr "固定選項欄位將繪製成單選按紐群組。" + +#: authentik/stages/prompt/models.py:73 +msgid "Fixed choice field rendered as a dropdown." +msgstr "固定選項欄位將繪製成下拉式選單。" + +#: authentik/stages/prompt/models.py:80 +msgid "" +"File: File upload for arbitrary files. File content will be available in " +"flow context as data-URI" +msgstr "檔案:任意檔案類型上傳。檔案內容將會作為流程內文的資料URI" + +#: authentik/stages/prompt/models.py:85 msgid "Separator: Static Separator Line" -msgstr "分隔符:静态分隔线" +msgstr "分隔符號:靜態分隔線" -#: authentik/stages/prompt/models.py:56 +#: authentik/stages/prompt/models.py:86 msgid "Hidden: Hidden field, can be used to insert data into form." -msgstr "隐藏:隐藏字段,可用于将数据插入表单。" +msgstr "隱藏:隱藏欄位,可用於將資料插入表單。" -#: authentik/stages/prompt/models.py:57 +#: authentik/stages/prompt/models.py:87 msgid "Static: Static value, displayed as-is." -msgstr "静态:静态值,按原样显示。" +msgstr "靜態:靜態數值,按原狀顯示。" -#: authentik/stages/prompt/models.py:66 +#: authentik/stages/prompt/models.py:89 +msgid "authentik: Selection of locales authentik supports" +msgstr "authentik:選擇 authentik 支援的語系" + +#: authentik/stages/prompt/models.py:116 msgid "Name of the form field, also used to store the value" -msgstr "表单域的名称,也用于存储值" +msgstr "表單名稱,也用於儲存數值。" -#: authentik/stages/prompt/models.py:131 +#: authentik/stages/prompt/models.py:124 +msgid "" +"Optionally provide a short hint that describes the expected input value. " +"When creating a fixed choice field, enable interpreting as expression and " +"return a list to return multiple choices." +msgstr "可選:提供一個簡短提示,描述預期的輸入值。當建立一個固定選擇欄位時,啟用解釋為表達式,並回傳一個列表以提供多個選擇。" + +#: authentik/stages/prompt/models.py:132 +msgid "" +"Optionally pre-fill the input with an initial value. When creating a fixed " +"choice field, enable interpreting as expression and return a list to return " +"multiple default choices." +msgstr "可選:預先填入輸入框以一個初始值。當建立一個固定選擇欄位時,啟用解釋為表達式,並回傳一個列表以提供多個預設選擇。" + +#: authentik/stages/prompt/models.py:321 msgid "Prompt" msgstr "提示" -#: authentik/stages/prompt/models.py:132 +#: authentik/stages/prompt/models.py:322 msgid "Prompts" msgstr "提示" -#: authentik/stages/prompt/models.py:160 +#: authentik/stages/prompt/models.py:349 msgid "Prompt Stage" -msgstr "提示阶段" +msgstr "提示階段" -#: authentik/stages/prompt/models.py:161 +#: authentik/stages/prompt/models.py:350 msgid "Prompt Stages" -msgstr "提示阶段" +msgstr "提示階段" -#: authentik/stages/prompt/stage.py:94 +#: authentik/stages/prompt/stage.py:108 msgid "Passwords don't match." -msgstr "密码不匹配。" +msgstr "密碼不符。" + +#: authentik/stages/user_delete/models.py:31 +msgid "User Delete Stage" +msgstr "使用者刪除階段" #: authentik/stages/user_delete/models.py:32 -msgid "User Delete Stage" -msgstr "用户删除阶段" - -#: authentik/stages/user_delete/models.py:33 msgid "User Delete Stages" -msgstr "用户删除阶段" +msgstr "使用者刪除階段" -#: authentik/stages/user_delete/stage.py:24 +#: authentik/stages/user_delete/stage.py:18 msgid "No Pending User." -msgstr "没有待处理的用户。" +msgstr "無待處理的使用者。" #: authentik/stages/user_login/models.py:19 msgid "" "Determines how long a session lasts. Default of 0 means that the sessions " "lasts until the browser is closed. (Format: hours=-1;minutes=-2;seconds=-3)" -msgstr "确定会话持续多长时间。默认值为 0 表示会话持续到浏览器关闭为止。(格式:hours=-1;minutes=-2;seconds=-3)" +msgstr "確定會談持續多久。預設值為 0 表示會談會持續到關閉瀏覽器為止。(格式:hours=-1;minutes=-2;seconds=-3)" -#: authentik/stages/user_login/models.py:43 +#: authentik/stages/user_login/models.py:25 +msgid "Terminate all other sessions of the user logging in." +msgstr "終止所有已登入的使用者連線。" + +#: authentik/stages/user_login/models.py:31 +msgid "" +"Offset the session will be extended by when the user picks the remember me " +"option. Default of 0 means that the remember me option will not be shown. " +"(Format: hours=-1;minutes=-2;seconds=-3)" +msgstr "" +"當使用者選擇記住我選項時,會延長會談的偏移時間。預設值為 0 " +"意味著不會顯示記住我選項。(格式:hours=-1;minutes=-2;seconds=-3)" + +#: authentik/stages/user_login/models.py:54 msgid "User Login Stage" -msgstr "用户登录阶段" +msgstr "使用者登入階段" -#: authentik/stages/user_login/models.py:44 +#: authentik/stages/user_login/models.py:55 msgid "User Login Stages" -msgstr "用户登录阶段" - -#: authentik/stages/user_login/stage.py:29 -msgid "No Pending user to login." -msgstr "没有待定用户可以登录。" +msgstr "使用者登入階段" #: authentik/stages/user_login/stage.py:57 +msgid "No Pending user to login." +msgstr "無待登入的使用者。" + +#: authentik/stages/user_login/stage.py:90 msgid "Successfully logged in!" msgstr "已成功登入!" -#: authentik/stages/user_logout/models.py:31 +#: authentik/stages/user_logout/models.py:30 msgid "User Logout Stage" -msgstr "用户注销阶段" +msgstr "使用者登出階段" -#: authentik/stages/user_logout/models.py:32 +#: authentik/stages/user_logout/models.py:31 msgid "User Logout Stages" -msgstr "用户注销阶段" +msgstr "使用者登出階段" -#: authentik/stages/user_write/models.py:18 +#: authentik/stages/user_write/models.py:31 msgid "When set, newly created users are inactive and cannot login." -msgstr "设置后,新创建的用户将处于非活动状态,且无法登录。" +msgstr "設定時,新建立的使用者會是非活躍狀態,無法登入。" -#: authentik/stages/user_write/models.py:26 +#: authentik/stages/user_write/models.py:39 msgid "Optionally add newly created users to this group." -msgstr "(可选)将新创建的用户添加到此组。" +msgstr "可選:將新建立的使用者加入此群組。" -#: authentik/stages/user_write/models.py:47 +#: authentik/stages/user_write/models.py:64 msgid "User Write Stage" -msgstr "用户写入阶段" +msgstr "使用者寫入階段" -#: authentik/stages/user_write/models.py:48 +#: authentik/stages/user_write/models.py:65 msgid "User Write Stages" -msgstr "用户写入阶段" +msgstr "使用者寫入階段" -#: authentik/stages/user_write/stage.py:53 +#: authentik/stages/user_write/stage.py:130 msgid "No Pending data." -msgstr "没有待处理的数据。" +msgstr "無待處理的資料。" -#: authentik/tenants/models.py:18 +#: authentik/stages/user_write/stage.py:136 +msgid "No user found and can't create new user." +msgstr "找不到使用者以及無法建立新的使用者。" + +#: authentik/stages/user_write/stage.py:153 +#: authentik/stages/user_write/stage.py:167 +msgid "Failed to update user. Please try again later." +msgstr "無法更新使用者,請稍後重新嘗試。" + +#: authentik/tenants/models.py:23 msgid "" "Domain that activates this tenant. Can be a superset, i.e. `a.b` for `aa.b` " "and `ba.b`" -msgstr "激活此租户的域。可以是超集,例如 `aa.b` 表示 `aa.b` 和 `ba.b`" +msgstr "啟用此租戶的網域。可以是超集合,例如 `a.b` 對應於 `aa.b` 和 `ba.b`" -#: authentik/tenants/models.py:70 +#: authentik/tenants/models.py:58 +msgid "" +"Events will be deleted after this duration.(Format: " +"weeks=3;days=2;hours=3,seconds=2)." +msgstr "事件將在此期間後刪除。(格式:weeks=3;days=2;hours=3,seconds=2)" + +#: authentik/tenants/models.py:67 +msgid "Web Certificate used by the authentik Core webserver." +msgstr "用於 authentik Core 網頁伺服器的網頁憑證。" + +#: authentik/tenants/models.py:93 msgid "Tenant" -msgstr "租户" +msgstr "租戶" -#: authentik/tenants/models.py:71 +#: authentik/tenants/models.py:94 msgid "Tenants" -msgstr "租户" +msgstr "租戶" From 5f3cbf6f7fd012a7f51155e7a28b2b907c4b138f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 13 Nov 2023 11:16:25 +0100 Subject: [PATCH 10/24] website: bump prism-react-renderer from 2.1.0 to 2.2.0 in /website (#7535) Bumps [prism-react-renderer](https://github.com/FormidableLabs/prism-react-renderer) from 2.1.0 to 2.2.0. - [Release notes](https://github.com/FormidableLabs/prism-react-renderer/releases) - [Commits](https://github.com/FormidableLabs/prism-react-renderer/compare/prism-react-renderer@2.1.0...prism-react-renderer@2.2.0) --- updated-dependencies: - dependency-name: prism-react-renderer dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- website/package-lock.json | 8 ++++---- website/package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/website/package-lock.json b/website/package-lock.json index bee8fdb65..8a3e1b88d 100644 --- a/website/package-lock.json +++ b/website/package-lock.json @@ -19,7 +19,7 @@ "clsx": "^2.0.0", "disqus-react": "^1.1.5", "postcss": "^8.4.31", - "prism-react-renderer": "^2.1.0", + "prism-react-renderer": "^2.2.0", "rapidoc": "^9.3.4", "react": "^18.2.0", "react-before-after-slider-component": "^1.1.8", @@ -13614,9 +13614,9 @@ } }, "node_modules/prism-react-renderer": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/prism-react-renderer/-/prism-react-renderer-2.1.0.tgz", - "integrity": "sha512-I5cvXHjA1PVGbGm1MsWCpvBCRrYyxEri0MC7/JbfIfYfcXAxHyO5PaUjs3A8H5GW6kJcLhTHxxMaOZZpRZD2iQ==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/prism-react-renderer/-/prism-react-renderer-2.2.0.tgz", + "integrity": "sha512-j4AN0VkEr72598+47xDvpzeYyeh/wPPRNTt9nJFZqIZUxwGKwYqYgt7RVigZ3ZICJWJWN84KEuMKPNyypyhNIw==", "dependencies": { "@types/prismjs": "^1.26.0", "clsx": "^1.2.1" diff --git a/website/package.json b/website/package.json index c1652599d..d1daba2e9 100644 --- a/website/package.json +++ b/website/package.json @@ -26,7 +26,7 @@ "clsx": "^2.0.0", "disqus-react": "^1.1.5", "postcss": "^8.4.31", - "prism-react-renderer": "^2.1.0", + "prism-react-renderer": "^2.2.0", "rapidoc": "^9.3.4", "react-before-after-slider-component": "^1.1.8", "react-dom": "^18.2.0", From d89adef9639d72abcd3ea020875bfd11e13e4792 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 13 Nov 2023 11:16:34 +0100 Subject: [PATCH 11/24] website: bump prettier from 3.0.3 to 3.1.0 in /website (#7534) Bumps [prettier](https://github.com/prettier/prettier) from 3.0.3 to 3.1.0. - [Release notes](https://github.com/prettier/prettier/releases) - [Changelog](https://github.com/prettier/prettier/blob/main/CHANGELOG.md) - [Commits](https://github.com/prettier/prettier/compare/3.0.3...3.1.0) --- updated-dependencies: - dependency-name: prettier dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- website/package-lock.json | 8 ++++---- website/package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/website/package-lock.json b/website/package-lock.json index 8a3e1b88d..eaa9776d8 100644 --- a/website/package-lock.json +++ b/website/package-lock.json @@ -34,7 +34,7 @@ "@docusaurus/tsconfig": "3.0.0", "@docusaurus/types": "3.0.0", "@types/react": "^18.2.37", - "prettier": "3.0.3", + "prettier": "3.1.0", "typescript": "~5.2.2" } }, @@ -13582,9 +13582,9 @@ } }, "node_modules/prettier": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.0.3.tgz", - "integrity": "sha512-L/4pUDMxcNa8R/EthV08Zt42WBO4h1rarVtK0K+QJG0X187OLo7l699jWw0GKuwzkPQ//jMFA/8Xm6Fh3J/DAg==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.1.0.tgz", + "integrity": "sha512-TQLvXjq5IAibjh8EpBIkNKxO749UEWABoiIZehEPiY4GNpVdhaFKqSTu+QrlU6D2dPAfubRmtJTi4K4YkQ5eXw==", "dev": true, "bin": { "prettier": "bin/prettier.cjs" diff --git a/website/package.json b/website/package.json index d1daba2e9..cfc46b44a 100644 --- a/website/package.json +++ b/website/package.json @@ -53,7 +53,7 @@ "@docusaurus/tsconfig": "3.0.0", "@docusaurus/types": "3.0.0", "@types/react": "^18.2.37", - "prettier": "3.0.3", + "prettier": "3.1.0", "typescript": "~5.2.2" } } From 143f092153a5ada5caacd554074ebe001c04b01b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 13 Nov 2023 11:16:46 +0100 Subject: [PATCH 12/24] web: bump @trivago/prettier-plugin-sort-imports from 4.2.1 to 4.3.0 in /tests/wdio (#7533) web: bump @trivago/prettier-plugin-sort-imports in /tests/wdio Bumps [@trivago/prettier-plugin-sort-imports](https://github.com/trivago/prettier-plugin-sort-imports) from 4.2.1 to 4.3.0. - [Release notes](https://github.com/trivago/prettier-plugin-sort-imports/releases) - [Changelog](https://github.com/trivago/prettier-plugin-sort-imports/blob/main/CHANGELOG.md) - [Commits](https://github.com/trivago/prettier-plugin-sort-imports/compare/v4.2.1...v4.3.0) --- updated-dependencies: - dependency-name: "@trivago/prettier-plugin-sort-imports" dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- tests/wdio/package-lock.json | 8 ++++---- tests/wdio/package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/wdio/package-lock.json b/tests/wdio/package-lock.json index 0ffd4fc50..092e9d09f 100644 --- a/tests/wdio/package-lock.json +++ b/tests/wdio/package-lock.json @@ -6,7 +6,7 @@ "": { "name": "@goauthentik/web-tests", "devDependencies": { - "@trivago/prettier-plugin-sort-imports": "^4.2.1", + "@trivago/prettier-plugin-sort-imports": "^4.3.0", "@typescript-eslint/eslint-plugin": "^6.10.0", "@typescript-eslint/parser": "^6.10.0", "@wdio/cli": "^8.22.1", @@ -787,9 +787,9 @@ "dev": true }, "node_modules/@trivago/prettier-plugin-sort-imports": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/@trivago/prettier-plugin-sort-imports/-/prettier-plugin-sort-imports-4.2.1.tgz", - "integrity": "sha512-iuy2MPVURGdxILTchHr15VAioItuYBejKfcTmQFlxIuqA7jeaT6ngr5aUIG6S6U096d6a6lJCgaOwlRrPLlOPg==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@trivago/prettier-plugin-sort-imports/-/prettier-plugin-sort-imports-4.3.0.tgz", + "integrity": "sha512-r3n0onD3BTOVUNPhR4lhVK4/pABGpbA7bW3eumZnYdKaHkf1qEC+Mag6DPbGNuuh0eG8AaYj+YqmVHSiGslaTQ==", "dev": true, "dependencies": { "@babel/generator": "7.17.7", diff --git a/tests/wdio/package.json b/tests/wdio/package.json index cf64248c4..b0d598aa2 100644 --- a/tests/wdio/package.json +++ b/tests/wdio/package.json @@ -3,7 +3,7 @@ "private": true, "type": "module", "devDependencies": { - "@trivago/prettier-plugin-sort-imports": "^4.2.1", + "@trivago/prettier-plugin-sort-imports": "^4.3.0", "@typescript-eslint/eslint-plugin": "^6.10.0", "@typescript-eslint/parser": "^6.10.0", "@wdio/cli": "^8.22.1", From ddb73db2877e866a5cc3e24c0d1241695a7572b5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 13 Nov 2023 11:17:02 +0100 Subject: [PATCH 13/24] web: bump prettier from 3.0.3 to 3.1.0 in /tests/wdio (#7532) Bumps [prettier](https://github.com/prettier/prettier) from 3.0.3 to 3.1.0. - [Release notes](https://github.com/prettier/prettier/releases) - [Changelog](https://github.com/prettier/prettier/blob/main/CHANGELOG.md) - [Commits](https://github.com/prettier/prettier/compare/3.0.3...3.1.0) --- updated-dependencies: - dependency-name: prettier dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- tests/wdio/package-lock.json | 8 ++++---- tests/wdio/package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/wdio/package-lock.json b/tests/wdio/package-lock.json index 092e9d09f..081e13d33 100644 --- a/tests/wdio/package-lock.json +++ b/tests/wdio/package-lock.json @@ -17,7 +17,7 @@ "eslint-config-google": "^0.14.0", "eslint-plugin-sonarjs": "^0.23.0", "npm-run-all": "^4.1.5", - "prettier": "^3.0.3", + "prettier": "^3.1.0", "ts-node": "^10.9.1", "typescript": "^5.2.2", "wdio-wait-for": "^3.0.8" @@ -6590,9 +6590,9 @@ } }, "node_modules/prettier": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.0.3.tgz", - "integrity": "sha512-L/4pUDMxcNa8R/EthV08Zt42WBO4h1rarVtK0K+QJG0X187OLo7l699jWw0GKuwzkPQ//jMFA/8Xm6Fh3J/DAg==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.1.0.tgz", + "integrity": "sha512-TQLvXjq5IAibjh8EpBIkNKxO749UEWABoiIZehEPiY4GNpVdhaFKqSTu+QrlU6D2dPAfubRmtJTi4K4YkQ5eXw==", "dev": true, "bin": { "prettier": "bin/prettier.cjs" diff --git a/tests/wdio/package.json b/tests/wdio/package.json index b0d598aa2..a5e1078fc 100644 --- a/tests/wdio/package.json +++ b/tests/wdio/package.json @@ -14,7 +14,7 @@ "eslint-config-google": "^0.14.0", "eslint-plugin-sonarjs": "^0.23.0", "npm-run-all": "^4.1.5", - "prettier": "^3.0.3", + "prettier": "^3.1.0", "ts-node": "^10.9.1", "typescript": "^5.2.2", "wdio-wait-for": "^3.0.8" From dbbb5e75cfba998646f89954a15278418bb41147 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 13 Nov 2023 11:17:23 +0100 Subject: [PATCH 14/24] web: bump @formatjs/intl-listformat from 7.5.1 to 7.5.2 in /web (#7530) Bumps [@formatjs/intl-listformat](https://github.com/formatjs/formatjs) from 7.5.1 to 7.5.2. - [Release notes](https://github.com/formatjs/formatjs/releases) - [Commits](https://github.com/formatjs/formatjs/compare/@formatjs/intl-listformat@7.5.1...@formatjs/intl-listformat@7.5.2) --- updated-dependencies: - dependency-name: "@formatjs/intl-listformat" dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- web/package-lock.json | 26 +++++++++++++------------- web/package.json | 2 +- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/web/package-lock.json b/web/package-lock.json index b24ceccc3..7835e8310 100644 --- a/web/package-lock.json +++ b/web/package-lock.json @@ -15,7 +15,7 @@ "@codemirror/lang-xml": "^6.0.2", "@codemirror/legacy-modes": "^6.3.3", "@codemirror/theme-one-dark": "^6.1.2", - "@formatjs/intl-listformat": "^7.5.1", + "@formatjs/intl-listformat": "^7.5.2", "@fortawesome/fontawesome-free": "^6.4.2", "@goauthentik/api": "^2023.10.3-1699554078", "@lit-labs/context": "^0.4.0", @@ -2884,28 +2884,28 @@ "integrity": "sha512-ou3elfqG/hZsbmF4bxeJhPHIf3G2pm0ujc39hYEZrfVqt7Vk/Zji6CXc3W0pmYM8BW1g40U+akTl9DKZhFhInQ==" }, "node_modules/@formatjs/ecma402-abstract": { - "version": "1.17.3", - "resolved": "https://registry.npmjs.org/@formatjs/ecma402-abstract/-/ecma402-abstract-1.17.3.tgz", - "integrity": "sha512-2Q4hmKQ6CM30mRG/YMdSBW8LXf32BfuOb1FZgG+uVWPC/SQMoiVFz5JaeOukt96v6TZ4ddE+bHCmd611PW38QA==", + "version": "1.17.4", + "resolved": "https://registry.npmjs.org/@formatjs/ecma402-abstract/-/ecma402-abstract-1.17.4.tgz", + "integrity": "sha512-mLxTq+UrMoOoafVxG5HdmrfPpjv0uINQw1d0ADKfQMqhDaR4SDXdw3olXkOP05DGSAsVvSxzfKEuVKcLB15b9A==", "dependencies": { - "@formatjs/intl-localematcher": "0.5.0", + "@formatjs/intl-localematcher": "0.5.1", "tslib": "^2.4.0" } }, "node_modules/@formatjs/intl-listformat": { - "version": "7.5.1", - "resolved": "https://registry.npmjs.org/@formatjs/intl-listformat/-/intl-listformat-7.5.1.tgz", - "integrity": "sha512-J6heE28cikJ2cUZ7Mvmets418lE96k5OcbgDYQkXDFHVbRnUKCHQwRAXKRCPFEGDrEmcvtqUj7NmZEJYbsJdqQ==", + "version": "7.5.2", + "resolved": "https://registry.npmjs.org/@formatjs/intl-listformat/-/intl-listformat-7.5.2.tgz", + "integrity": "sha512-1jIZ+tnJ2nLNBZkDl9jUnB2sf87faU082ICc+MHfNXzalEacYEeOKzfFoJhfGCG2nzc+MhaSL1AMalDlc8MSvQ==", "dependencies": { - "@formatjs/ecma402-abstract": "1.17.3", - "@formatjs/intl-localematcher": "0.5.0", + "@formatjs/ecma402-abstract": "1.17.4", + "@formatjs/intl-localematcher": "0.5.1", "tslib": "^2.4.0" } }, "node_modules/@formatjs/intl-localematcher": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/@formatjs/intl-localematcher/-/intl-localematcher-0.5.0.tgz", - "integrity": "sha512-K1Xpg/8oyfCMxisJQa/fILoeoeyndcM0wcN8QiNG/uM5OAe1BcO1+2yd0gIboDI2tRJEsUi/sSBEYPbgkIdq4A==", + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/@formatjs/intl-localematcher/-/intl-localematcher-0.5.1.tgz", + "integrity": "sha512-An6EtxT0txJI8dQwOmLqs4lC3/+Dl9YuTGDWdxxtAT/9sx0r9DupnC3/k6F87Tb5gqXdR/ACdB7bmR+Zo2eu+g==", "dependencies": { "tslib": "^2.4.0" } diff --git a/web/package.json b/web/package.json index 33f9a41bd..13cb1fcc2 100644 --- a/web/package.json +++ b/web/package.json @@ -36,7 +36,7 @@ "@codemirror/lang-xml": "^6.0.2", "@codemirror/legacy-modes": "^6.3.3", "@codemirror/theme-one-dark": "^6.1.2", - "@formatjs/intl-listformat": "^7.5.1", + "@formatjs/intl-listformat": "^7.5.2", "@fortawesome/fontawesome-free": "^6.4.2", "@goauthentik/api": "^2023.10.3-1699554078", "@lit-labs/context": "^0.4.0", From d594574ffa66b057a4eb9e3e8a62debdaac57bba Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 13 Nov 2023 11:18:11 +0100 Subject: [PATCH 15/24] core: bump celery from 5.3.4 to 5.3.5 (#7536) Bumps [celery](https://github.com/celery/celery) from 5.3.4 to 5.3.5. - [Release notes](https://github.com/celery/celery/releases) - [Changelog](https://github.com/celery/celery/blob/main/Changelog.rst) - [Commits](https://github.com/celery/celery/compare/v5.3.4...v5.3.5) --- updated-dependencies: - dependency-name: celery dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- poetry.lock | 48 ++++++++++++++++++++++++------------------------ 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/poetry.lock b/poetry.lock index 059215106..197b912fe 100644 --- a/poetry.lock +++ b/poetry.lock @@ -422,13 +422,13 @@ typecheck = ["mypy"] [[package]] name = "billiard" -version = "4.1.0" +version = "4.2.0" description = "Python multiprocessing fork with improvements and bugfixes" optional = false python-versions = ">=3.7" files = [ - {file = "billiard-4.1.0-py3-none-any.whl", hash = "sha256:0f50d6be051c6b2b75bfbc8bfd85af195c5739c281d3f5b86a5640c65563614a"}, - {file = "billiard-4.1.0.tar.gz", hash = "sha256:1ad2eeae8e28053d729ba3373d34d9d6e210f6e4d8bf0a9c64f92bd053f1edf5"}, + {file = "billiard-4.2.0-py3-none-any.whl", hash = "sha256:07aa978b308f334ff8282bd4a746e681b3513db5c9a514cbdd810cbbdc19714d"}, + {file = "billiard-4.2.0.tar.gz", hash = "sha256:9a3c3184cb275aa17a732f93f65b20c525d3d9f253722d26a82194803ade5a2c"}, ] [[package]] @@ -544,29 +544,29 @@ test = ["pytest", "pytest-cov"] [[package]] name = "celery" -version = "5.3.4" +version = "5.3.5" description = "Distributed Task Queue." optional = false python-versions = ">=3.8" files = [ - {file = "celery-5.3.4-py3-none-any.whl", hash = "sha256:1e6ed40af72695464ce98ca2c201ad0ef8fd192246f6c9eac8bba343b980ad34"}, - {file = "celery-5.3.4.tar.gz", hash = "sha256:9023df6a8962da79eb30c0c84d5f4863d9793a466354cc931d7f72423996de28"}, + {file = "celery-5.3.5-py3-none-any.whl", hash = "sha256:30b75ac60fb081c2d9f8881382c148ed7c9052031a75a1e8743ff4b4b071f184"}, + {file = "celery-5.3.5.tar.gz", hash = "sha256:6b65d8dd5db499dd6190c45aa6398e171b99592f2af62c312f7391587feb5458"}, ] [package.dependencies] -billiard = ">=4.1.0,<5.0" +billiard = ">=4.2.0,<5.0" click = ">=8.1.2,<9.0" click-didyoumean = ">=0.3.0" click-plugins = ">=1.1.1" click-repl = ">=0.2.0" -kombu = ">=5.3.2,<6.0" +kombu = ">=5.3.3,<6.0" python-dateutil = ">=2.8.2" tzdata = ">=2022.7" -vine = ">=5.0.0,<6.0" +vine = ">=5.1.0,<6.0" [package.extras] arangodb = ["pyArango (>=2.0.2)"] -auth = ["cryptography (==41.0.3)"] +auth = ["cryptography (==41.0.5)"] azureblockblob = ["azure-storage-blob (>=12.15.0)"] brotli = ["brotli (>=1.0.0)", "brotlipy (>=0.7.0)"] cassandra = ["cassandra-driver (>=3.25.0,<4)"] @@ -576,26 +576,26 @@ couchbase = ["couchbase (>=3.0.0)"] couchdb = ["pycouchdb (==1.14.2)"] django = ["Django (>=2.2.28)"] dynamodb = ["boto3 (>=1.26.143)"] -elasticsearch = ["elasticsearch (<8.0)"] +elasticsearch = ["elastic-transport (<=8.10.0)", "elasticsearch (<=8.10.1)"] eventlet = ["eventlet (>=0.32.0)"] gevent = ["gevent (>=1.5.0)"] librabbitmq = ["librabbitmq (>=2.0.0)"] memcache = ["pylibmc (==1.6.3)"] mongodb = ["pymongo[srv] (>=4.0.2)"] -msgpack = ["msgpack (==1.0.5)"] +msgpack = ["msgpack (==1.0.7)"] pymemcache = ["python-memcached (==1.59)"] pyro = ["pyro4 (==4.82)"] pytest = ["pytest-celery (==0.0.0)"] -redis = ["redis (>=4.5.2,!=4.5.5,<5.0.0)"] +redis = ["redis (>=4.5.2,!=4.5.5,<6.0.0)"] s3 = ["boto3 (>=1.26.143)"] slmq = ["softlayer-messaging (>=1.0.3)"] -solar = ["ephem (==4.1.4)"] +solar = ["ephem (==4.1.5)"] sqlalchemy = ["sqlalchemy (>=1.4.48,<2.1)"] sqs = ["boto3 (>=1.26.143)", "kombu[sqs] (>=5.3.0)", "pycurl (>=7.43.0.5)", "urllib3 (>=1.26.16)"] tblib = ["tblib (>=1.3.0)", "tblib (>=1.5.0)"] yaml = ["PyYAML (>=3.10)"] zookeeper = ["kazoo (>=1.3.1)"] -zstd = ["zstandard (==0.21.0)"] +zstd = ["zstandard (==0.22.0)"] [[package]] name = "certifi" @@ -1868,13 +1868,13 @@ referencing = ">=0.28.0" [[package]] name = "kombu" -version = "5.3.2" +version = "5.3.3" description = "Messaging library for Python." optional = false python-versions = ">=3.8" files = [ - {file = "kombu-5.3.2-py3-none-any.whl", hash = "sha256:b753c9cfc9b1e976e637a7cbc1a65d446a22e45546cd996ea28f932082b7dc9e"}, - {file = "kombu-5.3.2.tar.gz", hash = "sha256:0ba213f630a2cb2772728aef56ac6883dc3a2f13435e10048f6e97d48506dbbd"}, + {file = "kombu-5.3.3-py3-none-any.whl", hash = "sha256:6cd5c5d5ef77538434b8f81f3e265c414269418645dbb47dbf130a8a05c3e357"}, + {file = "kombu-5.3.3.tar.gz", hash = "sha256:1491df826cfc5178c80f3e89dd6dfba68e484ef334db81070eb5cb8094b31167"}, ] [package.dependencies] @@ -1884,14 +1884,14 @@ vine = "*" [package.extras] azureservicebus = ["azure-servicebus (>=7.10.0)"] azurestoragequeues = ["azure-identity (>=1.12.0)", "azure-storage-queue (>=12.6.0)"] -confluentkafka = ["confluent-kafka (==2.1.1)"] +confluentkafka = ["confluent-kafka (>=2.2.0)"] consul = ["python-consul2"] librabbitmq = ["librabbitmq (>=2.0.0)"] mongodb = ["pymongo (>=4.1.1)"] msgpack = ["msgpack"] pyro = ["pyro4"] qpid = ["qpid-python (>=0.26)", "qpid-tools (>=0.26)"] -redis = ["redis (>=4.5.2)"] +redis = ["redis (>=4.5.2,!=4.5.5,<6.0.0)"] slmq = ["softlayer-messaging (>=1.0.3)"] sqlalchemy = ["sqlalchemy (>=1.4.48,<2.1)"] sqs = ["boto3 (>=1.26.143)", "pycurl (>=7.43.0.5)", "urllib3 (>=1.26.16)"] @@ -3924,13 +3924,13 @@ test = ["Cython (>=0.29.32,<0.30.0)", "aiohttp", "flake8 (>=3.9.2,<3.10.0)", "my [[package]] name = "vine" -version = "5.0.0" -description = "Promises, promises, promises." +version = "5.1.0" +description = "Python promises." optional = false python-versions = ">=3.6" files = [ - {file = "vine-5.0.0-py2.py3-none-any.whl", hash = "sha256:4c9dceab6f76ed92105027c49c823800dd33cacce13bdedc5b914e3514b7fb30"}, - {file = "vine-5.0.0.tar.gz", hash = "sha256:7d3b1624a953da82ef63462013bbd271d3eb75751489f9807598e8f340bd637e"}, + {file = "vine-5.1.0-py3-none-any.whl", hash = "sha256:40fdf3c48b2cfe1c38a49e9ae2da6fda88e4794c810050a728bd7413811fb1dc"}, + {file = "vine-5.1.0.tar.gz", hash = "sha256:8b62e981d35c41049211cf62a0a1242d8c1ee9bd15bb196ce38aefd6799e61e0"}, ] [[package]] From a1efcc4da9bd2c7bb0c64239d9d9c10b214d527c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 13 Nov 2023 11:18:50 +0100 Subject: [PATCH 16/24] web: bump rollup from 4.3.0 to 4.4.0 in /web (#7529) Bumps [rollup](https://github.com/rollup/rollup) from 4.3.0 to 4.4.0. - [Release notes](https://github.com/rollup/rollup/releases) - [Changelog](https://github.com/rollup/rollup/blob/master/CHANGELOG.md) - [Commits](https://github.com/rollup/rollup/compare/v4.3.0...v4.4.0) --- updated-dependencies: - dependency-name: rollup dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- web/package-lock.json | 104 +++++++++++++++++++++--------------------- web/package.json | 2 +- 2 files changed, 53 insertions(+), 53 deletions(-) diff --git a/web/package-lock.json b/web/package-lock.json index 7835e8310..b1607b290 100644 --- a/web/package-lock.json +++ b/web/package-lock.json @@ -88,7 +88,7 @@ "pyright": "^1.1.335", "react": "^18.2.0", "react-dom": "^18.2.0", - "rollup": "^4.3.0", + "rollup": "^4.4.0", "rollup-plugin-copy": "^3.5.0", "rollup-plugin-cssimport": "^1.0.3", "rollup-plugin-postcss-lit": "^2.1.0", @@ -4576,9 +4576,9 @@ } }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.3.0.tgz", - "integrity": "sha512-/4pns6BYi8MXdwnXM44yoGAcFYVHL/BYlB2q1HXZ6AzH++LaiEVWFpBWQ/glXhbMbv3E3o09igrHFbP/snhAvA==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.4.0.tgz", + "integrity": "sha512-AD30wtT58hZZsXIeiksytR6Gm2gofUxn5KqrDBdyzekgxXB9bXN9dqWIEcPfYo9lA9MVRm0lC42LuYGsscRxiA==", "cpu": [ "arm" ], @@ -4589,9 +4589,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.3.0.tgz", - "integrity": "sha512-nLO/JsL9idr416vzi3lHm3Xm+QZh4qHij8k3Er13kZr5YhL7/+kBAx84kDmPc7HMexLmwisjDCeDIKNFp8mDlQ==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.4.0.tgz", + "integrity": "sha512-PlqvhzFxy5FRTB3wLSsGgPhiakv9jrgfu8tjSojLJFP0CdhfZSRDOFvQ2emWLUEBOSCnjpL63XSuFVMwg59ZtA==", "cpu": [ "arm64" ], @@ -4602,9 +4602,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.3.0.tgz", - "integrity": "sha512-dGhVBlllt4iHwTGy21IEoMOTN5wZoid19zEIxsdY29xcEiOEHqzDa7Sqrkh5OE7LKCowL61eFJXxYe/+pYa7ZQ==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.4.0.tgz", + "integrity": "sha512-BYmhn1Hebmkmdyn5mBFy7HptowyjtMALyTpywNSNZYigWwyv4L8WQVr0XvOQE7eE6WoKrupSVxtIcGZW8MgZUA==", "cpu": [ "arm64" ], @@ -4615,9 +4615,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.3.0.tgz", - "integrity": "sha512-h8wRfHeLEbU3NzaP1Oku7BYXCJQiTRr+8U0lklyOQXxXiEpHLL8tk1hFl+tezoRKLcPJD7joKaK74ASsqt3Ekg==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.4.0.tgz", + "integrity": "sha512-7GXsMiX/giTDBMs/gL3rePLBRC6gV7DT7JQ0lNqoNDe5hm+Gm4NEWky9fwEmer64fIUbOsTiLUsyQ5fDXUbXPA==", "cpu": [ "x64" ], @@ -4628,9 +4628,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.3.0.tgz", - "integrity": "sha512-wP4VgR/gfV18sylTuym3sxRTkAgUR2vh6YLeX/GEznk5jCYcYSlx585XlcUcl0c8UffIZlRJ09raWSX3JDb4GA==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.4.0.tgz", + "integrity": "sha512-kavnkaV50Gu6vESlOAwUad92wYY9mUrcaPmhzOQZKlNFnzWAUYyD/uhHmWvY7Z2chtwhWlng0LvCRBF5QiPO7w==", "cpu": [ "arm" ], @@ -4641,9 +4641,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.3.0.tgz", - "integrity": "sha512-v/14JCYVkqRSJeQbxFx4oUkwVQQw6lFMN7bd4vuARBc3X2lmomkxBsc+BFiIDL/BK+CTx5AOh/k9XmqDnKWRVg==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.4.0.tgz", + "integrity": "sha512-2hBHEtCjnBTeuLvDAlHRCqsuFQSyAhTQs9vbZEVBTV8ap35pDI1ukPbIVFFCWNvL/KE7xRor5YZFvfyGCfvLnA==", "cpu": [ "arm64" ], @@ -4654,9 +4654,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.3.0.tgz", - "integrity": "sha512-tNhfYqFH5OxtRzfkTOKdgFYlPSZnlDLNW4+leNEvQZhwTJxoTwsZAAhR97l3qVry/kkLyJPBK+Q8EAJLPinDIg==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.4.0.tgz", + "integrity": "sha512-u7zy0Ygzl7O5Gvr9TSNSQj+DBzvMJC7rXfyQNgZ13KwkhgJ8z0z+gt2AO4RPd01rZioMQ2/TA24XGGg4xqhd0Q==", "cpu": [ "arm64" ], @@ -4667,9 +4667,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.3.0.tgz", - "integrity": "sha512-pw77m8QywdsoFdFOgmc8roF1inBI0rciqzO8ffRUgLoq7+ee9o5eFqtEcS6hHOOplgifAUUisP8cAnwl9nUYPw==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.4.0.tgz", + "integrity": "sha512-VvpAdh5SgewmWo8sa5QPYG8aSKH9hU2Kr5+3of0GzBI/8n8PBqhLyvF0DbO+zDW8j5IM8NDebv82MpHrZaD0Cw==", "cpu": [ "x64" ], @@ -4680,9 +4680,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.3.0.tgz", - "integrity": "sha512-tJs7v2MnV2F8w6X1UpPHl/43OfxjUy9SuJ2ZPoxn79v9vYteChVYO/ueLHCpRMmyTUIVML3N9z4azl9ENH8Xxg==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.4.0.tgz", + "integrity": "sha512-3g6jaXxXVFaDnFoMn2+E3ludGcXFfEr6lDn+S1lh9Qe0JcL9sPt1wGh0g2cKIlb6OakNOFopZqJ5Yub9F7gQlA==", "cpu": [ "x64" ], @@ -4693,9 +4693,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.3.0.tgz", - "integrity": "sha512-OKGxp6kATQdTyI2DF+e9s+hB3/QZB45b6e+dzcfW1SUqiF6CviWyevhmT4USsMEdP3mlpC9zxLz3Oh+WaTMOSw==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.4.0.tgz", + "integrity": "sha512-jnoDRkg5Ve6Y1qx2m1+ehouOLQ4ddc15/iQSfFjcDUL6bqLdJJ5c4CKfUy/C6W1oCU4la+hMkveE9GG7ECN7dg==", "cpu": [ "arm64" ], @@ -4706,9 +4706,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.3.0.tgz", - "integrity": "sha512-DDZ5AH68JJ2ClQFEA1aNnfA7Ybqyeh0644rGbrLOdNehTmzfICHiWSn0OprzYi9HAshTPQvlwrM+bi2kuaIOjQ==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.4.0.tgz", + "integrity": "sha512-SoLQmJanozFow8o50ul2a3R+J7nk4pEhrp83PzTSXs5OzOmIZbPSp5kihtQ3f6ypo4MCbmh0V8Ev0bJIEp4Azw==", "cpu": [ "ia32" ], @@ -4719,9 +4719,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.3.0.tgz", - "integrity": "sha512-dMvGV8p92GQ8jhNlGIKpyhVZPzJlT258pPrM5q2F8lKcc9Iv9BbfdnhX1OfinYWnb9ms5zLw6MlaMnqLfUkKnQ==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.4.0.tgz", + "integrity": "sha512-Zaz6itfQ5sQF5Cia49YDW1ZTr+YfIKzTSb9npLyvQn346n7ulRDOv2J7GnL0zcOJ3cqW7HzG/ZisyO6fH43J9g==", "cpu": [ "x64" ], @@ -19154,9 +19154,9 @@ "integrity": "sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg==" }, "node_modules/rollup": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.3.0.tgz", - "integrity": "sha512-scIi1NrKLDIYSPK66jjECtII7vIgdAMFmFo8h6qm++I6nN9qDSV35Ku6erzGVqYjx+lj+j5wkusRMr++8SyDZg==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.4.0.tgz", + "integrity": "sha512-3L67ubCc1Qm49wUodsQ72FM6JmJ9M37d63rGPjxbcKrzNJrwFipl+lDNHeWd6BId09S6Tb9KiBgYKbWhIuqVyg==", "dev": true, "bin": { "rollup": "dist/bin/rollup" @@ -19166,18 +19166,18 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.3.0", - "@rollup/rollup-android-arm64": "4.3.0", - "@rollup/rollup-darwin-arm64": "4.3.0", - "@rollup/rollup-darwin-x64": "4.3.0", - "@rollup/rollup-linux-arm-gnueabihf": "4.3.0", - "@rollup/rollup-linux-arm64-gnu": "4.3.0", - "@rollup/rollup-linux-arm64-musl": "4.3.0", - "@rollup/rollup-linux-x64-gnu": "4.3.0", - "@rollup/rollup-linux-x64-musl": "4.3.0", - "@rollup/rollup-win32-arm64-msvc": "4.3.0", - "@rollup/rollup-win32-ia32-msvc": "4.3.0", - "@rollup/rollup-win32-x64-msvc": "4.3.0", + "@rollup/rollup-android-arm-eabi": "4.4.0", + "@rollup/rollup-android-arm64": "4.4.0", + "@rollup/rollup-darwin-arm64": "4.4.0", + "@rollup/rollup-darwin-x64": "4.4.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.4.0", + "@rollup/rollup-linux-arm64-gnu": "4.4.0", + "@rollup/rollup-linux-arm64-musl": "4.4.0", + "@rollup/rollup-linux-x64-gnu": "4.4.0", + "@rollup/rollup-linux-x64-musl": "4.4.0", + "@rollup/rollup-win32-arm64-msvc": "4.4.0", + "@rollup/rollup-win32-ia32-msvc": "4.4.0", + "@rollup/rollup-win32-x64-msvc": "4.4.0", "fsevents": "~2.3.2" } }, diff --git a/web/package.json b/web/package.json index 13cb1fcc2..132df62b1 100644 --- a/web/package.json +++ b/web/package.json @@ -109,7 +109,7 @@ "pyright": "^1.1.335", "react": "^18.2.0", "react-dom": "^18.2.0", - "rollup": "^4.3.0", + "rollup": "^4.4.0", "rollup-plugin-copy": "^3.5.0", "rollup-plugin-cssimport": "^1.0.3", "rollup-plugin-postcss-lit": "^2.1.0", From 73fbcde9248e000906e3f41f9320aef2d0a92bce Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 13 Nov 2023 12:12:43 +0100 Subject: [PATCH 17/24] web: bump @trivago/prettier-plugin-sort-imports from 4.2.1 to 4.3.0 in /web (#7531) web: bump @trivago/prettier-plugin-sort-imports in /web Bumps [@trivago/prettier-plugin-sort-imports](https://github.com/trivago/prettier-plugin-sort-imports) from 4.2.1 to 4.3.0. - [Release notes](https://github.com/trivago/prettier-plugin-sort-imports/releases) - [Changelog](https://github.com/trivago/prettier-plugin-sort-imports/blob/main/CHANGELOG.md) - [Commits](https://github.com/trivago/prettier-plugin-sort-imports/compare/v4.2.1...v4.3.0) --- updated-dependencies: - dependency-name: "@trivago/prettier-plugin-sort-imports" dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- web/package-lock.json | 8 ++++---- web/package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/web/package-lock.json b/web/package-lock.json index b1607b290..249834e4f 100644 --- a/web/package-lock.json +++ b/web/package-lock.json @@ -66,7 +66,7 @@ "@storybook/blocks": "^7.1.1", "@storybook/web-components": "^7.5.3", "@storybook/web-components-vite": "^7.5.3", - "@trivago/prettier-plugin-sort-imports": "^4.2.1", + "@trivago/prettier-plugin-sort-imports": "^4.3.0", "@types/chart.js": "^2.9.40", "@types/codemirror": "5.60.13", "@types/grecaptcha": "^3.0.7", @@ -9994,9 +9994,9 @@ } }, "node_modules/@trivago/prettier-plugin-sort-imports": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/@trivago/prettier-plugin-sort-imports/-/prettier-plugin-sort-imports-4.2.1.tgz", - "integrity": "sha512-iuy2MPVURGdxILTchHr15VAioItuYBejKfcTmQFlxIuqA7jeaT6ngr5aUIG6S6U096d6a6lJCgaOwlRrPLlOPg==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@trivago/prettier-plugin-sort-imports/-/prettier-plugin-sort-imports-4.3.0.tgz", + "integrity": "sha512-r3n0onD3BTOVUNPhR4lhVK4/pABGpbA7bW3eumZnYdKaHkf1qEC+Mag6DPbGNuuh0eG8AaYj+YqmVHSiGslaTQ==", "dev": true, "dependencies": { "@babel/generator": "7.17.7", diff --git a/web/package.json b/web/package.json index 132df62b1..a167f9a58 100644 --- a/web/package.json +++ b/web/package.json @@ -87,7 +87,7 @@ "@storybook/blocks": "^7.1.1", "@storybook/web-components": "^7.5.3", "@storybook/web-components-vite": "^7.5.3", - "@trivago/prettier-plugin-sort-imports": "^4.2.1", + "@trivago/prettier-plugin-sort-imports": "^4.3.0", "@types/chart.js": "^2.9.40", "@types/codemirror": "5.60.13", "@types/grecaptcha": "^3.0.7", From 7699a119a35cfc83b7c1fc64fa152ae07dda9914 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 13 Nov 2023 12:12:54 +0100 Subject: [PATCH 18/24] web: bump prettier from 3.0.3 to 3.1.0 in /web (#7528) Bumps [prettier](https://github.com/prettier/prettier) from 3.0.3 to 3.1.0. - [Release notes](https://github.com/prettier/prettier/releases) - [Changelog](https://github.com/prettier/prettier/blob/main/CHANGELOG.md) - [Commits](https://github.com/prettier/prettier/compare/3.0.3...3.1.0) --- updated-dependencies: - dependency-name: prettier dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- web/package-lock.json | 8 ++++---- web/package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/web/package-lock.json b/web/package-lock.json index 249834e4f..381a3c397 100644 --- a/web/package-lock.json +++ b/web/package-lock.json @@ -83,7 +83,7 @@ "eslint-plugin-storybook": "^0.6.15", "lit-analyzer": "^2.0.1", "npm-run-all": "^4.1.5", - "prettier": "^3.0.3", + "prettier": "^3.1.0", "pseudolocale": "^2.0.0", "pyright": "^1.1.335", "react": "^18.2.0", @@ -18195,9 +18195,9 @@ } }, "node_modules/prettier": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.0.3.tgz", - "integrity": "sha512-L/4pUDMxcNa8R/EthV08Zt42WBO4h1rarVtK0K+QJG0X187OLo7l699jWw0GKuwzkPQ//jMFA/8Xm6Fh3J/DAg==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.1.0.tgz", + "integrity": "sha512-TQLvXjq5IAibjh8EpBIkNKxO749UEWABoiIZehEPiY4GNpVdhaFKqSTu+QrlU6D2dPAfubRmtJTi4K4YkQ5eXw==", "dev": true, "bin": { "prettier": "bin/prettier.cjs" diff --git a/web/package.json b/web/package.json index a167f9a58..fd33d387c 100644 --- a/web/package.json +++ b/web/package.json @@ -104,7 +104,7 @@ "eslint-plugin-storybook": "^0.6.15", "lit-analyzer": "^2.0.1", "npm-run-all": "^4.1.5", - "prettier": "^3.0.3", + "prettier": "^3.1.0", "pseudolocale": "^2.0.0", "pyright": "^1.1.335", "react": "^18.2.0", From 0a0f87b9ca10576604b1ba68189f61da6fbe74f3 Mon Sep 17 00:00:00 2001 From: "authentik-automation[bot]" <135050075+authentik-automation[bot]@users.noreply.github.com> Date: Mon, 13 Nov 2023 12:13:22 +0100 Subject: [PATCH 19/24] core: compile backend translations (#7538) Signed-off-by: GitHub Co-authored-by: authentik-automation[bot] --- locale/zh_CN/LC_MESSAGES/django.mo | Bin 55050 -> 56897 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/locale/zh_CN/LC_MESSAGES/django.mo b/locale/zh_CN/LC_MESSAGES/django.mo index 64dba54307be03e1e7ffcf564c630fb0ecd21cdb..221747fab5fb6ea3ed1ef261c58701aa77f42e4f 100644 GIT binary patch delta 14168 zcmaLd2Xs|MzxVMSLg>ANluhrUiS&*rQltq8B821sfsn*=5~_GY?==vlN$*k*HKB-# zU;_(?1;vt+1W^$l8`k&xJ2Uw3-gVdA%i%L^&&>YM?47`J!T#`br^5YTl*qlx;i{j@ zaVla`amUFf|4ud4I?k9##~FdKI1}H(X4t!taRzRpd<+-ipvI0<88dMRhBtAX3HU4y zz^hmr>os+p_KxFs`jL5visjfA_hDZA7K`CsjK*+gEsUe_8BE4f_yN|zY-H_Dv4_ol z)llVT7=e#sN9=)9a1l0RekX5p$04UmI8vUARoNbtfTEH@_gxhc!zKSc*ZEdz7 zfJG>u!&3MjYN8#AXZExeCn=WtDcA`!u?p7e;5bFG8|v%~M9mX}&Cu7u?>J4#?4%+e zeu|y(8)OWpR!7Haf*x#+tFacoi|YRqD%5|W7C4*PE8?G60LwF&p1cM=jg4^?Eu1BXvWCbT8MDo#`3rqE8uw?h+m?fs6|&ZU^mo+{cU+ThEtA1ZD}G_ z#wDl)`uCC14JXjW*HImV$bU}wqmEM(AIIt#j}f>6b>EAqC)sAphp-yu)2P??OMC|J z;Bf5S&1}hj0Ctr zk%xA=@HN?lOK~hV?q^Q_I@A*!LoMV6w#7eDhqM)g6vkm#0>@z?d;t~Vg|>cgf0kK{ ziZfJbMVGMvW}@nEqe7@3T?L^8>abNt9@eReoHr*4bv90+&QkbO<~6H|dccmTLpKn$ zu<=*~r~1ig;034^rr8c#u{7mFI2A9T54&*058-jtLShG*g(sr=&$i`t_$=jvsMoLP zV4{n0I0W@I$`AgbWF98tLC%A-7RzD|YA@AWk!Wk}h2<$fi?wl*b(3wshzj{9s4e;q zbr?&tzxnVX)WT~Z5A1j9lTnCUqHcTw6{=yVg(RUuwg?rWwYIzyOHw|HrSMJb7pO@5 z2Q^N99$(|QSTKxvkT=um%85L!W4e@#7SM}$X#vBLZFIcY2rr-}`V}=%!Qp1_U2IG_ z0rjQagiSGsIt%4SnD5DOY(jYpw!>H!vFQQUw!T>Gr2Z2jA)t^N$_VX+wE-;qokG78!A))lA)>_UR$ zypEcv8ebWr=d?maA`NxlUep54p$_whsI9tzE`EpF`@*Bl-j_l3uQZDIYo(2-(17hx z1NKKfNi1sbCtK&D`mI6@um^PrPhl<0#0FS!v{^_?%tN^=YC%0v;|<2VIBGQU*XfR@ zLIe7-87@aH>^y2AS5O0GVtu@Ym9Xp>^JL9Y-;MUx?$!aQ`-h|ENkE;Y6x4&P^xKBr zsFkIoUayNd5x+*=FeKJ2Fdj8fiY+g_14Ecm2GZR-tZgA>gU2Ke+cnE63F{lVkL`}F1r{ijzkLAakt=)<)~Hk)E*B;-8Tm7;2cy$4`3~P1GRPE z<9hrX%j*4KmuN$T6)2~pLVpzt;~gx5|DXmc@|@Yb=2(pKP^^z}sP-4J3Z6xM`EH;V z^egIn;(AScJM=5m!^mi_o=26Z+YXzsAmvxE5Wa(2;3udM|Ag9-Kk#7;_c=~$Y>A!G zhb|sNE#w;B!`t`<-b^C?y~!L*HY@xGU!z=Sg4wI@FoLqntDp&M;V^87C2=9@HQH!B zg8F{EiII2%8)1=2rraKNcE+Q&cJ(CUU!6>lifWjDGW&=PPz#%l&G8DVUx6tmQjw^L zG(&AsM=XxLu>_7lZH>>?&$6c3_Fbs0$ncZVq4^lK=fBv75>rjN5vpSk)PQ496HP|F z-wRRqzi0gcbvO$>Zx$AbicnkZj(w5nJL^yn=r20Wg!ox(NJR_|!xgstBWmKxd{sC< zP9rRboAD7$M{UI&)LDoiqP%fVVN~R%px&N?s0g1#Me;fp)%)+HmUB%D^_x*4K8;oI18jHC6wo(7t1a(e{WcT z11TTCB+RqeypB^*3pj&{z?bN+K&BF-w8oa07k#KbpNg@#2(>l8U^M1gYEJ)H)WRpC z+S9NE?y#Ojy|(XQ2mBBdu;eoHo72o?#9ucYp+cwg0v5&M%k5dfLX?}JLe}1v2cZ@c zgQM^w>d6|dF!%MfMxnOkIV^$8QCqRi`pOF8uL-VGA#b97==_2uFf7$r%32#0q1M<4 zJ7W#>VtZVT93$r=)Pp>;(in%uDL;?8e+eqWX?`-Ac&GIU>I-%bd*C(PjMZ0}fzDg6 zT7%Y~u?zho(#&|>Q41Jo9fkTNPr!zF616q{Y%*HF52z>p19fAO)uuyb96-6Ibqan* z`7$=aQ!kpW_yM)Y{nnTeuRx8vA2n`<^%80UUtwdt|3%lDi8`Vh9>cDfjLk6J`UC0= zR9k1h3vG~ZlhYLk;j8!%R#Qrd4ZfQw!Yy8^<)2Alc`6;W2imyT4$jm zk%lF4hcz7sQ@(_H!rCtxAGUU~_Qr79hoTPQaH}76#x_dkclOwZqga9RReTJ8#ERH* zqj}AqLQR;23h8v~N>pTaq9XPR>TvypIzthg%s;*KMcseMdItS+u;=)iY2z0g~y{Ju?F=3@1hoP#hQ(JfZwrLfJIznQj#!^^ zw4aRjYN>S-hW5yM#@4@Wy^dw+|GhP0mpL<)uod+!F&Vws0(0A%W&0$Qz29!6T7V;K8f?s1@EdR2ZpbIJjeQbFomZ6-0 z+KM@*-tVlj6+2L&J82r6SFG>a`cE-G?O$PUyoHZq>wU%))Pmlyet}xRFV=kfO}T=# z0p`>D-#(P#mBZ59&D+FPJb`!v*(9>+&8h|RF#3G)j^ zAM12%OZ{P-g|{&cll0qYcQOUjP3WGojzN79r(!`|g|%_BZGY2x9Tmab)<3QJGfaIM zYjtc)zs6V}qp&qD_LI?`UBsgJ8CJ$ysQ0+QDbt>UgD9t>4%;p3U#RjYH48P=7UoAM4+R&;>I$R{96T(?0=wQC@{w$T!#lf5aNt_zhG46lx(O(M2y-##Gd& z{4i?5i>OndiPP~OYTl_Ah<_e3D=(Oi>#WC76Mty^5^Gcb9ua&X>9B#lbecu=;9#jB-9?Sv2I5_(IM1=FIX?3Uc;-{7M-_D zq}rh-nudzNM!bs|_#W`K95$~IR<*fCs?Xe8^_YKMZk0GPb`mL+1d#&eC6JE1^iwgB$SP5HyU?Mgc zwa3%2D6U5xvX`+Pp2rCo{-ODmYzpSl`~Mo5hWHl7;cr+SJy*;jn~wu1r`hr?R78Hm zQds?}iA+n3rQ89V<8I7{H&9!eV=erVSzuH2Yo(pZ6v2MhD9lee5eMQF+<@<6@i2a| zxMqHiPyd*IW~Kf*>H)@oV*c%D9qM(xhpn*Hr{;_5!yc4xqUxJ}#{O%?37?r8Kf(5t zTUJVK+oteL}B3Ag^>}d;ZO1U?d$LUxF*P#w&2CDy8sMqxG&xyZF zru-KsgsqVW3|-CmQ%|R>vmx|n>0G=ew$pFej?|FENAusSDCK{sU?@aY9;hotz7h3DNs~#fNqi1Mzm7xbuk8&U z=)aM=TckOppGmsf(5^$CK$;(>pTG9%LBnh0U&ZM-oTRgmpC>AY_pkSCh7Vroby88^ zjeDdl?!ABMK(4lBeM$eYc@OGPn~V9sB3H?VvIY5~NsBNKcUFk{%_c(`P;Y zK)OjPM!$2^Jx~7rb(Q>LQZ?GV57dt(um5pn6&**ZUe8~jOa^Jg{k!oOHF7;`aQM05 z45IEITVDs~QRlJkq6Bq%o1$#pV(ex67sQ7t^Z5^buGM7;$={AY!d2pWg-+KkH{HH$w}NzYJU zkv^TsPbVKw(iKm7TkroajT$y}vJMc={{vc(L3R3qTZL@9PU#OdE^ZK$y zkbbh|KICVRKBQce^b`5gr0t~cl=UU`&*u+aC8;<-x<%4;(%`&KIfs-@YD79t()Ad= zM7l&uB0Wv=Qoj~;omD-4PZ~*@Mp-{&u99NN@5a2ji2pkj>QZP-x=lVW=`i`dBwh7* z;vFXIw56>gX(eeYb@Q+=?E^8KbjJ3ZLcSDvA8CuN6O~B|Z2260I)<_T2g&H#i(5$> zNOx>q1Wq8`BUNCcmgpnt3XsC6TOTU@_mAebJ)E}B$v;ObL~{)csEztJBv+c=|A#3I z#{IVP1@g*-2(RDM;SMNNh@~YzJOLUA@$(Y9;-3s3}EyiB?^&koM4e|LQ>IV_Sa5Ru-qc z!`3BWSJF466SQ}euT~crJoi}C_GPP9a25=TX6;+$M10x2Js(! z0d>V%PvAz54P| zLMP~g?I>>0rxWQr@_q0IW?~$vFZna5>pJOC(kfe4-Dpxa>2K;5*!reejyb1L?=R0E zx_Xk5X=olQ@!6q6QJZ(kXOiDUYC)eZcA#mt{SM}}`3km8MLpa|(n8Wq$`4^{(r{7% z%JucEyD8{$NnhA}Zt`=;D=^hb3p?n!jVh%~yGo+c+-Nk6zw>q|@ z{2OVat?Qz%MIL6^PQ_&!bWJ3UC)K9zJKM3UR>F0gG?vtcG?}(h*o&m=2T~sDx`ayR zk9Y0;&tiYlc~U-__SrsV6(U{NNPpUVsKWj+nz|ykzOW>Pkrt6XKq^Q6CVoWHb(HcD z{GF7a{Qc_)nF5rT`b{iP|CwY@Ho|A@5CmiJ&^%4sBBzmmp~pNsiP$)t6*jcn+u zMEPf1H^A2I!WE<^NCk-G*R&5Kbqfm(!_O@Wsf{Dcqy`&)9*Axf5te!}a%Op_fE&6V zk9BL-N%ncX@loSFb$tyAq)u%do%%$>qA;#0bW*swR+eV>cWZ+uk3b_LLnvII6 z)HyEMljx1rP_c0yHzvX3(^#%&Qmij2FuvvSupo?l!yTXOOL9kg+~_f$=y9Hy!0s;5;SDCoN4ulF z3CW2(ame9jfo@E4Xb!Jud;+6;yxs(FYPZMSp(Zf@N3Yh56zX2r=X4`Po*1n)IWb17 zR8S+`K5?EXAH#bmn`OIkw0R=~iyuqR7ue8eQm*3NWAtE2lifbvgbA@R9&hRw{hmmj z+<&th?TP2sr+iVPJxn|jtY$xtFF7vBjU5#ltWN@CO=dqm(aE91F^cH;B2!bwlnJDa zxfM~$jqyz2iJbl#JKB^2Bjb;Sm40$SpZkpi{>=wUC5{gZOH7USwo1)-Zf96xAlmzS zc$NMh?*tFq-mkkmitX>;ySq#I-y<2QHeq}|zfNDnk!(T?$09B%w&AF#=p=eSaHMp6 zqX`ZthFyzsN3vOoiJthF*!aJ;#m|%rgrh&EJsz{9T`6jX@k#6XP z@r_AHj*D><;^QX!HL52*YNSpF;ZeMGG<@6_mE=y0r93iL<7yRg@R#$MgF{Do#HvfERna<6BlC+(gO!3$<>)o;^{oDFCp0*%`vm@+x=dF z#VK(SsY~X3ocjITA5!Dy#^!Pgq+Xp@J@xl_PpAGo+t=QFT(b6UyE$WjX2!AXm4|Mo ztj*rI{btIFn<>-(_b-SWT)LdbZ&GFidd?5a6&SKGUqtDg)D6LPXR^}fGD_x&#ld|q z2G{QjL@nDC);YK_Ju`iY+p}w@K5o|f#lZ!ev-cjzIWRr*vA?P%1PgwnQ{8& zo<&q$ z=j?j!y18;q&Vd8BPb~^ATa>kLdv?aG|M{Isy|tm{;Qw|A4Q0Q+_dhbhZHID>Y`=YK z?SDTkS?i8ur5&^rhniVg&Vl3EyA}tREx9>&an6BNib?C2vhxP~JG$k{W1cJZ?Ojz; zx9#ed+Ie?5lDA3D{u9Bap#YpdtKnwO4$e91{I9h+`ws?BuL=ZqKbNb}&6N4U{cE#! zZ4SP)F!hVQjUP8zrlcin;qGAiN=D1xwJ?~zlm+Se=B)`XI(c(8E8G5HD>2TRpOUqH zz8N7<;pMJH%V(b5oU>!tO2?0%b|hDp%>M*K9CP&z1CIVlltd>;9FAR zjiuqCkB2!5%#dj!6go7)HM{hM3G90F>%4y2^ngnbWM*(y*XEp^%W(@Hn3KI}I?tYU zJR`VZ6VDP{dOWydk$H79Gq%#2wPCv%)SOCFsYADIZE)SD>?4~VJd8Y7X2xtrHsQ+7 zSk4Xv=N-)Q@7tEObXn$^btc>jMCcUVoOwEU{4f#EKE2<}YMxmU4{dYiiG^A77qc1K zl4S?DD|8NbXsgWXITPsiGn|d}>pISQ+=C6VPd#HQs{Sxm#vu`o(;rhX z46otS7*OAF$~lhPX+zS2ilG>YYmh!T88{sGVj&D|;5Y-Z2A06NSOZsLG5i2^-$g8i zIkx^G22d_SFI!Q*-L)v#fC(#W7jU1;7mdD~a219T<2IC^6$Icooi2HCTp2Wcz z*4Vu9D_D~9Hq>*Epa%0xEP;RHQ&^~p<5Z-5C!9nLc1ATg1ocLVSQ6)ADO`nm&~DU7 zT|h?Pxr*voa8t)=jbZpIjz!)7J8ER|H#6;oqVBJQZZ*`{o@kHiKz|&B<8d*bMNPqw zNXIFR<4|uh4b{LR?2cP7Ki)%K@88^vTrmuzTmkc9Thw!&Z_fDZ0sW{@!||x0osE+) z9j9Sn6eHm0ICHQSfA?I@Wu}+|UO#v_nuG%*FCJxRv7+z^SOU@(T9D#kdr2qh2h9 z-l}717=dftBpS+dsFApd8i{*Y77Nk4Pz=L9_#EnuR-hiZ71iJ#TRw*Vl+R%WJdaP| zuc!_dVS(uSP;{ZYI*Bf9k8LmptKeIxZF3HF!v$1>H*EPQtW5bHYH^k4=7CrThhQpd zDsG|f{|EUbIQiO|_L?A5;&ytGu)dsm7=XvH6rMtj%ym@Hf5&|I2sIJ`?M#OTqDCwh zwV0=)MluccoD8gv2T?D26Lq~`dwqA@Tuj2ca(bXHd>y&Q*@HFl0qR3jy@TWQ#BLak zZ(=PB=xAOb0`pRiMQ!KtsD@^tUSKI|B-Ud^+>TXg-#JUdj&XiN4N>jq9j6)&Ko`!! zB;1HGSh|zx*mMk_yan~h%4*`8|(#p zP^Q%RUmu5HOI(ES;HP*HXAUuox#du^h&@=2`W;vv&tO5?cXCOzitl0>EW_7D zZ&)Ao1|3lQx<6_Wjj>L#_4813y&P-dC)f)AMvYkHFk?4V2V#(SaAu)f4ShqxOFMs} zMxy6%bHiv<2WFsFZ8~bIR-+5Iq2~S!YVN;4U4I4D(c7r!-A8q#=m_&7)ls{m$q2?@ zNgFD3VGq;;Mxhqr6s(RLFdRQZb>t6JgMNGt)uABNb4sEQg%Ji_dwIyl|bi)}q8rxtlY6!zen+H9IdXs^u`mv~~oP}y|IclyqqpmxS z8oAF=BX-T|zD1%N{;~$dnj1neFZGo%ABI`$S{q{^^)1jJ+n`3S13rZ#Q6o1OeQO7G z{c5aH!>s3EN~&Md;_sJV{D)tG?#02LW;M+o(Y zRbAB3cf{%#gVk^W>i*qW8$Zx_?f+j$Dq^X4^S~yk4s=C*C?=!MFF_6MyQr!8!j>=F z^M9c_PQO9X7_Fu?kjYPiaItU_tDHg|I(r|Bpuf8SpX|#f7$h?PSJZ7rbLHIF1_f zi>S452Q`;PUo!RK=$l(xjzK*z1@#;cYP)8j?!RRXnqn4RbyUYXphl*To1`PjSY%Y4 zJ*YRV`LY?>m#_}y8K|M%Zp#IxnuePpv*mQeGI#)+;04qa1Wz+-pdzxKoiNnMEx{mk zpCQo@e}NjxKd}ggPB#tILY1RzxfANffyfSXVsIyZj_gop)(pq-;%$t?^^CAOcm!Z6_&tc6}Ihu5(z{)5^^C1#uYR;VEzh}ta^ zQGaYNLhYIpsQYhXC47u!wErv3F+asf8>qz`!t1?`t+584$3A!;)o>5KX1uwRgrT(W>>_E7XHok#Fx3ow5sanmLQO#` z4#$N!11B#@^VG@@Q0pyRFBu zAm#I@MfQy?|BdQUz(T$W7>jzt&rtW@vF2eoG$qAR9c+M_ingya{z{^$Py^GgsaSyW z8>kyLTK8B#LXFhdSPySvRSZcpe~oX3%$745i{L|Rp>(rNE1>SLm(KWW|2CyU9q3@~ zjh!eD!wt9t^`I9P8HZXYSZ88u&ZncEbHUbsYyA!DQ17?cOhrA^bxqtPdc)SJ2Ku1p zY9#i;an|E_n{sK7`O%q|6{(?bf|}EnsFA#adhnlE9Q~IXOQAYY6C>m6S`^Z$?} zloJ(J@^3+~8ERY2L^ZSyHI&<}N3aa#^Qe*f5sPBQRc6gZ;1J5wQ1@T8{($-({E20C z{c1kPwC_ZcFceNSYEBlQ8uVBpkeSHPv@G=dfOJE%2u4+~@PMzc#o zu`=b(SR3O}Q?<&veWTm-=nxg^;Te14lJ$EmP5nJ27md$$v6mIo6R4uGq616TNsXkTTF)OHs&%e-rTPwd3vl|%2JAJzsOqDh7l%dAjZa}3CgYC1jK40Z`kq-tO|h6Rux>!z=tZsC53FZV zYvm$p&i}GLLM_gK_f5w`QO^&vHn;U%to_|K8HJkDB-9OQs4v_`tb?DR-tazZs>1h~ zhFhXWsExI|tsiX5G1dgE!F6ub^S4^v2T1e==THq?M0F(Je)GnaumI&+*2dOW7(#s~ z>kw4O60LJkBexU_VFrex7d7KfZR7d2yaP3bN3EyP_xJzvzJwnfs0ZD$KES+`3m-Bg6k-jvR>DBe*RbUX z)S75&?T6~%RO>v{^-EDxx(17A|9`9mzs7R-BkFq)c$l}xVmKX_px&tX5p!Kr)X?_C zG8l~-v6oS+{5p2Qhp3KpI%+=IFQT5a9Nju`h(sMYgD$*+dcb}34f!$CU<7J)cg9&5 zjcWKNY7IR=y@3C5V@1@qjzYcha8!GXuoA94&iq#=IZA~VM=oma^L$`#EQ#t!OVkYm ztus(lvmRZTVLgfJa4xDt53PAmnB5eNEvRpT&tT#Sw|TIa3ibRV-ofASGtBzX{DorA zNwWy=;ycvWIAw|tN|aHDJY0q%oD7$P-|!E@Gct#_?~ADi=`R(Bnnw6gZZQaoU! zbvkNDmssDj9<_dnYVfx8F=~j5pEbWFyJ1zz<4{w%7`4`RA#2C&93yE-#TA@{Wj--K zq0&%qbQ!gHzQH&wbk6*meHjZi(ZCiFeH6v08wOE^>p3?iC57<|o}+)S`QU$=Kox zwj}L4yGbJP5vqsHE|?oO;?tC!i{@ACGpHdPW}SuADX&MZkyBV6Z=$Bq`O^H0iPBh> z;`3M$N1ztp9CYi3w@9@8PN56GLk*e#C4OY!AN*rCX5hEPI91wXBY9uKpK>1JFG71> zM`0?~a_$)UW}*qXj$+o=HUA4uos)t85U&t{T<|RJ!kW09_+Li^=kpNEoHLA=OH3s6 z--C2~ZVfU;-#_nASAuwssNl!=FQ7Vz!bze#p~DX!m{dRaoDj-Ki0#BQ;uoR=F`PI} zH0K(2m~+kElb<(FwE0NR@3MJAaxKcmsAHeze>xG!4d&tq1=nS5Ah-qM!5>Q2p#%=Otix}zLNO~*NZwG4XkS4X-Br1(Gi#YH*SEdINjTL`P!i1&%>wodh9^bd|1)ICoWBJW5H zP$kD*!d-;7y}?O7R!#yA!as=H24+$NWsXJ^^x06a?IE7D$dBigc>U7kx_QyFkH)r_Qs3cRU>rFf)!ik&27V7WW zi~3RillX-Ag81*_tiJy`-ZJ?9Ci{)Oa3w|)-*WCgv55R-LdTP3qyN`jUdn&ldY#)# z{uxn=XsZg2dPFPAJBa}D;;3V?=Km{V2!(a{EU}in4zY$PNcjrpMIBYFuVOw^<@QTxA_TcN$T7iDZEHB!d9k{7qxRai@ZId;}?VP_g+_vm$ z@;Aw!CVnJF5W@%^w}}1Z`ThwL#0!*v#!19~ALXg|k@%e`@?;~YbAyXG z{jaMF+Mb`KUdQ)V<=u#x#1cYB3g^n=M6B$qF@H~}P5Bj~5YO_*cZlzZ7F@FwpS17$ z39b7YQ(1zG2jU`CaCFc=sQZDsJ-UhG0`Zu5m-0MfDtQZBMpPtp{ED?O9`|ECe2e&4 zCpj(=z7N?Hl0S*kG}0Y=6Tfkxj-JE^ zag+;V8Lm5pI*t<4lyJmwzMA%bIWD+p>YNogiW46Z|2~RQ827J=Eu2rVFP~BOnrBC9kY`xL zEYJ4T0@M}u4yYI47t$ftRjo#HVobvL=y5SM6T=I*T%HFJ!@ac|gyaeCIDTY&!no+9 z*!c0@28|K|yvHN=`gxB>EzIvtZacugdGw?hm+p1iMaRa)jBq8zyAr32AMP5J5T883 zH6l4iH3>1};*(-rF$oFr3AAO}@jU3@3j6;qXwId+TWThHCwJT*)N`b3N_?_ww3>__ zKgBgMIVMs4N(^_6Nlr|nl?icE)Lhc&*hE*%I6Cy*%q5d!!VIuGvBO8ZxS2OHuM#_Iye=CRA3J^&4fvW&tn2C= zqfW$(n~>yt+KAZ1=wWd&u0$^9LXThXP2SVJx90H%^qXGPn-LrC_vT+?@_9>4%=GhK zNr?6Hd%;sJInpydX^Y&S+jSv$S&r{xduURtuw z&%1Bg+#v6Obv678W*u3Row+=B$<~~C?|G(eEL-M3v+>Kp1=;Bfaxyb=4{ypnFvqiN zW3~Tv(%iXgV~Drjn>m5~HmBsQU7eG%HD~qwtOEzK4lT`Hw&;g9cJQ$8cfOasYHjwW zg*lm%jKx!}GHCrRU5^%X)vm9+H-xb$C_w`#Z8z zw|R@c-6@Y}LuR#S=xo;h*K;!u=N{Ufb#Q(5tNVF$&aRZ)m2kv!8d@>DHQ)KhFHjd}Mu`=I>qd>9>L2S1<4O^Cn(7=l_33JE`#i From 4080080acd62c349956f92b4e2dbf8d0a2ab3e18 Mon Sep 17 00:00:00 2001 From: Jens L Date: Mon, 13 Nov 2023 14:48:37 +0100 Subject: [PATCH 20/24] internal: remove deprecated metrics (#7540) Signed-off-by: Jens Langhammer --- internal/outpost/flow/executor.go | 18 ------- internal/outpost/ldap/bind.go | 11 ---- internal/outpost/ldap/bind/direct/bind.go | 30 ----------- internal/outpost/ldap/metrics/metrics.go | 10 ---- internal/outpost/ldap/search.go | 5 -- internal/outpost/ldap/search/direct/direct.go | 24 --------- internal/outpost/ldap/search/memory/memory.go | 18 ------- internal/outpost/ldap/unbind.go | 11 ---- .../proxyv2/application/application.go | 6 --- .../outpost/proxyv2/application/mode_proxy.go | 7 --- internal/outpost/proxyv2/handlers.go | 12 ----- internal/outpost/proxyv2/metrics/metrics.go | 10 ---- .../outpost/radius/handle_access_request.go | 20 ------- internal/outpost/radius/handler.go | 4 -- internal/outpost/radius/metrics/metrics.go | 10 ---- internal/web/metrics.go | 6 --- internal/web/proxy.go | 9 ---- website/docs/releases/2024/v2024.1.md | 52 +++++++++++++++++++ 18 files changed, 52 insertions(+), 211 deletions(-) create mode 100644 website/docs/releases/2024/v2024.1.md diff --git a/internal/outpost/flow/executor.go b/internal/outpost/flow/executor.go index 998249e5c..10dca6bb5 100644 --- a/internal/outpost/flow/executor.go +++ b/internal/outpost/flow/executor.go @@ -29,16 +29,6 @@ var ( Name: "authentik_outpost_flow_timing_post_seconds", Help: "Duration it took to send a challenge in seconds", }, []string{"stage", "flow"}) - - // NOTE: the following metrics are kept for compatibility purpose - FlowTimingGetLegacy = promauto.NewHistogramVec(prometheus.HistogramOpts{ - Name: "authentik_outpost_flow_timing_get", - Help: "Duration it took to get a challenge", - }, []string{"stage", "flow"}) - FlowTimingPostLegacy = promauto.NewHistogramVec(prometheus.HistogramOpts{ - Name: "authentik_outpost_flow_timing_post", - Help: "Duration it took to send a challenge", - }, []string{"stage", "flow"}) ) type SolverFunction func(*api.ChallengeTypes, api.ApiFlowsExecutorSolveRequest) (api.FlowChallengeResponseRequest, error) @@ -198,10 +188,6 @@ func (fe *FlowExecutor) getInitialChallenge() (*api.ChallengeTypes, error) { "stage": ch.GetComponent(), "flow": fe.flowSlug, }).Observe(float64(gcsp.EndTime.Sub(gcsp.StartTime)) / float64(time.Second)) - FlowTimingGetLegacy.With(prometheus.Labels{ - "stage": ch.GetComponent(), - "flow": fe.flowSlug, - }).Observe(float64(gcsp.EndTime.Sub(gcsp.StartTime))) return challenge, nil } @@ -259,10 +245,6 @@ func (fe *FlowExecutor) solveFlowChallenge(challenge *api.ChallengeTypes, depth "stage": ch.GetComponent(), "flow": fe.flowSlug, }).Observe(float64(scsp.EndTime.Sub(scsp.StartTime)) / float64(time.Second)) - FlowTimingPostLegacy.With(prometheus.Labels{ - "stage": ch.GetComponent(), - "flow": fe.flowSlug, - }).Observe(float64(scsp.EndTime.Sub(scsp.StartTime))) if depth >= 10 { return false, errors.New("exceeded stage recursion depth") diff --git a/internal/outpost/ldap/bind.go b/internal/outpost/ldap/bind.go index 5ab1e42c1..050dea646 100644 --- a/internal/outpost/ldap/bind.go +++ b/internal/outpost/ldap/bind.go @@ -22,11 +22,6 @@ func (ls *LDAPServer) Bind(bindDN string, bindPW string, conn net.Conn) (ldap.LD "type": "bind", "app": selectedApp, }).Observe(float64(span.EndTime.Sub(span.StartTime)) / float64(time.Second)) - metrics.RequestsLegacy.With(prometheus.Labels{ - "outpost_name": ls.ac.Outpost.Name, - "type": "bind", - "app": selectedApp, - }).Observe(float64(span.EndTime.Sub(span.StartTime))) req.Log().WithField("took-ms", span.EndTime.Sub(span.StartTime).Milliseconds()).Info("Bind request") }() @@ -55,12 +50,6 @@ func (ls *LDAPServer) Bind(bindDN string, bindPW string, conn net.Conn) (ldap.LD "reason": "no_provider", "app": "", }).Inc() - metrics.RequestsRejectedLegacy.With(prometheus.Labels{ - "outpost_name": ls.ac.Outpost.Name, - "type": "bind", - "reason": "no_provider", - "app": "", - }).Inc() return ldap.LDAPResultInsufficientAccessRights, nil } diff --git a/internal/outpost/ldap/bind/direct/bind.go b/internal/outpost/ldap/bind/direct/bind.go index f6e49ccfb..cffa0cf36 100644 --- a/internal/outpost/ldap/bind/direct/bind.go +++ b/internal/outpost/ldap/bind/direct/bind.go @@ -47,12 +47,6 @@ func (db *DirectBinder) Bind(username string, req *bind.Request) (ldap.LDAPResul "reason": "flow_error", "app": db.si.GetAppSlug(), }).Inc() - metrics.RequestsRejectedLegacy.With(prometheus.Labels{ - "outpost_name": db.si.GetOutpostName(), - "type": "bind", - "reason": "flow_error", - "app": db.si.GetAppSlug(), - }).Inc() req.Log().WithError(err).Warning("failed to execute flow") return ldap.LDAPResultInvalidCredentials, nil } @@ -63,12 +57,6 @@ func (db *DirectBinder) Bind(username string, req *bind.Request) (ldap.LDAPResul "reason": "invalid_credentials", "app": db.si.GetAppSlug(), }).Inc() - metrics.RequestsRejectedLegacy.With(prometheus.Labels{ - "outpost_name": db.si.GetOutpostName(), - "type": "bind", - "reason": "invalid_credentials", - "app": db.si.GetAppSlug(), - }).Inc() req.Log().Info("Invalid credentials") return ldap.LDAPResultInvalidCredentials, nil } @@ -82,12 +70,6 @@ func (db *DirectBinder) Bind(username string, req *bind.Request) (ldap.LDAPResul "reason": "access_denied", "app": db.si.GetAppSlug(), }).Inc() - metrics.RequestsRejectedLegacy.With(prometheus.Labels{ - "outpost_name": db.si.GetOutpostName(), - "type": "bind", - "reason": "access_denied", - "app": db.si.GetAppSlug(), - }).Inc() return ldap.LDAPResultInsufficientAccessRights, nil } if err != nil { @@ -97,12 +79,6 @@ func (db *DirectBinder) Bind(username string, req *bind.Request) (ldap.LDAPResul "reason": "access_check_fail", "app": db.si.GetAppSlug(), }).Inc() - metrics.RequestsRejectedLegacy.With(prometheus.Labels{ - "outpost_name": db.si.GetOutpostName(), - "type": "bind", - "reason": "access_check_fail", - "app": db.si.GetAppSlug(), - }).Inc() req.Log().WithError(err).Warning("failed to check access") return ldap.LDAPResultOperationsError, nil } @@ -117,12 +93,6 @@ func (db *DirectBinder) Bind(username string, req *bind.Request) (ldap.LDAPResul "reason": "user_info_fail", "app": db.si.GetAppSlug(), }).Inc() - metrics.RequestsRejectedLegacy.With(prometheus.Labels{ - "outpost_name": db.si.GetOutpostName(), - "type": "bind", - "reason": "user_info_fail", - "app": db.si.GetAppSlug(), - }).Inc() req.Log().WithError(err).Warning("failed to get user info") return ldap.LDAPResultOperationsError, nil } diff --git a/internal/outpost/ldap/metrics/metrics.go b/internal/outpost/ldap/metrics/metrics.go index 150f89e7f..8c36b2f88 100644 --- a/internal/outpost/ldap/metrics/metrics.go +++ b/internal/outpost/ldap/metrics/metrics.go @@ -22,16 +22,6 @@ var ( Name: "authentik_outpost_ldap_requests_rejected_total", Help: "Total number of rejected requests", }, []string{"outpost_name", "type", "reason", "app"}) - - // NOTE: the following metrics are kept for compatibility purpose - RequestsLegacy = promauto.NewHistogramVec(prometheus.HistogramOpts{ - Name: "authentik_outpost_ldap_requests", - Help: "The total number of configured providers", - }, []string{"outpost_name", "type", "app"}) - RequestsRejectedLegacy = promauto.NewCounterVec(prometheus.CounterOpts{ - Name: "authentik_outpost_ldap_requests_rejected", - Help: "Total number of rejected requests", - }, []string{"outpost_name", "type", "reason", "app"}) ) func RunServer() { diff --git a/internal/outpost/ldap/search.go b/internal/outpost/ldap/search.go index a330e3fb8..b26df5023 100644 --- a/internal/outpost/ldap/search.go +++ b/internal/outpost/ldap/search.go @@ -23,11 +23,6 @@ func (ls *LDAPServer) Search(bindDN string, searchReq ldap.SearchRequest, conn n "type": "search", "app": selectedApp, }).Observe(float64(span.EndTime.Sub(span.StartTime)) / float64(time.Second)) - metrics.RequestsLegacy.With(prometheus.Labels{ - "outpost_name": ls.ac.Outpost.Name, - "type": "search", - "app": selectedApp, - }).Observe(float64(span.EndTime.Sub(span.StartTime))) req.Log().WithField("attributes", searchReq.Attributes).WithField("took-ms", span.EndTime.Sub(span.StartTime).Milliseconds()).Info("Search request") }() diff --git a/internal/outpost/ldap/search/direct/direct.go b/internal/outpost/ldap/search/direct/direct.go index 9f7ccd124..7ac59f834 100644 --- a/internal/outpost/ldap/search/direct/direct.go +++ b/internal/outpost/ldap/search/direct/direct.go @@ -45,12 +45,6 @@ func (ds *DirectSearcher) Search(req *search.Request) (ldap.ServerSearchResult, "reason": "empty_bind_dn", "app": ds.si.GetAppSlug(), }).Inc() - metrics.RequestsRejectedLegacy.With(prometheus.Labels{ - "outpost_name": ds.si.GetOutpostName(), - "type": "search", - "reason": "empty_bind_dn", - "app": ds.si.GetAppSlug(), - }).Inc() return ldap.ServerSearchResult{ResultCode: ldap.LDAPResultInsufficientAccessRights}, fmt.Errorf("Search Error: Anonymous BindDN not allowed %s", req.BindDN) } if !utils.HasSuffixNoCase(req.BindDN, ","+baseDN) { @@ -60,12 +54,6 @@ func (ds *DirectSearcher) Search(req *search.Request) (ldap.ServerSearchResult, "reason": "invalid_bind_dn", "app": ds.si.GetAppSlug(), }).Inc() - metrics.RequestsRejectedLegacy.With(prometheus.Labels{ - "outpost_name": ds.si.GetOutpostName(), - "type": "search", - "reason": "invalid_bind_dn", - "app": ds.si.GetAppSlug(), - }).Inc() return ldap.ServerSearchResult{ResultCode: ldap.LDAPResultInsufficientAccessRights}, fmt.Errorf("Search Error: BindDN %s not in our BaseDN %s", req.BindDN, ds.si.GetBaseDN()) } @@ -78,12 +66,6 @@ func (ds *DirectSearcher) Search(req *search.Request) (ldap.ServerSearchResult, "reason": "user_info_not_cached", "app": ds.si.GetAppSlug(), }).Inc() - metrics.RequestsRejectedLegacy.With(prometheus.Labels{ - "outpost_name": ds.si.GetOutpostName(), - "type": "search", - "reason": "user_info_not_cached", - "app": ds.si.GetAppSlug(), - }).Inc() return ldap.ServerSearchResult{ResultCode: ldap.LDAPResultInsufficientAccessRights}, errors.New("access denied") } accsp.Finish() @@ -96,12 +78,6 @@ func (ds *DirectSearcher) Search(req *search.Request) (ldap.ServerSearchResult, "reason": "filter_parse_fail", "app": ds.si.GetAppSlug(), }).Inc() - metrics.RequestsRejectedLegacy.With(prometheus.Labels{ - "outpost_name": ds.si.GetOutpostName(), - "type": "search", - "reason": "filter_parse_fail", - "app": ds.si.GetAppSlug(), - }).Inc() return ldap.ServerSearchResult{ResultCode: ldap.LDAPResultOperationsError}, fmt.Errorf("Search Error: error parsing filter: %s", req.Filter) } diff --git a/internal/outpost/ldap/search/memory/memory.go b/internal/outpost/ldap/search/memory/memory.go index 177099f7e..2b80bbbbb 100644 --- a/internal/outpost/ldap/search/memory/memory.go +++ b/internal/outpost/ldap/search/memory/memory.go @@ -62,12 +62,6 @@ func (ms *MemorySearcher) Search(req *search.Request) (ldap.ServerSearchResult, "reason": "empty_bind_dn", "app": ms.si.GetAppSlug(), }).Inc() - metrics.RequestsRejectedLegacy.With(prometheus.Labels{ - "outpost_name": ms.si.GetOutpostName(), - "type": "search", - "reason": "empty_bind_dn", - "app": ms.si.GetAppSlug(), - }).Inc() return ldap.ServerSearchResult{ResultCode: ldap.LDAPResultInsufficientAccessRights}, fmt.Errorf("Search Error: Anonymous BindDN not allowed %s", req.BindDN) } if !utils.HasSuffixNoCase(req.BindDN, ","+baseDN) { @@ -77,12 +71,6 @@ func (ms *MemorySearcher) Search(req *search.Request) (ldap.ServerSearchResult, "reason": "invalid_bind_dn", "app": ms.si.GetAppSlug(), }).Inc() - metrics.RequestsRejectedLegacy.With(prometheus.Labels{ - "outpost_name": ms.si.GetOutpostName(), - "type": "search", - "reason": "invalid_bind_dn", - "app": ms.si.GetAppSlug(), - }).Inc() return ldap.ServerSearchResult{ResultCode: ldap.LDAPResultInsufficientAccessRights}, fmt.Errorf("Search Error: BindDN %s not in our BaseDN %s", req.BindDN, ms.si.GetBaseDN()) } @@ -95,12 +83,6 @@ func (ms *MemorySearcher) Search(req *search.Request) (ldap.ServerSearchResult, "reason": "user_info_not_cached", "app": ms.si.GetAppSlug(), }).Inc() - metrics.RequestsRejectedLegacy.With(prometheus.Labels{ - "outpost_name": ms.si.GetOutpostName(), - "type": "search", - "reason": "user_info_not_cached", - "app": ms.si.GetAppSlug(), - }).Inc() return ldap.ServerSearchResult{ResultCode: ldap.LDAPResultInsufficientAccessRights}, errors.New("access denied") } accsp.Finish() diff --git a/internal/outpost/ldap/unbind.go b/internal/outpost/ldap/unbind.go index 35c608c32..b293cb2c0 100644 --- a/internal/outpost/ldap/unbind.go +++ b/internal/outpost/ldap/unbind.go @@ -22,11 +22,6 @@ func (ls *LDAPServer) Unbind(boundDN string, conn net.Conn) (ldap.LDAPResultCode "type": "unbind", "app": selectedApp, }).Observe(float64(span.EndTime.Sub(span.StartTime)) / float64(time.Second)) - metrics.RequestsLegacy.With(prometheus.Labels{ - "outpost_name": ls.ac.Outpost.Name, - "type": "unbind", - "app": selectedApp, - }).Observe(float64(span.EndTime.Sub(span.StartTime))) req.Log().WithField("took-ms", span.EndTime.Sub(span.StartTime).Milliseconds()).Info("Unbind request") }() @@ -55,11 +50,5 @@ func (ls *LDAPServer) Unbind(boundDN string, conn net.Conn) (ldap.LDAPResultCode "reason": "no_provider", "app": "", }).Inc() - metrics.RequestsRejectedLegacy.With(prometheus.Labels{ - "outpost_name": ls.ac.Outpost.Name, - "type": "unbind", - "reason": "no_provider", - "app": "", - }).Inc() return ldap.LDAPResultOperationsError, nil } diff --git a/internal/outpost/proxyv2/application/application.go b/internal/outpost/proxyv2/application/application.go index eae4c6774..dc3a87950 100644 --- a/internal/outpost/proxyv2/application/application.go +++ b/internal/outpost/proxyv2/application/application.go @@ -173,12 +173,6 @@ func NewApplication(p api.ProxyOutpostConfig, c *http.Client, server Server) (*A "method": r.Method, "host": web.GetHost(r), }).Observe(float64(elapsed) / float64(time.Second)) - metrics.RequestsLegacy.With(prometheus.Labels{ - "outpost_name": a.outpostName, - "type": "app", - "method": r.Method, - "host": web.GetHost(r), - }).Observe(float64(elapsed)) }) }) if server.API().GlobalConfig.ErrorReporting.Enabled { diff --git a/internal/outpost/proxyv2/application/mode_proxy.go b/internal/outpost/proxyv2/application/mode_proxy.go index 07a53f2d6..d987cd72b 100644 --- a/internal/outpost/proxyv2/application/mode_proxy.go +++ b/internal/outpost/proxyv2/application/mode_proxy.go @@ -64,13 +64,6 @@ func (a *Application) configureProxy() error { "scheme": r.URL.Scheme, "host": web.GetHost(r), }).Observe(float64(elapsed) / float64(time.Second)) - metrics.UpstreamTimingLegacy.With(prometheus.Labels{ - "outpost_name": a.outpostName, - "upstream_host": r.URL.Host, - "method": r.Method, - "scheme": r.URL.Scheme, - "host": web.GetHost(r), - }).Observe(float64(elapsed)) }) return nil } diff --git a/internal/outpost/proxyv2/handlers.go b/internal/outpost/proxyv2/handlers.go index 97d86a9fb..5ea61060b 100644 --- a/internal/outpost/proxyv2/handlers.go +++ b/internal/outpost/proxyv2/handlers.go @@ -26,12 +26,6 @@ func (ps *ProxyServer) HandlePing(rw http.ResponseWriter, r *http.Request) { "host": web.GetHost(r), "type": "ping", }).Observe(float64(elapsed) / float64(time.Second)) - metrics.RequestsLegacy.With(prometheus.Labels{ - "outpost_name": ps.akAPI.Outpost.Name, - "method": r.Method, - "host": web.GetHost(r), - "type": "ping", - }).Observe(float64(elapsed)) } func (ps *ProxyServer) HandleStatic(rw http.ResponseWriter, r *http.Request) { @@ -44,12 +38,6 @@ func (ps *ProxyServer) HandleStatic(rw http.ResponseWriter, r *http.Request) { "host": web.GetHost(r), "type": "static", }).Observe(float64(elapsed) / float64(time.Second)) - metrics.RequestsLegacy.With(prometheus.Labels{ - "outpost_name": ps.akAPI.Outpost.Name, - "method": r.Method, - "host": web.GetHost(r), - "type": "static", - }).Observe(float64(elapsed)) } func (ps *ProxyServer) lookupApp(r *http.Request) (*application.Application, string) { diff --git a/internal/outpost/proxyv2/metrics/metrics.go b/internal/outpost/proxyv2/metrics/metrics.go index 564a010d0..6f589025f 100644 --- a/internal/outpost/proxyv2/metrics/metrics.go +++ b/internal/outpost/proxyv2/metrics/metrics.go @@ -22,16 +22,6 @@ var ( Name: "authentik_outpost_proxy_upstream_response_duration_seconds", Help: "Proxy upstream response latencies in seconds", }, []string{"outpost_name", "method", "scheme", "host", "upstream_host"}) - - // NOTE: the following metric is kept for compatibility purpose - RequestsLegacy = promauto.NewHistogramVec(prometheus.HistogramOpts{ - Name: "authentik_outpost_proxy_requests", - Help: "The total number of configured providers", - }, []string{"outpost_name", "method", "host", "type"}) - UpstreamTimingLegacy = promauto.NewHistogramVec(prometheus.HistogramOpts{ - Name: "authentik_outpost_proxy_upstream_time", - Help: "A summary of the duration we wait for the upstream reply", - }, []string{"outpost_name", "method", "scheme", "host", "upstream_host"}) ) func RunServer() { diff --git a/internal/outpost/radius/handle_access_request.go b/internal/outpost/radius/handle_access_request.go index 6ea387f53..1c5f32202 100644 --- a/internal/outpost/radius/handle_access_request.go +++ b/internal/outpost/radius/handle_access_request.go @@ -35,11 +35,6 @@ func (rs *RadiusServer) Handle_AccessRequest(w radius.ResponseWriter, r *RadiusR "reason": "flow_error", "app": r.pi.appSlug, }).Inc() - metrics.RequestsRejectedLegacy.With(prometheus.Labels{ - "outpost_name": rs.ac.Outpost.Name, - "reason": "flow_error", - "app": r.pi.appSlug, - }).Inc() _ = w.Write(r.Response(radius.CodeAccessReject)) return } @@ -49,11 +44,6 @@ func (rs *RadiusServer) Handle_AccessRequest(w radius.ResponseWriter, r *RadiusR "reason": "invalid_credentials", "app": r.pi.appSlug, }).Inc() - metrics.RequestsRejectedLegacy.With(prometheus.Labels{ - "outpost_name": rs.ac.Outpost.Name, - "reason": "invalid_credentials", - "app": r.pi.appSlug, - }).Inc() _ = w.Write(r.Response(radius.CodeAccessReject)) return } @@ -66,11 +56,6 @@ func (rs *RadiusServer) Handle_AccessRequest(w radius.ResponseWriter, r *RadiusR "reason": "access_check_fail", "app": r.pi.appSlug, }).Inc() - metrics.RequestsRejectedLegacy.With(prometheus.Labels{ - "outpost_name": rs.ac.Outpost.Name, - "reason": "access_check_fail", - "app": r.pi.appSlug, - }).Inc() return } if !access { @@ -81,11 +66,6 @@ func (rs *RadiusServer) Handle_AccessRequest(w radius.ResponseWriter, r *RadiusR "reason": "access_denied", "app": r.pi.appSlug, }).Inc() - metrics.RequestsRejectedLegacy.With(prometheus.Labels{ - "outpost_name": rs.ac.Outpost.Name, - "reason": "access_denied", - "app": r.pi.appSlug, - }).Inc() return } _ = w.Write(r.Response(radius.CodeAccessAccept)) diff --git a/internal/outpost/radius/handler.go b/internal/outpost/radius/handler.go index e1d3cb531..958e88b70 100644 --- a/internal/outpost/radius/handler.go +++ b/internal/outpost/radius/handler.go @@ -47,10 +47,6 @@ func (rs *RadiusServer) ServeRADIUS(w radius.ResponseWriter, r *radius.Request) "outpost_name": rs.ac.Outpost.Name, "app": selectedApp, }).Observe(float64(span.EndTime.Sub(span.StartTime)) / float64(time.Second)) - metrics.RequestsLegacy.With(prometheus.Labels{ - "outpost_name": rs.ac.Outpost.Name, - "app": selectedApp, - }).Observe(float64(span.EndTime.Sub(span.StartTime))) }() nr := &RadiusRequest{ diff --git a/internal/outpost/radius/metrics/metrics.go b/internal/outpost/radius/metrics/metrics.go index 1bcecfdc2..c741c04ed 100644 --- a/internal/outpost/radius/metrics/metrics.go +++ b/internal/outpost/radius/metrics/metrics.go @@ -22,16 +22,6 @@ var ( Name: "authentik_outpost_radius_requests_rejected_total", Help: "Total number of rejected requests", }, []string{"outpost_name", "reason", "app"}) - - // NOTE: the following metric is kept for compatibility purpose - RequestsLegacy = promauto.NewHistogramVec(prometheus.HistogramOpts{ - Name: "authentik_outpost_radius_requests", - Help: "The total number of successful requests", - }, []string{"outpost_name", "app"}) - RequestsRejectedLegacy = promauto.NewCounterVec(prometheus.CounterOpts{ - Name: "authentik_outpost_radius_requests_rejected", - Help: "Total number of rejected requests", - }, []string{"outpost_name", "reason", "app"}) ) func RunServer() { diff --git a/internal/web/metrics.go b/internal/web/metrics.go index 0b8670b61..2e6b0def1 100644 --- a/internal/web/metrics.go +++ b/internal/web/metrics.go @@ -19,12 +19,6 @@ var ( Name: "authentik_main_request_duration_seconds", Help: "API request latencies in seconds", }, []string{"dest"}) - - // NOTE: the following metric is kept for compatibility purpose - RequestsLegacy = promauto.NewHistogramVec(prometheus.HistogramOpts{ - Name: "authentik_main_requests", - Help: "The total number of configured providers", - }, []string{"dest"}) ) func (ws *WebServer) runMetricsServer() { diff --git a/internal/web/proxy.go b/internal/web/proxy.go index b52d24c3b..c1e38a397 100644 --- a/internal/web/proxy.go +++ b/internal/web/proxy.go @@ -40,9 +40,6 @@ func (ws *WebServer) configureProxy() { Requests.With(prometheus.Labels{ "dest": "embedded_outpost", }).Observe(float64(elapsed) / float64(time.Second)) - RequestsLegacy.With(prometheus.Labels{ - "dest": "embedded_outpost", - }).Observe(float64(elapsed)) return } ws.proxyErrorHandler(rw, r, errors.New("proxy not running")) @@ -62,9 +59,6 @@ func (ws *WebServer) configureProxy() { Requests.With(prometheus.Labels{ "dest": "embedded_outpost", }).Observe(float64(elapsed) / float64(time.Second)) - RequestsLegacy.With(prometheus.Labels{ - "dest": "embedded_outpost", - }).Observe(float64(elapsed)) return } } @@ -72,9 +66,6 @@ func (ws *WebServer) configureProxy() { Requests.With(prometheus.Labels{ "dest": "core", }).Observe(float64(elapsed) / float64(time.Second)) - RequestsLegacy.With(prometheus.Labels{ - "dest": "core", - }).Observe(float64(elapsed)) r.Body = http.MaxBytesReader(rw, r.Body, 32*1024*1024) rp.ServeHTTP(rw, r) })) diff --git a/website/docs/releases/2024/v2024.1.md b/website/docs/releases/2024/v2024.1.md new file mode 100644 index 000000000..fb6a71107 --- /dev/null +++ b/website/docs/releases/2024/v2024.1.md @@ -0,0 +1,52 @@ +--- +title: Release 2024.1 +slug: "/releases/2024.1" +--- + +## Breaking changes + +- Removal of deprecated metrics + + - `authentik_outpost_flow_timing_get` -> `authentik_outpost_flow_timing_get_seconds` + - `authentik_outpost_flow_timing_post` -> `authentik_outpost_flow_timing_post_seconds` + - `authentik_outpost_ldap_requests` -> `authentik_outpost_ldap_request_duration_seconds` + - `authentik_outpost_ldap_requests_rejected` -> `authentik_outpost_ldap_requests_rejected_total` + - `authentik_outpost_proxy_requests` -> `authentik_outpost_proxy_request_duration_seconds` + - `authentik_outpost_proxy_upstream_time` -> `authentik_outpost_proxy_upstream_response_duration_seconds` + - `authentik_outpost_radius_requests` -> `authentik_outpost_radius_request_duration_seconds` + - `authentik_outpost_radius_requests_rejected` -> `authentik_outpost_radius_requests_rejected_total` + - `authentik_main_requests` -> `authentik_main_request_duration_seconds` + +## New features + +## Upgrading + +This release does not introduce any new requirements. + +### docker-compose + +To upgrade, download the new docker-compose file and update the Docker stack with the new version, using these commands: + +``` +wget -O docker-compose.yml https://goauthentik.io/version/2024.1/docker-compose.yml +docker-compose up -d +``` + +The `-O` flag retains the downloaded file's name, overwriting any existing local file with the same name. + +### Kubernetes + +Upgrade the Helm Chart to the new version, using the following commands: + +```shell +helm repo update +helm upgrade authentik authentik/authentik -f values.yaml --version ^2024.1 +``` + +## Minor changes/fixes + + + +## API Changes + + From f728bbb14b3a8abb6d2d67da69e4291d5e0a83da Mon Sep 17 00:00:00 2001 From: Jens L Date: Mon, 13 Nov 2023 15:01:40 +0100 Subject: [PATCH 21/24] sources/ldap: add check command to verify ldap connectivity (#7263) * sources/ldap: add check command to verify ldap connectivity Signed-off-by: Jens Langhammer * default to checking all sources Signed-off-by: Jens Langhammer * start adding an API for ldap connectivity Signed-off-by: Jens Langhammer * add webui for ldap source connection status Signed-off-by: Jens Langhammer * better show sync status, clear previous tasks Signed-off-by: Jens Langhammer * set timeout on redis lock for ldap sync Signed-off-by: Jens Langhammer * fix py lint Signed-off-by: Jens Langhammer * fix web lint Signed-off-by: Jens Langhammer --------- Signed-off-by: Jens Langhammer --- authentik/sources/ldap/api.py | 37 +++++-- .../commands/ldap_check_connection.py | 24 +++++ authentik/sources/ldap/models.py | 61 ++++++++++- authentik/sources/ldap/settings.py | 7 +- authentik/sources/ldap/signals.py | 3 +- authentik/sources/ldap/sync/base.py | 23 ++-- authentik/sources/ldap/sync/groups.py | 6 +- authentik/sources/ldap/sync/users.py | 6 +- authentik/sources/ldap/sync/vendor/freeipa.py | 4 +- authentik/sources/ldap/tasks.py | 22 +++- schema.yml | 31 +++++- .../admin-overview/charts/SyncStatusChart.ts | 6 +- .../sources/ldap/LDAPSourceConnectivity.ts | 50 +++++++++ .../admin/sources/ldap/LDAPSourceViewPage.ts | 102 +++++++++++------- .../stories/ak-number-input.stories.ts | 5 +- .../stories/ak-switch-input.stories.ts | 5 +- .../stories/ak-textarea-input.stories.ts | 5 +- .../stories/ak-toggle-group.stories.ts | 5 +- .../buttons/SpinnerButton/BaseTaskButton.ts | 5 + website/docs/troubleshooting/ldap_source.md | 12 +++ 20 files changed, 322 insertions(+), 97 deletions(-) create mode 100644 authentik/sources/ldap/management/commands/ldap_check_connection.py create mode 100644 web/src/admin/sources/ldap/LDAPSourceConnectivity.ts diff --git a/authentik/sources/ldap/api.py b/authentik/sources/ldap/api.py index 1914c66da..08e530bbb 100644 --- a/authentik/sources/ldap/api.py +++ b/authentik/sources/ldap/api.py @@ -1,13 +1,14 @@ """Source API Views""" -from typing import Any +from typing import Any, Optional +from django.core.cache import cache from django_filters.filters import AllValuesMultipleFilter from django_filters.filterset import FilterSet from drf_spectacular.types import OpenApiTypes from drf_spectacular.utils import extend_schema, extend_schema_field, inline_serializer from rest_framework.decorators import action from rest_framework.exceptions import ValidationError -from rest_framework.fields import DictField, ListField +from rest_framework.fields import BooleanField, DictField, ListField, SerializerMethodField from rest_framework.relations import PrimaryKeyRelatedField from rest_framework.request import Request from rest_framework.response import Response @@ -17,15 +18,17 @@ from authentik.admin.api.tasks import TaskSerializer from authentik.core.api.propertymappings import PropertyMappingSerializer from authentik.core.api.sources import SourceSerializer from authentik.core.api.used_by import UsedByMixin +from authentik.core.api.utils import PassiveSerializer from authentik.crypto.models import CertificateKeyPair from authentik.events.monitored_tasks import TaskInfo from authentik.sources.ldap.models import LDAPPropertyMapping, LDAPSource -from authentik.sources.ldap.tasks import SYNC_CLASSES +from authentik.sources.ldap.tasks import CACHE_KEY_STATUS, SYNC_CLASSES class LDAPSourceSerializer(SourceSerializer): """LDAP Source Serializer""" + connectivity = SerializerMethodField() client_certificate = PrimaryKeyRelatedField( allow_null=True, help_text="Client certificate to authenticate against the LDAP Server's Certificate.", @@ -35,6 +38,10 @@ class LDAPSourceSerializer(SourceSerializer): required=False, ) + def get_connectivity(self, source: LDAPSource) -> Optional[dict[str, dict[str, str]]]: + """Get cached source connectivity""" + return cache.get(CACHE_KEY_STATUS + source.slug, None) + def validate(self, attrs: dict[str, Any]) -> dict[str, Any]: """Check that only a single source has password_sync on""" sync_users_password = attrs.get("sync_users_password", True) @@ -75,10 +82,18 @@ class LDAPSourceSerializer(SourceSerializer): "sync_parent_group", "property_mappings", "property_mappings_group", + "connectivity", ] extra_kwargs = {"bind_password": {"write_only": True}} +class LDAPSyncStatusSerializer(PassiveSerializer): + """LDAP Source sync status""" + + is_running = BooleanField(read_only=True) + tasks = TaskSerializer(many=True, read_only=True) + + class LDAPSourceViewSet(UsedByMixin, ModelViewSet): """LDAP Source Viewset""" @@ -114,19 +129,19 @@ class LDAPSourceViewSet(UsedByMixin, ModelViewSet): @extend_schema( responses={ - 200: TaskSerializer(many=True), + 200: LDAPSyncStatusSerializer(), } ) @action(methods=["GET"], detail=True, pagination_class=None, filter_backends=[]) def sync_status(self, request: Request, slug: str) -> Response: """Get source's sync status""" - source = self.get_object() - results = [] - tasks = TaskInfo.by_name(f"ldap_sync:{source.slug}:*") - if tasks: - for task in tasks: - results.append(task) - return Response(TaskSerializer(results, many=True).data) + source: LDAPSource = self.get_object() + tasks = TaskInfo.by_name(f"ldap_sync:{source.slug}:*") or [] + status = { + "tasks": tasks, + "is_running": source.sync_lock.locked(), + } + return Response(LDAPSyncStatusSerializer(status).data) @extend_schema( responses={ diff --git a/authentik/sources/ldap/management/commands/ldap_check_connection.py b/authentik/sources/ldap/management/commands/ldap_check_connection.py new file mode 100644 index 000000000..6da316aa4 --- /dev/null +++ b/authentik/sources/ldap/management/commands/ldap_check_connection.py @@ -0,0 +1,24 @@ +"""LDAP Connection check""" +from json import dumps + +from django.core.management.base import BaseCommand +from structlog.stdlib import get_logger + +from authentik.sources.ldap.models import LDAPSource + +LOGGER = get_logger() + + +class Command(BaseCommand): + """Check connectivity to LDAP servers for a source""" + + def add_arguments(self, parser): + parser.add_argument("source_slugs", nargs="?", type=str) + + def handle(self, **options): + sources = LDAPSource.objects.filter(enabled=True) + if options["source_slugs"]: + sources = LDAPSource.objects.filter(slug__in=options["source_slugs"]) + for source in sources.order_by("slug"): + status = source.check_connection() + self.stdout.write(dumps(status, indent=4)) diff --git a/authentik/sources/ldap/models.py b/authentik/sources/ldap/models.py index ac7f32aca..a09791593 100644 --- a/authentik/sources/ldap/models.py +++ b/authentik/sources/ldap/models.py @@ -4,10 +4,12 @@ from ssl import CERT_REQUIRED from tempfile import NamedTemporaryFile, mkdtemp from typing import Optional +from django.core.cache import cache from django.db import models from django.utils.translation import gettext_lazy as _ from ldap3 import ALL, NONE, RANDOM, Connection, Server, ServerPool, Tls -from ldap3.core.exceptions import LDAPInsufficientAccessRightsResult, LDAPSchemaError +from ldap3.core.exceptions import LDAPException, LDAPInsufficientAccessRightsResult, LDAPSchemaError +from redis.lock import Lock from rest_framework.serializers import Serializer from authentik.core.models import Group, PropertyMapping, Source @@ -117,7 +119,7 @@ class LDAPSource(Source): return LDAPSourceSerializer - def server(self, **kwargs) -> Server: + def server(self, **kwargs) -> ServerPool: """Get LDAP Server/ServerPool""" servers = [] tls_kwargs = {} @@ -154,7 +156,10 @@ class LDAPSource(Source): return ServerPool(servers, RANDOM, active=5, exhaust=True) def connection( - self, server_kwargs: Optional[dict] = None, connection_kwargs: Optional[dict] = None + self, + server: Optional[Server] = None, + server_kwargs: Optional[dict] = None, + connection_kwargs: Optional[dict] = None, ) -> Connection: """Get a fully connected and bound LDAP Connection""" server_kwargs = server_kwargs or {} @@ -164,7 +169,7 @@ class LDAPSource(Source): if self.bind_password is not None: connection_kwargs.setdefault("password", self.bind_password) connection = Connection( - self.server(**server_kwargs), + server or self.server(**server_kwargs), raise_exceptions=True, receive_timeout=LDAP_TIMEOUT, **connection_kwargs, @@ -183,9 +188,55 @@ class LDAPSource(Source): if server_kwargs.get("get_info", ALL) == NONE: raise exc server_kwargs["get_info"] = NONE - return self.connection(server_kwargs, connection_kwargs) + return self.connection(server, server_kwargs, connection_kwargs) return RuntimeError("Failed to bind") + @property + def sync_lock(self) -> Lock: + """Redis lock for syncing LDAP to prevent multiple parallel syncs happening""" + return Lock( + cache.client.get_client(), + name=f"goauthentik.io/sources/ldap/sync-{self.slug}", + # Convert task timeout hours to seconds, and multiply times 3 + # (see authentik/sources/ldap/tasks.py:54) + # multiply by 3 to add even more leeway + timeout=(60 * 60 * CONFIG.get_int("ldap.task_timeout_hours")) * 3, + ) + + def check_connection(self) -> dict[str, dict[str, str]]: + """Check LDAP Connection""" + from authentik.sources.ldap.sync.base import flatten + + servers = self.server() + server_info = {} + # Check each individual server + for server in servers.servers: + server: Server + try: + connection = self.connection(server=server) + server_info[server.host] = { + "vendor": str(flatten(connection.server.info.vendor_name)), + "version": str(flatten(connection.server.info.vendor_version)), + "status": "ok", + } + except LDAPException as exc: + server_info[server.host] = { + "status": str(exc), + } + # Check server pool + try: + connection = self.connection() + server_info["__all__"] = { + "vendor": str(flatten(connection.server.info.vendor_name)), + "version": str(flatten(connection.server.info.vendor_version)), + "status": "ok", + } + except LDAPException as exc: + server_info["__all__"] = { + "status": str(exc), + } + return server_info + class Meta: verbose_name = _("LDAP Source") verbose_name_plural = _("LDAP Sources") diff --git a/authentik/sources/ldap/settings.py b/authentik/sources/ldap/settings.py index 6b526b357..b141687f5 100644 --- a/authentik/sources/ldap/settings.py +++ b/authentik/sources/ldap/settings.py @@ -8,5 +8,10 @@ CELERY_BEAT_SCHEDULE = { "task": "authentik.sources.ldap.tasks.ldap_sync_all", "schedule": crontab(minute=fqdn_rand("sources_ldap_sync"), hour="*/2"), "options": {"queue": "authentik_scheduled"}, - } + }, + "sources_ldap_connectivity_check": { + "task": "authentik.sources.ldap.tasks.ldap_connectivity_check", + "schedule": crontab(minute=fqdn_rand("sources_ldap_connectivity_check"), hour="*"), + "options": {"queue": "authentik_scheduled"}, + }, } diff --git a/authentik/sources/ldap/signals.py b/authentik/sources/ldap/signals.py index 5af97376d..f95662e33 100644 --- a/authentik/sources/ldap/signals.py +++ b/authentik/sources/ldap/signals.py @@ -14,7 +14,7 @@ from authentik.events.models import Event, EventAction from authentik.flows.planner import PLAN_CONTEXT_PENDING_USER from authentik.sources.ldap.models import LDAPSource from authentik.sources.ldap.password import LDAPPasswordChanger -from authentik.sources.ldap.tasks import ldap_sync_single +from authentik.sources.ldap.tasks import ldap_connectivity_check, ldap_sync_single from authentik.stages.prompt.signals import password_validate LOGGER = get_logger() @@ -32,6 +32,7 @@ def sync_ldap_source_on_save(sender, instance: LDAPSource, **_): if not instance.property_mappings.exists() or not instance.property_mappings_group.exists(): return ldap_sync_single.delay(instance.pk) + ldap_connectivity_check.delay(instance.pk) @receiver(password_validate) diff --git a/authentik/sources/ldap/sync/base.py b/authentik/sources/ldap/sync/base.py index 7490449ec..d3ae11f32 100644 --- a/authentik/sources/ldap/sync/base.py +++ b/authentik/sources/ldap/sync/base.py @@ -17,6 +17,15 @@ from authentik.sources.ldap.models import LDAPPropertyMapping, LDAPSource LDAP_UNIQUENESS = "ldap_uniq" +def flatten(value: Any) -> Any: + """Flatten `value` if its a list""" + if isinstance(value, list): + if len(value) < 1: + return None + return value[0] + return value + + class BaseLDAPSynchronizer: """Sync LDAP Users and groups into authentik""" @@ -122,14 +131,6 @@ class BaseLDAPSynchronizer: cookie = None yield self._connection.response - def _flatten(self, value: Any) -> Any: - """Flatten `value` if its a list""" - if isinstance(value, list): - if len(value) < 1: - return None - return value[0] - return value - def build_user_properties(self, user_dn: str, **kwargs) -> dict[str, Any]: """Build attributes for User object based on property mappings.""" props = self._build_object_properties(user_dn, self._source.property_mappings, **kwargs) @@ -163,10 +164,10 @@ class BaseLDAPSynchronizer: object_field = mapping.object_field if object_field.startswith("attributes."): # Because returning a list might desired, we can't - # rely on self._flatten here. Instead, just save the result as-is + # rely on flatten here. Instead, just save the result as-is set_path_in_dict(properties, object_field, value) else: - properties[object_field] = self._flatten(value) + properties[object_field] = flatten(value) except PropertyMappingExpressionException as exc: Event.new( EventAction.CONFIGURATION_ERROR, @@ -177,7 +178,7 @@ class BaseLDAPSynchronizer: self._logger.warning("Mapping failed to evaluate", exc=exc, mapping=mapping) continue if self._source.object_uniqueness_field in kwargs: - properties["attributes"][LDAP_UNIQUENESS] = self._flatten( + properties["attributes"][LDAP_UNIQUENESS] = flatten( kwargs.get(self._source.object_uniqueness_field) ) properties["attributes"][LDAP_DISTINGUISHED_NAME] = object_dn diff --git a/authentik/sources/ldap/sync/groups.py b/authentik/sources/ldap/sync/groups.py index 68eedcc34..92781c3ac 100644 --- a/authentik/sources/ldap/sync/groups.py +++ b/authentik/sources/ldap/sync/groups.py @@ -7,7 +7,7 @@ from ldap3 import ALL_ATTRIBUTES, ALL_OPERATIONAL_ATTRIBUTES, SUBTREE from authentik.core.models import Group from authentik.events.models import Event, EventAction -from authentik.sources.ldap.sync.base import LDAP_UNIQUENESS, BaseLDAPSynchronizer +from authentik.sources.ldap.sync.base import LDAP_UNIQUENESS, BaseLDAPSynchronizer, flatten class GroupLDAPSynchronizer(BaseLDAPSynchronizer): @@ -39,7 +39,7 @@ class GroupLDAPSynchronizer(BaseLDAPSynchronizer): if "attributes" not in group: continue attributes = group.get("attributes", {}) - group_dn = self._flatten(self._flatten(group.get("entryDN", group.get("dn")))) + group_dn = flatten(flatten(group.get("entryDN", group.get("dn")))) if self._source.object_uniqueness_field not in attributes: self.message( f"Cannot find uniqueness field in attributes: '{group_dn}'", @@ -47,7 +47,7 @@ class GroupLDAPSynchronizer(BaseLDAPSynchronizer): dn=group_dn, ) continue - uniq = self._flatten(attributes[self._source.object_uniqueness_field]) + uniq = flatten(attributes[self._source.object_uniqueness_field]) try: defaults = self.build_group_properties(group_dn, **attributes) defaults["parent"] = self._source.sync_parent_group diff --git a/authentik/sources/ldap/sync/users.py b/authentik/sources/ldap/sync/users.py index 68d966022..6c4d3bd0e 100644 --- a/authentik/sources/ldap/sync/users.py +++ b/authentik/sources/ldap/sync/users.py @@ -7,7 +7,7 @@ from ldap3 import ALL_ATTRIBUTES, ALL_OPERATIONAL_ATTRIBUTES, SUBTREE from authentik.core.models import User from authentik.events.models import Event, EventAction -from authentik.sources.ldap.sync.base import LDAP_UNIQUENESS, BaseLDAPSynchronizer +from authentik.sources.ldap.sync.base import LDAP_UNIQUENESS, BaseLDAPSynchronizer, flatten from authentik.sources.ldap.sync.vendor.freeipa import FreeIPA from authentik.sources.ldap.sync.vendor.ms_ad import MicrosoftActiveDirectory @@ -41,7 +41,7 @@ class UserLDAPSynchronizer(BaseLDAPSynchronizer): if "attributes" not in user: continue attributes = user.get("attributes", {}) - user_dn = self._flatten(user.get("entryDN", user.get("dn"))) + user_dn = flatten(user.get("entryDN", user.get("dn"))) if self._source.object_uniqueness_field not in attributes: self.message( f"Cannot find uniqueness field in attributes: '{user_dn}'", @@ -49,7 +49,7 @@ class UserLDAPSynchronizer(BaseLDAPSynchronizer): dn=user_dn, ) continue - uniq = self._flatten(attributes[self._source.object_uniqueness_field]) + uniq = flatten(attributes[self._source.object_uniqueness_field]) try: defaults = self.build_user_properties(user_dn, **attributes) self._logger.debug("Writing user with attributes", **defaults) diff --git a/authentik/sources/ldap/sync/vendor/freeipa.py b/authentik/sources/ldap/sync/vendor/freeipa.py index fd42c001c..d0bce0584 100644 --- a/authentik/sources/ldap/sync/vendor/freeipa.py +++ b/authentik/sources/ldap/sync/vendor/freeipa.py @@ -5,7 +5,7 @@ from typing import Any, Generator from pytz import UTC from authentik.core.models import User -from authentik.sources.ldap.sync.base import BaseLDAPSynchronizer +from authentik.sources.ldap.sync.base import BaseLDAPSynchronizer, flatten class FreeIPA(BaseLDAPSynchronizer): @@ -47,7 +47,7 @@ class FreeIPA(BaseLDAPSynchronizer): return # For some reason, nsaccountlock is not defined properly in the schema as bool # hence we get it as a list of strings - _is_locked = str(self._flatten(attributes.get("nsaccountlock", ["FALSE"]))) + _is_locked = str(flatten(attributes.get("nsaccountlock", ["FALSE"]))) # So we have to attempt to convert it to a bool is_locked = _is_locked.lower() == "true" # And then invert it since freeipa saves locked and we save active diff --git a/authentik/sources/ldap/tasks.py b/authentik/sources/ldap/tasks.py index 9c4d6af73..7f00d6bb3 100644 --- a/authentik/sources/ldap/tasks.py +++ b/authentik/sources/ldap/tasks.py @@ -1,13 +1,14 @@ """LDAP Sync tasks""" +from typing import Optional from uuid import uuid4 from celery import chain, group from django.core.cache import cache from ldap3.core.exceptions import LDAPException from redis.exceptions import LockError -from redis.lock import Lock from structlog.stdlib import get_logger +from authentik.events.monitored_tasks import CACHE_KEY_PREFIX as CACHE_KEY_PREFIX_TASKS from authentik.events.monitored_tasks import MonitoredTask, TaskResult, TaskResultStatus from authentik.lib.config import CONFIG from authentik.lib.utils.errors import exception_to_string @@ -26,6 +27,7 @@ SYNC_CLASSES = [ MembershipLDAPSynchronizer, ] CACHE_KEY_PREFIX = "goauthentik.io/sources/ldap/page/" +CACHE_KEY_STATUS = "goauthentik.io/sources/ldap/status/" @CELERY_APP.task() @@ -35,6 +37,19 @@ def ldap_sync_all(): ldap_sync_single.apply_async(args=[source.pk]) +@CELERY_APP.task() +def ldap_connectivity_check(pk: Optional[str] = None): + """Check connectivity for LDAP Sources""" + # 2 hour timeout, this task should run every hour + timeout = 60 * 60 * 2 + sources = LDAPSource.objects.filter(enabled=True) + if pk: + sources = sources.filter(pk=pk) + for source in sources: + status = source.check_connection() + cache.set(CACHE_KEY_STATUS + source.slug, status, timeout=timeout) + + @CELERY_APP.task( # We take the configured hours timeout time by 2.5 as we run user and # group in parallel and then membership, so 2x is to cover the serial tasks, @@ -47,12 +62,15 @@ def ldap_sync_single(source_pk: str): source: LDAPSource = LDAPSource.objects.filter(pk=source_pk).first() if not source: return - lock = Lock(cache.client.get_client(), name=f"goauthentik.io/sources/ldap/sync-{source.slug}") + lock = source.sync_lock if lock.locked(): LOGGER.debug("LDAP sync locked, skipping task", source=source.slug) return try: with lock: + # Delete all sync tasks from the cache + keys = cache.keys(f"{CACHE_KEY_PREFIX_TASKS}ldap_sync:{source.slug}*") + cache.delete_many(keys) task = chain( # User and group sync can happen at once, they have no dependencies on each other group( diff --git a/schema.yml b/schema.yml index d8c13331e..fd025466a 100644 --- a/schema.yml +++ b/schema.yml @@ -18942,7 +18942,7 @@ paths: description: '' /sources/ldap/{slug}/sync_status/: get: - operationId: sources_ldap_sync_status_list + operationId: sources_ldap_sync_status_retrieve description: Get source's sync status parameters: - in: path @@ -18960,9 +18960,7 @@ paths: content: application/json: schema: - type: array - items: - $ref: '#/components/schemas/Task' + $ref: '#/components/schemas/LDAPSyncStatus' description: '' '400': content: @@ -32812,9 +32810,19 @@ components: type: string format: uuid description: Property mappings used for group creation/updating. + connectivity: + type: object + additionalProperties: + type: object + additionalProperties: + type: string + nullable: true + description: Get cached source connectivity + readOnly: true required: - base_dn - component + - connectivity - icon - managed - meta_model_name @@ -32948,6 +32956,21 @@ components: - name - server_uri - slug + LDAPSyncStatus: + type: object + description: LDAP Source sync status + properties: + is_running: + type: boolean + readOnly: true + tasks: + type: array + items: + $ref: '#/components/schemas/Task' + readOnly: true + required: + - is_running + - tasks LayoutEnum: enum: - stacked diff --git a/web/src/admin/admin-overview/charts/SyncStatusChart.ts b/web/src/admin/admin-overview/charts/SyncStatusChart.ts index f306a578d..28747d682 100644 --- a/web/src/admin/admin-overview/charts/SyncStatusChart.ts +++ b/web/src/admin/admin-overview/charts/SyncStatusChart.ts @@ -44,11 +44,11 @@ export class LDAPSyncStatusChart extends AKChart { await Promise.all( sources.results.map(async (element) => { try { - const health = await api.sourcesLdapSyncStatusList({ + const health = await api.sourcesLdapSyncStatusRetrieve({ slug: element.slug, }); - health.forEach((task) => { + health.tasks.forEach((task) => { if (task.status !== TaskStatusEnum.Successful) { metrics.failed += 1; } @@ -60,7 +60,7 @@ export class LDAPSyncStatusChart extends AKChart { metrics.healthy += 1; } }); - if (health.length < 1) { + if (health.tasks.length < 1) { metrics.unsynced += 1; } } catch { diff --git a/web/src/admin/sources/ldap/LDAPSourceConnectivity.ts b/web/src/admin/sources/ldap/LDAPSourceConnectivity.ts new file mode 100644 index 000000000..34cdc2ffe --- /dev/null +++ b/web/src/admin/sources/ldap/LDAPSourceConnectivity.ts @@ -0,0 +1,50 @@ +import { AKElement } from "@goauthentik/app/elements/Base"; +import "@patternfly/elements/pf-tooltip/pf-tooltip.js"; + +import { msg } from "@lit/localize"; +import { CSSResult, TemplateResult, html } from "lit"; +import { customElement, property } from "lit/decorators.js"; + +import PFList from "@patternfly/patternfly/components/List/list.css"; +import PFBase from "@patternfly/patternfly/patternfly-base.css"; + +@customElement("ak-source-ldap-connectivity") +export class LDAPSourceConnectivity extends AKElement { + @property() + connectivity?: { + [key: string]: { + [key: string]: string; + }; + }; + + static get styles(): CSSResult[] { + return [PFBase, PFList]; + } + + render(): TemplateResult { + if (!this.connectivity) { + return html``; + } + return html`
    + ${Object.keys(this.connectivity).map((serverKey) => { + let serverLabel = html`${serverKey}`; + if (serverKey === "__all__") { + serverLabel = html`${msg("Global status")}`; + } + const server = this.connectivity![serverKey]; + const content = html`${serverLabel}: ${server.status}`; + let tooltip = html`${content}`; + if (server.status === "ok") { + tooltip = html` +
      +
    • ${msg("Vendor")}: ${server.vendor}
    • +
    • ${msg("Version")}: ${server.version}
    • +
    + ${content} +
    `; + } + return html`
  • ${tooltip}
  • `; + })} +
`; + } +} diff --git a/web/src/admin/sources/ldap/LDAPSourceViewPage.ts b/web/src/admin/sources/ldap/LDAPSourceViewPage.ts index 36129c3c4..6ac64c14b 100644 --- a/web/src/admin/sources/ldap/LDAPSourceViewPage.ts +++ b/web/src/admin/sources/ldap/LDAPSourceViewPage.ts @@ -1,3 +1,4 @@ +import "@goauthentik/admin/sources/ldap/LDAPSourceConnectivity"; import "@goauthentik/admin/sources/ldap/LDAPSourceForm"; import "@goauthentik/app/elements/rbac/ObjectPermissionsPage"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; @@ -25,9 +26,9 @@ import PFBase from "@patternfly/patternfly/patternfly-base.css"; import { LDAPSource, + LDAPSyncStatus, RbacPermissionsAssignedByUsersListModelEnum, SourcesApi, - Task, TaskStatusEnum, } from "@goauthentik/api"; @@ -48,7 +49,7 @@ export class LDAPSourceViewPage extends AKElement { source!: LDAPSource; @state() - syncState: Task[] = []; + syncState?: LDAPSyncStatus; static get styles(): CSSResult[] { return [PFBase, PFPage, PFButton, PFGrid, PFContent, PFCard, PFDescriptionList, PFList]; @@ -62,6 +63,51 @@ export class LDAPSourceViewPage extends AKElement { }); } + renderSyncStatus(): TemplateResult { + if (!this.syncState) { + return html`${msg("No sync status.")}`; + } + if (this.syncState.isRunning) { + return html`${msg("Sync currently running.")}`; + } + if (this.syncState.tasks.length < 1) { + return html`${msg("Not synced yet.")}`; + } + return html` +
    + ${this.syncState.tasks.map((task) => { + let header = ""; + if (task.status === TaskStatusEnum.Warning) { + header = msg("Task finished with warnings"); + } else if (task.status === TaskStatusEnum.Error) { + header = msg("Task finished with errors"); + } else { + header = msg(str`Last sync: ${task.taskFinishTimestamp.toLocaleString()}`); + } + return html`
  • +

    ${task.taskName}

    +
      +
    • ${header}
    • + ${task.messages.map((m) => { + return html`
    • ${m}
    • `; + })} +
    +
  • `; + })} +
+ `; + } + + load(): void { + new SourcesApi(DEFAULT_CONFIG) + .sourcesLdapSyncStatusRetrieve({ + slug: this.source.slug, + }) + .then((state) => { + this.syncState = state; + }); + } + render(): TemplateResult { if (!this.source) { return html``; @@ -72,13 +118,7 @@ export class LDAPSourceViewPage extends AKElement { data-tab-title="${msg("Overview")}" class="pf-c-page__main-section pf-m-no-padding-mobile" @activate=${() => { - new SourcesApi(DEFAULT_CONFIG) - .sourcesLdapSyncStatusList({ - slug: this.source.slug, - }) - .then((state) => { - this.syncState = state; - }); + this.load(); }} >
@@ -137,42 +177,25 @@ export class LDAPSourceViewPage extends AKElement {
-
+
+
+

${msg("Connectivity")}

+
+
+ +
+
+

${msg("Sync status")}

-
- ${this.syncState.length < 1 - ? html`

${msg("Not synced yet.")}

` - : html` -
    - ${this.syncState.map((task) => { - let header = ""; - if (task.status === TaskStatusEnum.Warning) { - header = msg("Task finished with warnings"); - } else if (task.status === TaskStatusEnum.Error) { - header = msg("Task finished with errors"); - } else { - header = msg( - str`Last sync: ${task.taskFinishTimestamp.toLocaleString()}`, - ); - } - return html`
  • -

    ${task.taskName}

    -
      -
    • ${header}
    • - ${task.messages.map((m) => { - return html`
    • ${m}
    • `; - })} -
    -
  • `; - })} -
- `} -
+
${this.renderSyncStatus()}