Skip to content

Commit 3bf1a96

Browse files
committed
Merge branch '6.0/rest2-rights-api-2' into 6.0-trunk
2 parents 562155d + 14f74d8 commit 3bf1a96

21 files changed

Lines changed: 3283 additions & 15 deletions

lib/RT/REST2.pm

Lines changed: 283 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -997,6 +997,22 @@ Below are some examples using the endpoints above.
997997
998998
POST /customfield/:id/value
999999
add a value to a custom field; provide JSON content
1000+
accepts a JSON object for a single value, or a JSON array
1001+
of objects to create multiple values in one request
1002+
1003+
single value:
1004+
1005+
{ "Name": "High", "SortOrder": 1 }
1006+
1007+
multiple values:
1008+
1009+
[
1010+
{ "Name": "High", "SortOrder": 1 },
1011+
{ "Name": "Medium", "SortOrder": 2 },
1012+
{ "Name": "Low", "SortOrder": 3 }
1013+
]
1014+
1015+
bulk creation returns a JSON array of results, one per value
10001016
10011017
GET /customfield/:id/value/:id
10021018
retrieve a value of a custom field
@@ -1026,6 +1042,273 @@ Below are some examples using the endpoints above.
10261042
GET /search/:description
10271043
retrieve a saved search
10281044
1045+
=head3 Rights
1046+
1047+
Rights can be listed, granted, and revoked on queues, groups, classes,
1048+
catalogs, custom fields, and globally. Rights are associated with groups
1049+
and users and both can be referenced with the rights endpoints.
1050+
1051+
As with other APIs, the account accessing the API must have rights to view or
1052+
edit rights, just as they would in the RT user interface. The available endpoints
1053+
are the following:
1054+
1055+
GET /queue/:id/rights
1056+
GET /queue/:name/rights
1057+
GET /group/:id/rights
1058+
GET /class/:id/rights
1059+
GET /class/:name/rights
1060+
GET /catalog/:id/rights
1061+
GET /catalog/:name/rights
1062+
GET /customfield/:id/rights
1063+
GET /global/rights
1064+
list all rights granted on the object; returns items with
1065+
Right, and either Group or User (each with id, Name, _url)
1066+
1067+
GET /queue/:id/rights?group=<id or name>
1068+
GET /queue/:id/rights?user=<id or name>
1069+
filter the rights list to a specific group or user
1070+
1071+
POST /queue/:id/rights
1072+
POST /queue/:name/rights
1073+
POST /group/:id/rights
1074+
POST /class/:id/rights
1075+
POST /class/:name/rights
1076+
POST /catalog/:id/rights
1077+
POST /catalog/:name/rights
1078+
POST /customfield/:id/rights
1079+
POST /global/rights
1080+
grant a right; provide JSON content with Right and either
1081+
Group or User
1082+
1083+
DELETE /queue/:id/rights/:right/group/:id
1084+
DELETE /queue/:id/rights/:right/user/:id
1085+
DELETE /queue/:name/rights/:right/group/:id
1086+
DELETE /queue/:name/rights/:right/user/:id
1087+
DELETE /group/:id/rights/:right/group/:id
1088+
DELETE /group/:id/rights/:right/user/:id
1089+
DELETE /class/:id/rights/:right/group/:id
1090+
DELETE /class/:id/rights/:right/user/:id
1091+
DELETE /class/:name/rights/:right/group/:id
1092+
DELETE /class/:name/rights/:right/user/:id
1093+
DELETE /catalog/:id/rights/:right/group/:id
1094+
DELETE /catalog/:id/rights/:right/user/:id
1095+
DELETE /catalog/:name/rights/:right/group/:id
1096+
DELETE /catalog/:name/rights/:right/user/:id
1097+
DELETE /customfield/:id/rights/:right/group/:id
1098+
DELETE /customfield/:id/rights/:right/user/:id
1099+
DELETE /global/rights/:right/group/:id
1100+
DELETE /global/rights/:right/user/:id
1101+
revoke a specific right from a group or user; returns 204 on
1102+
success, 404 if the right was not granted
1103+
1104+
GET /queue/:id/rights/available
1105+
GET /queue/:name/rights/available
1106+
GET /group/:id/rights/available
1107+
GET /class/:id/rights/available
1108+
GET /class/:name/rights/available
1109+
GET /catalog/:id/rights/available
1110+
GET /catalog/:name/rights/available
1111+
GET /customfield/:id/rights/available
1112+
GET /global/rights/available
1113+
list all rights that can be granted on this object type,
1114+
grouped by category
1115+
1116+
POST /queue/:id/rights/bulk
1117+
POST /queue/:name/rights/bulk
1118+
POST /group/:id/rights/bulk
1119+
POST /class/:id/rights/bulk
1120+
POST /class/:name/rights/bulk
1121+
POST /catalog/:id/rights/bulk
1122+
POST /catalog/:name/rights/bulk
1123+
POST /customfield/:id/rights/bulk
1124+
POST /global/rights/bulk
1125+
grant and/or revoke multiple rights in a single request;
1126+
provide JSON content with grant and/or revoke arrays
1127+
1128+
Hypermedia links to the rights and rights-available endpoints are
1129+
included in responses for queue, group, class, catalog, and custom
1130+
field objects when the current user has the appropriate read right.
1131+
1132+
=head3 Rights Examples
1133+
1134+
# List all rights granted on a queue
1135+
curl -H 'Authorization: token XX_TOKEN_XX'
1136+
'https://myrt.com/REST/2.0/queue/1/rights'
1137+
1138+
{
1139+
"total": 2,
1140+
"count": 2,
1141+
"items": [
1142+
{
1143+
"Right": "CreateTicket",
1144+
"Group": {
1145+
"id": 7,
1146+
"Name": "Staff",
1147+
"_url": "https://myrt.com/REST/2.0/group/7"
1148+
}
1149+
},
1150+
{
1151+
"Right": "OwnTicket",
1152+
"User": {
1153+
"id": 4,
1154+
"Name": "jsmith",
1155+
"_url": "https://myrt.com/REST/2.0/user/4"
1156+
}
1157+
}
1158+
]
1159+
}
1160+
1161+
# Grant a right to a group by name
1162+
curl -X POST -H "Content-Type: application/json"
1163+
-H 'Authorization: token XX_TOKEN_XX'
1164+
-d '{ "Right": "CreateTicket", "Group": "Staff" }'
1165+
'https://myrt.com/REST/2.0/queue/1/rights'
1166+
1167+
# Grant a right using a group or user id
1168+
curl -X POST -H "Content-Type: application/json"
1169+
-H 'Authorization: token XX_TOKEN_XX'
1170+
-d '{ "Right": "ReplyToTicket", "Group": { "id": 7 } }'
1171+
'https://myrt.com/REST/2.0/queue/1/rights'
1172+
1173+
# Revoke a right from a group
1174+
curl -X DELETE -H 'Authorization: token XX_TOKEN_XX'
1175+
'https://myrt.com/REST/2.0/queue/1/rights/CreateTicket/group/7'
1176+
1177+
# List available rights on a queue, grouped by category
1178+
curl -H 'Authorization: token XX_TOKEN_XX'
1179+
'https://myrt.com/REST/2.0/queue/1/rights/available'
1180+
1181+
{
1182+
"General": {
1183+
"CreateTicket": "Create tickets in this queue",
1184+
"ReplyToTicket": "Reply to tickets",
1185+
...
1186+
},
1187+
"Admin": {
1188+
"ModifyACL": "Modify access control list",
1189+
...
1190+
}
1191+
}
1192+
1193+
# Bulk grant and revoke in one request
1194+
curl -X POST -H "Content-Type: application/json"
1195+
-H 'Authorization: token XX_TOKEN_XX'
1196+
-d '{
1197+
"grant": [
1198+
{ "Right": "CreateTicket", "Group": "Staff" },
1199+
{ "Right": "ReplyToTicket", "Group": "Staff" },
1200+
{ "Right": "OwnTicket", "User": "jsmith" }
1201+
],
1202+
"revoke": [
1203+
{ "Right": "CommentOnTicket", "Group": "Staff" }
1204+
]
1205+
}'
1206+
'https://myrt.com/REST/2.0/queue/1/rights/bulk'
1207+
1208+
The bulk response includes a C<granted> array and a C<revoked> array.
1209+
Each entry has the original C<Right> and C<Group>/C<User> fields plus a
1210+
C<status> code (201 for a successful grant, 204 for a successful
1211+
revoke, 400/403/404/409 for errors) and a C<message> on failure.
1212+
1213+
=head3 Lifecycles
1214+
1215+
Lifecycle configuration can be managed through the REST 2 API.
1216+
All lifecycle endpoints require C<SuperUser> rights.
1217+
1218+
The JSON structure for lifecycle configuration follows the format
1219+
described in L<Lifecycles|docs/customizing/lifecycles.pod>. The C<validate>
1220+
endpoint can be used to check a configuration before submitting a
1221+
create or update call.
1222+
1223+
GET /lifecycles
1224+
list all lifecycles (excluding approvals)
1225+
1226+
GET /lifecycles?type=ticket
1227+
list lifecycles filtered by type (ticket or asset)
1228+
1229+
POST /lifecycles
1230+
create a new lifecycle
1231+
1232+
GET /lifecycle/:name
1233+
retrieve a lifecycle's full configuration
1234+
1235+
PUT /lifecycle/:name
1236+
update a lifecycle's configuration
1237+
1238+
DELETE /lifecycle/:name
1239+
delete a lifecycle (fails if in use by queues/catalogs)
1240+
1241+
GET /lifecycle/:name/maps
1242+
retrieve transition mappings for a lifecycle
1243+
1244+
PUT /lifecycle/:name/maps
1245+
update transition mappings for a lifecycle
1246+
1247+
POST /lifecycle/:name/validate
1248+
validate a lifecycle configuration without saving
1249+
1250+
=head3 Lifecycle Examples
1251+
1252+
# List all lifecycles
1253+
curl -H 'Authorization: token XX_TOKEN_XX'
1254+
'https://myrt.com/REST/2.0/lifecycles'
1255+
1256+
# Get a specific lifecycle
1257+
curl -H 'Authorization: token XX_TOKEN_XX'
1258+
'https://myrt.com/REST/2.0/lifecycle/default'
1259+
1260+
# Create a new lifecycle
1261+
curl -X POST -H 'Content-Type: application/json'
1262+
-H 'Authorization: token XX_TOKEN_XX'
1263+
-d '{ "Name": "support", "Type": "ticket" }'
1264+
'https://myrt.com/REST/2.0/lifecycles'
1265+
1266+
# Create by cloning an existing lifecycle
1267+
curl -X POST -H 'Content-Type: application/json'
1268+
-H 'Authorization: token XX_TOKEN_XX'
1269+
-d '{ "Name": "support", "Type": "ticket", "Clone": "default" }'
1270+
'https://myrt.com/REST/2.0/lifecycles'
1271+
1272+
# Update a lifecycle's configuration
1273+
curl -X PUT -H 'Content-Type: application/json'
1274+
-H 'Authorization: token XX_TOKEN_XX'
1275+
-d '{
1276+
"type": "ticket",
1277+
"initial": ["new"],
1278+
"active": ["open", "stalled"],
1279+
"inactive": ["resolved", "rejected", "deleted"],
1280+
"defaults": { "on_create": "new", "on_resolve": "resolved" },
1281+
"transitions": {
1282+
"": ["new"],
1283+
"new": ["open", "resolved", "rejected", "deleted"],
1284+
"open": ["stalled", "resolved", "rejected", "deleted"],
1285+
"stalled": ["open", "resolved", "rejected", "deleted"],
1286+
"resolved": ["open"],
1287+
"rejected": ["open"],
1288+
"deleted": ["open"]
1289+
},
1290+
"colors": {
1291+
"new": "#2c5f90",
1292+
"open": "#1976d2",
1293+
"stalled": "#b45309",
1294+
"resolved": "#2e7d32",
1295+
"rejected": "#5f6b7a",
1296+
"deleted": "#757575"
1297+
}
1298+
}'
1299+
'https://myrt.com/REST/2.0/lifecycle/support'
1300+
1301+
# Validate a lifecycle configuration without saving
1302+
curl -X POST -H 'Content-Type: application/json'
1303+
-H 'Authorization: token XX_TOKEN_XX'
1304+
-d '{ "type": "ticket", "initial": ["new"], "active": ["open"],
1305+
"inactive": ["resolved"] }'
1306+
'https://myrt.com/REST/2.0/lifecycle/support/validate'
1307+
1308+
# Delete a lifecycle (must not be in use)
1309+
curl -X DELETE -H 'Authorization: token XX_TOKEN_XX'
1310+
'https://myrt.com/REST/2.0/lifecycle/support'
1311+
10291312
=head3 Miscellaneous
10301313
10311314
GET /

