mirror of
https://github.com/bitwarden/browser.git
synced 2024-12-29 17:38:04 +01:00
attachments for org logins
This commit is contained in:
parent
76da9b1f18
commit
abed4df973
@ -1,10 +1,19 @@
|
||||
angular
|
||||
.module('bit.global')
|
||||
|
||||
.controller('paidOrgRequiredController', function ($scope, $state, $uibModalInstance, $analytics, $uibModalStack, orgId) {
|
||||
.controller('paidOrgRequiredController', function ($scope, $state, $uibModalInstance, $analytics, $uibModalStack, orgId,
|
||||
constants, authService) {
|
||||
$analytics.eventTrack('paidOrgRequiredController', { category: 'Modal' });
|
||||
|
||||
authService.getUserProfile().then(function (profile) {
|
||||
$scope.admin = profile.organizations[orgId].type !== constants.orgUserType.user
|
||||
});
|
||||
|
||||
$scope.go = function () {
|
||||
if (!$scope.admin) {
|
||||
return;
|
||||
}
|
||||
|
||||
$analytics.eventTrack('Get Paid Org');
|
||||
$state.go('backend.org.billing', { orgId: orgId }).then(function () {
|
||||
$uibModalStack.dismissAll();
|
||||
|
@ -1,7 +1,7 @@
|
||||
angular
|
||||
.module('bit.global')
|
||||
|
||||
.controller('sideNavController', function ($scope, $state, authService, toastr, $analytics) {
|
||||
.controller('sideNavController', function ($scope, $state, authService, toastr, $analytics, constants) {
|
||||
$scope.$state = $state;
|
||||
$scope.params = $state.params;
|
||||
$scope.orgs = [];
|
||||
@ -31,7 +31,7 @@ angular
|
||||
});
|
||||
|
||||
$scope.viewOrganization = function (org) {
|
||||
if (org.type === 2) { // 2 = User
|
||||
if (org.type === constants.orgUserType.user) {
|
||||
toastr.error('You cannot manage this organization.');
|
||||
return;
|
||||
}
|
||||
@ -49,6 +49,6 @@ angular
|
||||
};
|
||||
|
||||
$scope.isOrgOwner = function (org) {
|
||||
return org && org.type === 0;
|
||||
return org && org.type === constants.orgUserType.owner;
|
||||
};
|
||||
});
|
||||
|
@ -1,5 +1,5 @@
|
||||
angular
|
||||
.module('bit.vault')
|
||||
.module('bit.organization')
|
||||
|
||||
.controller('organizationVaultAddLoginController', function ($scope, apiService, $uibModalInstance, cryptoService,
|
||||
cipherService, passwordService, $analytics, authService, orgId, $uibModal) {
|
||||
|
127
src/app/organization/organizationVaultAttachmentsController.js
Normal file
127
src/app/organization/organizationVaultAttachmentsController.js
Normal file
@ -0,0 +1,127 @@
|
||||
angular
|
||||
.module('bit.organization')
|
||||
|
||||
.controller('organizationVaultAttachmentsController', function ($scope, apiService, $uibModalInstance, cryptoService,
|
||||
cipherService, loginId, $analytics, validationService, toastr) {
|
||||
$analytics.eventTrack('organizationVaultAttachmentsController', { category: 'Modal' });
|
||||
$scope.login = {};
|
||||
$scope.loading = true;
|
||||
var closing = false;
|
||||
|
||||
apiService.logins.getAdmin({ id: loginId }, function (login) {
|
||||
$scope.login = cipherService.decryptLogin(login);
|
||||
$scope.loading = false;
|
||||
}, function () {
|
||||
$scope.loading = false;
|
||||
});
|
||||
|
||||
$scope.save = function (form) {
|
||||
var files = document.getElementById('file').files;
|
||||
if (!files || !files.length) {
|
||||
validationService.addError(form, 'file', 'Select a file.', true);
|
||||
return;
|
||||
}
|
||||
|
||||
var file = files[0];
|
||||
if (file.size > 104857600) { // 100 MB
|
||||
validationService.addError(form, 'file', 'Maximum file size is 100 MB.', true);
|
||||
return;
|
||||
}
|
||||
|
||||
var reader = new FileReader();
|
||||
reader.readAsArrayBuffer(file);
|
||||
reader.onload = function (evt) {
|
||||
form.$loading = true;
|
||||
$scope.$apply();
|
||||
|
||||
var key = cryptoService.getOrgKey($scope.login.organizationId);
|
||||
var encFilename = cryptoService.encrypt(file.name, key);
|
||||
$scope.savePromise = cryptoService.encryptToBytes(evt.target.result, key).then(function (encData) {
|
||||
var fd = new FormData();
|
||||
var blob = new Blob([encData], { type: 'application/octet-stream' });
|
||||
fd.append('data', blob, encFilename);
|
||||
return apiService.ciphers.postAttachment({ id: loginId }, fd).$promise;
|
||||
}).then(function (response) {
|
||||
$analytics.eventTrack('Added Organization Attachment');
|
||||
toastr.success('The attachment has been added.');
|
||||
closing = true;
|
||||
$uibModalInstance.close(true);
|
||||
});
|
||||
};
|
||||
reader.onerror = function (evt) {
|
||||
validationService.addError(form, 'file', 'Error reading file.', true);
|
||||
};
|
||||
}
|
||||
|
||||
$scope.download = function (attachment) {
|
||||
attachment.loading = true;
|
||||
|
||||
var req = new XMLHttpRequest();
|
||||
req.open('GET', attachment.url, true);
|
||||
req.responseType = 'arraybuffer';
|
||||
req.onload = function (evt) {
|
||||
if (!req.response) {
|
||||
attachment.loading = false;
|
||||
$scope.$apply();
|
||||
|
||||
// error
|
||||
return;
|
||||
}
|
||||
|
||||
var key = cryptoService.getOrgKey($scope.login.organizationId);
|
||||
cryptoService.decryptFromBytes(req.response, key).then(function (decBuf) {
|
||||
var blob = new Blob([decBuf]);
|
||||
|
||||
// IE hack. ref http://msdn.microsoft.com/en-us/library/ie/hh779016.aspx
|
||||
if (window.navigator.msSaveOrOpenBlob) {
|
||||
window.navigator.msSaveBlob(blob, attachment.fileName);
|
||||
}
|
||||
else {
|
||||
var a = window.document.createElement('a');
|
||||
a.href = window.URL.createObjectURL(blob);
|
||||
a.download = attachment.fileName;
|
||||
document.body.appendChild(a);
|
||||
a.click();
|
||||
document.body.removeChild(a);
|
||||
}
|
||||
|
||||
attachment.loading = false;
|
||||
$scope.$apply();
|
||||
});
|
||||
};
|
||||
req.send(null);
|
||||
};
|
||||
|
||||
$scope.remove = function (attachment) {
|
||||
if (!confirm('Are you sure you want to delete this attachment (' + attachment.fileName + ')?')) {
|
||||
return;
|
||||
}
|
||||
|
||||
attachment.loading = true;
|
||||
apiService.ciphers.delAttachment({ id: loginId, attachmentId: attachment.id }).$promise.then(function () {
|
||||
attachment.loading = false;
|
||||
$analytics.eventTrack('Deleted Organization Attachment');
|
||||
var index = $scope.login.attachments.indexOf(attachment);
|
||||
if (index > -1) {
|
||||
$scope.login.attachments.splice(index, 1);
|
||||
}
|
||||
}, function () {
|
||||
toastr.error('Cannot delete attachment.');
|
||||
attachment.loading = false;
|
||||
});
|
||||
};
|
||||
|
||||
$scope.close = function () {
|
||||
$uibModalInstance.dismiss('cancel');
|
||||
};
|
||||
|
||||
$scope.$on('modal.closing', function (e, reason, closed) {
|
||||
if (closing) {
|
||||
return;
|
||||
}
|
||||
|
||||
e.preventDefault();
|
||||
closing = true;
|
||||
$uibModalInstance.close(!!$scope.login.attachments && $scope.login.attachments.length > 0);
|
||||
});
|
||||
});
|
@ -2,7 +2,7 @@
|
||||
.module('bit.organization')
|
||||
|
||||
.controller('organizationVaultController', function ($scope, apiService, cipherService, $analytics, $q, $state,
|
||||
$localStorage, $uibModal, $filter) {
|
||||
$localStorage, $uibModal, $filter, authService) {
|
||||
$scope.logins = [];
|
||||
$scope.collections = [];
|
||||
$scope.loading = true;
|
||||
@ -139,6 +139,37 @@
|
||||
});
|
||||
};
|
||||
|
||||
$scope.attachments = function (login) {
|
||||
authService.getUserProfile().then(function (profile) {
|
||||
return !!profile.organizations[login.organizationId].maxStorageGb;
|
||||
}).then(function (useStorage) {
|
||||
if (!useStorage) {
|
||||
$uibModal.open({
|
||||
animation: true,
|
||||
templateUrl: 'app/views/paidOrgRequired.html',
|
||||
controller: 'paidOrgRequiredController',
|
||||
resolve: {
|
||||
orgId: function () { return login.organizationId; }
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
var attachmentModel = $uibModal.open({
|
||||
animation: true,
|
||||
templateUrl: 'app/vault/views/vaultAttachments.html',
|
||||
controller: 'organizationVaultAttachmentsController',
|
||||
resolve: {
|
||||
loginId: function () { return login.id; }
|
||||
}
|
||||
});
|
||||
|
||||
attachmentModel.result.then(function (hasAttachments) {
|
||||
login.hasAttachments = hasAttachments;
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
$scope.removeLogin = function (login, collection) {
|
||||
if (!confirm('Are you sure you want to remove this login (' + login.name + ') from the ' +
|
||||
'collection (' + collection.name + ') ?')) {
|
||||
|
@ -1,5 +1,5 @@
|
||||
angular
|
||||
.module('bit.vault')
|
||||
.module('bit.organization')
|
||||
|
||||
.controller('organizationVaultEditLoginController', function ($scope, apiService, $uibModalInstance, cryptoService,
|
||||
cipherService, passwordService, loginId, $analytics, orgId, $uibModal) {
|
||||
|
@ -46,6 +46,11 @@
|
||||
<i class="fa fa-fw fa-pencil"></i> Edit
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#" stop-click ng-click="attachments(login)">
|
||||
<i class="fa fa-fw fa-paperclip"></i> Attachments
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#" stop-click ng-click="editCollections(login)">
|
||||
<i class="fa fa-fw fa-cubes"></i> Collections
|
||||
|
@ -5,7 +5,7 @@
|
||||
loginId, $analytics, validationService, toastr) {
|
||||
$analytics.eventTrack('vaultAttachmentsController', { category: 'Modal' });
|
||||
$scope.login = {};
|
||||
$scope.readOnly = false;
|
||||
$scope.readOnly = true;
|
||||
$scope.loading = true;
|
||||
var closing = false;
|
||||
|
||||
|
@ -201,9 +201,24 @@
|
||||
|
||||
$scope.attachments = function (login) {
|
||||
authService.getUserProfile().then(function (profile) {
|
||||
return profile.premium;
|
||||
}).then(function (isPremium) {
|
||||
if (!isPremium) {
|
||||
return {
|
||||
isPremium: profile.premium,
|
||||
orgUseStorage: login.organizationId && !!profile.organizations[login.organizationId].maxStorageGb
|
||||
};
|
||||
}).then(function (perms) {
|
||||
if (login.organizationId && !perms.orgUseStorage) {
|
||||
$uibModal.open({
|
||||
animation: true,
|
||||
templateUrl: 'app/views/paidOrgRequired.html',
|
||||
controller: 'paidOrgRequiredController',
|
||||
resolve: {
|
||||
orgId: function () { return login.organizationId; }
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (!login.organizationId && !perms.isPremium) {
|
||||
$uibModal.open({
|
||||
animation: true,
|
||||
templateUrl: 'app/views/premiumRequired.html',
|
||||
@ -212,7 +227,7 @@
|
||||
return;
|
||||
}
|
||||
|
||||
if (!cryptoService.getEncKey()) {
|
||||
if (!login.organizationId && !cryptoService.getEncKey()) {
|
||||
toastr.error('You cannot use this feature until you update your encryption key.', 'Feature Unavailable');
|
||||
return;
|
||||
}
|
||||
|
@ -86,7 +86,7 @@
|
||||
<i class="fa fa-fw fa-pencil"></i> Edit
|
||||
</a>
|
||||
</li>
|
||||
<li ng-show="login.edit">
|
||||
<li>
|
||||
<a href="#" stop-click ng-click="attachments(login)">
|
||||
<i class="fa fa-fw fa-paperclip"></i> Attachments
|
||||
</a>
|
||||
@ -196,7 +196,7 @@
|
||||
<i class="fa fa-fw fa-pencil"></i> Edit
|
||||
</a>
|
||||
</li>
|
||||
<li ng-show="login.edit">
|
||||
<li>
|
||||
<a href="#" stop-click ng-click="attachments(login)">
|
||||
<i class="fa fa-fw fa-paperclip"></i> Attachments
|
||||
</a>
|
||||
|
@ -45,22 +45,24 @@
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<hr />
|
||||
<h4>Add New Attachment</h4>
|
||||
<div class="callout callout-danger validation-errors" ng-show="form.$errors">
|
||||
<h4>Errors have occurred</h4>
|
||||
<ul>
|
||||
<li ng-repeat="e in form.$errors">{{e}}</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="form-group" show-error>
|
||||
<label for="file" class="sr-only">File</label>
|
||||
<input type="file" id="file" name="file" />
|
||||
<p class="help-block">Maximum size per file is 100 MB.</p>
|
||||
<div ng-if="!readOnly">
|
||||
<hr />
|
||||
<h4>Add New Attachment</h4>
|
||||
<div class="callout callout-danger validation-errors" ng-show="form.$errors">
|
||||
<h4>Errors have occurred</h4>
|
||||
<ul>
|
||||
<li ng-repeat="e in form.$errors">{{e}}</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="form-group" show-error>
|
||||
<label for="file" class="sr-only">File</label>
|
||||
<input type="file" id="file" name="file" />
|
||||
<p class="help-block">Maximum size per file is 100 MB.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="submit" class="btn btn-primary btn-flat" ng-disabled="form.$loading">
|
||||
<button type="submit" class="btn btn-primary btn-flat" ng-disabled="form.$loading" ng-if="!readOnly">
|
||||
<i class="fa fa-refresh fa-spin loading-icon" ng-show="form.$loading"></i>Save
|
||||
</button>
|
||||
<button type="button" class="btn btn-default btn-flat" ng-click="close()">Close</button>
|
||||
|
@ -6,7 +6,7 @@
|
||||
This feature is not available for free organizations. Switch to a paid plan to unlock more features.
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="submit" class="btn btn-primary btn-flat" ng-click="go()">
|
||||
<button type="submit" class="btn btn-primary btn-flat" ng-click="go()" ng-if="admin">
|
||||
Upgrade Organization
|
||||
</button>
|
||||
<button type="button" class="btn btn-default btn-flat" ng-click="close()">Close</button>
|
||||
|
@ -189,6 +189,7 @@
|
||||
<script src="app/organization/organizationVaultAddLoginController.js"></script>
|
||||
<script src="app/organization/organizationVaultEditLoginController.js"></script>
|
||||
<script src="app/organization/organizationVaultLoginCollectionsController.js"></script>
|
||||
<script src="app/organization/organizationVaultAttachmentsController.js"></script>
|
||||
<script src="app/organization/organizationGroupsController.js"></script>
|
||||
<script src="app/organization/organizationGroupsAddController.js"></script>
|
||||
<script src="app/organization/organizationGroupsEditController.js"></script>
|
||||
|
Loading…
Reference in New Issue
Block a user