mirror of
https://github.com/bitwarden/browser.git
synced 2024-11-28 12:45:45 +01:00
attachments for org logins
This commit is contained in:
parent
76da9b1f18
commit
abed4df973
@ -1,10 +1,19 @@
|
|||||||
angular
|
angular
|
||||||
.module('bit.global')
|
.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' });
|
$analytics.eventTrack('paidOrgRequiredController', { category: 'Modal' });
|
||||||
|
|
||||||
|
authService.getUserProfile().then(function (profile) {
|
||||||
|
$scope.admin = profile.organizations[orgId].type !== constants.orgUserType.user
|
||||||
|
});
|
||||||
|
|
||||||
$scope.go = function () {
|
$scope.go = function () {
|
||||||
|
if (!$scope.admin) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
$analytics.eventTrack('Get Paid Org');
|
$analytics.eventTrack('Get Paid Org');
|
||||||
$state.go('backend.org.billing', { orgId: orgId }).then(function () {
|
$state.go('backend.org.billing', { orgId: orgId }).then(function () {
|
||||||
$uibModalStack.dismissAll();
|
$uibModalStack.dismissAll();
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
angular
|
angular
|
||||||
.module('bit.global')
|
.module('bit.global')
|
||||||
|
|
||||||
.controller('sideNavController', function ($scope, $state, authService, toastr, $analytics) {
|
.controller('sideNavController', function ($scope, $state, authService, toastr, $analytics, constants) {
|
||||||
$scope.$state = $state;
|
$scope.$state = $state;
|
||||||
$scope.params = $state.params;
|
$scope.params = $state.params;
|
||||||
$scope.orgs = [];
|
$scope.orgs = [];
|
||||||
@ -31,7 +31,7 @@ angular
|
|||||||
});
|
});
|
||||||
|
|
||||||
$scope.viewOrganization = function (org) {
|
$scope.viewOrganization = function (org) {
|
||||||
if (org.type === 2) { // 2 = User
|
if (org.type === constants.orgUserType.user) {
|
||||||
toastr.error('You cannot manage this organization.');
|
toastr.error('You cannot manage this organization.');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -49,6 +49,6 @@ angular
|
|||||||
};
|
};
|
||||||
|
|
||||||
$scope.isOrgOwner = function (org) {
|
$scope.isOrgOwner = function (org) {
|
||||||
return org && org.type === 0;
|
return org && org.type === constants.orgUserType.owner;
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
angular
|
angular
|
||||||
.module('bit.vault')
|
.module('bit.organization')
|
||||||
|
|
||||||
.controller('organizationVaultAddLoginController', function ($scope, apiService, $uibModalInstance, cryptoService,
|
.controller('organizationVaultAddLoginController', function ($scope, apiService, $uibModalInstance, cryptoService,
|
||||||
cipherService, passwordService, $analytics, authService, orgId, $uibModal) {
|
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')
|
.module('bit.organization')
|
||||||
|
|
||||||
.controller('organizationVaultController', function ($scope, apiService, cipherService, $analytics, $q, $state,
|
.controller('organizationVaultController', function ($scope, apiService, cipherService, $analytics, $q, $state,
|
||||||
$localStorage, $uibModal, $filter) {
|
$localStorage, $uibModal, $filter, authService) {
|
||||||
$scope.logins = [];
|
$scope.logins = [];
|
||||||
$scope.collections = [];
|
$scope.collections = [];
|
||||||
$scope.loading = true;
|
$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) {
|
$scope.removeLogin = function (login, collection) {
|
||||||
if (!confirm('Are you sure you want to remove this login (' + login.name + ') from the ' +
|
if (!confirm('Are you sure you want to remove this login (' + login.name + ') from the ' +
|
||||||
'collection (' + collection.name + ') ?')) {
|
'collection (' + collection.name + ') ?')) {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
angular
|
angular
|
||||||
.module('bit.vault')
|
.module('bit.organization')
|
||||||
|
|
||||||
.controller('organizationVaultEditLoginController', function ($scope, apiService, $uibModalInstance, cryptoService,
|
.controller('organizationVaultEditLoginController', function ($scope, apiService, $uibModalInstance, cryptoService,
|
||||||
cipherService, passwordService, loginId, $analytics, orgId, $uibModal) {
|
cipherService, passwordService, loginId, $analytics, orgId, $uibModal) {
|
||||||
|
@ -46,6 +46,11 @@
|
|||||||
<i class="fa fa-fw fa-pencil"></i> Edit
|
<i class="fa fa-fw fa-pencil"></i> Edit
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="#" stop-click ng-click="attachments(login)">
|
||||||
|
<i class="fa fa-fw fa-paperclip"></i> Attachments
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a href="#" stop-click ng-click="editCollections(login)">
|
<a href="#" stop-click ng-click="editCollections(login)">
|
||||||
<i class="fa fa-fw fa-cubes"></i> Collections
|
<i class="fa fa-fw fa-cubes"></i> Collections
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
loginId, $analytics, validationService, toastr) {
|
loginId, $analytics, validationService, toastr) {
|
||||||
$analytics.eventTrack('vaultAttachmentsController', { category: 'Modal' });
|
$analytics.eventTrack('vaultAttachmentsController', { category: 'Modal' });
|
||||||
$scope.login = {};
|
$scope.login = {};
|
||||||
$scope.readOnly = false;
|
$scope.readOnly = true;
|
||||||
$scope.loading = true;
|
$scope.loading = true;
|
||||||
var closing = false;
|
var closing = false;
|
||||||
|
|
||||||
|
@ -201,9 +201,24 @@
|
|||||||
|
|
||||||
$scope.attachments = function (login) {
|
$scope.attachments = function (login) {
|
||||||
authService.getUserProfile().then(function (profile) {
|
authService.getUserProfile().then(function (profile) {
|
||||||
return profile.premium;
|
return {
|
||||||
}).then(function (isPremium) {
|
isPremium: profile.premium,
|
||||||
if (!isPremium) {
|
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({
|
$uibModal.open({
|
||||||
animation: true,
|
animation: true,
|
||||||
templateUrl: 'app/views/premiumRequired.html',
|
templateUrl: 'app/views/premiumRequired.html',
|
||||||
@ -212,7 +227,7 @@
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!cryptoService.getEncKey()) {
|
if (!login.organizationId && !cryptoService.getEncKey()) {
|
||||||
toastr.error('You cannot use this feature until you update your encryption key.', 'Feature Unavailable');
|
toastr.error('You cannot use this feature until you update your encryption key.', 'Feature Unavailable');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -86,7 +86,7 @@
|
|||||||
<i class="fa fa-fw fa-pencil"></i> Edit
|
<i class="fa fa-fw fa-pencil"></i> Edit
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li ng-show="login.edit">
|
<li>
|
||||||
<a href="#" stop-click ng-click="attachments(login)">
|
<a href="#" stop-click ng-click="attachments(login)">
|
||||||
<i class="fa fa-fw fa-paperclip"></i> Attachments
|
<i class="fa fa-fw fa-paperclip"></i> Attachments
|
||||||
</a>
|
</a>
|
||||||
@ -196,7 +196,7 @@
|
|||||||
<i class="fa fa-fw fa-pencil"></i> Edit
|
<i class="fa fa-fw fa-pencil"></i> Edit
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li ng-show="login.edit">
|
<li>
|
||||||
<a href="#" stop-click ng-click="attachments(login)">
|
<a href="#" stop-click ng-click="attachments(login)">
|
||||||
<i class="fa fa-fw fa-paperclip"></i> Attachments
|
<i class="fa fa-fw fa-paperclip"></i> Attachments
|
||||||
</a>
|
</a>
|
||||||
|
@ -45,22 +45,24 @@
|
|||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
<hr />
|
<div ng-if="!readOnly">
|
||||||
<h4>Add New Attachment</h4>
|
<hr />
|
||||||
<div class="callout callout-danger validation-errors" ng-show="form.$errors">
|
<h4>Add New Attachment</h4>
|
||||||
<h4>Errors have occurred</h4>
|
<div class="callout callout-danger validation-errors" ng-show="form.$errors">
|
||||||
<ul>
|
<h4>Errors have occurred</h4>
|
||||||
<li ng-repeat="e in form.$errors">{{e}}</li>
|
<ul>
|
||||||
</ul>
|
<li ng-repeat="e in form.$errors">{{e}}</li>
|
||||||
</div>
|
</ul>
|
||||||
<div class="form-group" show-error>
|
</div>
|
||||||
<label for="file" class="sr-only">File</label>
|
<div class="form-group" show-error>
|
||||||
<input type="file" id="file" name="file" />
|
<label for="file" class="sr-only">File</label>
|
||||||
<p class="help-block">Maximum size per file is 100 MB.</p>
|
<input type="file" id="file" name="file" />
|
||||||
|
<p class="help-block">Maximum size per file is 100 MB.</p>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<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
|
<i class="fa fa-refresh fa-spin loading-icon" ng-show="form.$loading"></i>Save
|
||||||
</button>
|
</button>
|
||||||
<button type="button" class="btn btn-default btn-flat" ng-click="close()">Close</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.
|
This feature is not available for free organizations. Switch to a paid plan to unlock more features.
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<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
|
Upgrade Organization
|
||||||
</button>
|
</button>
|
||||||
<button type="button" class="btn btn-default btn-flat" ng-click="close()">Close</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/organizationVaultAddLoginController.js"></script>
|
||||||
<script src="app/organization/organizationVaultEditLoginController.js"></script>
|
<script src="app/organization/organizationVaultEditLoginController.js"></script>
|
||||||
<script src="app/organization/organizationVaultLoginCollectionsController.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/organizationGroupsController.js"></script>
|
||||||
<script src="app/organization/organizationGroupsAddController.js"></script>
|
<script src="app/organization/organizationGroupsAddController.js"></script>
|
||||||
<script src="app/organization/organizationGroupsEditController.js"></script>
|
<script src="app/organization/organizationGroupsEditController.js"></script>
|
||||||
|
Loading…
Reference in New Issue
Block a user