lib/RT/REST2/Dispatcher.pm

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,9 @@ sub to_psgi_app {
9898

9999
RT->SetCurrentInterface('REST2');
100100
RT::ConnectToDatabase();
101+
RT->Config->RefreshConfigFromDatabase();
102+
RT->System->MaybeRebuildLifecycleCache();
103+
RT::Interface::Web::MaybeRebuildCustomRolesCache();
101104
RT::Interface::Web::MaybeEnableSQLStatementLog();
102105

103106
my $dispatch = $self->_dispatcher->dispatch($env->{PATH_INFO});

lib/RT/REST2/Resource/Catalog.pm

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,13 @@ sub hypermedia_links {
9393
_url => RT::REST2->base_uri . '/asset?Catalog=' . $catalog->Id,
9494
} if $catalog->CurrentUserHasRight('CreateAsset');
9595

96+
if ( $catalog->CurrentUserHasRight('AdminCatalog') ) {
97+
my $base = RT::REST2->base_uri . '/catalog/' . $catalog->Id;
98+
push @$links,
99+
{ ref => 'rights', _url => "$base/rights" },
100+
{ ref => 'rights-available', _url => "$base/rights/available" };
101+
}
102+
96103
return $links;
97104
}
98105

lib/RT/REST2/Resource/Class.pm

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,13 @@ sub hypermedia_links {
9494
_url => RT::REST2->base_uri . '/article?Class=' . $class->Id,
9595
} if $class->CurrentUserHasRight('CreateArticle');
9696

97+
if ( $class->CurrentUserHasRight('AdminClass') ) {
98+
my $base = RT::REST2->base_uri . '/class/' . $class->Id;
99+
push @$links,
100+
{ ref => 'rights', _url => "$base/rights" },
101+
{ ref => 'rights-available', _url => "$base/rights/available" };
102+
}
103+
97104
return $links;
98105
}
99106

lib/RT/REST2/Resource/CustomField.pm

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,15 @@ sub hypermedia_links {
9797
_url => RT::REST2->base_uri . "/customfield/" . $self->record->id . "/values",
9898
};
9999
}
100+
101+
if ( $self->record->CurrentUserHasRight('AdminCustomField') ) {
102+
my $base = RT::REST2->base_uri . '/customfield/' . $self->record->Id;
103+
push @$links,
104+
{ ref => 'appliesto', _url => "$base/appliesto" },
105+
{ ref => 'rights', _url => "$base/rights" },
106+
{ ref => 'rights-available', _url => "$base/rights/available" };
107+
}
108+
100109
return $links;
101110
}
102111

0 commit comments

Comments
 (0)