zoneinfo
@@ -9045,14 +9045,14 @@ exports[` should return empty array when selecting nothing 1`] =
Map a custom user attribute to a token claim.
@@ -9139,7 +9139,7 @@ exports[` should return empty array when selecting nothing 1`] =
},
"header": Object {
"formatters": Array [],
- "label": "name",
+ "label": "Name",
"transforms": Array [
[Function],
[Function],
@@ -9148,7 +9148,7 @@ exports[` should return empty array when selecting nothing 1`] =
"property": "name",
"props": Object {
"data-key": 1,
- "data-label": "name",
+ "data-label": "Name",
},
},
Object {
@@ -9182,7 +9182,7 @@ exports[` should return empty array when selecting nothing 1`] =
},
"header": Object {
"formatters": Array [],
- "label": "description",
+ "label": "Description",
"transforms": Array [
[Function],
[Function],
@@ -9191,7 +9191,7 @@ exports[` should return empty array when selecting nothing 1`] =
"property": "description",
"props": Object {
"data-key": 2,
- "data-label": "description",
+ "data-label": "Description",
},
},
]
@@ -9341,14 +9341,14 @@ exports[` should return empty array when selecting nothing 1`] =
birthdate
@@ -9356,14 +9356,14 @@ exports[` should return empty array when selecting nothing 1`] =
Map a custom user attribute to a token claim.
@@ -9450,7 +9450,7 @@ exports[` should return empty array when selecting nothing 1`] =
},
"header": Object {
"formatters": Array [],
- "label": "name",
+ "label": "Name",
"transforms": Array [
[Function],
[Function],
@@ -9459,7 +9459,7 @@ exports[` should return empty array when selecting nothing 1`] =
"property": "name",
"props": Object {
"data-key": 1,
- "data-label": "name",
+ "data-label": "Name",
},
},
Object {
@@ -9493,7 +9493,7 @@ exports[` should return empty array when selecting nothing 1`] =
},
"header": Object {
"formatters": Array [],
- "label": "description",
+ "label": "Description",
"transforms": Array [
[Function],
[Function],
@@ -9502,7 +9502,7 @@ exports[` should return empty array when selecting nothing 1`] =
"property": "description",
"props": Object {
"data-key": 2,
- "data-label": "description",
+ "data-label": "Description",
},
},
]
@@ -9652,14 +9652,14 @@ exports[` should return empty array when selecting nothing 1`] =
family name
@@ -9667,14 +9667,14 @@ exports[` should return empty array when selecting nothing 1`] =
Map a built in user property (email, firstName, lastName) to a token claim.
@@ -9761,7 +9761,7 @@ exports[` should return empty array when selecting nothing 1`] =
},
"header": Object {
"formatters": Array [],
- "label": "name",
+ "label": "Name",
"transforms": Array [
[Function],
[Function],
@@ -9770,7 +9770,7 @@ exports[` should return empty array when selecting nothing 1`] =
"property": "name",
"props": Object {
"data-key": 1,
- "data-label": "name",
+ "data-label": "Name",
},
},
Object {
@@ -9804,7 +9804,7 @@ exports[` should return empty array when selecting nothing 1`] =
},
"header": Object {
"formatters": Array [],
- "label": "description",
+ "label": "Description",
"transforms": Array [
[Function],
[Function],
@@ -9813,7 +9813,7 @@ exports[` should return empty array when selecting nothing 1`] =
"property": "description",
"props": Object {
"data-key": 2,
- "data-label": "description",
+ "data-label": "Description",
},
},
]
@@ -9963,14 +9963,14 @@ exports[` should return empty array when selecting nothing 1`] =
gender
@@ -9978,14 +9978,14 @@ exports[` should return empty array when selecting nothing 1`] =
Map a custom user attribute to a token claim.
@@ -10072,7 +10072,7 @@ exports[` should return empty array when selecting nothing 1`] =
},
"header": Object {
"formatters": Array [],
- "label": "name",
+ "label": "Name",
"transforms": Array [
[Function],
[Function],
@@ -10081,7 +10081,7 @@ exports[` should return empty array when selecting nothing 1`] =
"property": "name",
"props": Object {
"data-key": 1,
- "data-label": "name",
+ "data-label": "Name",
},
},
Object {
@@ -10115,7 +10115,7 @@ exports[` should return empty array when selecting nothing 1`] =
},
"header": Object {
"formatters": Array [],
- "label": "description",
+ "label": "Description",
"transforms": Array [
[Function],
[Function],
@@ -10124,7 +10124,7 @@ exports[` should return empty array when selecting nothing 1`] =
"property": "description",
"props": Object {
"data-key": 2,
- "data-label": "description",
+ "data-label": "Description",
},
},
]
@@ -10272,14 +10272,14 @@ exports[` should return empty array when selecting nothing 1`] =
Impersonator Username
@@ -10287,14 +10287,14 @@ exports[` should return empty array when selecting nothing 1`] =
Map a custom user session note to a token claim.
@@ -10381,7 +10381,7 @@ exports[` should return empty array when selecting nothing 1`] =
},
"header": Object {
"formatters": Array [],
- "label": "name",
+ "label": "Name",
"transforms": Array [
[Function],
[Function],
@@ -10390,7 +10390,7 @@ exports[` should return empty array when selecting nothing 1`] =
"property": "name",
"props": Object {
"data-key": 1,
- "data-label": "name",
+ "data-label": "Name",
},
},
Object {
@@ -10424,7 +10424,7 @@ exports[` should return empty array when selecting nothing 1`] =
},
"header": Object {
"formatters": Array [],
- "label": "description",
+ "label": "Description",
"transforms": Array [
[Function],
[Function],
@@ -10433,7 +10433,7 @@ exports[` should return empty array when selecting nothing 1`] =
"property": "description",
"props": Object {
"data-key": 2,
- "data-label": "description",
+ "data-label": "Description",
},
},
]
@@ -10583,14 +10583,14 @@ exports[` should return empty array when selecting nothing 1`] =
phone number verified
@@ -10598,14 +10598,14 @@ exports[` should return empty array when selecting nothing 1`] =
Map a custom user attribute to a token claim.
@@ -10692,7 +10692,7 @@ exports[` should return empty array when selecting nothing 1`] =
},
"header": Object {
"formatters": Array [],
- "label": "name",
+ "label": "Name",
"transforms": Array [
[Function],
[Function],
@@ -10701,7 +10701,7 @@ exports[` should return empty array when selecting nothing 1`] =
"property": "name",
"props": Object {
"data-key": 1,
- "data-label": "name",
+ "data-label": "Name",
},
},
Object {
@@ -10735,7 +10735,7 @@ exports[` should return empty array when selecting nothing 1`] =
},
"header": Object {
"formatters": Array [],
- "label": "description",
+ "label": "Description",
"transforms": Array [
[Function],
[Function],
@@ -10744,7 +10744,7 @@ exports[` should return empty array when selecting nothing 1`] =
"property": "description",
"props": Object {
"data-key": 2,
- "data-label": "description",
+ "data-label": "Description",
},
},
]
@@ -10894,14 +10894,14 @@ exports[` should return empty array when selecting nothing 1`] =
locale
@@ -10909,14 +10909,14 @@ exports[` should return empty array when selecting nothing 1`] =
Map a custom user attribute to a token claim.
@@ -11003,7 +11003,7 @@ exports[` should return empty array when selecting nothing 1`] =
},
"header": Object {
"formatters": Array [],
- "label": "name",
+ "label": "Name",
"transforms": Array [
[Function],
[Function],
@@ -11012,7 +11012,7 @@ exports[` should return empty array when selecting nothing 1`] =
"property": "name",
"props": Object {
"data-key": 1,
- "data-label": "name",
+ "data-label": "Name",
},
},
Object {
@@ -11046,7 +11046,7 @@ exports[` should return empty array when selecting nothing 1`] =
},
"header": Object {
"formatters": Array [],
- "label": "description",
+ "label": "Description",
"transforms": Array [
[Function],
[Function],
@@ -11055,7 +11055,7 @@ exports[` should return empty array when selecting nothing 1`] =
"property": "description",
"props": Object {
"data-key": 2,
- "data-label": "description",
+ "data-label": "Description",
},
},
]
@@ -11201,14 +11201,14 @@ exports[` should return empty array when selecting nothing 1`] =
gss delegation credential
@@ -11216,14 +11216,14 @@ exports[` should return empty array when selecting nothing 1`] =
Map a custom user session note to a token claim.
@@ -11310,7 +11310,7 @@ exports[` should return empty array when selecting nothing 1`] =
},
"header": Object {
"formatters": Array [],
- "label": "name",
+ "label": "Name",
"transforms": Array [
[Function],
[Function],
@@ -11319,7 +11319,7 @@ exports[` should return empty array when selecting nothing 1`] =
"property": "name",
"props": Object {
"data-key": 1,
- "data-label": "name",
+ "data-label": "Name",
},
},
Object {
@@ -11353,7 +11353,7 @@ exports[` should return empty array when selecting nothing 1`] =
},
"header": Object {
"formatters": Array [],
- "label": "description",
+ "label": "Description",
"transforms": Array [
[Function],
[Function],
@@ -11362,7 +11362,7 @@ exports[` should return empty array when selecting nothing 1`] =
"property": "description",
"props": Object {
"data-key": 2,
- "data-label": "description",
+ "data-label": "Description",
},
},
]
@@ -11498,14 +11498,14 @@ exports[` should return empty array when selecting nothing 1`] =
allowed web origins
@@ -11513,14 +11513,14 @@ exports[` should return empty array when selecting nothing 1`] =
Adds all allowed web origins to the 'allowed-origins' claim in the token
@@ -11607,7 +11607,7 @@ exports[` should return empty array when selecting nothing 1`] =
},
"header": Object {
"formatters": Array [],
- "label": "name",
+ "label": "Name",
"transforms": Array [
[Function],
[Function],
@@ -11616,7 +11616,7 @@ exports[` should return empty array when selecting nothing 1`] =
"property": "name",
"props": Object {
"data-key": 1,
- "data-label": "name",
+ "data-label": "Name",
},
},
Object {
@@ -11650,7 +11650,7 @@ exports[` should return empty array when selecting nothing 1`] =
},
"header": Object {
"formatters": Array [],
- "label": "description",
+ "label": "Description",
"transforms": Array [
[Function],
[Function],
@@ -11659,7 +11659,7 @@ exports[` should return empty array when selecting nothing 1`] =
"property": "description",
"props": Object {
"data-key": 2,
- "data-label": "description",
+ "data-label": "Description",
},
},
]
@@ -11809,14 +11809,14 @@ exports[` should return empty array when selecting nothing 1`] =
middle name
@@ -11824,14 +11824,14 @@ exports[` should return empty array when selecting nothing 1`] =
Map a custom user attribute to a token claim.
@@ -11918,7 +11918,7 @@ exports[` should return empty array when selecting nothing 1`] =
},
"header": Object {
"formatters": Array [],
- "label": "name",
+ "label": "Name",
"transforms": Array [
[Function],
[Function],
@@ -11927,7 +11927,7 @@ exports[` should return empty array when selecting nothing 1`] =
"property": "name",
"props": Object {
"data-key": 1,
- "data-label": "name",
+ "data-label": "Name",
},
},
Object {
@@ -11961,7 +11961,7 @@ exports[` should return empty array when selecting nothing 1`] =
},
"header": Object {
"formatters": Array [],
- "label": "description",
+ "label": "Description",
"transforms": Array [
[Function],
[Function],
@@ -11970,7 +11970,7 @@ exports[` should return empty array when selecting nothing 1`] =
"property": "description",
"props": Object {
"data-key": 2,
- "data-label": "description",
+ "data-label": "Description",
},
},
]
@@ -12120,14 +12120,14 @@ exports[` should return empty array when selecting nothing 1`] =
nickname
@@ -12135,14 +12135,14 @@ exports[` should return empty array when selecting nothing 1`] =
Map a custom user attribute to a token claim.
@@ -12229,7 +12229,7 @@ exports[` should return empty array when selecting nothing 1`] =
},
"header": Object {
"formatters": Array [],
- "label": "name",
+ "label": "Name",
"transforms": Array [
[Function],
[Function],
@@ -12238,7 +12238,7 @@ exports[` should return empty array when selecting nothing 1`] =
"property": "name",
"props": Object {
"data-key": 1,
- "data-label": "name",
+ "data-label": "Name",
},
},
Object {
@@ -12272,7 +12272,7 @@ exports[` should return empty array when selecting nothing 1`] =
},
"header": Object {
"formatters": Array [],
- "label": "description",
+ "label": "Description",
"transforms": Array [
[Function],
[Function],
@@ -12281,7 +12281,7 @@ exports[` should return empty array when selecting nothing 1`] =
"property": "description",
"props": Object {
"data-key": 2,
- "data-label": "description",
+ "data-label": "Description",
},
},
]
@@ -12431,14 +12431,14 @@ exports[` should return empty array when selecting nothing 1`] =
updated at
@@ -12446,14 +12446,14 @@ exports[` should return empty array when selecting nothing 1`] =
Map a custom user attribute to a token claim.
@@ -12540,7 +12540,7 @@ exports[` should return empty array when selecting nothing 1`] =
},
"header": Object {
"formatters": Array [],
- "label": "name",
+ "label": "Name",
"transforms": Array [
[Function],
[Function],
@@ -12549,7 +12549,7 @@ exports[` should return empty array when selecting nothing 1`] =
"property": "name",
"props": Object {
"data-key": 1,
- "data-label": "name",
+ "data-label": "Name",
},
},
Object {
@@ -12583,7 +12583,7 @@ exports[` should return empty array when selecting nothing 1`] =
},
"header": Object {
"formatters": Array [],
- "label": "description",
+ "label": "Description",
"transforms": Array [
[Function],
[Function],
@@ -12592,7 +12592,7 @@ exports[` should return empty array when selecting nothing 1`] =
"property": "description",
"props": Object {
"data-key": 2,
- "data-label": "description",
+ "data-label": "Description",
},
},
]
@@ -12742,14 +12742,14 @@ exports[` should return empty array when selecting nothing 1`] =
email verified
@@ -12757,14 +12757,14 @@ exports[` should return empty array when selecting nothing 1`] =
Map a built in user property (email, firstName, lastName) to a token claim.
@@ -12851,7 +12851,7 @@ exports[` should return empty array when selecting nothing 1`] =
},
"header": Object {
"formatters": Array [],
- "label": "name",
+ "label": "Name",
"transforms": Array [
[Function],
[Function],
@@ -12860,7 +12860,7 @@ exports[` should return empty array when selecting nothing 1`] =
"property": "name",
"props": Object {
"data-key": 1,
- "data-label": "name",
+ "data-label": "Name",
},
},
Object {
@@ -12894,7 +12894,7 @@ exports[` should return empty array when selecting nothing 1`] =
},
"header": Object {
"formatters": Array [],
- "label": "description",
+ "label": "Description",
"transforms": Array [
[Function],
[Function],
@@ -12903,7 +12903,7 @@ exports[` should return empty array when selecting nothing 1`] =
"property": "description",
"props": Object {
"data-key": 2,
- "data-label": "description",
+ "data-label": "Description",
},
},
]
@@ -13053,14 +13053,14 @@ exports[` should return empty array when selecting nothing 1`] =
email
@@ -13068,14 +13068,14 @@ exports[` should return empty array when selecting nothing 1`] =
Map a built in user property (email, firstName, lastName) to a token claim.
@@ -13162,7 +13162,7 @@ exports[` should return empty array when selecting nothing 1`] =
},
"header": Object {
"formatters": Array [],
- "label": "name",
+ "label": "Name",
"transforms": Array [
[Function],
[Function],
@@ -13171,7 +13171,7 @@ exports[` should return empty array when selecting nothing 1`] =
"property": "name",
"props": Object {
"data-key": 1,
- "data-label": "name",
+ "data-label": "Name",
},
},
Object {
@@ -13205,7 +13205,7 @@ exports[` should return empty array when selecting nothing 1`] =
},
"header": Object {
"formatters": Array [],
- "label": "description",
+ "label": "Description",
"transforms": Array [
[Function],
[Function],
@@ -13214,7 +13214,7 @@ exports[` should return empty array when selecting nothing 1`] =
"property": "description",
"props": Object {
"data-key": 2,
- "data-label": "description",
+ "data-label": "Description",
},
},
]
@@ -13362,14 +13362,14 @@ exports[` should return empty array when selecting nothing 1`] =
client roles
@@ -13377,14 +13377,14 @@ exports[` should return empty array when selecting nothing 1`] =
Map a user client role to a token claim.
@@ -13471,7 +13471,7 @@ exports[` should return empty array when selecting nothing 1`] =
},
"header": Object {
"formatters": Array [],
- "label": "name",
+ "label": "Name",
"transforms": Array [
[Function],
[Function],
@@ -13480,7 +13480,7 @@ exports[` should return empty array when selecting nothing 1`] =
"property": "name",
"props": Object {
"data-key": 1,
- "data-label": "name",
+ "data-label": "Name",
},
},
Object {
@@ -13514,7 +13514,7 @@ exports[` should return empty array when selecting nothing 1`] =
},
"header": Object {
"formatters": Array [],
- "label": "description",
+ "label": "Description",
"transforms": Array [
[Function],
[Function],
@@ -13523,7 +13523,7 @@ exports[` should return empty array when selecting nothing 1`] =
"property": "description",
"props": Object {
"data-key": 2,
- "data-label": "description",
+ "data-label": "Description",
},
},
]
@@ -13671,14 +13671,14 @@ exports[` should return empty array when selecting nothing 1`] =
Impersonator User ID
@@ -13686,14 +13686,14 @@ exports[` should return empty array when selecting nothing 1`] =
Map a custom user session note to a token claim.
@@ -13780,7 +13780,7 @@ exports[` should return empty array when selecting nothing 1`] =
},
"header": Object {
"formatters": Array [],
- "label": "name",
+ "label": "Name",
"transforms": Array [
[Function],
[Function],
@@ -13789,7 +13789,7 @@ exports[` should return empty array when selecting nothing 1`] =
"property": "name",
"props": Object {
"data-key": 1,
- "data-label": "name",
+ "data-label": "Name",
},
},
Object {
@@ -13823,7 +13823,7 @@ exports[` should return empty array when selecting nothing 1`] =
},
"header": Object {
"formatters": Array [],
- "label": "description",
+ "label": "Description",
"transforms": Array [
[Function],
[Function],
@@ -13832,7 +13832,7 @@ exports[` should return empty array when selecting nothing 1`] =
"property": "description",
"props": Object {
"data-key": 2,
- "data-label": "description",
+ "data-label": "Description",
},
},
]
@@ -13982,14 +13982,14 @@ exports[` should return empty array when selecting nothing 1`] =
website
@@ -13997,14 +13997,14 @@ exports[` should return empty array when selecting nothing 1`] =
Map a custom user attribute to a token claim.
@@ -14091,7 +14091,7 @@ exports[` should return empty array when selecting nothing 1`] =
},
"header": Object {
"formatters": Array [],
- "label": "name",
+ "label": "Name",
"transforms": Array [
[Function],
[Function],
@@ -14100,7 +14100,7 @@ exports[` should return empty array when selecting nothing 1`] =
"property": "name",
"props": Object {
"data-key": 1,
- "data-label": "name",
+ "data-label": "Name",
},
},
Object {
@@ -14134,7 +14134,7 @@ exports[` should return empty array when selecting nothing 1`] =
},
"header": Object {
"formatters": Array [],
- "label": "description",
+ "label": "Description",
"transforms": Array [
[Function],
[Function],
@@ -14143,7 +14143,7 @@ exports[` should return empty array when selecting nothing 1`] =
"property": "description",
"props": Object {
"data-key": 2,
- "data-label": "description",
+ "data-label": "Description",
},
},
]
@@ -14299,14 +14299,14 @@ exports[` should return empty array when selecting nothing 1`] =
address
@@ -14314,14 +14314,14 @@ exports[` should return empty array when selecting nothing 1`] =
Maps user address attributes (street, locality, region, postal_code, and country) to the OpenID Connect 'address' claim.
@@ -14408,7 +14408,7 @@ exports[` should return empty array when selecting nothing 1`] =
},
"header": Object {
"formatters": Array [],
- "label": "name",
+ "label": "Name",
"transforms": Array [
[Function],
[Function],
@@ -14417,7 +14417,7 @@ exports[` should return empty array when selecting nothing 1`] =
"property": "name",
"props": Object {
"data-key": 1,
- "data-label": "name",
+ "data-label": "Name",
},
},
Object {
@@ -14451,7 +14451,7 @@ exports[` should return empty array when selecting nothing 1`] =
},
"header": Object {
"formatters": Array [],
- "label": "description",
+ "label": "Description",
"transforms": Array [
[Function],
[Function],
@@ -14460,7 +14460,7 @@ exports[` should return empty array when selecting nothing 1`] =
"property": "description",
"props": Object {
"data-key": 2,
- "data-label": "description",
+ "data-label": "Description",
},
},
]
@@ -14610,14 +14610,14 @@ exports[` should return empty array when selecting nothing 1`] =
given name
@@ -14625,14 +14625,14 @@ exports[` should return empty array when selecting nothing 1`] =
Map a built in user property (email, firstName, lastName) to a token claim.
@@ -14719,7 +14719,7 @@ exports[` should return empty array when selecting nothing 1`] =
},
"header": Object {
"formatters": Array [],
- "label": "name",
+ "label": "Name",
"transforms": Array [
[Function],
[Function],
@@ -14728,7 +14728,7 @@ exports[` should return empty array when selecting nothing 1`] =
"property": "name",
"props": Object {
"data-key": 1,
- "data-label": "name",
+ "data-label": "Name",
},
},
Object {
@@ -14762,7 +14762,7 @@ exports[` should return empty array when selecting nothing 1`] =
},
"header": Object {
"formatters": Array [],
- "label": "description",
+ "label": "Description",
"transforms": Array [
[Function],
[Function],
@@ -14771,7 +14771,7 @@ exports[` should return empty array when selecting nothing 1`] =
"property": "description",
"props": Object {
"data-key": 2,
- "data-label": "description",
+ "data-label": "Description",
},
},
]
@@ -14921,14 +14921,14 @@ exports[` should return empty array when selecting nothing 1`] =
profile
@@ -14936,14 +14936,14 @@ exports[` should return empty array when selecting nothing 1`] =
Map a custom user attribute to a token claim.
@@ -15030,7 +15030,7 @@ exports[` should return empty array when selecting nothing 1`] =
},
"header": Object {
"formatters": Array [],
- "label": "name",
+ "label": "Name",
"transforms": Array [
[Function],
[Function],
@@ -15039,7 +15039,7 @@ exports[` should return empty array when selecting nothing 1`] =
"property": "name",
"props": Object {
"data-key": 1,
- "data-label": "name",
+ "data-label": "Name",
},
},
Object {
@@ -15073,7 +15073,7 @@ exports[` should return empty array when selecting nothing 1`] =
},
"header": Object {
"formatters": Array [],
- "label": "description",
+ "label": "Description",
"transforms": Array [
[Function],
[Function],
@@ -15082,7 +15082,7 @@ exports[` should return empty array when selecting nothing 1`] =
"property": "description",
"props": Object {
"data-key": 2,
- "data-label": "description",
+ "data-label": "Description",
},
},
]
@@ -15232,14 +15232,14 @@ exports[` should return empty array when selecting nothing 1`] =
groups
@@ -15247,14 +15247,14 @@ exports[` should return empty array when selecting nothing 1`] =
Map a user realm role to a token claim.
@@ -15341,7 +15341,7 @@ exports[` should return empty array when selecting nothing 1`] =
},
"header": Object {
"formatters": Array [],
- "label": "name",
+ "label": "Name",
"transforms": Array [
[Function],
[Function],
@@ -15350,7 +15350,7 @@ exports[` should return empty array when selecting nothing 1`] =
"property": "name",
"props": Object {
"data-key": 1,
- "data-label": "name",
+ "data-label": "Name",
},
},
Object {
@@ -15384,7 +15384,7 @@ exports[` should return empty array when selecting nothing 1`] =
},
"header": Object {
"formatters": Array [],
- "label": "description",
+ "label": "Description",
"transforms": Array [
[Function],
[Function],
@@ -15393,7 +15393,7 @@ exports[` should return empty array when selecting nothing 1`] =
"property": "description",
"props": Object {
"data-key": 2,
- "data-label": "description",
+ "data-label": "Description",
},
},
]
@@ -15543,14 +15543,14 @@ exports[` should return empty array when selecting nothing 1`] =
phone number
@@ -15558,14 +15558,14 @@ exports[` should return empty array when selecting nothing 1`] =
Map a custom user attribute to a token claim.
@@ -15652,7 +15652,7 @@ exports[` should return empty array when selecting nothing 1`] =
},
"header": Object {
"formatters": Array [],
- "label": "name",
+ "label": "Name",
"transforms": Array [
[Function],
[Function],
@@ -15661,7 +15661,7 @@ exports[` should return empty array when selecting nothing 1`] =
"property": "name",
"props": Object {
"data-key": 1,
- "data-label": "name",
+ "data-label": "Name",
},
},
Object {
@@ -15695,7 +15695,7 @@ exports[` should return empty array when selecting nothing 1`] =
},
"header": Object {
"formatters": Array [],
- "label": "description",
+ "label": "Description",
"transforms": Array [
[Function],
[Function],
@@ -15704,7 +15704,7 @@ exports[` should return empty array when selecting nothing 1`] =
"property": "description",
"props": Object {
"data-key": 2,
- "data-label": "description",
+ "data-label": "Description",
},
},
]
@@ -15848,14 +15848,14 @@ exports[` should return empty array when selecting nothing 1`] =
full name
@@ -15863,14 +15863,14 @@ exports[` should return empty array when selecting nothing 1`] =
Maps the user's first and last name to the OpenID Connect 'name' claim. Format is <first> + ' ' + <last>
@@ -15957,7 +15957,7 @@ exports[` should return empty array when selecting nothing 1`] =
},
"header": Object {
"formatters": Array [],
- "label": "name",
+ "label": "Name",
"transforms": Array [
[Function],
[Function],
@@ -15966,7 +15966,7 @@ exports[` should return empty array when selecting nothing 1`] =
"property": "name",
"props": Object {
"data-key": 1,
- "data-label": "name",
+ "data-label": "Name",
},
},
Object {
@@ -16000,7 +16000,7 @@ exports[` should return empty array when selecting nothing 1`] =
},
"header": Object {
"formatters": Array [],
- "label": "description",
+ "label": "Description",
"transforms": Array [
[Function],
[Function],
@@ -16009,7 +16009,7 @@ exports[` should return empty array when selecting nothing 1`] =
"property": "description",
"props": Object {
"data-key": 2,
- "data-label": "description",
+ "data-label": "Description",
},
},
]
@@ -16149,14 +16149,14 @@ exports[` should return empty array when selecting nothing 1`] =
audience resolve
@@ -16164,14 +16164,14 @@ exports[` should return empty array when selecting nothing 1`] =
Adds all client_ids of "allowed" clients to the audience field of the token. Allowed client means the client
@@ -16259,7 +16259,7 @@ exports[` should return empty array when selecting nothing 1`] =
},
"header": Object {
"formatters": Array [],
- "label": "name",
+ "label": "Name",
"transforms": Array [
[Function],
[Function],
@@ -16268,7 +16268,7 @@ exports[` should return empty array when selecting nothing 1`] =
"property": "name",
"props": Object {
"data-key": 1,
- "data-label": "name",
+ "data-label": "Name",
},
},
Object {
@@ -16302,7 +16302,7 @@ exports[` should return empty array when selecting nothing 1`] =
},
"header": Object {
"formatters": Array [],
- "label": "description",
+ "label": "Description",
"transforms": Array [
[Function],
[Function],
@@ -16311,7 +16311,7 @@ exports[` should return empty array when selecting nothing 1`] =
"property": "description",
"props": Object {
"data-key": 2,
- "data-label": "description",
+ "data-label": "Description",
},
},
]
@@ -16461,14 +16461,14 @@ exports[` should return empty array when selecting nothing 1`] =
picture
@@ -16476,14 +16476,14 @@ exports[` should return empty array when selecting nothing 1`] =
Map a custom user attribute to a token claim.
@@ -16570,7 +16570,7 @@ exports[` should return empty array when selecting nothing 1`] =
},
"header": Object {
"formatters": Array [],
- "label": "name",
+ "label": "Name",
"transforms": Array [
[Function],
[Function],
@@ -16579,7 +16579,7 @@ exports[` should return empty array when selecting nothing 1`] =
"property": "name",
"props": Object {
"data-key": 1,
- "data-label": "name",
+ "data-label": "Name",
},
},
Object {
@@ -16613,7 +16613,7 @@ exports[` should return empty array when selecting nothing 1`] =
},
"header": Object {
"formatters": Array [],
- "label": "description",
+ "label": "Description",
"transforms": Array [
[Function],
[Function],
@@ -16622,7 +16622,7 @@ exports[` should return empty array when selecting nothing 1`] =
"property": "description",
"props": Object {
"data-key": 2,
- "data-label": "description",
+ "data-label": "Description",
},
},
]
@@ -16772,14 +16772,14 @@ exports[` should return empty array when selecting nothing 1`] =
upn
@@ -16787,14 +16787,14 @@ exports[` should return empty array when selecting nothing 1`] =
Map a built in user property (email, firstName, lastName) to a token claim.
@@ -16881,7 +16881,7 @@ exports[` should return empty array when selecting nothing 1`] =
},
"header": Object {
"formatters": Array [],
- "label": "name",
+ "label": "Name",
"transforms": Array [
[Function],
[Function],
@@ -16890,7 +16890,7 @@ exports[` should return empty array when selecting nothing 1`] =
"property": "name",
"props": Object {
"data-key": 1,
- "data-label": "name",
+ "data-label": "Name",
},
},
Object {
@@ -16924,7 +16924,7 @@ exports[` should return empty array when selecting nothing 1`] =
},
"header": Object {
"formatters": Array [],
- "label": "description",
+ "label": "Description",
"transforms": Array [
[Function],
[Function],
@@ -16933,7 +16933,7 @@ exports[` should return empty array when selecting nothing 1`] =
"property": "description",
"props": Object {
"data-key": 2,
- "data-label": "description",
+ "data-label": "Description",
},
},
]
@@ -17081,14 +17081,14 @@ exports[` should return empty array when selecting nothing 1`] =
realm roles
@@ -17096,14 +17096,14 @@ exports[` should return empty array when selecting nothing 1`] =
Map a user realm role to a token claim.
@@ -17190,7 +17190,7 @@ exports[` should return empty array when selecting nothing 1`] =
},
"header": Object {
"formatters": Array [],
- "label": "name",
+ "label": "Name",
"transforms": Array [
[Function],
[Function],
@@ -17199,7 +17199,7 @@ exports[` should return empty array when selecting nothing 1`] =
"property": "name",
"props": Object {
"data-key": 1,
- "data-label": "name",
+ "data-label": "Name",
},
},
Object {
@@ -17233,7 +17233,7 @@ exports[` should return empty array when selecting nothing 1`] =
},
"header": Object {
"formatters": Array [],
- "label": "description",
+ "label": "Description",
"transforms": Array [
[Function],
[Function],
@@ -17242,7 +17242,7 @@ exports[` should return empty array when selecting nothing 1`] =
"property": "description",
"props": Object {
"data-key": 2,
- "data-label": "description",
+ "data-label": "Description",
},
},
]
@@ -17392,14 +17392,14 @@ exports[` should return empty array when selecting nothing 1`] =
username
@@ -17407,14 +17407,14 @@ exports[` should return empty array when selecting nothing 1`] =
Map a built in user property (email, firstName, lastName) to a token claim.
@@ -17456,7 +17456,7 @@ exports[` should return empty array when selecting nothing 1`] =
onClick={[Function]}
type="button"
>
- add
+ Add
should return empty array when selecting nothing 1`] =
onClick={[Function]}
type="button"
>
- cancel
+ Cancel
@@ -17537,7 +17537,7 @@ exports[` should return selected protocol mapping type on click 1
onClose={[Function]}
ouiaSafe={true}
showClose={true}
- title="chooseAMapperType"
+ title="Choose a mapper type"
variant="medium"
>
should return selected protocol mapping type on click 1
class="pf-c-modal-box__title pf-c-modal-box__title"
id="pf-modal-part-3"
>
- chooseAMapperType
+ Choose a mapper type
should return selected protocol mapping type on click 1
class=""
data-pf-content="true"
>
- predefinedMappingDescription
+ Choose one of the predefined mappings from this table
should return selected protocol mapping type on click 1
ouiaId="OUIA-Generated-Modal-medium-3"
ouiaSafe={true}
showClose={true}
- title="chooseAMapperType"
+ title="Choose a mapper type"
variant="medium"
>
@@ -18109,13 +18109,13 @@ exports[` should return selected protocol mapping type on click 1
- chooseAMapperType
+ Choose a mapper type
@@ -18136,18 +18136,18 @@ exports[` should return selected protocol mapping type on click 1
className=""
data-pf-content={true}
>
- predefinedMappingDescription
+ Choose one of the predefined mappings from this table
{
const { t } = useTranslation("client-scopes");
- const httpClient = useContext(HttpClientContext)!;
- const { realm } = useContext(RealmContext);
+ const adminClient = useAdminClient();
const { addAlert } = useAlerts();
const [filteredData, setFilteredData] = useState<
@@ -56,7 +49,7 @@ export const MapperList = ({ clientScope, refresh }: MapperListProps) => {
>();
const [mapperAction, setMapperAction] = useState(false);
const mapperList = clientScope.protocolMappers!;
- const mapperTypes = useServerInfo().protocolMapperTypes[
+ const mapperTypes = useServerInfo().protocolMapperTypes![
clientScope.protocol!
];
@@ -67,9 +60,9 @@ export const MapperList = ({ clientScope, refresh }: MapperListProps) => {
mappers: ProtocolMapperTypeRepresentation | ProtocolMapperRepresentation[]
) => {
try {
- await httpClient.doPost(
- `/admin/realms/${realm}/client-scopes/${clientScope.id}/protocol-mappers/add-models`,
- mappers
+ await adminClient.clientScopes.addMultipleProtocolMappers(
+ { id: clientScope.id! },
+ mappers as ProtocolMapperRepresentation[]
);
refresh();
addAlert(t("mappingCreatedSuccess"), AlertVariant.success);
@@ -83,7 +76,7 @@ export const MapperList = ({ clientScope, refresh }: MapperListProps) => {
<>
{
>
{
title: t("common:delete"),
onClick: async (_, rowId) => {
try {
- await httpClient.doDelete(
- `/admin/realms/${realm}/client-scopes/${clientScope.id}/protocol-mappers/models/${data[rowId].mapper.id}`
- );
+ await adminClient.clientScopes.delProtocolMapper({
+ id: clientScope.id!,
+ mapperId: data[rowId].mapper.id!,
+ });
refresh();
addAlert(t("mappingDeletedSuccess"), AlertVariant.success);
} catch (error) {
diff --git a/src/client-scopes/details/MappingDetails.tsx b/src/client-scopes/details/MappingDetails.tsx
index be275b6a9f..aa7e5a86eb 100644
--- a/src/client-scopes/details/MappingDetails.tsx
+++ b/src/client-scopes/details/MappingDetails.tsx
@@ -1,4 +1,4 @@
-import React, { useContext, useEffect, useState } from "react";
+import React, { useEffect, useState } from "react";
import { useHistory, useParams } from "react-router-dom";
import { useTranslation } from "react-i18next";
import {
@@ -19,23 +19,21 @@ import {
Switch,
TextInput,
} from "@patternfly/react-core";
+import { ConfigPropertyRepresentation } from "keycloak-admin/lib/defs/configPropertyRepresentation";
import { ViewHeader } from "../../components/view-header/ViewHeader";
-import { HttpClientContext } from "../../context/http-service/HttpClientContext";
-import { RealmContext } from "../../context/realm-context/RealmContext";
+import { useAdminClient } from "../../context/auth/AdminClient";
import { ProtocolMapperRepresentation } from "../models/client-scope";
import { Controller, useForm } from "react-hook-form";
import { useConfirmDialog } from "../../components/confirm-dialog/ConfirmDialog";
import { useAlerts } from "../../components/alert/Alerts";
import { HelpItem } from "../../components/help-enabler/HelpItem";
import { useServerInfo } from "../../context/server-info/ServerInfoProvider";
-import { ConfigPropertyRepresentation } from "../../context/server-info/server-info";
import { convertFormValuesToObject, convertToFormValues } from "../../util";
export const MappingDetails = () => {
const { t } = useTranslation("client-scopes");
- const httpClient = useContext(HttpClientContext)!;
- const { realm } = useContext(RealmContext);
+ const adminClient = useAdminClient();
const { addAlert } = useAlerts();
const { scopeId, id } = useParams<{ scopeId: string; id: string }>();
@@ -47,28 +45,27 @@ export const MappingDetails = () => {
>();
const serverInfo = useServerInfo();
- const url = `/admin/realms/${realm}/client-scopes/${scopeId}/protocol-mappers/models/${id}`;
const history = useHistory();
useEffect(() => {
(async () => {
- const response = await httpClient.doGet(
- url
- );
- if (response.data) {
- Object.entries(response.data).map((entry) => {
+ const data = await adminClient.clientScopes.findProtocolMapper({
+ id: scopeId,
+ mapperId: id,
+ });
+ if (data) {
+ Object.entries(data).map((entry) => {
if (entry[0] === "config") {
convertToFormValues(entry[1], "config", setValue);
}
setValue(entry[0], entry[1]);
});
}
- setMapping(response.data);
- const mapperTypes =
- serverInfo.protocolMapperTypes[response.data!.protocol!];
+ setMapping(data);
+ const mapperTypes = serverInfo.protocolMapperTypes![data!.protocol!];
const properties = mapperTypes.find(
- (type) => type.id === response.data!.protocolMapper
- )?.properties;
+ (type) => type.id === data.protocolMapper
+ )?.properties!;
setConfigProperties(properties);
})();
}, []);
@@ -78,9 +75,12 @@ export const MappingDetails = () => {
messageKey: "client-scopes:deleteMappingConfirm",
continueButtonLabel: "common:delete",
continueButtonVariant: ButtonVariant.danger,
- onConfirm: () => {
+ onConfirm: async () => {
try {
- httpClient.doDelete(url);
+ await adminClient.clientScopes.delClientScopeMappings(
+ { client: scopeId, id },
+ []
+ );
addAlert(t("mappingDeletedSuccess"), AlertVariant.success);
history.push(`/client-scopes/${scopeId}`);
} catch (error) {
@@ -93,7 +93,10 @@ export const MappingDetails = () => {
const config = convertFormValuesToObject(formMapping.config);
const map = { ...mapping, config };
try {
- await httpClient.doPut(url, map);
+ await adminClient.clientScopes.updateProtocolMapper(
+ { id: scopeId, mapperId: id },
+ map
+ );
addAlert(t("mappingUpdatedSuccess"), AlertVariant.success);
} catch (error) {
addAlert(t("mappingUpdatedError", { error }), AlertVariant.danger);
@@ -211,8 +214,8 @@ export const MappingDetails = () => {
>
{configProperties &&
configProperties
- .find((property) => property.name === "jsonType.label")
- ?.options.map((option) => (
+ .find((property) => property.name! === "jsonType.label")
+ ?.options!.map((option) => (
{
const [clientScope, setClientScope] = useState();
const [activeTab, setActiveTab] = useState(0);
- const httpClient = useContext(HttpClientContext)!;
- const { realm } = useContext(RealmContext);
+ const adminClient = useAdminClient();
const providers = useLoginProviders();
const { id } = useParams<{ id: string }>();
@@ -49,11 +47,9 @@ export const ClientScopeForm = () => {
const load = async () => {
if (id) {
- const response = await httpClient.doGet(
- `/admin/realms/${realm}/client-scopes/${id}`
- );
- if (response.data) {
- Object.entries(response.data).map((entry) => {
+ const data = await adminClient.clientScopes.findOne({ id });
+ if (data) {
+ Object.entries(data).map((entry) => {
if (entry[0] === "attributes") {
convertToFormValues(entry[1], "attributes", setValue);
}
@@ -61,7 +57,7 @@ export const ClientScopeForm = () => {
});
}
- setClientScope(response.data);
+ setClientScope(data);
}
};
@@ -75,11 +71,10 @@ export const ClientScopeForm = () => {
clientScopes.attributes!
);
- const url = `/admin/realms/${realm}/client-scopes/`;
if (id) {
- await httpClient.doPut(url + id, clientScopes);
+ await adminClient.clientScopes.update({ id }, clientScopes);
} else {
- await httpClient.doPost(url, clientScopes);
+ await adminClient.clientScopes.create(clientScopes);
}
addAlert(t((id ? "update" : "create") + "Success"), AlertVariant.success);
} catch (error) {
diff --git a/src/clients/ClientDetails.tsx b/src/clients/ClientDetails.tsx
index 36089e1144..07f313d735 100644
--- a/src/clients/ClientDetails.tsx
+++ b/src/clients/ClientDetails.tsx
@@ -1,4 +1,4 @@
-import React, { useContext, useEffect, useState } from "react";
+import React, { useEffect, useState } from "react";
import {
AlertVariant,
ButtonVariant,
@@ -11,16 +11,15 @@ import {
import { useTranslation } from "react-i18next";
import { Controller, useForm, useWatch } from "react-hook-form";
import { useParams } from "react-router-dom";
+import ClientRepresentation from "keycloak-admin/lib/defs/clientRepresentation";
import { ClientSettings } from "./ClientSettings";
import { useAlerts } from "../components/alert/Alerts";
import { useConfirmDialog } from "../components/confirm-dialog/ConfirmDialog";
import { useDownloadDialog } from "../components/download-dialog/DownloadDialog";
import { ViewHeader } from "../components/view-header/ViewHeader";
-import { HttpClientContext } from "../context/http-service/HttpClientContext";
-import { RealmContext } from "../context/realm-context/RealmContext";
+import { useAdminClient } from "../context/auth/AdminClient";
import { Credentials } from "./credentials/Credentials";
-import { ClientRepresentation } from "../realm/models/Realm";
import {
convertFormValuesToObject,
convertToFormValues,
@@ -33,8 +32,7 @@ import {
export const ClientDetails = () => {
const { t } = useTranslation("clients");
- const httpClient = useContext(HttpClientContext)!;
- const { realm } = useContext(RealmContext);
+ const adminClient = useAdminClient();
const { addAlert } = useAlerts();
const form = useForm();
@@ -47,16 +45,15 @@ export const ClientDetails = () => {
const [activeTab, setActiveTab] = useState(0);
const [name, setName] = useState("");
- const url = `/admin/realms/${realm}/clients/${id}`;
const [toggleDeleteDialog, DeleteConfirm] = useConfirmDialog({
titleKey: "clients:clientDeleteConfirmTitle",
messageKey: "clients:clientDeleteConfirm",
continueButtonLabel: "common:delete",
continueButtonVariant: ButtonVariant.danger,
- onConfirm: () => {
+ onConfirm: async () => {
try {
- httpClient.doDelete(`/admin/realms/${realm}/clients/${id}`);
+ await adminClient.clients.del({ id });
addAlert(t("clientDeletedSuccess"), AlertVariant.success);
} catch (error) {
addAlert(`${t("clientDeleteError")} ${error}`, AlertVariant.danger);
@@ -84,10 +81,10 @@ export const ClientDetails = () => {
useEffect(() => {
(async () => {
- const fetchedClient = await httpClient.doGet(url);
- if (fetchedClient.data) {
- setName(fetchedClient.data.clientId);
- setupForm(fetchedClient.data);
+ const fetchedClient = await adminClient.clients.findOne({ id });
+ if (fetchedClient) {
+ setName(fetchedClient.clientId!);
+ setupForm(fetchedClient);
}
})();
}, []);
@@ -105,7 +102,7 @@ export const ClientDetails = () => {
redirectUris,
attributes,
};
- await httpClient.doPut(url, client);
+ await adminClient.clients.update({ id }, client);
setupForm(client as ClientRepresentation);
addAlert(t("clientSaveSuccess"), AlertVariant.success);
} catch (error) {
diff --git a/src/clients/ClientList.tsx b/src/clients/ClientList.tsx
index f140c4a862..63c18112eb 100644
--- a/src/clients/ClientList.tsx
+++ b/src/clients/ClientList.tsx
@@ -1,4 +1,4 @@
-import React, { useContext } from "react";
+import React from "react";
import { useTranslation } from "react-i18next";
import { Link } from "react-router-dom";
import {
@@ -10,12 +10,11 @@ import {
IFormatterValueType,
} from "@patternfly/react-table";
import { Badge, AlertVariant } from "@patternfly/react-core";
+import ClientRepresentation from "keycloak-admin/lib/defs/clientRepresentation";
import { ExternalLink } from "../components/external-link/ExternalLink";
-import { HttpClientContext } from "../context/http-service/HttpClientContext";
import { useAlerts } from "../components/alert/Alerts";
-import { ClientRepresentation } from "./models/client-model";
-import { RealmContext } from "../context/realm-context/RealmContext";
+import { useAdminClient } from "../context/auth/AdminClient";
import { exportClient } from "../util";
type ClientListProps = {
@@ -33,8 +32,7 @@ const columns: (keyof ClientRepresentation)[] = [
export const ClientList = ({ baseUrl, clients, refresh }: ClientListProps) => {
const { t } = useTranslation("clients");
- const httpClient = useContext(HttpClientContext)!;
- const { realm } = useContext(RealmContext);
+ const adminClient = useAdminClient();
const { addAlert } = useAlerts();
const emptyFormatter = (): IFormatter => (data?: IFormatterValueType) => {
@@ -108,9 +106,9 @@ export const ClientList = ({ baseUrl, clients, refresh }: ClientListProps) => {
title: t("common:delete"),
onClick: async (_, rowId) => {
try {
- await httpClient.doDelete(
- `/admin/realms/${realm}/clients/${data[rowId].client.id}`
- );
+ await adminClient.clients.del({
+ id: data[rowId].client.id!,
+ });
refresh();
addAlert(t("clientDeletedSuccess"), AlertVariant.success);
} catch (error) {
diff --git a/src/clients/ClientsSection.tsx b/src/clients/ClientsSection.tsx
index eb87751cfd..babd090cdf 100644
--- a/src/clients/ClientsSection.tsx
+++ b/src/clients/ClientsSection.tsx
@@ -1,15 +1,13 @@
-import React, { useState, useContext, useEffect } from "react";
+import React, { useState, useEffect } from "react";
import { useHistory } from "react-router-dom";
import { useTranslation } from "react-i18next";
import { Button, PageSection, Spinner } from "@patternfly/react-core";
+import ClientRepresentation from "keycloak-admin/lib/defs/clientRepresentation";
import { ClientList } from "./ClientList";
-import { HttpClientContext } from "../context/http-service/HttpClientContext";
-import { KeycloakContext } from "../context/auth/KeycloakContext";
-import { ClientRepresentation } from "./models/client-model";
-import { RealmContext } from "../context/realm-context/RealmContext";
import { ViewHeader } from "../components/view-header/ViewHeader";
import { PaginatingTableToolbar } from "../components/table-toolbar/PaginatingTableToolbar";
+import { useAdminClient } from "../context/auth/AdminClient";
export const ClientsSection = () => {
const { t } = useTranslation("clients");
@@ -18,10 +16,8 @@ export const ClientsSection = () => {
const [max, setMax] = useState(10);
const [first, setFirst] = useState(0);
const [search, setSearch] = useState("");
+ const adminClient = useAdminClient();
const [clients, setClients] = useState();
- const httpClient = useContext(HttpClientContext)!;
- const keycloak = useContext(KeycloakContext);
- const { realm } = useContext(RealmContext);
const loader = async () => {
const params: { [name: string]: string | number } = { first, max };
@@ -29,11 +25,8 @@ export const ClientsSection = () => {
params.clientId = search;
params.search = "true";
}
- const result = await httpClient.doGet(
- `/admin/realms/${realm}/clients`,
- { params: params }
- );
- setClients(result.data);
+ const result = await adminClient.clients.find({ ...params });
+ setClients(result);
};
useEffect(() => {
@@ -84,7 +77,7 @@ export const ClientsSection = () => {
)}
diff --git a/src/clients/__tests__/ClientList.test.tsx b/src/clients/__tests__/ClientList.test.tsx
index be79ab3a2c..c7ab1696bf 100644
--- a/src/clients/__tests__/ClientList.test.tsx
+++ b/src/clients/__tests__/ClientList.test.tsx
@@ -1,18 +1,28 @@
import React from "react";
import { MemoryRouter } from "react-router-dom";
import { render } from "@testing-library/react";
+import KeycloakAdminClient from "keycloak-admin";
import clientMock from "./mock-clients.json";
import { ClientList } from "../ClientList";
+import { AdminClient } from "../../context/auth/AdminClient";
test("renders ClientList", () => {
const container = render(
- {}}
- />
+ {},
+ } as unknown) as KeycloakAdminClient
+ }
+ >
+ {}}
+ />
+
);
expect(container).toMatchSnapshot();
diff --git a/src/clients/add/NewClientForm.tsx b/src/clients/add/NewClientForm.tsx
index ac3c46f8d8..3f5a8a3abe 100644
--- a/src/clients/add/NewClientForm.tsx
+++ b/src/clients/add/NewClientForm.tsx
@@ -1,4 +1,4 @@
-import React, { useState, useContext } from "react";
+import React, { useState } from "react";
import { useHistory } from "react-router-dom";
import {
PageSection,
@@ -11,18 +11,16 @@ import {
import { useTranslation } from "react-i18next";
import { useForm } from "react-hook-form";
-import { HttpClientContext } from "../../context/http-service/HttpClientContext";
import { GeneralSettings } from "./GeneralSettings";
import { CapabilityConfig } from "./CapabilityConfig";
-import { ClientRepresentation } from "../models/client-model";
import { useAlerts } from "../../components/alert/Alerts";
-import { RealmContext } from "../../context/realm-context/RealmContext";
import { ViewHeader } from "../../components/view-header/ViewHeader";
+import ClientRepresentation from "keycloak-admin/lib/defs/clientRepresentation";
+import { useAdminClient } from "../../context/auth/AdminClient";
export const NewClientForm = () => {
const { t } = useTranslation("clients");
- const httpClient = useContext(HttpClientContext)!;
- const { realm } = useContext(RealmContext);
+ const adminClient = useAdminClient();
const history = useHistory();
const [client, setClient] = useState({
@@ -42,7 +40,7 @@ export const NewClientForm = () => {
const save = async () => {
try {
- await httpClient.doPost(`/admin/realms/${realm}/clients`, client);
+ await adminClient.clients.create({ ...client });
addAlert(t("createSuccess"), AlertVariant.success);
} catch (error) {
addAlert(t("createError", { error }), AlertVariant.danger);
diff --git a/src/clients/credentials/Credentials.tsx b/src/clients/credentials/Credentials.tsx
index 5f2aeab352..ca9f8e6640 100644
--- a/src/clients/credentials/Credentials.tsx
+++ b/src/clients/credentials/Credentials.tsx
@@ -14,15 +14,15 @@ import {
Split,
SplitItem,
} from "@patternfly/react-core";
-import React, { useContext, useEffect, useState } from "react";
+import CredentialRepresentation from "keycloak-admin/lib/defs/credentialRepresentation";
+import React, { useEffect, useState } from "react";
import { Controller, UseFormMethods, useWatch } from "react-hook-form";
import { useTranslation } from "react-i18next";
import { useAlerts } from "../../components/alert/Alerts";
import { useConfirmDialog } from "../../components/confirm-dialog/ConfirmDialog";
import { HelpItem } from "../../components/help-enabler/HelpItem";
-import { HttpClientContext } from "../../context/http-service/HttpClientContext";
-import { RealmContext } from "../../context/realm-context/RealmContext";
+import { useAdminClient } from "../../context/auth/AdminClient";
import { ClientSecret } from "./ClientSecret";
import { SignedJWT } from "./SignedJWT";
import { X509 } from "./X509";
@@ -49,8 +49,7 @@ export type CredentialsProps = {
export const Credentials = ({ clientId, form, save }: CredentialsProps) => {
const { t } = useTranslation("clients");
- const httpClient = useContext(HttpClientContext)!;
- const { realm } = useContext(RealmContext);
+ const adminClient = useAdminClient();
const { addAlert } = useAlerts();
const clientAuthenticatorType = useWatch({
control: form.control,
@@ -66,36 +65,37 @@ export const Credentials = ({ clientId, form, save }: CredentialsProps) => {
useEffect(() => {
(async () => {
- const response = await httpClient.doGet(
- `/admin/realms/${realm}/authentication/client-authenticator-providers`
+ const providers = await adminClient.authenticationManagement.getClientAuthenticatorProviders(
+ { id: clientId }
);
- setProviders(response.data!);
+ setProviders(providers);
- const secretResponse = await httpClient.doGet(
- `/admin/realms/${realm}/clients/${clientId}/client-secret`
- );
- setSecret(secretResponse.data!.value);
+ const secret = await adminClient.clients.getClientSecret({
+ id: clientId,
+ });
+ setSecret(secret.value!);
})();
}, []);
async function regenerate(
- endpoint: string,
+ call: (clientId: string) => Promise,
message: string
): Promise {
try {
- const response = await httpClient.doPost(
- `/admin/realms/${realm}/clients/${clientId}/${endpoint}`,
- { client: clientId, realm }
- );
+ const data = await call(clientId);
addAlert(t(`${message}Success`), AlertVariant.success);
- return response.data!;
+ return data;
} catch (error) {
addAlert(t(`${message}Error`, { error }), AlertVariant.danger);
}
}
const regenerateClientSecret = async () => {
- const secret = await regenerate("client-secret", "clientSecret");
+ const secret = await regenerate(
+ (clientId) =>
+ adminClient.clients.generateNewClientSecret({ id: clientId }),
+ "clientSecret"
+ );
setSecret(secret?.value || "");
};
@@ -109,7 +109,8 @@ export const Credentials = ({ clientId, form, save }: CredentialsProps) => {
const regenerateAccessToken = async () => {
const accessToken = await regenerate(
- "registration-access-token",
+ (clientId) =>
+ adminClient.clients.generateRegistrationAccessToken({ id: clientId }),
"accessToken"
);
setAccessToken(accessToken?.registrationAccessToken || "");
diff --git a/src/clients/credentials/SignedJWT.tsx b/src/clients/credentials/SignedJWT.tsx
index 4b766ba640..00942d64ad 100644
--- a/src/clients/credentials/SignedJWT.tsx
+++ b/src/clients/credentials/SignedJWT.tsx
@@ -18,7 +18,7 @@ export type SignedJWTProps = {
export const SignedJWT = ({ form }: SignedJWTProps) => {
const providers = sortProviders(
- useServerInfo().providers.clientSignature.providers
+ useServerInfo().providers!.clientSignature.providers
);
const { t } = useTranslation("clients");
diff --git a/src/clients/import/ImportForm.tsx b/src/clients/import/ImportForm.tsx
index 85a1d78a0f..7c262e0460 100644
--- a/src/clients/import/ImportForm.tsx
+++ b/src/clients/import/ImportForm.tsx
@@ -1,4 +1,4 @@
-import React, { useContext } from "react";
+import React from "react";
import {
PageSection,
Form,
@@ -11,18 +11,16 @@ import {
import { useForm } from "react-hook-form";
import { useTranslation } from "react-i18next";
-import { ClientRepresentation } from "../models/client-model";
import { ClientDescription } from "../ClientDescription";
-import { HttpClientContext } from "../../context/http-service/HttpClientContext";
import { JsonFileUpload } from "../../components/json-file-upload/JsonFileUpload";
import { useAlerts } from "../../components/alert/Alerts";
-import { RealmContext } from "../../context/realm-context/RealmContext";
import { ViewHeader } from "../../components/view-header/ViewHeader";
+import ClientRepresentation from "keycloak-admin/lib/defs/clientRepresentation";
+import { useAdminClient } from "../../context/auth/AdminClient";
export const ImportForm = () => {
const { t } = useTranslation("clients");
- const httpClient = useContext(HttpClientContext)!;
- const { realm } = useContext(RealmContext);
+ const adminClient = useAdminClient();
const form = useForm();
const { register, handleSubmit, setValue } = form;
@@ -44,7 +42,7 @@ export const ImportForm = () => {
const save = async (client: ClientRepresentation) => {
try {
- await httpClient.doPost(`/admin/realms/${realm}/clients`, client);
+ await adminClient.clients.create({ ...client });
addAlert(t("clientImportSuccess"), AlertVariant.success);
} catch (error) {
addAlert(`${t("clientImportError")} '${error}'`, AlertVariant.danger);
diff --git a/src/components/download-dialog/DownloadDialog.tsx b/src/components/download-dialog/DownloadDialog.tsx
index 0e22a9e49c..e4ee750ff2 100644
--- a/src/components/download-dialog/DownloadDialog.tsx
+++ b/src/components/download-dialog/DownloadDialog.tsx
@@ -1,4 +1,4 @@
-import React, { useContext, useState, useEffect, ReactElement } from "react";
+import React, { useState, useEffect, ReactElement, useContext } from "react";
import {
Alert,
AlertVariant,
@@ -15,11 +15,10 @@ import {
import FileSaver from "file-saver";
import { ConfirmDialogModal } from "../confirm-dialog/ConfirmDialog";
-import { HttpClientContext } from "../../context/http-service/HttpClientContext";
-import { RealmContext } from "../../context/realm-context/RealmContext";
import { HelpItem } from "../help-enabler/HelpItem";
import { useTranslation } from "react-i18next";
import { useServerInfo } from "../../context/server-info/ServerInfoProvider";
+import { useAdminClient } from "../../context/auth/AdminClient";
import { HelpContext } from "../help-enabler/HelpHeader";
export type DownloadDialogProps = {
@@ -53,13 +52,12 @@ export const DownloadDialog = ({
toggleDialog,
protocol = "openid-connect",
}: DownloadDialogModalProps) => {
- const httpClient = useContext(HttpClientContext)!;
- const { realm } = useContext(RealmContext);
+ const adminClient = useAdminClient();
const { t } = useTranslation("common");
const { enabled } = useContext(HelpContext);
const serverInfo = useServerInfo();
- const configFormats = serverInfo.clientInstallations[protocol];
+ const configFormats = serverInfo.clientInstallations![protocol];
const [selected, setSelected] = useState(
configFormats[configFormats.length - 1].id
);
@@ -69,11 +67,16 @@ export const DownloadDialog = ({
useEffect(() => {
let isMounted = true;
(async () => {
- const response = await httpClient.doGet(
- `/admin/realms/${realm}/clients/${id}/installation/providers/${selected}`
- );
+ const snippet = await adminClient.clients.getInstallationProviders({
+ id,
+ providerId: selected,
+ });
if (isMounted) {
- setSnippet(await response.text());
+ if (typeof snippet === "string") {
+ setSnippet(snippet);
+ } else {
+ setSnippet(JSON.stringify(snippet, undefined, 3));
+ }
}
})();
return () => {
diff --git a/src/components/form-access/FormAccess.tsx b/src/components/form-access/FormAccess.tsx
index 3f143df292..5b1b000cab 100644
--- a/src/components/form-access/FormAccess.tsx
+++ b/src/components/form-access/FormAccess.tsx
@@ -14,9 +14,9 @@ import {
GridItem,
TextArea,
} from "@patternfly/react-core";
+import { AccessType } from "keycloak-admin/lib/defs/whoAmIRepresentation";
import { useAccess } from "../../context/access/Access";
-import { AccessType } from "../../context/whoami/who-am-i-model";
export type FormAccessProps = FormProps & {
/**
diff --git a/src/components/realm-selector/RealmSelector.tsx b/src/components/realm-selector/RealmSelector.tsx
index 644e65969e..f0ca95a988 100644
--- a/src/components/realm-selector/RealmSelector.tsx
+++ b/src/components/realm-selector/RealmSelector.tsx
@@ -15,7 +15,7 @@ import {
} from "@patternfly/react-core";
import { CheckIcon } from "@patternfly/react-icons";
-import { RealmRepresentation } from "../../realm/models/Realm";
+import RealmRepresentation from "keycloak-admin/lib/defs/realmRepresentation";
import { RealmContext } from "../../context/realm-context/RealmContext";
import { WhoAmIContext } from "../../context/whoami/WhoAmI";
@@ -60,7 +60,7 @@ export const RealmSelector = ({ realmList }: RealmSelectorProps) => {
search === ""
? realmList
: realmList.filter(
- (r) => r.realm.toLowerCase().indexOf(search.toLowerCase()) !== -1
+ (r) => r.realm!.toLowerCase().indexOf(search.toLowerCase()) !== -1
);
setFilteredItems(filtered || []);
};
@@ -73,11 +73,11 @@ export const RealmSelector = ({ realmList }: RealmSelectorProps) => {
{
- setRealm(r.realm);
+ setRealm(r.realm!);
setOpen(!open);
}}
>
-
+
));
@@ -114,7 +114,7 @@ export const RealmSelector = ({ realmList }: RealmSelectorProps) => {
>
{filteredItems.map((item) => (
-
+
))}
diff --git a/src/context/access/Access.tsx b/src/context/access/Access.tsx
index 0688b2cbd5..62df305bff 100644
--- a/src/context/access/Access.tsx
+++ b/src/context/access/Access.tsx
@@ -1,8 +1,8 @@
import React, { createContext, useContext } from "react";
+import { AccessType } from "keycloak-admin/lib/defs/whoAmIRepresentation";
import { RealmContext } from "../../context/realm-context/RealmContext";
import { WhoAmIContext } from "../../context/whoami/WhoAmI";
-import { AccessType } from "../../context/whoami/who-am-i-model";
type AccessContextProps = {
hasAccess: (...types: AccessType[]) => boolean;
diff --git a/src/context/auth/AdminClient.tsx b/src/context/auth/AdminClient.tsx
new file mode 100644
index 0000000000..839cfe05fb
--- /dev/null
+++ b/src/context/auth/AdminClient.tsx
@@ -0,0 +1,18 @@
+import { createContext, useContext } from "react";
+import KeycloakAdminClient from "keycloak-admin";
+import { RealmContext } from "../realm-context/RealmContext";
+
+export const AdminClient = createContext(
+ undefined
+);
+
+export const useAdminClient = () => {
+ const adminClient = useContext(AdminClient)!;
+ const { realm } = useContext(RealmContext);
+
+ adminClient.setConfig({
+ realmName: realm,
+ });
+
+ return adminClient;
+};
diff --git a/src/context/auth/KeycloakContext.tsx b/src/context/auth/KeycloakContext.tsx
deleted file mode 100644
index 8a426ca73f..0000000000
--- a/src/context/auth/KeycloakContext.tsx
+++ /dev/null
@@ -1,6 +0,0 @@
-import * as React from "react";
-import { KeycloakService } from "./keycloak.service";
-
-export const KeycloakContext = React.createContext(
- undefined
-);
diff --git a/src/context/auth/keycloak.service.ts b/src/context/auth/keycloak.service.ts
deleted file mode 100644
index 7bcf8fd5b6..0000000000
--- a/src/context/auth/keycloak.service.ts
+++ /dev/null
@@ -1,84 +0,0 @@
-import { KeycloakLoginOptions } from "keycloak-js";
-import { useTranslation } from "react-i18next";
-
-export type KeycloakClient = Keycloak.KeycloakInstance;
-
-type Token = {
- given_name: string;
- family_name: string;
- preferred_username: string;
-};
-
-export class KeycloakService {
- private keycloakAuth: KeycloakClient;
-
- public constructor(keycloak: KeycloakClient) {
- this.keycloakAuth = keycloak;
- }
-
- public authenticated(): boolean {
- return this.keycloakAuth.authenticated
- ? this.keycloakAuth.authenticated
- : false;
- }
-
- public login(options?: KeycloakLoginOptions): void {
- this.keycloakAuth.login(options);
- }
-
- public logout(redirectUri: string = ""): void {
- this.keycloakAuth.logout({ redirectUri: redirectUri });
- }
-
- public account(): void {
- this.keycloakAuth.accountManagement();
- }
-
- public authServerUrl(): string | undefined {
- const authServerUrl = this.keycloakAuth.authServerUrl;
- return authServerUrl!.charAt(authServerUrl!.length - 1) === "/"
- ? authServerUrl
- : authServerUrl + "/";
- }
-
- public realm(): string | undefined {
- return this.keycloakAuth.realm;
- }
-
- public get loggedInUser(): string {
- const { t } = useTranslation();
- return this.loggedInUserName(t, this.keycloakAuth.tokenParsed as Token);
- }
-
- private loggedInUserName = (t: Function, tokenParsed: Token) => {
- let userName = t("unknownUser");
- if (tokenParsed) {
- const givenName = tokenParsed.given_name;
- const familyName = tokenParsed.family_name;
- const preferredUsername = tokenParsed.preferred_username;
- if (givenName && familyName) {
- userName = t("fullName", { givenName, familyName });
- } else {
- userName = givenName || familyName || preferredUsername || userName;
- }
- }
- return userName;
- };
-
- public getToken(): Promise {
- return new Promise((resolve, reject) => {
- if (this.keycloakAuth.token) {
- this.keycloakAuth
- .updateToken(5)
- .then(() => {
- resolve(this.keycloakAuth.token as string);
- })
- .catch(() => {
- reject("Failed to refresh token");
- });
- } else {
- reject("Not logged in");
- }
- });
- }
-}
diff --git a/src/context/auth/keycloak.ts b/src/context/auth/keycloak.ts
index 59d5785927..b8d0896959 100644
--- a/src/context/auth/keycloak.ts
+++ b/src/context/auth/keycloak.ts
@@ -1,17 +1,24 @@
-import Keycloak, { KeycloakInstance } from "keycloak-js";
+import KcAdminClient from "keycloak-admin";
-const realm =
- new URLSearchParams(window.location.search).get("realm") || "master";
+export default async function (): Promise {
+ const realm =
+ new URLSearchParams(window.location.search).get("realm") || "master";
-const keycloak: KeycloakInstance = Keycloak({
- url: "http://localhost:8180/auth/",
- realm: realm,
- clientId: "security-admin-console-v2",
-});
+ const kcAdminClient = new KcAdminClient();
-export default async function (): Promise {
- await keycloak.init({ onLoad: "check-sso", pkceMethod: "S256" }).catch(() => {
+ try {
+ await kcAdminClient.init(
+ { onLoad: "check-sso", pkceMethod: "S256" },
+ {
+ url: "http://localhost:8180/auth/",
+ realm: realm,
+ clientId: "security-admin-console-v2",
+ }
+ );
+ kcAdminClient.baseUrl = "";
+ } catch (error) {
alert("failed to initialize keycloak");
- });
- return keycloak;
+ }
+
+ return kcAdminClient;
}
diff --git a/src/context/http-service/HttpClientContext.tsx b/src/context/http-service/HttpClientContext.tsx
deleted file mode 100644
index 79389e6fc8..0000000000
--- a/src/context/http-service/HttpClientContext.tsx
+++ /dev/null
@@ -1,6 +0,0 @@
-import { createContext } from "react";
-import { HttpClient } from "./http-client";
-
-export const HttpClientContext = createContext(
- undefined
-);
diff --git a/src/context/http-service/http-client.ts b/src/context/http-service/http-client.ts
deleted file mode 100644
index fe21d628a1..0000000000
--- a/src/context/http-service/http-client.ts
+++ /dev/null
@@ -1,150 +0,0 @@
-import { KeycloakService } from "../auth/keycloak.service";
-
-type ConfigResolve = (config: RequestInit) => void;
-
-export interface HttpResponse extends Response {
- data?: T;
-}
-
-export interface RequestInitWithParams extends RequestInit {
- params?: { [name: string]: string | number };
-}
-
-export class AccountServiceError extends Error {
- constructor(message: string) {
- super(message);
- }
-}
-
-/**
- *
- * @author Stan Silvert ssilvert@redhat.com (C) 2018 Red Hat Inc.
- */
-export class HttpClient {
- private kcSvc: KeycloakService;
-
- public constructor(keycloakService: KeycloakService) {
- this.kcSvc = keycloakService;
- }
-
- public async doGet(
- endpoint: string,
- config?: RequestInitWithParams
- ): Promise> {
- return this.doRequest(endpoint, { ...config, method: "get" });
- }
-
- public async doDelete(
- endpoint: string,
- config?: RequestInitWithParams
- ): Promise> {
- return this.doRequest(endpoint, { ...config, method: "delete" });
- }
-
- public async doPost(
- endpoint: string,
- body: string | {},
- config?: RequestInitWithParams
- ): Promise> {
- return this.doRequest(endpoint, {
- ...config,
- body: JSON.stringify(body),
- method: "post",
- });
- }
-
- public async doPut(
- endpoint: string,
- body: string | {},
- config?: RequestInitWithParams
- ): Promise> {
- return this.doRequest(endpoint, {
- ...config,
- body: JSON.stringify(body),
- method: "put",
- });
- }
-
- public async doRequest(
- endpoint: string,
- config?: RequestInitWithParams
- ): Promise> {
- const response: HttpResponse = await fetch(
- this.makeUrl(endpoint, config).toString(),
- await this.makeConfig(config)
- );
-
- const contentType = response.headers.get("content-type");
- if (contentType && contentType.indexOf("application/json") !== -1) {
- try {
- response.data = await response.json();
- } catch (e) {
- console.warn(e);
- }
- }
-
- if (!response.ok) {
- this.handleError(response);
- }
-
- return response;
- }
-
- private handleError(response: HttpResponse): void {
- if (response != null && response.status === 401) {
- // session timed out?
- this.kcSvc.login();
- }
-
- if (response != null && response.data != null) {
- throw new AccountServiceError((response.data as any).errorMessage);
- } else {
- throw new AccountServiceError(response.statusText);
- }
- }
-
- private makeUrl(url: string, config?: RequestInitWithParams): string {
- const searchParams = new URLSearchParams();
- // add request params
- if (config && {}.hasOwnProperty.call(config, "params")) {
- const params: { [name: string]: string } = (config.params as {}) || {};
- Object.keys(params).forEach((key) =>
- searchParams.append(key, params[key])
- );
- }
-
- return url + "?" + searchParams.toString();
- }
-
- private makeConfig(config: RequestInit = {}): Promise {
- return new Promise((resolve: ConfigResolve) => {
- this.kcSvc
- .getToken()
- .then((token: string) => {
- resolve({
- ...config,
- headers: {
- "Content-Type": "application/json",
- ...config.headers,
- Authorization: "Bearer " + token,
- },
- });
- })
- .catch(() => {
- this.kcSvc.login();
- });
- });
- }
-}
-
-window.addEventListener(
- "unhandledrejection",
- (event: PromiseRejectionEvent) => {
- event.promise.catch((error) => {
- if (error instanceof AccountServiceError) {
- // We already handled the error. Ignore unhandled rejection.
- event.preventDefault();
- }
- });
- }
-);
diff --git a/src/context/server-info/ServerInfoProvider.tsx b/src/context/server-info/ServerInfoProvider.tsx
index a20e5fa6ba..35c9810950 100644
--- a/src/context/server-info/ServerInfoProvider.tsx
+++ b/src/context/server-info/ServerInfoProvider.tsx
@@ -1,8 +1,9 @@
import React, { createContext, ReactNode, useContext } from "react";
-import { ServerInfoRepresentation } from "./server-info";
-import { HttpClientContext } from "../http-service/HttpClientContext";
+import { ServerInfoRepresentation } from "keycloak-admin/lib/defs/serverInfoRepesentation";
+
import { sortProviders } from "../../util";
import { DataLoader } from "../../components/data-loader/DataLoader";
+import { useAdminClient } from "../auth/AdminClient";
export const ServerInfoContext = createContext(
{} as ServerInfoRepresentation
@@ -11,16 +12,13 @@ export const ServerInfoContext = createContext(
export const useServerInfo = () => useContext(ServerInfoContext);
export const useLoginProviders = () => {
- return sortProviders(useServerInfo().providers["login-protocol"].providers);
+ return sortProviders(useServerInfo().providers!["login-protocol"].providers);
};
export const ServerInfoProvider = ({ children }: { children: ReactNode }) => {
- const httpClient = useContext(HttpClientContext)!;
+ const adminClient = useAdminClient();
const loader = async () => {
- const response = await httpClient.doGet(
- "/admin/serverinfo"
- );
- return response.data!;
+ return await adminClient.serverInfo.find();
};
return (
diff --git a/src/context/server-info/server-info.ts b/src/context/server-info/server-info.ts
deleted file mode 100644
index 4c88d54031..0000000000
--- a/src/context/server-info/server-info.ts
+++ /dev/null
@@ -1,123 +0,0 @@
-export interface ServerInfoRepresentation {
- systemInfo: SystemInfoRepresentation;
- memoryInfo: MemoryInfoRepresentation;
- profileInfo: ProfileInfoRepresentation;
- themes: { [index: string]: ThemeInfoRepresentation[] };
- socialProviders: { [index: string]: string }[];
- identityProviders: { [index: string]: string }[];
- clientImporters: { [index: string]: string }[];
- providers: { [index: string]: SpiInfoRepresentation };
- protocolMapperTypes: { [index: string]: ProtocolMapperTypeRepresentation[] };
- builtinProtocolMappers: { [index: string]: ProtocolMapperRepresentation[] };
- clientInstallations: { [index: string]: ClientInstallationRepresentation[] };
- componentTypes: { [index: string]: ComponentTypeRepresentation[] };
- passwordPolicies: PasswordPolicyTypeRepresentation[];
- enums: { [index: string]: string[] };
-}
-
-export interface SystemInfoRepresentation {
- version: string;
- serverTime: string;
- uptime: string;
- uptimeMillis: number;
- javaVersion: string;
- javaVendor: string;
- javaVm: string;
- javaVmVersion: string;
- javaRuntime: string;
- javaHome: string;
- osName: string;
- osArchitecture: string;
- osVersion: string;
- fileEncoding: string;
- userName: string;
- userDir: string;
- userTimezone: string;
- userLocale: string;
-}
-
-export interface MemoryInfoRepresentation {
- total: number;
- totalFormated: string;
- used: number;
- usedFormated: string;
- free: number;
- freePercentage: number;
- freeFormated: string;
-}
-
-export interface ProfileInfoRepresentation {
- name: string;
- disabledFeatures: string[];
- previewFeatures: string[];
- experimentalFeatures: string[];
-}
-
-export interface ThemeInfoRepresentation {
- name: string;
- locales: string[];
-}
-
-export interface SpiInfoRepresentation {
- internal: boolean;
- providers: { [index: string]: ProviderRepresentation };
-}
-
-export interface ProtocolMapperTypeRepresentation {
- id: string;
- name: string;
- category: string;
- helpText: string;
- priority: number;
- properties: ConfigPropertyRepresentation[];
-}
-
-export interface ProtocolMapperRepresentation {
- id: string;
- name: string;
- protocol: string;
- protocolMapper: string;
- consentRequired: boolean;
- consentText: string;
- config: { [index: string]: string };
-}
-
-export interface ClientInstallationRepresentation {
- id: string;
- protocol: string;
- downloadOnly: boolean;
- displayType: string;
- helpText: string;
- filename: string;
- mediaType: string;
-}
-
-export interface ComponentTypeRepresentation {
- id: string;
- helpText: string;
- properties: ConfigPropertyRepresentation[];
- metadata: { [index: string]: any };
-}
-
-export interface PasswordPolicyTypeRepresentation {
- id: string;
- displayName: string;
- configType: string;
- defaultValue: string;
- multipleSupported: boolean;
-}
-
-export interface ProviderRepresentation {
- order: number;
- operationalInfo: { [index: string]: string };
-}
-
-export interface ConfigPropertyRepresentation {
- name: string;
- label: string;
- helpText: string;
- type: string;
- defaultValue: any;
- options: string[];
- secret: boolean;
-}
diff --git a/src/context/whoami/WhoAmI.tsx b/src/context/whoami/WhoAmI.tsx
index b742cb06e6..74b4ae6245 100644
--- a/src/context/whoami/WhoAmI.tsx
+++ b/src/context/whoami/WhoAmI.tsx
@@ -1,11 +1,11 @@
-import React, { useContext } from "react";
+import React from "react";
import i18n from "../../i18n";
-import WhoAmIRepresentation, { AccessType } from "./who-am-i-model";
-
-import { HttpClientContext } from "../http-service/HttpClientContext";
-import { KeycloakContext } from "../auth/KeycloakContext";
import { DataLoader } from "../../components/data-loader/DataLoader";
+import { useAdminClient } from "../auth/AdminClient";
+import WhoAmIRepresentation, {
+ AccessType,
+} from "keycloak-admin/lib/defs/whoAmIRepresentation";
export class WhoAmI {
constructor(
@@ -53,24 +53,19 @@ export const WhoAmIContext = React.createContext(new WhoAmI());
type WhoAmIProviderProps = { children: React.ReactNode };
export const WhoAmIContextProvider = ({ children }: WhoAmIProviderProps) => {
- const httpClient = useContext(HttpClientContext)!;
- const keycloak = useContext(KeycloakContext);
+ const adminClient = useAdminClient();
const whoAmILoader = async () => {
- if (keycloak === undefined) return undefined;
+ if (adminClient.keycloak === undefined) return undefined;
- const realm = keycloak.realm();
-
- return await httpClient
- .doGet(`/admin/${realm}/console/whoami/`)
- .then((r) => r.data as WhoAmIRepresentation);
+ return await adminClient.whoAmI.find();
};
return (
{(whoamirep) => (
{children}
diff --git a/src/context/whoami/who-am-i-model.ts b/src/context/whoami/who-am-i-model.ts
deleted file mode 100644
index 1086f93a82..0000000000
--- a/src/context/whoami/who-am-i-model.ts
+++ /dev/null
@@ -1,29 +0,0 @@
-export type AccessType =
- | "view-realm"
- | "view-identity-providers"
- | "manage-identity-providers"
- | "impersonation"
- | "create-client"
- | "manage-users"
- | "query-realms"
- | "view-authorization"
- | "query-clients"
- | "query-users"
- | "manage-events"
- | "manage-realm"
- | "view-events"
- | "view-users"
- | "view-clients"
- | "manage-authorization"
- | "manage-clients"
- | "query-groups"
- | "anyone";
-
-export default interface WhoAmIRepresentation {
- userId: string;
- realm: string;
- displayName: string;
- locale: string;
- createRealm: boolean;
- realm_access: { [key: string]: AccessType[] };
-}
diff --git a/src/groups/GroupsCreateModal.tsx b/src/groups/GroupsCreateModal.tsx
index b0e27c12df..e6c9ffdd64 100644
--- a/src/groups/GroupsCreateModal.tsx
+++ b/src/groups/GroupsCreateModal.tsx
@@ -1,4 +1,4 @@
-import React, { useContext } from "react";
+import React from "react";
import {
AlertVariant,
Button,
@@ -10,8 +10,7 @@ import {
ValidatedOptions,
} from "@patternfly/react-core";
import { useTranslation } from "react-i18next";
-import { HttpClientContext } from "../context/http-service/HttpClientContext";
-import { RealmContext } from "../context/realm-context/RealmContext";
+import { useAdminClient } from "../context/auth/AdminClient";
import { useAlerts } from "../components/alert/Alerts";
import { useForm } from "react-hook-form";
@@ -33,8 +32,7 @@ export const GroupsCreateModal = ({
refresh,
}: GroupsCreateModalProps) => {
const { t } = useTranslation("groups");
- const httpClient = useContext(HttpClientContext)!;
- const { realm } = useContext(RealmContext);
+ const adminClient = useAdminClient();
const { addAlert } = useAlerts();
const form = useForm();
const { register, errors } = form;
@@ -46,9 +44,7 @@ export const GroupsCreateModal = ({
const submitForm = async () => {
if (await form.trigger()) {
try {
- await httpClient.doPost(`/admin/realms/${realm}/groups`, {
- name: createGroupName,
- });
+ await adminClient.groups.create({ name: createGroupName });
refresh();
setIsCreateModalOpen(false);
setCreateGroupName("");
diff --git a/src/groups/GroupsList.tsx b/src/groups/GroupsList.tsx
index 9194d8b4f8..a2514c3379 100644
--- a/src/groups/GroupsList.tsx
+++ b/src/groups/GroupsList.tsx
@@ -1,4 +1,4 @@
-import React, { useState, useEffect, useContext } from "react";
+import React, { useState, useEffect } from "react";
import {
Table,
TableHeader,
@@ -9,8 +9,7 @@ import { Button, AlertVariant } from "@patternfly/react-core";
import { useTranslation } from "react-i18next";
import { GroupRepresentation } from "./models/groups";
import { UsersIcon } from "@patternfly/react-icons";
-import { HttpClientContext } from "../context/http-service/HttpClientContext";
-import { RealmContext } from "../context/realm-context/RealmContext";
+import { useAdminClient } from "../context/auth/AdminClient";
import { useAlerts } from "../components/alert/Alerts";
export type GroupsListProps = {
@@ -32,10 +31,9 @@ export const GroupsList = ({
setTableRowSelectedArray,
}: GroupsListProps) => {
const { t } = useTranslation("groups");
- const httpClient = useContext(HttpClientContext)!;
+ const adminClient = useAdminClient();
const columnGroupName: keyof GroupRepresentation = "name";
const columnGroupNumber: keyof GroupRepresentation = "membersLength";
- const { realm } = useContext(RealmContext);
const { addAlert } = useAlerts();
const [formattedData, setFormattedData] = useState([]);
@@ -107,9 +105,7 @@ export const GroupsList = ({
rowId: number
) => {
try {
- await httpClient.doDelete(
- `/admin/realms/${realm}/groups/${list![rowId].id}`
- );
+ await adminClient.groups.del({ id: list![rowId].id! });
refresh();
setTableRowSelectedArray([]);
addAlert(t("Group deleted"), AlertVariant.success);
diff --git a/src/groups/GroupsSection.tsx b/src/groups/GroupsSection.tsx
index e78153cbfa..d28673087c 100644
--- a/src/groups/GroupsSection.tsx
+++ b/src/groups/GroupsSection.tsx
@@ -1,17 +1,11 @@
-import React, { useContext, useEffect, useState } from "react";
+import React, { useEffect, useState } from "react";
import { useTranslation } from "react-i18next";
-import { HttpClientContext } from "../context/http-service/HttpClientContext";
import { GroupsList } from "./GroupsList";
import { GroupsCreateModal } from "./GroupsCreateModal";
-import { GroupRepresentation } from "./models/groups";
-import {
- ServerGroupsArrayRepresentation,
- ServerGroupMembersRepresentation,
-} from "./models/server-info";
import { TableToolbar } from "../components/table-toolbar/TableToolbar";
import { ViewHeader } from "../components/view-header/ViewHeader";
import { ListEmptyState } from "../components/list-empty-state/ListEmptyState";
-import { RealmContext } from "../context/realm-context/RealmContext";
+import { useAdminClient } from "../context/auth/AdminClient";
import { useAlerts } from "../components/alert/Alerts";
import {
Button,
@@ -25,10 +19,11 @@ import {
AlertVariant,
} from "@patternfly/react-core";
import "./GroupsSection.css";
+import GroupRepresentation from "keycloak-admin/lib/defs/groupRepresentation";
export const GroupsSection = () => {
const { t } = useTranslation("groups");
- const httpClient = useContext(HttpClientContext)!;
+ const adminClient = useAdminClient();
const [rawData, setRawData] = useState<{ [key: string]: any }[]>();
const [filteredData, setFilteredData] = useState<{ [key: string]: any }[]>();
const [isKebabOpen, setIsKebabOpen] = useState(false);
@@ -38,22 +33,16 @@ export const GroupsSection = () => {
Array
>([]);
const columnID: keyof GroupRepresentation = "id";
- const membersLength: keyof GroupRepresentation = "membersLength";
const columnGroupName: keyof GroupRepresentation = "name";
const { addAlert } = useAlerts();
- const { realm } = useContext(RealmContext);
+ const membersLength = "membersLength";
const loader = async () => {
- const groups = await httpClient.doGet(
- `/admin/realms/${realm}/groups`
- );
- const groupsData = groups.data!;
- const getMembers = async (id: number) => {
- const response = await httpClient.doGet<
- ServerGroupMembersRepresentation[]
- >(`/admin/realms/${realm}/groups/${id}/members`);
- const responseData = response.data!;
- return responseData.length;
+ const groupsData = await adminClient.groups.find();
+
+ const getMembers = async (id: string) => {
+ const response = await adminClient.groups.listMembers({ id });
+ return response.length;
};
const memberPromises = groupsData.map((group: { [key: string]: any }) =>
@@ -101,11 +90,9 @@ export const GroupsSection = () => {
if (tableRowSelectedArray.length !== 0) {
const deleteGroup = async (rowId: number) => {
try {
- await httpClient.doDelete(
- `/admin/realms/${realm}/groups/${
- filteredData ? filteredData![rowId].id : rawData![rowId].id
- }`
- );
+ await adminClient.groups.del({
+ id: filteredData ? filteredData![rowId].id : rawData![rowId].id,
+ });
loader();
} catch (error) {
addAlert(`${t("groupDeleteError")} ${error}`, AlertVariant.danger);
diff --git a/src/index.tsx b/src/index.tsx
index 7c82d9db61..3db73c3f4f 100644
--- a/src/index.tsx
+++ b/src/index.tsx
@@ -2,22 +2,20 @@ import React from "react";
import ReactDom from "react-dom";
import i18n from "./i18n";
-import { App } from "./App";
+import { AdminClient } from "./context/auth/AdminClient";
import init from "./context/auth/keycloak";
-import { KeycloakContext } from "./context/auth/KeycloakContext";
-import { KeycloakService } from "./context/auth/keycloak.service";
-import { HttpClientContext } from "./context/http-service/HttpClientContext";
-import { HttpClient } from "./context/http-service/http-client";
+import { App } from "./App";
+import { RealmContextProvider } from "./context/realm-context/RealmContext";
console.info("supported languages", ...i18n.languages);
-init().then((keycloak) => {
- const keycloakService = new KeycloakService(keycloak);
+
+init().then((adminClient) => {
ReactDom.render(
-
-
+
+
-
- ,
+
+ ,
document.getElementById("app")
);
});
diff --git a/src/realm-roles/RealmRolesSection.tsx b/src/realm-roles/RealmRolesSection.tsx
index e6511ff236..c71e7e84db 100644
--- a/src/realm-roles/RealmRolesSection.tsx
+++ b/src/realm-roles/RealmRolesSection.tsx
@@ -1,14 +1,13 @@
-import React, { useContext, useEffect, useState } from "react";
+import React, { useEffect, useState } from "react";
import { useHistory } from "react-router-dom";
import { useTranslation } from "react-i18next";
import { Button, PageSection } from "@patternfly/react-core";
-import { HttpClientContext } from "../context/http-service/HttpClientContext";
-import { RoleRepresentation } from "../model/role-model";
import { RolesList } from "./RoleList";
-import { RealmContext } from "../context/realm-context/RealmContext";
-import { ViewHeader } from "../components/view-header/ViewHeader";
+import { useAdminClient } from "../context/auth/AdminClient";
import { PaginatingTableToolbar } from "../components/table-toolbar/PaginatingTableToolbar";
+import { ViewHeader } from "../components/view-header/ViewHeader";
+import RoleRepresentation from "keycloak-admin/lib/defs/roleRepresentation";
import { ListEmptyState } from "../components/list-empty-state/ListEmptyState";
export const RealmRolesSection = () => {
@@ -16,19 +15,11 @@ export const RealmRolesSection = () => {
const [first, setFirst] = useState(0);
const { t } = useTranslation("roles");
const history = useHistory();
- const httpClient = useContext(HttpClientContext)!;
+ const adminClient = useAdminClient();
const [roles, setRoles] = useState();
- const { realm } = useContext(RealmContext);
- const loader = async () => {
- const params: { [name: string]: string | number } = { first, max };
-
- const result = await httpClient.doGet(
- `/admin/realms/${realm}/roles`,
- { params: params }
- );
- setRoles(result.data);
- };
+ const params: { [name: string]: string | number } = { first, max };
+ const loader = async () => setRoles(await adminClient.roles.find(params));
useEffect(() => {
loader();
diff --git a/src/realm-roles/RoleList.tsx b/src/realm-roles/RoleList.tsx
index 2fc4e2b1a7..47ed4e3f17 100644
--- a/src/realm-roles/RoleList.tsx
+++ b/src/realm-roles/RoleList.tsx
@@ -1,4 +1,4 @@
-import React, { useContext, useState } from "react";
+import React, { useState } from "react";
import { useTranslation } from "react-i18next";
import {
@@ -11,11 +11,10 @@ import {
} from "@patternfly/react-table";
import { ExternalLink } from "../components/external-link/ExternalLink";
-import { RoleRepresentation } from "../model/role-model";
+import RoleRepresentation from "keycloak-admin/lib/defs/roleRepresentation";
import { AlertVariant, ButtonVariant } from "@patternfly/react-core";
-import { HttpClientContext } from "../context/http-service/HttpClientContext";
+import { useAdminClient } from "../context/auth/AdminClient";
import { useAlerts } from "../components/alert/Alerts";
-import { RealmContext } from "../context/realm-context/RealmContext";
import { useConfirmDialog } from "../components/confirm-dialog/ConfirmDialog";
type RolesListProps = {
@@ -31,8 +30,7 @@ const columns: (keyof RoleRepresentation)[] = [
export const RolesList = ({ roles, refresh }: RolesListProps) => {
const { t } = useTranslation("roles");
- const httpClient = useContext(HttpClientContext)!;
- const { realm } = useContext(RealmContext);
+ const adminClient = useAdminClient();
const { addAlert } = useAlerts();
const [selectedRowId, setSelectedRowId] = useState(-1);
@@ -71,9 +69,9 @@ export const RolesList = ({ roles, refresh }: RolesListProps) => {
continueButtonVariant: ButtonVariant.danger,
onConfirm: async () => {
try {
- await httpClient.doDelete(
- `/admin/realms/${realm}/roles/${data[selectedRowId].role.name}`
- );
+ await adminClient.roles.delByName({
+ name: data[selectedRowId].role.name!,
+ });
refresh();
addAlert(t("roleDeletedSuccess"), AlertVariant.success);
} catch (error) {
diff --git a/src/realm-roles/add/NewRoleForm.tsx b/src/realm-roles/add/NewRoleForm.tsx
index 8cc567da44..83a3e142a4 100644
--- a/src/realm-roles/add/NewRoleForm.tsx
+++ b/src/realm-roles/add/NewRoleForm.tsx
@@ -1,4 +1,4 @@
-import React, { useContext } from "react";
+import React from "react";
import { useTranslation } from "react-i18next";
import {
Text,
@@ -15,17 +15,15 @@ import {
ValidatedOptions,
} from "@patternfly/react-core";
-import { RoleRepresentation } from "../../model/role-model";
-import { HttpClientContext } from "../../context/http-service/HttpClientContext";
import { useAlerts } from "../../components/alert/Alerts";
import { Controller, useForm } from "react-hook-form";
-import { RealmContext } from "../../context/realm-context/RealmContext";
+import RoleRepresentation from "keycloak-admin/lib/defs/roleRepresentation";
+import { useAdminClient } from "../../context/auth/AdminClient";
export const NewRoleForm = () => {
const { t } = useTranslation("roles");
- const httpClient = useContext(HttpClientContext)!;
const { addAlert } = useAlerts();
- const { realm } = useContext(RealmContext);
+ const adminClient = useAdminClient();
const { register, control, errors, handleSubmit } = useForm<
RoleRepresentation
@@ -33,7 +31,7 @@ export const NewRoleForm = () => {
const save = async (role: RoleRepresentation) => {
try {
- await httpClient.doPost(`admin/realms/${realm}/roles`, role);
+ await adminClient.roles.create(role);
addAlert(t("roleCreated"), AlertVariant.success);
} catch (error) {
addAlert(`${t("roleCreateError")} '${error}'`, AlertVariant.danger);
diff --git a/src/realm/add/NewRealmForm.tsx b/src/realm/add/NewRealmForm.tsx
index 2f94645ba9..d44354d687 100644
--- a/src/realm/add/NewRealmForm.tsx
+++ b/src/realm/add/NewRealmForm.tsx
@@ -1,4 +1,4 @@
-import React, { useContext } from "react";
+import React from "react";
import { useTranslation } from "react-i18next";
import {
PageSection,
@@ -12,15 +12,15 @@ import {
} from "@patternfly/react-core";
import { JsonFileUpload } from "../../components/json-file-upload/JsonFileUpload";
-import { RealmRepresentation } from "../models/Realm";
-import { HttpClientContext } from "../../context/http-service/HttpClientContext";
import { useAlerts } from "../../components/alert/Alerts";
import { useForm, Controller } from "react-hook-form";
import { ViewHeader } from "../../components/view-header/ViewHeader";
+import RealmRepresentation from "keycloak-admin/lib/defs/realmRepresentation";
+import { useAdminClient } from "../../context/auth/AdminClient";
export const NewRealmForm = () => {
const { t } = useTranslation("realm");
- const httpClient = useContext(HttpClientContext)!;
+ const adminClient = useAdminClient();
const { addAlert } = useAlerts();
const { register, handleSubmit, setValue, control } = useForm<
@@ -38,7 +38,7 @@ export const NewRealmForm = () => {
const save = async (realm: RealmRepresentation) => {
try {
- await httpClient.doPost("/admin/realms", realm);
+ await adminClient.realms.create(realm);
addAlert(t("Realm created"), AlertVariant.success);
} catch (error) {
addAlert(
diff --git a/src/route-config.ts b/src/route-config.ts
index 7701322d8b..2e8090584d 100644
--- a/src/route-config.ts
+++ b/src/route-config.ts
@@ -1,4 +1,6 @@
import { TFunction } from "i18next";
+import { AccessType } from "keycloak-admin/lib/defs/whoAmIRepresentation";
+
import { AuthenticationSection } from "./authentication/AuthenticationSection";
import { ClientScopeForm } from "./client-scopes/form/ClientScopeForm";
import { ClientScopesSection } from "./client-scopes/ClientScopesSection";
@@ -17,8 +19,6 @@ import { SessionsSection } from "./sessions/SessionsSection";
import { UserFederationSection } from "./user-federation/UserFederationSection";
import { UsersSection } from "./user/UsersSection";
import { MappingDetails } from "./client-scopes/details/MappingDetails";
-
-import { AccessType } from "./context/whoami/who-am-i-model";
import { ClientDetails } from "./clients/ClientDetails";
export type RouteDef = {
diff --git a/src/stories/RoleMappingForm.stories.tsx b/src/stories/RoleMappingForm.stories.tsx
index 248d938ee4..79c1eabc0c 100644
--- a/src/stories/RoleMappingForm.stories.tsx
+++ b/src/stories/RoleMappingForm.stories.tsx
@@ -7,8 +7,8 @@ import roles from "../realm-roles/__tests__/mock-roles.json";
import { ServerInfoContext } from "../context/server-info/ServerInfoProvider";
import { RoleMappingForm } from "../client-scopes/add/RoleMappingForm";
-import { HttpClientContext } from "../context/http-service/HttpClientContext";
-import { HttpClient } from "../context/http-service/http-client";
+import { AdminClient } from "../context/auth/AdminClient";
+import KeycloakAdminClient from "keycloak-admin";
export default {
title: "Role Mapping Form",
@@ -17,18 +17,24 @@ export default {
export const RoleMappingFormExample = () => (
- {
- return { data: roles };
+ setConfig: () => {},
+ roles: {
+ find: () => {
+ return roles;
+ },
},
- } as unknown) as HttpClient
+ clients: {
+ find: () => roles,
+ },
+ } as unknown) as KeycloakAdminClient
}
>
-
+
);
diff --git a/src/user-federation/UserFederationSection.tsx b/src/user-federation/UserFederationSection.tsx
index 4b93257904..934d38cfcc 100644
--- a/src/user-federation/UserFederationSection.tsx
+++ b/src/user-federation/UserFederationSection.tsx
@@ -15,45 +15,43 @@ import {
TextVariants,
} from "@patternfly/react-core";
+import ComponentRepresentation from "keycloak-admin/lib/defs/componentRepresentation";
import { KeycloakCard } from "../components/keycloak-card/KeycloakCard";
import { useAlerts } from "../components/alert/Alerts";
import { ViewHeader } from "../components/view-header/ViewHeader";
import { DatabaseIcon } from "@patternfly/react-icons";
import { useTranslation } from "react-i18next";
import { RealmContext } from "../context/realm-context/RealmContext";
-import { HttpClientContext } from "../context/http-service/HttpClientContext";
-import { UserFederationRepresentation } from "./model/userFederation";
+import { useAdminClient } from "../context/auth/AdminClient";
import { useConfirmDialog } from "../components/confirm-dialog/ConfirmDialog";
import "./user-federation.css";
+type Config = {
+ enabled: string[];
+};
+
export const UserFederationSection = () => {
const [userFederations, setUserFederations] = useState<
- UserFederationRepresentation[]
+ ComponentRepresentation[]
>();
const { addAlert } = useAlerts();
+ const { t } = useTranslation("user-federation");
+ const { realm } = useContext(RealmContext);
+ const adminClient = useAdminClient();
const loader = async () => {
const testParams: { [name: string]: string | number } = {
parentId: realm,
type: "org.keycloak.storage.UserStorageProvider", // MF note that this is providerType in the output, but API call is still type
};
- const result = await httpClient.doGet(
- `/admin/realms/${realm}/components`,
- {
- params: testParams,
- }
- );
- setUserFederations(result.data);
+ const userFederations = await adminClient.components.find(testParams);
+ setUserFederations(userFederations);
};
useEffect(() => {
loader();
}, []);
- const { t } = useTranslation("user-federation");
- const httpClient = useContext(HttpClientContext)!;
- const { realm } = useContext(RealmContext);
-
const ufAddProviderDropdownItems = [
LDAP ,
Kerberos ,
@@ -75,9 +73,8 @@ export const UserFederationSection = () => {
continueButtonVariant: ButtonVariant.danger,
onConfirm: async () => {
try {
- httpClient
- .doDelete(`/admin/realms/${realm}/components/${currentCard}`)
- .then(() => loader());
+ await adminClient.components.del({ id: currentCard });
+ await loader();
addAlert(t("userFedDeletedSuccess"), AlertVariant.success);
} catch (error) {
addAlert(t("userFedDeleteError", { error }), AlertVariant.danger);
@@ -96,7 +93,7 @@ export const UserFederationSection = () => {
{
- toggleDeleteForCard(userFederation.id);
+ toggleDeleteForCard(userFederation.id!);
}}
>
{t("common:delete")}
@@ -105,14 +102,14 @@ export const UserFederationSection = () => {
return (
=3.5 <5", lodash@^4.0.1, lodash@^4.15.0, lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.5, lodash@~4.17.10, lodash@~4.17.5:
+"lodash@>=3.5 <5", lodash@^4.0.1, lodash@^4.15.0, lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.5, lodash@~4.17.10, lodash@~4.17.5:
version "4.17.20"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52"
integrity sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==
@@ -15492,6 +15522,15 @@ query-string@^4.1.0:
object-assign "^4.1.0"
strict-uri-encode "^1.0.0"
+query-string@^6.13.7:
+ version "6.13.7"
+ resolved "https://registry.yarnpkg.com/query-string/-/query-string-6.13.7.tgz#af53802ff6ed56f3345f92d40a056f93681026ee"
+ integrity sha512-CsGs8ZYb39zu0WLkeOhe0NMePqgYdAuCqxOYKDR5LVCytDZYMGx3Bb+xypvQvPHVPijRXB0HZNFllCzHRe4gEA==
+ dependencies:
+ decode-uri-component "^0.2.0"
+ split-on-first "^1.0.0"
+ strict-uri-encode "^2.0.0"
+
querystring-es3@^0.2.0:
version "0.2.1"
resolved "https://registry.yarnpkg.com/querystring-es3/-/querystring-es3-0.2.1.tgz#9ec61f79049875707d69414596fd907a4d711e73"
@@ -17270,6 +17309,11 @@ spdy@^4.0.1:
select-hose "^2.0.0"
spdy-transport "^3.0.0"
+split-on-first@^1.0.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/split-on-first/-/split-on-first-1.1.0.tgz#f610afeee3b12bce1d0c30425e76398b78249a5f"
+ integrity sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw==
+
split-string@^3.0.1, split-string@^3.0.2:
version "3.1.0"
resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2"
@@ -17399,6 +17443,11 @@ strict-uri-encode@^1.0.0:
resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713"
integrity sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=
+strict-uri-encode@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz#b9c7330c7042862f6b142dc274bbcc5866ce3546"
+ integrity sha1-ucczDHBChi9rFC3CdLvMWGbONUY=
+
string-length@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/string-length/-/string-length-2.0.0.tgz#d40dbb686a3ace960c1cffca562bf2c45f8363ed"
@@ -18421,6 +18470,11 @@ urix@^0.1.0:
resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72"
integrity sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=
+url-join@^4.0.0:
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/url-join/-/url-join-4.0.1.tgz#b642e21a2646808ffa178c4c5fda39844e12cde7"
+ integrity sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==
+
url-loader@2.3.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/url-loader/-/url-loader-2.3.0.tgz#e0e2ef658f003efb8ca41b0f3ffbf76bab88658b"
@@ -18447,6 +18501,11 @@ url-parse@^1.4.3:
querystringify "^2.1.1"
requires-port "^1.0.0"
+url-template@^2.0.8:
+ version "2.0.8"
+ resolved "https://registry.yarnpkg.com/url-template/-/url-template-2.0.8.tgz#fc565a3cccbff7730c775f5641f9555791439f21"
+ integrity sha1-/FZaPMy/93MMd19WQflVV5FDnyE=
+
url@^0.11.0:
version "0.11.0"
resolved "https://registry.yarnpkg.com/url/-/url-0.11.0.tgz#3838e97cfc60521eb73c525a8e55bfdd9e2e28f1"