+PVE::JSONSchema::register_standard_option('tokenid', {
+ description => "API token identifier.",
+ type => "string",
+ format => "pve-tokenid",
+});
+
+our $token_subid_regex = $PVE::Auth::Plugin::realm_regex;
+
+# username@realm username realm tokenid
+our $token_full_regex = qr/((${PVE::Auth::Plugin::user_regex})\@(${PVE::Auth::Plugin::realm_regex}))!(${token_subid_regex})/;
+
+our $userid_or_token_regex = qr/^$PVE::Auth::Plugin::user_regex\@$PVE::Auth::Plugin::realm_regex(?:!$token_subid_regex)?$/;
+
+sub split_tokenid {
+ my ($tokenid, $noerr) = @_;
+
+ if ($tokenid =~ /^${token_full_regex}$/) {
+ return ($1, $4);
+ }
+
+ die "'$tokenid' is not a valid token ID - not able to split into user and token parts\n" if !$noerr;
+
+ return undef;
+}
+
+sub join_tokenid {
+ my ($username, $tokensubid) = @_;
+
+ my $joined = "${username}!${tokensubid}";
+
+ return pve_verify_tokenid($joined);
+}
+
+PVE::JSONSchema::register_format('pve-tokenid', \&pve_verify_tokenid);
+sub pve_verify_tokenid {
+ my ($tokenid, $noerr) = @_;
+
+ if ($tokenid =~ /^${token_full_regex}$/) {
+ return wantarray ? ($tokenid, $2, $3, $4) : $tokenid;
+ }
+
+ die "value '$tokenid' does not look like a valid token ID\n" if !$noerr;
+
+ return undef;
+}
+
+