diff --git a/seahub/templates/js/templates.html b/seahub/templates/js/templates.html index 8dc4591565..1d50e82ec2 100644 --- a/seahub/templates/js/templates.html +++ b/seahub/templates/js/templates.html @@ -263,6 +263,7 @@ <% } %> <% } else { %> <% if (is_staff) { %> +
@@ -320,6 +321,7 @@
<% } %> - <% if (!is_virtual && (is_repo_owner || is_admin)) { %> + <% if (enable_dir_private_share) { %> {# dir private share #} <% if (!repo_encrypted) { %>
<% } else { %> @@ -1284,7 +1287,7 @@ @@ -1320,7 +1323,7 @@ @@ -1331,7 +1334,7 @@

- <% } %> {# if (!is_virtual && is_repo_owner) #} + <% } %> {# end of 'dir private share' #} <% } %> {# if is_dir #}
diff --git a/static/scripts/app/views/dir.js b/static/scripts/app/views/dir.js index 1e0cc033b0..cde2157ed3 100644 --- a/static/scripts/app/views/dir.js +++ b/static/scripts/app/views/dir.js @@ -450,6 +450,7 @@ define([ }, success: function() { _this.dir.user_can_set_folder_perm = false; + _this.is_address_book_group_admin = false; if (_this.contextOptions && _this.contextOptions.group_id) { // the repo is in a group _this.getGroupInfo(); @@ -490,6 +491,9 @@ define([ if (data.parent_group_id != 0 && // address book group $.inArray(app.pageOptions.username, data.admins) != -1) { // user is group admin _this.dir.user_can_set_folder_perm = true; + + _this.is_address_book_group_admin = true; + _this.parent_group_id = data.parent_group_id; } _this.reset(); }, @@ -860,6 +864,13 @@ define([ }; if (app.pageOptions.is_pro) { options.is_admin = dir.is_admin; + + if (this.is_address_book_group_admin) { + $.extend(options, { + is_address_book_group_admin: true, + parent_group_id: this.parent_group_id + }); + } } new ShareView(options); }, diff --git a/static/scripts/app/views/folder-share-item.js b/static/scripts/app/views/folder-share-item.js index d5f7e73e45..36cd1283ec 100644 --- a/static/scripts/app/views/folder-share-item.js +++ b/static/scripts/app/views/folder-share-item.js @@ -22,7 +22,9 @@ define([ // show info about 'is_admin' this.show_admin = false; - if (app.pageOptions.is_pro && this.path == '/') { + if (app.pageOptions.is_pro && + this.path == '/' && + !this.item_data.parent_group_id) { // not for group owned repo this.show_admin = true; } @@ -60,27 +62,55 @@ define([ editPerm: function (e) { var _this = this; - var item_data = this.item_data; - var url = Common.getUrl({ - name: 'dir_shared_items', - repo_id: this.repo_id - }) + '?p=' + encodeURIComponent(this.path); - if (item_data.for_user) { - url += '&share_type=user&username=' + encodeURIComponent(item_data.user_email); - } else { - url += '&share_type=group&group_id=' + encodeURIComponent(item_data.group_id); - } var perm = $(e.currentTarget).val(); + var item_data = this.item_data; + var url, method, data; + if (item_data.parent_group_id) { // group owned repo + if (item_data.for_user) { + url = Common.getUrl({ + name: 'group_owned_repo_user_share', + repo_id: this.repo_id + }); + data = { + 'username': item_data.user_email, + 'permission': perm, + 'path': this.path + }; + } else { + url = Common.getUrl({ + name: 'group_owned_repo_group_share', + repo_id: this.repo_id + }); + data = { + 'group_id': item_data.group_id, + 'permission': perm, + 'path': this.path + }; + } + method = 'PUT'; + } else { + url = Common.getUrl({ + name: 'dir_shared_items', + repo_id: this.repo_id + }) + '?p=' + encodeURIComponent(this.path); + if (item_data.for_user) { + url += '&share_type=user&username=' + encodeURIComponent(item_data.user_email); + } else { + url += '&share_type=group&group_id=' + encodeURIComponent(item_data.group_id); + } + data = { + 'permission': perm + }; + method = 'POST'; + } $.ajax({ url: url, dataType: 'json', - method: 'POST', + method: method, beforeSend: Common.prepareCSRFToken, - data: { - 'permission': perm - }, + data: data, success: function () { - if (perm == 'admin'){ + if (perm == 'admin') { item_data.is_admin = true; item_data.permission = 'rw'; } else { @@ -108,20 +138,45 @@ define([ del: function () { var _this = this; var item_data = this.item_data; - var url = Common.getUrl({ - name: 'dir_shared_items', - repo_id: this.repo_id - }) + '?p=' + encodeURIComponent(this.path); - if (item_data.for_user) { - url += '&share_type=user&username=' + encodeURIComponent(item_data.user_email); + var url, data = {}; + + if (item_data.parent_group_id) { // group owned repo + if (item_data.for_user) { + url = Common.getUrl({ + name: 'group_owned_repo_user_share', + repo_id: this.repo_id + }); + data = { + 'username': item_data.user_email, + 'path': this.path + }; + } else { + url = Common.getUrl({ + name: 'group_owned_repo_group_share', + repo_id: this.repo_id + }); + data = { + 'group_id': item_data.group_id, + 'p': this.path // TODO: 'p'? + }; + } } else { - url += '&share_type=group&group_id=' + encodeURIComponent(item_data.group_id); + url = Common.getUrl({ + name: 'dir_shared_items', + repo_id: this.repo_id + }) + '?p=' + encodeURIComponent(this.path); + if (item_data.for_user) { + url += '&share_type=user&username=' + encodeURIComponent(item_data.user_email); + } else { + url += '&share_type=group&group_id=' + encodeURIComponent(item_data.group_id); + } } $.ajax({ url: url, dataType: 'json', method: 'DELETE', beforeSend: Common.prepareCSRFToken, + data: data, success: function () { _this.remove(); }, diff --git a/static/scripts/app/views/group-repo.js b/static/scripts/app/views/group-repo.js index 6e31707e59..5b613c627c 100644 --- a/static/scripts/app/views/group-repo.js +++ b/static/scripts/app/views/group-repo.js @@ -16,6 +16,7 @@ define([ template: _.template($('#group-repo-tmpl').html()), mobileTemplate: _.template($('#group-repo-mobile-tmpl').html()), + renameTemplate: _.template($("#repo-rename-form-template").html()), events: { @@ -259,6 +260,14 @@ define([ if (app.pageOptions.is_pro) { options.is_admin = this.model.get('is_admin'); // 'is_admin': repo is shared to the group with 'admin' perm + + // private share group owned repo + if (this.parent_group_id && this.is_staff) { + $.extend(options, { + 'is_address_book_group_admin': true, + 'parent_group_id': this.parent_group_id + }); + } } new ShareView(options); diff --git a/static/scripts/app/views/share.js b/static/scripts/app/views/share.js index 2b054dd78d..e3c6925007 100644 --- a/static/scripts/app/views/share.js +++ b/static/scripts/app/views/share.js @@ -15,8 +15,14 @@ define([ initialize: function(options) { this.is_repo_owner = options.is_repo_owner; + // for shared repo this.is_admin = options.is_admin; // true or undefined + + // for group owned repo + this.is_address_book_group_admin = options.is_address_book_group_admin; + this.parent_group_id = options.parent_group_id; + this.is_virtual = options.is_virtual; this.user_perm = options.user_perm; this.repo_id = options.repo_id; @@ -25,6 +31,15 @@ define([ this.obj_name = options.obj_name; this.is_dir = options.is_dir; + // share to user/group + var enable_dir_private_share = false; + if (!this.is_virtual && + (this.is_repo_owner || this.is_admin || + (this.is_address_book_group_admin && this.dirent_path == '/'))) { + enable_dir_private_share = true; + } + this.enable_dir_private_share = enable_dir_private_share; + this.render(); if ($(window).width() >= 768) { @@ -47,7 +62,7 @@ define([ if (this.user_perm == 'rw' && !this.repo_encrypted && app.pageOptions.can_generate_upload_link) { this.uploadLinkPanelInit(); } - if (!this.is_virtual && (this.is_repo_owner || this.is_admin)) { + if (this.enable_dir_private_share) { this.dirUserSharePanelInit(); this.dirGroupSharePanelInit(); @@ -64,19 +79,27 @@ define([ }, render: function () { + var show_admin_perm_option = false; + if (app.pageOptions.is_pro && + this.dirent_path == '/' && // only for repo + !this.parent_group_id) { // not for group owned repo + show_admin_perm_option = true; + } + this.$el.html(this.template({ title: gettext("Share {placeholder}") .replace('{placeholder}', '' + Common.HTMLescape(this.obj_name) + ''), + is_dir: this.is_dir, - is_repo_owner: this.is_repo_owner, - is_admin: this.is_admin, - is_virtual: this.is_virtual, + + enable_dir_private_share: this.enable_dir_private_share, + show_admin_perm_option: show_admin_perm_option, + user_perm: this.user_perm, repo_id: this.repo_id, - can_generate_share_link: app.pageOptions.can_generate_share_link, - can_generate_upload_link: app.pageOptions.can_generate_upload_link, repo_encrypted: this.repo_encrypted, - dirent_path: this.dirent_path + can_generate_share_link: app.pageOptions.can_generate_share_link, + can_generate_upload_link: app.pageOptions.can_generate_upload_link })); return this; @@ -572,23 +595,63 @@ define([ }); }, + prepareUserItemData: function(item) { + var item_data = { + 'for_user': true + }; + if (this.parent_group_id) { // group owned repo + // [{permission: "rw", user_name: "llj", user_email: "llj@1.com", user_contact_email: "llj@1.com"}] + $.extend(item_data, { + "user_email": item.user_email, + "user_name": item.user_name, + "permission": item.permission, + 'parent_group_id': this.parent_group_id + }); + } else { + $.extend(item_data, { + "user_email": item.user_info.name, + "user_name": item.user_info.nickname, + "permission": item.permission, + 'is_admin': item.is_admin + }); + } + + return item_data; + }, + dirUserSharePanelInit: function() { + var _this = this; + var $loadingTip = this.$('.loading-tip').show(); var $panel = this.$('#dir-user-share'); var $table = $('table', $panel); var $add_item = $('#add-dir-user-share-item'); + var repo_id = this.repo_id, path = this.dirent_path; - - $.ajax({ - url: Common.getUrl({ + var url, data; + if (this.parent_group_id) { + url = Common.getUrl({ + name: 'group_owned_repo_user_share', + repo_id: repo_id + }); + data = { + 'path': path + }; + } else { + url = Common.getUrl({ name: 'dir_shared_items', repo_id: repo_id - }), - data: { + }); + data = { 'p': path, 'share_type': 'user' - }, + }; + } + + $.ajax({ + url: url, + data: data, cache: false, dataType: 'json', success: function(data) { @@ -596,13 +659,7 @@ define([ var new_item = new FolderShareItemView({ 'repo_id': repo_id, 'path': path, - 'item_data': { - "user_email": item.user_info.name, - "user_name": item.user_info.nickname, - "permission": item.permission, - 'is_admin': item.is_admin, - 'for_user': true - } + 'item_data': _this.prepareUserItemData(item) }); $add_item.after(new_item.el); }); @@ -630,43 +687,144 @@ define([ }); }, + prepareGroupItemData: function(item) { + var item_data = { + 'for_user': false + }; + if (this.parent_group_id) { // address book group + $.extend(item_data, { + "group_id": item.group_id, + "group_name": item.group_name, + "permission": item.permission, + "parent_group_id": this.parent_group_id + }); + } else { + $.extend(item_data, { + "group_id": item.group_info.id, + "group_name": item.group_info.name, + "permission": item.permission, + 'is_admin': item.is_admin + }); + } + + return item_data; + }, + + // for common repo + prepareAvailableGroups: function(options) { + var groups = []; + + if (app.pageOptions.enable_share_to_all_groups) { + $.ajax({ + url: Common.getUrl({ + name: 'shareable_groups' + }), + type: 'GET', + dataType: 'json', + cache: false, + success: function(data){ + for (var i = 0, len = data.length; i < len; i++) { + groups.push({ + 'id': data[i].id, + 'name': data[i].name + }); + } + groups.sort(function(a, b) { + return Common.compareTwoWord(a.name, b.name); + }); + }, + error: function(xhr, textStatus, errorThrown) { + // do nothing + }, + complete: function() { + options.callback(groups); + } + }); + } else { + groups = app.pageOptions.joined_groups_exclude_address_book || []; + options.callback(groups); + } + }, + + // for group owned repo + prepareAvailableGroupsForGroupOwnedRepo: function(options) { + var groups = []; + $.ajax({ + url: Common.getUrl({ + name: 'all_groups' + }), + type: 'GET', + dataType: 'json', + cache: false, + success: function(data){ + for (var i = 0, len = data.length; i < len; i++) { + groups.push({ + 'id': data[i].id, + 'name': data[i].name + }); + } + groups.sort(function(a, b) { + return Common.compareTwoWord(a.name, b.name); + }); + }, + error: function(xhr, textStatus, errorThrown) { + // do nothing + }, + complete: function() { + options.callback(groups); + } + }); + }, + dirGroupSharePanelInit: function() { + var _this = this; + var $loadingTip = this.$('.loading-tip').show(); var $panel = this.$('#dir-group-share'); var $table = $('table', $panel); var $add_item = $('#add-dir-group-share-item'); + + var url, data; var repo_id = this.repo_id, path = this.dirent_path; - $.ajax({ - url: Common.getUrl({ + if (this.parent_group_id) { // group owned repo + url = Common.getUrl({ + name: 'group_owned_repo_group_share', + repo_id: repo_id + }); + data = { + 'path': path + }; + } else { + url = Common.getUrl({ name: 'dir_shared_items', repo_id: repo_id - }), - data: { + }); + data = { 'p': path, 'share_type': 'group' - }, + }; + } + + $.ajax({ + url: url, + data: data, cache: false, dataType: 'json', success: function(data) { + // for 'group owned repo', the data is like + // `[{"permission":"rw","group_id":4,"group_name":"ab group"}]` $(data).each(function(index, item) { var new_item = new FolderShareItemView({ 'repo_id': repo_id, 'path': path, - 'item_data': { - "group_id": item.group_info.id, - "group_name": item.group_info.name, - "permission": item.permission, - 'is_admin': item.is_admin, - 'for_user': false - } + 'item_data': _this.prepareGroupItemData(item) }); $add_item.after(new_item.el); }); - var groups = []; - var prepareGroupsSelector = function() { + var prepareGroupsSelector = function(groups) { var g_opts = ''; for (var i = 0, len = groups.length; i < len; i++) { g_opts += ''; @@ -675,49 +833,12 @@ define([ placeholder: gettext("Select groups"), escapeMarkup: function(m) { return m; } }); - }; - if (app.pageOptions.enable_share_to_all_groups) { - $.ajax({ - url: Common.getUrl({ - name: 'shareable_groups' - }), - type: 'GET', - dataType: 'json', - cache: false, - success: function(data){ - for (var i = 0, len = data.length; i < len; i++) { - groups.push({ - 'id': data[i].id, - 'name': data[i].name - }); - } - groups.sort(function(a, b) { - return Common.compareTwoWord(a.name, b.name); - }); - }, - error: function(xhr, textStatus, errorThrown) { - var pre_msg = gettext("Failed to fetch groups:"); - var err_msg; - if (xhr.responseText) { - if (xhr.status == 403) { - err_msg = gettext("Permission error"); - } else { - err_msg = xhr.responseJSON.error_msg ? xhr.responseJSON.error_msg : gettext('Error'); - } - } else { - err_msg = gettext('Please check the network.'); - } - $('.error', $panel).html(pre_msg + ' ' + err_msg).show(); - }, - complete: function() { - prepareGroupsSelector(); - $table.removeClass('hide'); - } - }); - } else { - groups = app.pageOptions.joined_groups_exclude_address_book || []; - prepareGroupsSelector(); $table.removeClass('hide'); + }; + if (_this.parent_group_id) { // group owned repo + _this.prepareAvailableGroupsForGroupOwnedRepo({'callback': prepareGroupsSelector}); + } else { + _this.prepareAvailableGroups({'callback': prepareGroupsSelector}); } }, error: function(xhr, textStatus, errorThrown) { @@ -744,6 +865,8 @@ define([ }, dirUserShare: function () { + var _this = this; + var $panel = $('#dir-user-share'); var $form = this.$('#add-dir-user-share-item'); // pseudo form @@ -761,34 +884,47 @@ define([ var $error = $('.error', $panel); var $submitBtn = $('[type="submit"]', $form); - Common.disableButton($submitBtn); - $.ajax({ - url: Common.getUrl({ + var url, method, data; + if (this.parent_group_id) { // group owned repo + url = Common.getUrl({ + name: 'group_owned_repo_user_share', + repo_id: repo_id + }); + method = 'POST'; + data = { + 'permission': perm, + 'path': path, + 'username': emails.split(',') + }; + } else { + url = Common.getUrl({ name: 'dir_shared_items', repo_id: repo_id - }) + '?p=' + encodeURIComponent(path), - dataType: 'json', - method: 'PUT', - beforeSend: Common.prepareCSRFToken, - traditional: true, - data: { + }) + '?p=' + encodeURIComponent(path); + method = 'PUT'; + data = { 'share_type': 'user', 'username': emails.split(','), 'permission': perm - }, + }; + } + + Common.disableButton($submitBtn); + $.ajax({ + url: url, + dataType: 'json', + method: method, + beforeSend: Common.prepareCSRFToken, + traditional: true, + data: data, success: function(data) { + // success: [{permission: "rw", user_name: "llj", user_email: "llj@1.com", user_contact_email: "llj@1.com"}] if (data.success.length > 0) { $(data.success).each(function(index, item) { var new_item = new FolderShareItemView({ 'repo_id': repo_id, 'path': path, - 'item_data': { - "user_email": item.user_info.name, - "user_name": item.user_info.nickname, - "permission": item.permission, - 'is_admin': item.is_admin, - 'for_user': true - } + 'item_data': _this.prepareUserItemData(item) }); $add_item.after(new_item.el); }); @@ -822,6 +958,8 @@ define([ }, dirGroupShare: function () { + var _this = this; + var $panel = $('#dir-group-share'); var $form = this.$('#add-dir-group-share-item'); // pseudo form @@ -840,34 +978,46 @@ define([ var $error = $('.error', $panel); var $submitBtn = $('[type="submit"]', $form); - Common.disableButton($submitBtn); - $.ajax({ - url: Common.getUrl({ + var url, method, data; + if (this.parent_group_id) { + url = Common.getUrl({ + name: 'group_owned_repo_group_share', + repo_id: repo_id + }); + method = 'POST'; + data = { + 'path': path, + 'group_id': groups, + 'permission': perm + }; + } else { + url = Common.getUrl({ name: 'dir_shared_items', repo_id: repo_id - }) + '?p=' + encodeURIComponent(path), - dataType: 'json', - method: 'PUT', - beforeSend: Common.prepareCSRFToken, - traditional: true, - data: { + }) + '?p=' + encodeURIComponent(path); + method = 'PUT'; + data = { 'share_type': 'group', 'group_id': groups, 'permission': perm - }, + }; + } + + Common.disableButton($submitBtn); + $.ajax({ + url: url, + dataType: 'json', + method: method, + beforeSend: Common.prepareCSRFToken, + traditional: true, + data: data, success: function(data) { if (data.success.length > 0) { $(data.success).each(function(index, item) { var new_item = new FolderShareItemView({ 'repo_id': repo_id, 'path': path, - 'item_data': { - "group_id": item.group_info.id, - "group_name": item.group_info.name, - "permission": item.permission, - 'is_admin': item.is_admin, - 'for_user': false - } + 'item_data': _this.prepareGroupItemData(item) }); $add_item.after(new_item.el); }); diff --git a/static/scripts/common.js b/static/scripts/common.js index cb773bb24c..df76904762 100644 --- a/static/scripts/common.js +++ b/static/scripts/common.js @@ -143,6 +143,7 @@ define([ // Group case 'groups': return siteRoot + 'api/v2.1/groups/'; + case 'all_groups': return siteRoot + 'api/v2.1/all-groups/'; case 'shareable_groups': return siteRoot + 'api/v2.1/shareable-groups/'; case 'search_group': return siteRoot + 'api/v2.1/search-group/'; case 'group': return siteRoot + 'api/v2.1/groups/' + options.group_id + '/'; @@ -153,6 +154,8 @@ define([ case 'group_repos': return siteRoot + 'api2/groups/' + options.group_id + '/repos/'; case 'group_owned_repos': return siteRoot + 'api/v2.1/groups/' + options.group_id + '/group-owned-libraries/'; case 'group_owned_repo': return siteRoot + 'api/v2.1/groups/' + options.group_id + '/group-owned-libraries/' + options.repo_id + '/'; + case 'group_owned_repo_user_share': return siteRoot + 'api/v2.1/group-owned-libraries/' + options.repo_id + '/user-share/'; + case 'group_owned_repo_group_share': return siteRoot + 'api/v2.1/group-owned-libraries/' + options.repo_id + '/group-share/'; case 'address_book_sub_groups': return siteRoot + 'api/v2.1/address-book/groups/' + options.group_id + '/sub-groups/'; case 'address_book_group_search_members': return siteRoot + 'api/v2.1/address-book/groups/' + options.group_id + '/search-member/'; case 'group_discussions': return siteRoot + 'api2/groups/' + options.group_id + '/discussions/';