From 5b99cbc7730c9d42740230d30794b06ac7fdb934 Mon Sep 17 00:00:00 2001 From: Jeremy Mitchell Date: Fri, 2 Jun 2017 10:38:16 -0600 Subject: [PATCH 1/3] repoints api away from controller that will soon be deprecated --- traffic_ops/app/lib/API/Deliveryservice.pm | 56 +++++++++++++++++++++ traffic_ops/app/lib/API/Deliveryservice2.pm | 56 --------------------- traffic_ops/app/lib/TrafficOpsRoutes.pm | 2 +- 3 files changed, 57 insertions(+), 57 deletions(-) diff --git a/traffic_ops/app/lib/API/Deliveryservice.pm b/traffic_ops/app/lib/API/Deliveryservice.pm index 2017e4252b..ee68788058 100644 --- a/traffic_ops/app/lib/API/Deliveryservice.pm +++ b/traffic_ops/app/lib/API/Deliveryservice.pm @@ -976,6 +976,62 @@ sub request { } } +sub assign_servers { + my $self = shift; + my $ds_xml_Id = $self->param('xml_id'); + my $params = $self->req->json; + + if ( !defined($params) ) { + return $self->alert("parameters are JSON format, please check!"); + } + if ( !&is_oper($self) ) { + return $self->alert("You must be an ADMIN or OPER to perform this operation!"); + } + + if ( !exists( $params->{serverNames} ) ) { + return $self->alert("Parameter 'serverNames' is required."); + } + + my $dsid = $self->db->resultset('Deliveryservice')->search( { xml_id => $ds_xml_Id } )->get_column('id')->single(); + if ( !defined($dsid) ) { + return $self->alert( "DeliveryService[" . $ds_xml_Id . "] is not found." ); + } + + my @server_ids; + my $svrs = $params->{serverNames}; + foreach my $svr (@$svrs) { + my $svr_id = $self->db->resultset('Server')->search( { host_name => $svr } )->get_column('id')->single(); + if ( !defined($svr_id) ) { + return $self->alert( "Server[" . $svr . "] is not found in database." ); + } + push( @server_ids, $svr_id ); + } + + # clean up + my $delete = $self->db->resultset('DeliveryserviceServer')->search( { deliveryservice => $dsid } ); + $delete->delete(); + + # assign servers + foreach my $s_id (@server_ids) { + my $insert = $self->db->resultset('DeliveryserviceServer')->create( + { + deliveryservice => $dsid, + server => $s_id, + } + ); + $insert->insert(); + } + + my $ds = $self->db->resultset('Deliveryservice')->search( { id => $dsid } )->single(); + &UI::DeliveryService::header_rewrite( $self, $ds->id, $ds->profile, $ds->xml_id, $ds->edge_header_rewrite, "edge" ); + + my $response; + $response->{xmlId} = $ds->xml_id; + $response->{'serverNames'} = \@$svrs; + + return $self->success($response); +} + sub is_deliveryservice_request_valid { my $self = shift; my $details = shift; diff --git a/traffic_ops/app/lib/API/Deliveryservice2.pm b/traffic_ops/app/lib/API/Deliveryservice2.pm index 81b340c33a..de443f7788 100644 --- a/traffic_ops/app/lib/API/Deliveryservice2.pm +++ b/traffic_ops/app/lib/API/Deliveryservice2.pm @@ -305,62 +305,6 @@ sub get_types { return $types; } -sub assign_servers { - my $self = shift; - my $ds_xml_Id = $self->param('xml_id'); - my $params = $self->req->json; - - if ( !defined($params) ) { - return $self->alert("parameters are JSON format, please check!"); - } - if ( !&is_oper($self) ) { - return $self->alert("You must be an ADMIN or OPER to perform this operation!"); - } - - if ( !exists( $params->{serverNames} ) ) { - return $self->alert("Parameter 'serverNames' is required."); - } - - my $dsid = $self->db->resultset('Deliveryservice')->search( { xml_id => $ds_xml_Id } )->get_column('id')->single(); - if ( !defined($dsid) ) { - return $self->alert( "DeliveryService[" . $ds_xml_Id . "] is not found." ); - } - - my @server_ids; - my $svrs = $params->{serverNames}; - foreach my $svr (@$svrs) { - my $svr_id = $self->db->resultset('Server')->search( { host_name => $svr } )->get_column('id')->single(); - if ( !defined($svr_id) ) { - return $self->alert( "Server[" . $svr . "] is not found in database." ); - } - push( @server_ids, $svr_id ); - } - - # clean up - my $delete = $self->db->resultset('DeliveryserviceServer')->search( { deliveryservice => $dsid } ); - $delete->delete(); - - # assign servers - foreach my $s_id (@server_ids) { - my $insert = $self->db->resultset('DeliveryserviceServer')->create( - { - deliveryservice => $dsid, - server => $s_id, - } - ); - $insert->insert(); - } - - my $ds = $self->db->resultset('Deliveryservice')->search( { id => $dsid } )->single(); - &UI::DeliveryService::header_rewrite( $self, $ds->id, $ds->profile, $ds->xml_id, $ds->edge_header_rewrite, "edge" ); - - my $response; - $response->{xmlId} = $ds->xml_id; - $response->{'serverNames'} = \@$svrs; - - return $self->success($response); -} - sub _check_params { my $self = shift; my $params = shift; diff --git a/traffic_ops/app/lib/TrafficOpsRoutes.pm b/traffic_ops/app/lib/TrafficOpsRoutes.pm index b4da30e3de..aa4ac70924 100644 --- a/traffic_ops/app/lib/TrafficOpsRoutes.pm +++ b/traffic_ops/app/lib/TrafficOpsRoutes.pm @@ -506,7 +506,7 @@ sub api_routes { # delivery service / server assignments $r->post("/api/$version/deliveryservices/:xml_id/servers")->over( authenticated => 1 ) - ->to( 'Deliveryservice2#assign_servers', namespace => $namespace ); + ->to( 'Deliveryservice#assign_servers', namespace => $namespace ); $r->delete("/api/$version/deliveryservice_server/:dsId/:serverId" => [ dsId => qr/\d+/, serverId => qr/\d+/ ] )->over( authenticated => 1 )->to( 'DeliveryServiceServer#remove_server_from_ds', namespace => $namespace ); # alternate deliveryservice routes From 55dfec9504fd9def23914250f7d10e5cc1b5004b Mon Sep 17 00:00:00 2001 From: Jeremy Mitchell Date: Fri, 2 Jun 2017 16:39:47 -0600 Subject: [PATCH 2/3] fixes ability to edit current user --- .../ui/app/src/common/api/UserService.js | 28 ++++++------------- .../modules/private/user/UserController.js | 18 ++++++++++-- .../private/user/edit/UserEditController.js | 2 +- 3 files changed, 25 insertions(+), 23 deletions(-) diff --git a/traffic_ops/experimental/ui/app/src/common/api/UserService.js b/traffic_ops/experimental/ui/app/src/common/api/UserService.js index 0995d627f5..40e0fa325e 100644 --- a/traffic_ops/experimental/ui/app/src/common/api/UserService.js +++ b/traffic_ops/experimental/ui/app/src/common/api/UserService.js @@ -17,7 +17,7 @@ * under the License. */ -var UserService = function(Restangular, $http, $location, $q, authService, locationUtils, userModel, messageModel, ENV) { +var UserService = function(Restangular, $http, $location, $q, authService, httpService, locationUtils, userModel, messageModel, ENV) { var service = this; @@ -49,20 +49,6 @@ var UserService = function(Restangular, $http, $location, $q, authService, locat } }; - - this.updateCurrentUser = function(user) { - return user.put() - .then( - function() { - userModel.setUser(user); - messageModel.setMessages([ { level: 'success', text: 'User updated' } ], false); - }, - function() { - messageModel.setMessages([ { level: 'error', text: 'User updated failed' } ], false); - } - ); - }; - this.getUsers = function(queryParams) { return Restangular.all('users').getList(queryParams); }; @@ -85,13 +71,17 @@ var UserService = function(Restangular, $http, $location, $q, authService, locat }; this.updateUser = function(user) { - return user.put() + return $http.put(ENV.api['root'] + "users/" + user.id, user) .then( function() { + if (userModel.user.id == user.id) { + // if you are updating the currently logged in user... + userModel.setUser(user); + } messageModel.setMessages([ { level: 'success', text: 'User updated' } ], false); }, - function(fault) { - messageModel.setMessages(fault.data.alerts, false); + function() { + messageModel.setMessages([ { level: 'error', text: 'User updated failed' } ], false); } ); }; @@ -110,5 +100,5 @@ var UserService = function(Restangular, $http, $location, $q, authService, locat }; -UserService.$inject = ['Restangular', '$http', '$location', '$q', 'authService', 'locationUtils', 'userModel', 'messageModel', 'ENV']; +UserService.$inject = ['Restangular', '$http', '$location', '$q', 'authService', 'httpService', 'locationUtils', 'userModel', 'messageModel', 'ENV']; module.exports = UserService; diff --git a/traffic_ops/experimental/ui/app/src/modules/private/user/UserController.js b/traffic_ops/experimental/ui/app/src/modules/private/user/UserController.js index bb68bd1bc9..01439f9d74 100644 --- a/traffic_ops/experimental/ui/app/src/modules/private/user/UserController.js +++ b/traffic_ops/experimental/ui/app/src/modules/private/user/UserController.js @@ -17,10 +17,10 @@ * under the License. */ -var UserController = function($scope, $state, $uibModal, formUtils, locationUtils, userService, authService, roleService, userModel) { +var UserController = function($scope, $state, $location, $uibModal, formUtils, locationUtils, userService, authService, roleService, tenantService, userModel) { var updateUser = function(user, options) { - userService.updateCurrentUser(user) + userService.updateUser(user) .then(function() { if (options.signout) { authService.logout(); @@ -35,6 +35,13 @@ var UserController = function($scope, $state, $uibModal, formUtils, locationUtil }); }; + var getTenants = function() { + tenantService.getTenants() + .then(function(result) { + $scope.tenants = result; + }); + }; + $scope.userName = angular.copy(userModel.user.username); $scope.user = userModel.user; @@ -65,6 +72,10 @@ var UserController = function($scope, $state, $uibModal, formUtils, locationUtil } }; + $scope.viewDeliveryServices = function() { + $location.path('/admin/users/' + $scope.user.id + '/delivery-services'); + }; + $scope.navigateToPath = locationUtils.navigateToPath; $scope.hasError = formUtils.hasError; @@ -73,10 +84,11 @@ var UserController = function($scope, $state, $uibModal, formUtils, locationUtil var init = function () { getRoles(); + getTenants(); }; init(); }; -UserController.$inject = ['$scope', '$state', '$uibModal', 'formUtils', 'locationUtils', 'userService', 'authService', 'roleService', 'userModel']; +UserController.$inject = ['$scope', '$state', '$location', '$uibModal', 'formUtils', 'locationUtils', 'userService', 'authService', 'roleService', 'tenantService', 'userModel']; module.exports = UserController; diff --git a/traffic_ops/experimental/ui/app/src/modules/private/user/edit/UserEditController.js b/traffic_ops/experimental/ui/app/src/modules/private/user/edit/UserEditController.js index 1f855085bd..b52613e052 100644 --- a/traffic_ops/experimental/ui/app/src/modules/private/user/edit/UserEditController.js +++ b/traffic_ops/experimental/ui/app/src/modules/private/user/edit/UserEditController.js @@ -20,7 +20,7 @@ var UserEditController = function($scope) { $scope.settings = { - isNew: true, + isNew: false, saveLabel: 'Update' }; From aedddb734f7a470275fd5b81dfeeb1713091d68d Mon Sep 17 00:00:00 2001 From: Jeremy Mitchell Date: Mon, 5 Jun 2017 14:42:20 -0600 Subject: [PATCH 3/3] adds the ability to add/remove ds's from a user thru the api and also hooks it into the new TO UI --- .../traffic_ops_api/v12/deliveryservice.rst | 87 +++++++++++++++++ .../development/traffic_ops_api/v12/user.rst | 18 ++-- .../app/lib/API/DeliveryServiceServer.pm | 2 +- .../app/lib/API/DeliveryServiceUser.pm | 50 ++++++++++ traffic_ops/app/lib/API/User.pm | 48 ++++++++- traffic_ops/app/lib/TrafficOpsRoutes.pm | 19 ++-- .../app/t/api/1.2/deliveryservice_user.t | 97 +++++++++++++++++++ .../ui/app/src/common/api/UserService.js | 40 ++++++++ .../TableUserDSUnassignedController.js | 70 +++++++++++++ .../TableUserDeliveryServicesController.js | 41 ++++++-- .../table/userDeliveryServices/index.js | 3 +- .../table.userDSUnassigned.tpl.html | 47 +++++++++ .../table.userDeliveryServices.tpl.html | 4 +- 13 files changed, 497 insertions(+), 29 deletions(-) create mode 100644 traffic_ops/app/lib/API/DeliveryServiceUser.pm create mode 100644 traffic_ops/app/t/api/1.2/deliveryservice_user.t create mode 100644 traffic_ops/experimental/ui/app/src/common/modules/table/userDeliveryServices/TableUserDSUnassignedController.js create mode 100644 traffic_ops/experimental/ui/app/src/common/modules/table/userDeliveryServices/table.userDSUnassigned.tpl.html diff --git a/docs/source/development/traffic_ops_api/v12/deliveryservice.rst b/docs/source/development/traffic_ops_api/v12/deliveryservice.rst index 0a2103421b..df674fa6fd 100644 --- a/docs/source/development/traffic_ops_api/v12/deliveryservice.rst +++ b/docs/source/development/traffic_ops_api/v12/deliveryservice.rst @@ -1148,6 +1148,93 @@ Delivery Service Server | +.. _to-api-v12-ds-user: + +Delivery Service User ++++++++++++++++++++++ + +**POST /api/1.2/deliveryservice_user** + + Create one or more user / delivery service assignments. + + Authentication Required: Yes + + Role(s) Required: Admin or Operations + + **Request Parameters** + + +---------------------------------+----------+-------------------------------------------------------------------+ + | Name | Required | Description | + +=================================+==========+===================================================================+ + | ``userId`` | yes | The ID of the user. | + +---------------------------------+----------+-------------------------------------------------------------------+ + | ``deliveryServices`` | yes | An array of delivery service IDs. | + +---------------------------------+----------+-------------------------------------------------------------------+ + + **Request Example** :: + + { + "userId": 50, + "deliveryServices": [ 23, 34, 45, 56, 67 ] + } + + **Response Properties** + + +------------------------------------+--------+-------------------------------------------------------------------+ + | Parameter | Type | Description | + +====================================+========+===================================================================+ + | ``dsId`` | int | The ID of the delivery service. | + +------------------------------------+--------+-------------------------------------------------------------------+ + | ``servers`` | array | An array of server IDs. | + +------------------------------------+--------+-------------------------------------------------------------------+ + + **Response Example** :: + + { + "alerts": [ + { + "level": "success", + "text": "Delivery service assignments complete." + } + ], + "response": { + "userId" : 50, + "deliveryServices": [ 23, 34, 45, 56, 67 ] + } + } + +| + +**DELETE /api/1.2/deliveryservice_user/:dsId/:userId** + + Removes a delivery service from a user. + + Authentication Required: Yes + + Role(s) Required: Admin or Operations + + **Request Route Parameters** + + +-----------------+----------+---------------------------------------------------+ + | Name | Required | Description | + +=================+==========+===================================================+ + | ``dsId`` | yes | Delivery service ID. | + +-----------------+----------+---------------------------------------------------+ + | ``userId`` | yes | User ID. | + +-----------------+----------+---------------------------------------------------+ + + **Response Example** :: + + { + "alerts": [ + { + "level": "success", + "text": "User and delivery service were unlinked." + } + ], + } + +| .. _to-api-v12-ds-sslkeys: diff --git a/docs/source/development/traffic_ops_api/v12/user.rst b/docs/source/development/traffic_ops_api/v12/user.rst index a95582e495..8681dcaed5 100644 --- a/docs/source/development/traffic_ops_api/v12/user.rst +++ b/docs/source/development/traffic_ops_api/v12/user.rst @@ -1004,7 +1004,7 @@ Role(s) Required: None | -**GET /api/1.2/user/:id/deliveryservices/available.json** +**GET /api/1.2/user/:id/deliveryservices/available** Authentication Required: Yes @@ -1023,10 +1023,12 @@ Role(s) Required: None +----------------------+--------+------------------------------------------------+ | Parameter | Type | Description | +======================+========+================================================+ - |``xmlId`` | string | | - +----------------------+--------+------------------------------------------------+ |``id`` | string | | +----------------------+--------+------------------------------------------------+ + |``displayName`` | string | | + +----------------------+--------+------------------------------------------------+ + |``xmlId`` | string | | + +----------------------+--------+------------------------------------------------+ **Response Example** :: @@ -1034,12 +1036,14 @@ Role(s) Required: None { "response": [ { - "xmlId": "ns-img", - "id": "90" + "id": "90", + "displayName": "Foo Bar DS", + "xmlId": "foo-bar" }, { - "xmlId": "ns-img-secure", - "id": "280" + "id": "92", + "displayName": "Foo Baz DS", + "xmlId": "foo-baz" } ], } diff --git a/traffic_ops/app/lib/API/DeliveryServiceServer.pm b/traffic_ops/app/lib/API/DeliveryServiceServer.pm index 1326267411..c07be679d8 100644 --- a/traffic_ops/app/lib/API/DeliveryServiceServer.pm +++ b/traffic_ops/app/lib/API/DeliveryServiceServer.pm @@ -68,7 +68,7 @@ sub domains { $self->success( \@data ); } -sub create { +sub assign_servers_to_ds { my $self = shift; my $params = $self->req->json; my $ds_id = $params->{dsId}; diff --git a/traffic_ops/app/lib/API/DeliveryServiceUser.pm b/traffic_ops/app/lib/API/DeliveryServiceUser.pm new file mode 100644 index 0000000000..dea69ce264 --- /dev/null +++ b/traffic_ops/app/lib/API/DeliveryServiceUser.pm @@ -0,0 +1,50 @@ +package API::DeliveryServiceUser; +# +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# + +# JvD Note: you always want to put Utils as the first use. Sh*t don't work if it's after the Mojo lines. +use UI::Utils; +use Mojo::Base 'Mojolicious::Controller'; +use Data::Dumper; +use Utils::Helper; + +sub delete { + my $self = shift; + my $ds_id = $self->param('dsId'); + my $user_id = $self->param('userId'); + + if ( !&is_oper($self) ) { + return $self->forbidden(); + } + + my $ds_user = $self->db->resultset('DeliveryserviceTmuser')->search( { deliveryservice => $ds_id, tm_user_id => $user_id }, { prefetch => [ 'deliveryservice', 'tm_user' ] } ); + if ( $ds_user->count == 0 ) { + return $self->not_found(); + } + + my $row = $ds_user->next; + my $rs = $ds_user->delete(); + if ($rs) { + my $msg = "User [ " . $row->tm_user->username . " ] unlinked from deliveryservice [ " . $row->deliveryservice->id . " | " . $row->deliveryservice->xml_id . " ]."; + &log( $self, $msg, "APICHANGE" ); + return $self->success_message($msg); + } + + return $self->alert( "Failed to unlink user from delivery service." ); +} + +1; diff --git a/traffic_ops/app/lib/API/User.pm b/traffic_ops/app/lib/API/User.pm index 13fdc5cec1..ee5ff86e3d 100644 --- a/traffic_ops/app/lib/API/User.pm +++ b/traffic_ops/app/lib/API/User.pm @@ -330,11 +330,10 @@ sub reset_password { } -sub get_available_deliveryservices { +sub get_deliveryservices_not_assigned_to_user { my $self = shift; my @data; my $id = $self->param('id'); - my %dsids; my %takendsids; my $rs_takendsids = undef; @@ -347,13 +346,56 @@ sub get_available_deliveryservices { my $rs_links = $self->db->resultset("Deliveryservice")->search( undef, { order_by => "xml_id" } ); while ( my $row = $rs_links->next ) { if ( !exists( $takendsids{ $row->id } ) ) { - push( @data, { "id" => $row->id, "xmlId" => $row->xml_id } ); + push( @data, { + "id" => $row->id, + "xmlId" => $row->xml_id, + "displayName" => $row->display_name, + } ); } } $self->success( \@data ); } +sub assign_deliveryservices { + my $self = shift; + my $params = $self->req->json; + my $user_id = $params->{userId}; + my $delivery_services = $params->{deliveryServices}; + + if ( !&is_oper($self) ) { + return $self->forbidden(); + } + + if ( ref($delivery_services) ne 'ARRAY' ) { + return $self->alert("Delivery services must be an array"); + } + + my $user = $self->db->resultset('TmUser')->find( { id => $user_id } ); + if ( !defined($user) ) { + return $self->not_found(); + } + + $self->db->txn_begin(); + foreach my $ds_id (@{ $delivery_services }) { + my $ds_exist = $self->db->resultset('Deliveryservice')->find( { id => $ds_id } ); + if ( !defined($ds_exist) ) { + $self->db->txn_rollback(); + return $self->alert("Delivery service with id [ " . $ds_id . " ] doesn't exist"); + } + my $ds_user_exist = $self->db->resultset('DeliveryserviceTmuser')->find( { deliveryservice => $ds_id, tm_user_id => $user_id } ); + if ( !defined($ds_user_exist) ) { + $self->db->resultset('DeliveryserviceTmuser')->create( { deliveryservice => $ds_id, tm_user_id => $user_id } )->insert(); + } + } + $self->db->txn_commit(); + + &log( $self, "Delivery services were assigned to " . $user->username, "APICHANGE" ); + + my $response = $params; + return $self->success($response, "Delivery service assignments complete."); +} + # Read the current user profile and produce the result sub current { my $self = shift; diff --git a/traffic_ops/app/lib/TrafficOpsRoutes.pm b/traffic_ops/app/lib/TrafficOpsRoutes.pm index aa4ac70924..e4db8f29a3 100644 --- a/traffic_ops/app/lib/TrafficOpsRoutes.pm +++ b/traffic_ops/app/lib/TrafficOpsRoutes.pm @@ -491,19 +491,13 @@ sub api_routes { $r->get("/api/$version/deliveryservices")->over( authenticated => 1 )->to( 'Deliveryservice#index', namespace => $namespace ); $r->get( "/api/$version/deliveryservices/:id" => [ id => qr/\d+/ ] )->over( authenticated => 1 )->to( 'Deliveryservice#show', namespace => $namespace ); $r->post("/api/$version/deliveryservices")->over( authenticated => 1 )->to( 'Deliveryservice#create', namespace => $namespace ); + $r->post("/api/$version/deliveryservices")->over( authenticated => 1 )->to( 'Deliveryservice#create', namespace => $namespace ); $r->put("/api/$version/deliveryservices/:id" => [ id => qr/\d+/ ] )->over( authenticated => 1 )->to( 'Deliveryservice#update', namespace => $namespace ); $r->delete("/api/$version/deliveryservices/:id" => [ id => qr/\d+/ ] )->over( authenticated => 1 )->to( 'Deliveryservice#delete', namespace => $namespace ); # get all delivery services associated with a server (from deliveryservice_server table) $r->get( "/api/$version/servers/:id/deliveryservices" => [ id => qr/\d+/ ] )->over( authenticated => 1 )->to( 'Deliveryservice#get_deliveryservices_by_serverId', namespace => $namespace ); - # get all deliveryservices assigned to a user (from deliveryservice_tmuser table) - $r->get( "/api/$version/users/:id/deliveryservices" => [ id => qr/\d+/ ] )->over( authenticated => 1 )->to( 'Deliveryservice#get_deliveryservices_by_userId', namespace => $namespace ); - - # get all deliveryservices available (not assigned) to a user - $r->get("/api/$version/user/:id/deliveryservices/available" => [ id => qr/\d+/ ] )->over( authenticated => 1 ) - ->to( 'User#get_available_deliveryservices', namespace => $namespace ); - # delivery service / server assignments $r->post("/api/$version/deliveryservices/:xml_id/servers")->over( authenticated => 1 ) ->to( 'Deliveryservice#assign_servers', namespace => $namespace ); @@ -575,7 +569,7 @@ sub api_routes { # -- DELIVERYSERVICES: SERVERS # Supports ?orderby=key $r->get("/api/$version/deliveryserviceserver")->over( authenticated => 1 )->to( 'DeliveryServiceServer#index', namespace => $namespace ); - $r->post("/api/$version/deliveryserviceserver")->over( authenticated => 1 )->to( 'DeliveryServiceServer#create', namespace => $namespace ); + $r->post("/api/$version/deliveryserviceserver")->over( authenticated => 1 )->to( 'DeliveryServiceServer#assign_servers_to_ds', namespace => $namespace ); # -- DIVISIONS $r->get("/api/$version/divisions")->over( authenticated => 1 )->to( 'Division#index', namespace => $namespace ); @@ -778,7 +772,14 @@ sub api_routes { $r->put("/api/$version/users/:id" => [ id => qr/\d+/ ] )->over( authenticated => 1 )->to( 'User#update', namespace => $namespace ); $r->post("/api/$version/users")->over( authenticated => 1 )->to( 'User#create', namespace => $namespace ); - # -- USERS: CURRENT USER + # -- USERS: DELIVERY SERVICE ASSIGNMENTS + $r->get( "/api/$version/users/:id/deliveryservices" => [ id => qr/\d+/ ] )->over( authenticated => 1 )->to( 'Deliveryservice#get_deliveryservices_by_userId', namespace => $namespace ); + $r->get("/api/$version/user/:id/deliveryservices/available" => [ id => qr/\d+/ ] )->over( authenticated => 1 ) + ->to( 'User#get_deliveryservices_not_assigned_to_user', namespace => $namespace ); + $r->post("/api/$version/deliveryservice_user")->over( authenticated => 1 )->to( 'User#assign_deliveryservices', namespace => $namespace ); + $r->delete("/api/$version/deliveryservice_user/:dsId/:userId" => [ dsId => qr/\d+/, userId => qr/\d+/ ] )->over( authenticated => 1 )->to( 'DeliveryServiceUser#delete', namespace => $namespace ); + + # -- USERS: CURRENT USER $r->get("/api/$version/user/current")->over( authenticated => 1 )->to( 'User#current', namespace => $namespace ); $r->put("/api/$version/user/current")->over( authenticated => 1 )->to( 'User#update_current', namespace => $namespace ); diff --git a/traffic_ops/app/t/api/1.2/deliveryservice_user.t b/traffic_ops/app/t/api/1.2/deliveryservice_user.t new file mode 100644 index 0000000000..54193831a2 --- /dev/null +++ b/traffic_ops/app/t/api/1.2/deliveryservice_user.t @@ -0,0 +1,97 @@ +package main; +# +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ->json_is( "/response/hostname" => "http://10.75.168.91") +# ->json_is( "/response/ds_assigned/1" => "ds1") +# , 'Does the deliveryservice details return?'; +use Mojo::Base -strict; +use Test::More; +use Test::Mojo; +use DBI; +use JSON; +use strict; +use warnings; +no warnings 'once'; +use warnings 'all'; +use Test::TestHelper; + +#no_transactions=>1 ==> keep fixtures after every execution, beware of duplicate data! +#no_transactions=>0 ==> delete fixtures after every execution + +BEGIN { $ENV{MOJO_MODE} = "test" } + +my $schema = Schema->connect_to_database; +my $dbh = Schema->database_handle; +my $t = Test::Mojo->new('TrafficOps'); + +Test::TestHelper->unload_core_data($schema); +Test::TestHelper->load_core_data($schema); + +ok $t->post_ok( '/login', => form => { u => Test::TestHelper::ADMIN_USER, p => Test::TestHelper::ADMIN_USER_PASSWORD } )->status_is(302) + ->or( sub { diag $t->tx->res->content->asset->{content}; } ), 'Should login?'; + +# Count the 'response number' +my $count_response = sub { + my ( $t, $count ) = @_; + my $json = decode_json( $t->tx->res->content->asset->slurp ); + my $r = $json->{response}; + return $t->success( is( scalar(@$r), $count ) ); +}; + +# there is currently 1 delivery service assigned to user with id=200 +$t->get_ok('/api/1.2/users/200/deliveryservices')->status_is(200)->$count_response(1) + ->or( sub { diag $t->tx->res->content->asset->{content}; } ); + +# there are currently 12 delivery services NOT assigned to user with id=200 +$t->get_ok('/api/1.2/user/200/deliveryservices/available')->status_is(200)->$count_response(12) + ->or( sub { diag $t->tx->res->content->asset->{content}; } ); + +# assign one ds to user with id=200 +ok $t->post_ok('/api/1.2/deliveryservice_user' => {Accept => 'application/json'} => json => { + "userId" => 200, + "deliveryServices" => [ 300 ] + }) + ->status_is(200)->or( sub { diag $t->tx->res->content->asset->{content}; } ) + ->json_is( "/response/userId" => 200 ) + ->json_is( "/response/deliveryServices/0" => 300 ) + ->json_is( "/alerts/0/level" => "success" ) + ->json_is( "/alerts/0/text" => "Delivery service assignments complete." ) + , 'Does the delivery services assign details return?'; + +# there are now 2 delivery services assigned to user with id=200 +$t->get_ok('/api/1.2/users/200/deliveryservices')->status_is(200)->$count_response(2) + ->or( sub { diag $t->tx->res->content->asset->{content}; } ); + +# there are now 11 delivery services NOT assigned to user with id=200 +$t->get_ok('/api/1.2/user/200/deliveryservices/available')->status_is(200)->$count_response(11) + ->or( sub { diag $t->tx->res->content->asset->{content}; } ); + +# now remove ds=300 from user=200 +ok $t->delete_ok('/api/1.2/deliveryservice_user/300/200')->status_is(200)->or( sub { diag $t->tx->res->content->asset->{content}; } ); + +# now remove ds=300 from user=200 again, should fail as it is no longer there +ok $t->delete_ok('/api/1.2/deliveryservice_user/200/200')->status_is(404)->or( sub { diag $t->tx->res->content->asset->{content}; } ); + +# there is now 1 delivery service assigned to user with id=200 +$t->get_ok('/api/1.2/users/200/deliveryservices')->status_is(200)->$count_response(1) + ->or( sub { diag $t->tx->res->content->asset->{content}; } ); + +# there are now 12 delivery services NOT assigned to user with id=200 +$t->get_ok('/api/1.2/user/200/deliveryservices/available')->status_is(200)->$count_response(12) + ->or( sub { diag $t->tx->res->content->asset->{content}; } ); + +ok $t->get_ok('/logout')->status_is(302)->or( sub { diag $t->tx->res->content->asset->{content}; } ); +$dbh->disconnect(); +done_testing(); diff --git a/traffic_ops/experimental/ui/app/src/common/api/UserService.js b/traffic_ops/experimental/ui/app/src/common/api/UserService.js index 40e0fa325e..6fcc2ac689 100644 --- a/traffic_ops/experimental/ui/app/src/common/api/UserService.js +++ b/traffic_ops/experimental/ui/app/src/common/api/UserService.js @@ -98,6 +98,46 @@ var UserService = function(Restangular, $http, $location, $q, authService, httpS ); }; + this.getUnassignedUserDeliveryServices = function(userId) { + var deferred = $q.defer(); + + $http.get(ENV.api['root'] + "user/" + userId + "/deliveryservices/available") + .then( + function(result) { + deferred.resolve(result.data.response); + }, + function(fault) { + deferred.reject(fault); + } + ); + + return deferred.promise; + }; + + this.deleteUserDeliveryService = function(userId, dsId) { + return httpService.delete(ENV.api['root'] + 'deliveryservice_user/' + dsId + '/' + userId) + .then( + function() { + messageModel.setMessages([ { level: 'success', text: 'User and delivery service were unlinked.' } ], false); + }, + function(fault) { + messageModel.setMessages(fault.data.alerts, true); + } + ); + }; + + this.assignUserDeliveryServices = function(userDSMappings) { + return Restangular.service('deliveryservice_user').post(userDSMappings) + .then( + function() { + messageModel.setMessages([ { level: 'success', text: 'Delivery services linked to user' } ], false); + }, + function(fault) { + messageModel.setMessages(fault.data.alerts, false); + } + ); + }; + }; UserService.$inject = ['Restangular', '$http', '$location', '$q', 'authService', 'httpService', 'locationUtils', 'userModel', 'messageModel', 'ENV']; diff --git a/traffic_ops/experimental/ui/app/src/common/modules/table/userDeliveryServices/TableUserDSUnassignedController.js b/traffic_ops/experimental/ui/app/src/common/modules/table/userDeliveryServices/TableUserDSUnassignedController.js new file mode 100644 index 0000000000..746433eeef --- /dev/null +++ b/traffic_ops/experimental/ui/app/src/common/modules/table/userDeliveryServices/TableUserDSUnassignedController.js @@ -0,0 +1,70 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +var TableUserDSUnassignedController = function(user, deliveryServices, $scope, $uibModalInstance) { + + var selectedDeliveryServices = []; + + $scope.user = user; + + $scope.unassignedDeliveryServices = deliveryServices; + + var addDS = function(dsId) { + if (_.indexOf(selectedDeliveryServices, dsId) == -1) { + selectedDeliveryServices.push(dsId); + } + }; + + var removeDS = function(dsId) { + selectedDeliveryServices = _.without(selectedDeliveryServices, dsId); + }; + + $scope.updateDeliveryServices = function($event, dsId) { + var checkbox = $event.target; + if (checkbox.checked) { + addDS(dsId); + } else { + removeDS(dsId); + } + }; + + $scope.submit = function() { + $uibModalInstance.close(selectedDeliveryServices); + }; + + $scope.cancel = function () { + $uibModalInstance.dismiss('cancel'); + }; + + angular.element(document).ready(function () { + $('#userDSUnassignedTable').dataTable({ + "aLengthMenu": [[25, 50, 100, -1], [25, 50, 100, "All"]], + "iDisplayLength": 25, + "order": [[ 1, 'asc' ]], + "columnDefs": [ + { 'orderable': false, 'targets': 0 }, + { "width": "5%", "targets": 0 } + ] + }); + }); + +}; + +TableUserDSUnassignedController.$inject = ['user', 'deliveryServices', '$scope', '$uibModalInstance']; +module.exports = TableUserDSUnassignedController; diff --git a/traffic_ops/experimental/ui/app/src/common/modules/table/userDeliveryServices/TableUserDeliveryServicesController.js b/traffic_ops/experimental/ui/app/src/common/modules/table/userDeliveryServices/TableUserDeliveryServicesController.js index a04bbf8135..763ebe4aaf 100644 --- a/traffic_ops/experimental/ui/app/src/common/modules/table/userDeliveryServices/TableUserDeliveryServicesController.js +++ b/traffic_ops/experimental/ui/app/src/common/modules/table/userDeliveryServices/TableUserDeliveryServicesController.js @@ -17,18 +17,47 @@ * under the License. */ -var TableUserDeliveryServicesController = function(user, userDeliveryServices, $scope, $state, locationUtils) { +var TableUserDeliveryServicesController = function(user, userDeliveryServices, $scope, $state, $uibModal, locationUtils, userService) { $scope.user = user; $scope.userDeliveryServices = userDeliveryServices; - $scope.addDeliveryService = function() { - alert('not hooked up yet: addDeliveryService to user'); + $scope.removeDS = function(dsId) { + userService.deleteUserDeliveryService(user.id, dsId) + .then( + function() { + $scope.refresh(); + } + ); }; - $scope.removeDeliveryService = function() { - alert('not hooked up yet: removeDeliveryService from user'); + $scope.selectDSs = function() { + var modalInstance = $uibModal.open({ + templateUrl: 'common/modules/table/userDeliveryServices/table.userDSUnassigned.tpl.html', + controller: 'TableUserDSUnassignedController', + size: 'lg', + resolve: { + user: function() { + return user; + }, + deliveryServices: function(userService) { + return userService.getUnassignedUserDeliveryServices(user.id); + } + } + }); + modalInstance.result.then(function(selectedDSIds) { + console.log(selectedDSIds); + var userDSAssignments = { userId: user.id, deliveryServices: selectedDSIds }; + userService.assignUserDeliveryServices(userDSAssignments) + .then( + function() { + $scope.refresh(); + } + ); + }, function () { + // do nothing + }); }; $scope.refresh = function() { @@ -47,5 +76,5 @@ var TableUserDeliveryServicesController = function(user, userDeliveryServices, $ }; -TableUserDeliveryServicesController.$inject = ['user', 'userDeliveryServices', '$scope', '$state', 'locationUtils']; +TableUserDeliveryServicesController.$inject = ['user', 'userDeliveryServices', '$scope', '$state', '$uibModal', 'locationUtils', 'userService']; module.exports = TableUserDeliveryServicesController; diff --git a/traffic_ops/experimental/ui/app/src/common/modules/table/userDeliveryServices/index.js b/traffic_ops/experimental/ui/app/src/common/modules/table/userDeliveryServices/index.js index 84a696277e..55ba9a1fb4 100644 --- a/traffic_ops/experimental/ui/app/src/common/modules/table/userDeliveryServices/index.js +++ b/traffic_ops/experimental/ui/app/src/common/modules/table/userDeliveryServices/index.js @@ -18,4 +18,5 @@ */ module.exports = angular.module('trafficOps.table.userDeliveryServices', []) - .controller('TableUserDeliveryServicesController', require('./TableUserDeliveryServicesController')); + .controller('TableUserDeliveryServicesController', require('./TableUserDeliveryServicesController')) + .controller('TableUserDSUnassignedController', require('./TableUserDSUnassignedController')); diff --git a/traffic_ops/experimental/ui/app/src/common/modules/table/userDeliveryServices/table.userDSUnassigned.tpl.html b/traffic_ops/experimental/ui/app/src/common/modules/table/userDeliveryServices/table.userDSUnassigned.tpl.html new file mode 100644 index 0000000000..e5e10187f1 --- /dev/null +++ b/traffic_ops/experimental/ui/app/src/common/modules/table/userDeliveryServices/table.userDSUnassigned.tpl.html @@ -0,0 +1,47 @@ + + + + + + + diff --git a/traffic_ops/experimental/ui/app/src/common/modules/table/userDeliveryServices/table.userDeliveryServices.tpl.html b/traffic_ops/experimental/ui/app/src/common/modules/table/userDeliveryServices/table.userDeliveryServices.tpl.html index 1afa120bac..c0122cbca5 100644 --- a/traffic_ops/experimental/ui/app/src/common/modules/table/userDeliveryServices/table.userDeliveryServices.tpl.html +++ b/traffic_ops/experimental/ui/app/src/common/modules/table/userDeliveryServices/table.userDeliveryServices.tpl.html @@ -25,7 +25,7 @@
  • Delivery Services
  • - +
    @@ -46,7 +46,7 @@ {{::deliveryService.xmlId}} {{::deliveryService.orgServerFqdn}} {{::deliveryService.cdnName}} - +