diff --git a/main.py b/main.py index 5701c8af..5c132cfd 100644 --- a/main.py +++ b/main.py @@ -145,11 +145,89 @@ def unsubscribe_to_resource(resource_type, resource_id): @login_required def enroll_request(resource_type, resource_id): actor_id = session.get('actor_id') if session.has_key('actor_id') else None - print 'zzzzz', actor_id, resource_id resp = ServiceApi.enroll_request(resource_id, actor_id) - return jsonify(data=actor_id) - # return render_json_response(resp) + return render_json_response(resp) + +@app.route('//status//request_role/', methods=['POST']) +@app.route('//face//request_role/', methods=['POST']) +@app.route('//related//request_role/', methods=['POST']) +@login_required +def request_role(resource_type, resource_id): + actor_id = session.get('actor_id') if session.has_key('actor_id') else None + role_name = request.form.get('role_name', None) + + resp = ServiceApi.request_role(resource_id, actor_id, role_name) + return render_json_response(resp) + +@app.route('//status//invite_user/', methods=['POST']) +@app.route('//face//invite_user/', methods=['POST']) +@app.route('//related//invite_user/', methods=['POST']) +@login_required +def invite_user(resource_type, resource_id): + user_id = request.form.get('user_id', None) + + resp = ServiceApi.invite_user(resource_id, user_id) + return render_json_response(resp) + +@app.route('//status//offer_user_role/', methods=['POST']) +@app.route('//face//offer_user_role/', methods=['POST']) +@app.route('//related//offer_user_role/', methods=['POST']) +@login_required +def offer_user_role(resource_type, resource_id): + user_id = request.form.get('user_id', None) + role_name = request.form.get('role_name', None) + + resp = ServiceApi.offer_user_role(resource_id, user_id, role_name) + return render_json_response(resp) + +@app.route('//status//request_access/', methods=['POST']) +@app.route('//face//request_access/', methods=['POST']) +@app.route('//related//request_access/', methods=['POST']) +@login_required +def request_access(resource_type, resource_id): + org_id = request.form.get('org_id', None) + actor_id = session.get('actor_id') if session.has_key('actor_id') else None + resp = ServiceApi.request_access(resource_id, actor_id, org_id) + return render_json_response(resp) + +@app.route('//status//release_access/', methods=['POST']) +@app.route('//face//release_access/', methods=['POST']) +@app.route('//related//release_access/', methods=['POST']) +@login_required +def release_access(resource_type, resource_id): + commitment_id = request.form.get('commitment_id', None) + + resp = ServiceApi.release_access(commitment_id) + return render_json_response(resp) + +@app.route('//status//request_exclusive_access/', methods=['POST']) +@app.route('//face//request_exclusive_access/', methods=['POST']) +@app.route('//related//request_exclusive_access/', methods=['POST']) +@login_required +def request_exclusive_access(resource_type, resource_id): + expiration = int(request.form.get('expiration', None)) + curtime = int(round(time.time() * 1000)) + full_expiration = curtime + (expiration * 60 * 60 * 1000) # in ms + actor_id = session.get('actor_id') if session.has_key('actor_id') else None + org_id = request.form.get('org_id', None) + + resp = ServiceApi.request_exclusive_access(resource_id, actor_id, org_id, full_expiration) + return render_json_response(resp) + +@app.route('/negotiation/accept/', methods=['POST']) +@login_required +def accept_negotiation(): + negotiation_id = request.form.get('negotiation_id', None) + resp = ServiceApi.accept_negotiation(negotiation_id) + return render_json_response(resp) + +@app.route('/negotiation/reject/', methods=['POST']) +@login_required +def reject_negotiation(): + negotiation_id = request.form.get('negotiation_id', None) + resp = ServiceApi.reject_negotiation(negotiation_id) + return render_json_response(resp) @app.route('//status//transition/', methods=['POST']) @app.route('//face//transition/', methods=['POST']) @@ -480,7 +558,7 @@ def session_info(): session_values = {'user_id': None, 'roles': None, 'is_registered': False, 'is_logged_in': False, 'ui_mode': UI_MODE, 'version': version } if session.has_key('user_id'): - session_values.update({'name': session['name'], 'user_id': session['user_id'], 'roles': session['roles'], 'is_registered': session['is_registered'], 'is_logged_in': True}) + session_values.update({'name': session['name'], 'user_id': session['user_id'], 'actor_id': session['actor_id'], 'roles': session['roles'], 'is_registered': session['is_registered'], 'is_logged_in': True}) return jsonify(data=session_values) diff --git a/service_api.py b/service_api.py index a816b06a..22ab0961 100644 --- a/service_api.py +++ b/service_api.py @@ -101,11 +101,105 @@ def delete_user_subscription(notification_id): @staticmethod def enroll_request(resource_id, actor_id): - print 'zzzzz', resource_id, actor_id - return True - # return service_gateway_post('user_notification', 'delete_notification', params={'notification_id': notification_id}) + sap = {'type_': 'EnrollmentProposal', + 'originator': 1, + 'consumer': actor_id, + 'provider': resource_id, + 'proposal_status': 1 } + return service_gateway_post('org_management', 'negotiate', params={'sap':sap}) + @staticmethod + def request_role(resource_id, actor_id, role_name): + sap = {'type_': 'RequestRoleProposal', + 'originator': 1, + 'consumer': actor_id, + 'provider': resource_id, + 'proposal_status': 1, + 'role_name': role_name } + + return service_gateway_post('org_management', 'negotiate', params={'sap':sap}) + + @staticmethod + def invite_user(resource_id, user_id): + # look up actor id from user id + actor_id = service_gateway_get('resource_registry', 'find_subjects', params={'predicate': 'hasInfo', 'object': user_id, 'id_only': True})[0] + + sap = {'type_': 'EnrollmentProposal', + 'originator': 2, + 'consumer': actor_id, + 'provider': resource_id, + 'proposal_status': 1 } + + return service_gateway_post('org_management', 'negotiate', params={'negotiation_type': 2, + 'sap':sap}) + + @staticmethod + def offer_user_role(resource_id, user_id, role_name): + # look up actor id from user id + actor_id = service_gateway_get('resource_registry', 'find_subjects', params={'predicate': 'hasInfo', 'object': user_id, 'id_only': True})[0] + + sap = {'type_': 'RequestRoleProposal', + 'originator': 2, + 'consumer': actor_id, + 'provider': resource_id, + 'proposal_status': 1, + 'role_name': role_name } + + return service_gateway_post('org_management', 'negotiate', params={'negotiation_type': 2, + 'sap':sap}) + + @staticmethod + def request_access(resource_id, actor_id, org_id): + sap = {'type_': 'AcquireResourceProposal', + 'originator': 1, + 'consumer': actor_id, + 'provider': org_id, + 'proposal_status': 1, + 'resource_id': resource_id } + + return service_gateway_post('org_management', 'negotiate', params={'sap':sap}) + @staticmethod + def release_access(commitment_id): + return service_gateway_post('org_management', 'release_commitment', params={'commitment_id':commitment_id}) + + @staticmethod + def request_exclusive_access(resource_id, actor_id, org_id, expiration): + sap = {'type_': 'AcquireResourceExclusiveProposal', + 'originator': 1, + 'consumer': actor_id, + 'provider': org_id, + 'proposal_status': 1, + 'resource_id': resource_id, + 'expiration': expiration} + + return service_gateway_post('org_management', 'negotiate', params={'sap':sap}) + + @staticmethod + def _accept_reject_negotiation(negotiation_id, accept_value): + if not accept_value in [3,4]: + return error_message("Unknown accept_value %s" % accept_value) + + # read the negotiation first so we can determine the sap to send + negotiation = service_gateway_get('resource_registry', 'read', params={'object_id': negotiation_id}) + + sap = {'type_': negotiation['proposals'][0]['type_'], + 'negotiation_id': negotiation_id, + 'sequence_num': int(negotiation['proposals'][0]['sequence_num']) + 1, + 'originator': 2, + 'proposal_status': accept_value, + 'consumer': negotiation['proposals'][0]['consumer'], + 'provider': negotiation['proposals'][0]['provider']} + + return service_gateway_post('org_management', 'negotiate', params={'sap':sap}) + + @staticmethod + def accept_negotiation(negotiation_id): + return ServiceApi._accept_reject_negotiation(negotiation_id, 3) # 3 == accepted + + @staticmethod + def reject_negotiation(negotiation_id): + return ServiceApi._accept_reject_negotiation(negotiation_id, 4) # 4 == rejected @staticmethod def get_event_types(): diff --git a/static/js/ion-ux.js b/static/js/ion-ux.js index 9f42d6f5..9ff2595e 100644 --- a/static/js/ion-ux.js +++ b/static/js/ion-ux.js @@ -37,7 +37,7 @@ IONUX = { }, is_owner: function(){ var user_id = IONUX.SESSION_MODEL.get('user_id'); - var owner_match = _.findWhere(MODEL_DATA.owners[0], {_id: user_id}) ? true : false; + var owner_match = _.findWhere(MODEL_DATA.owners, {_id: user_id}) ? true : false; return owner_match; } } diff --git a/static/js/ux-models.js b/static/js/ux-models.js index 463b84fc..99864fe9 100644 --- a/static/js/ux-models.js +++ b/static/js/ux-models.js @@ -64,7 +64,7 @@ IONUX.Models.Session = Backbone.Model.extend({ return this.get('is_registered'); }, is_resource_owner: function(){ - return _.findWhere(MODEL_DATA.owners[0], {_id: this.get('user_id')}) ? true : false; + return _.findWhere(MODEL_DATA.owners, {_id: this.get('user_id')}) ? true : false; } }); diff --git a/static/js/ux-router.js b/static/js/ux-router.js index 28eaef0a..e8099001 100644 --- a/static/js/ux-router.js +++ b/static/js/ux-router.js @@ -194,6 +194,28 @@ function replace_url_with_html_links(text) { return text.replace(exp,"$1"); }; +// Filter method for open negotiations shown in a data table +// If this method returns true, there should be a column indicating +// the view will be shown on row click. +function negotiation_show_controls(row_data) { + // row data first column should always be of form resource_id/resource_type + // use this info to go and look up the real item, because UI columns may change + var neg = _.findWhere(window.MODEL_DATA.open_negotiations, {_id:row_data[0].split("::")[0]}); + if (neg && + window.MODEL_DATA.resource_type == "Org" && + neg.proposals[0].originator == 1 && // originator == user proposed (1) + _.contains(IONUX.SESSION_MODEL.get('roles')[window.MODEL_DATA.resource.org_governance_name], 'ORG_MANAGER')) + return true; + + if (neg && + window.MODEL_DATA.resource_type == "UserInfo" && + neg.proposals[0].originator == 2 && // originator == org proposed (2) + neg.proposals[0].consumer == IONUX.SESSION_MODEL.get('actor_id')) // this is likely redundant + return true; + + return false; +}; + // Returns a displayable resource type for the resource_type given. // If the type is not displayable, traverse up the heirarchy of resources // until one is found. @@ -287,7 +309,13 @@ function render_page(resource_type, resource_id, model) { var data_path = $(el).data('path'); var raw_table_data = get_descendant_properties(window.MODEL_DATA, data_path); if (!_.isEmpty(raw_table_data)) { - var table = new IONUX.Views.DataTable({el: $(el), data: raw_table_data}); + var opts = {el: $(el), data: raw_table_data} + if (data_path == "open_negotiations") { + _.extend(opts, {popup_view: IONUX.Views.NegotiationCommands, + popup_label: "Accept/Reject", + popup_filter_method: negotiation_show_controls}); + } + var table = new IONUX.Views.DataTable(opts); } else { var table = new IONUX.Views.DataTable({el: $(el), data: []}); }; @@ -359,9 +387,6 @@ function render_page(resource_type, resource_id, model) { case 'Recent Events': new IONUX.Views.EventActions({el:$(el)}); break; - case 'Participants': - new IONUX.Views.NegotiationActions({el: $(el)}); - break; default: new IONUX.Views.GroupActions({el:$(el)}); }; diff --git a/static/js/ux-templates.js b/static/js/ux-templates.js index 874040da..8f5997c7 100644 --- a/static/js/ux-templates.js +++ b/static/js/ux-templates.js @@ -3,4 +3,9 @@ IONUX.Templates = { modal_template: '', -} \ No newline at end of file + full_modal_template: '', +} diff --git a/static/js/ux-views-actionmenu.js b/static/js/ux-views-actionmenu.js index ba5e3b86..a0a721c5 100644 --- a/static/js/ux-views-actionmenu.js +++ b/static/js/ux-views-actionmenu.js @@ -64,7 +64,64 @@ IONUX.Views.ViewActions = IONUX.Views.ActionMenu.extend({ modal_template: '