user image

This commit is contained in:
Bernat Exposito 2020-11-10 08:39:34 +01:00
parent fc957eda6c
commit 4ea5993dcc
18 changed files with 205 additions and 11 deletions

View File

@ -0,0 +1,94 @@
const UserError = require('vn-loopback/util/user-error');
const fs = require('fs-extra');
module.exports = Self => {
Self.remoteMethod('download', {
description: 'Get the user image',
accessType: 'READ',
accepts: [
{
arg: 'collection',
type: 'String',
description: 'The image collection',
http: {source: 'path'}
},
{
arg: 'size',
type: 'String',
description: 'The image size',
http: {source: 'path'}
},
{
arg: 'id',
type: 'Number',
description: 'The user id',
http: {source: 'path'}
}
],
returns: [
{
arg: 'body',
type: 'file',
root: true
},
{
arg: 'Content-Type',
type: 'String',
http: {target: 'header'}
},
{
arg: 'Content-Disposition',
type: 'String',
http: {target: 'header'}
}
],
http: {
path: `/:collection/:size/:id/download`,
verb: 'GET'
}
});
Self.download = async function(collection, size, id) {
const filter = {
where: {
collectionFk: collection,
name: id},
include: {
relation: 'collection',
scope: {
fields: ['name', 'readRoleFk'],
include: {
relation: 'readRole'
}
}
}
};
const image = await Self.app.models.Image.findOne(filter);
if (!image) return;
const imageRole = image.collection().readRole().name;
const hasRole = await Self.app.models.Account.hasRole(id, imageRole);
if (!hasRole)
throw new UserError(`You don't have enough privileges`);
let file;
let env = process.env.NODE_ENV;
if (env && env != 'development') {
file = {
path: `/var/lib/salix/image/${collection}/${size}/${id}.png`,
contentType: 'image/png',
name: `${id}.png`
};
} else {
file = {
path: `${process.cwd()}/storage/image/${collection}/${size}/${id}.png`,
contentType: 'image/png',
name: `${id}.png`
};
}
await fs.access(file.path);
let stream = fs.createReadStream(file.path);
return [stream, file.contentType, `filename="${file.name}"`];
};
};

View File

@ -0,0 +1,20 @@
const app = require('vn-loopback/server/server');
describe('image download()', () => {
const collection = 'user';
const size = '160x160';
it('should return the image content-type of the user', async() => {
const userId = 9;
const image = await app.models.Image.download(collection, size, userId);
expect(image[1]).toEqual('image/png');
});
it(`should don't return an image if the user don't have it`, async() => {
const userId = 8;
const image = await app.models.Image.download(collection, size, userId);
expect(image).toBeUndefined();
});
});

View File

@ -43,7 +43,12 @@
"model": "ImageCollectionSize",
"foreignKey": "collectionFk",
"property": "id"
}
},
"readRole": {
"type": "belongsTo",
"model": "Role",
"foreignKey": "readRoleFk"
}
},
"acls": [
{

View File

@ -3,6 +3,8 @@ const sharp = require('sharp');
const path = require('path');
module.exports = Self => {
require('../methods/image/download')(Self);
Self.getPath = function() {
return '/var/lib/salix/image';
};

View File

@ -29,6 +29,14 @@
"default": 0
}
},
"relations": {
"collection": {
"type": "belongsTo",
"model": "ImageCollection",
"foreignKey": "collectionFk",
"primaryKey": "name"
}
},
"acls": [
{
"accessType": "READ",

View File

@ -1,2 +1,2 @@
INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`) VALUES ('supplier', '*', 'WRITE', 'ALLOW', 'ROLE', 'administrative');
INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`) VALUES ('Supplier', '*', 'WRITE', 'ALLOW', 'ROLE', 'administrative');
INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`) VALUES ('SupplierContact', '*', 'WRITE', 'ALLOW', 'ROLE', 'administrative');

View File

@ -0,0 +1,5 @@
ALTER TABLE `hedera`.`imageCollection`
ADD COLUMN `readRoleFk` VARCHAR(45) NULL DEFAULT NULL AFTER `column`;
update `hedera`.`imageCollection` set `readRoleFk` = 1 where id = 6;

View File

@ -443,7 +443,7 @@ USE `hedera`;
LOCK TABLES `imageCollection` WRITE;
/*!40000 ALTER TABLE `imageCollection` DISABLE KEYS */;
INSERT INTO `imageCollection` VALUES (1,'catalog','Artículo',3840,2160,'Item','image','vn','item','image'),(4,'link','Enlace',200,200,'Link','image','hedera','link','image'),(5,'news','Noticias',800,1200,'New','image','hedera','news','image');
INSERT INTO `imageCollection` VALUES (1,'catalog','Artículo',3840,2160,'Item','image','vn','item','image'),(4,'link','Enlace',200,200,'Link','image','hedera','link','image'),(5,'news','Noticias',800,1200,'New','image','hedera','news','image'),('6','user','Usuario','800','1200','Account','image','account','user','image');
/*!40000 ALTER TABLE `imageCollection` ENABLE KEYS */;
UNLOCK TABLES;

View File

@ -2141,3 +2141,10 @@ INSERT INTO `vn`.`campaign`(`code`, `dated`)
('allSaints', CONCAT(YEAR(DATE_ADD(CURDATE(), INTERVAL -2 YEAR)), '-11-01')),
('allSaints', CONCAT(YEAR(DATE_ADD(CURDATE(), INTERVAL -3 YEAR)), '-11-01'));
INSERT INTO `hedera`.`image`(`collectionFk`, `name`)
VALUES
('user', 9);
INSERT INTO `hedera`.`imageCollectionSize`(`id`, `collectionFk`,`width`, `height`)
VALUES
(1, 4, 160, 160);

View File

@ -31,12 +31,14 @@
ng-if="$ctrl.rightMenu"
ng-click="$ctrl.rightMenu.show()">
</vn-icon-button>
<vn-icon-button
id="user"
icon="account_circle"
<button class="buttonAccount">
<img
ng-src="{{$ctrl.getImageUrl()}}"
ng-click="userPopover.show($event)"
translate-attr="{title: 'Account'}">
</vn-icon-button>
translate-attr="{title: 'Account'}"
on-error-src/>
</button>
</div>
<vn-menu vn-id="apps-menu">
<vn-list class="modules-menu">

View File

@ -18,6 +18,14 @@ export class Layout extends Component {
window.localStorage.currentUserWorkerId = json.data.id;
});
}
getImageUrl() {
if (!this.$.$root.user) return;
const userId = this.$.$root.user.id;
const token = this.vnToken.token;
return `/api/Images/user/160x160/${userId}/download?access_token=${token}`;
}
}
Layout.$inject = ['$element', '$scope', 'vnModules'];

View File

@ -22,4 +22,19 @@ describe('Component vnLayout', () => {
expect(controller.$.$root.user.name).toEqual('batman');
});
});
describe('getImageUrl()', () => {
it('should return the url image if the user is defined', () => {
controller.$.$root.user = {id: 1};
const url = controller.getImageUrl();
expect(url).not.toBe(3);
});
it('should return undefined if the user is not defined', () => {
const url = controller.getImageUrl();
expect(url).not.toBeDefined();
});
});
});

View File

@ -109,6 +109,14 @@ vn-layout {
}
}
}
img {
width: 40px;
border-radius: 50%;
}
.buttonAccount {
background: none;
border: none;
}
@media screen and (max-width: $mobile-width) {
& > vn-topbar {
& > .start > .logo {
@ -147,3 +155,4 @@ vn-layout {
font-size: 1.5rem;
height: auto;
}

View File

@ -13,7 +13,9 @@
<vn-popover vn-id="popover">
<vn-vertical class="user-popover vn-pa-md">
<div class="profile-card vn-pb-md">
<vn-icon icon="account_circle"></vn-icon>
<img
ng-src="{{$ctrl.getImageUrl($root.user.id)}}"
on-error-src/>
<div class="vn-pl-sm">
<div>
<div class="user">

View File

@ -3,12 +3,13 @@ import './style.scss';
import config from '../../config.json';
class Controller {
constructor($, $translate, vnConfig, vnAuth) {
constructor($, $translate, vnConfig, vnAuth, vnToken) {
Object.assign(this, {
$,
$translate,
vnConfig,
vnAuth,
vnToken,
lang: $translate.use(),
langs: []
});
@ -77,8 +78,12 @@ class Controller {
this.$.companies.refresh();
this.$.popover.show(event.target);
}
getImageUrl(userId) {
return '/api/Images/user/160x160/' + userId + '/download?access_token=' + this.vnToken.token;
}
}
Controller.$inject = ['$scope', '$translate', 'vnConfig', 'vnAuth'];
Controller.$inject = ['$scope', '$translate', 'vnConfig', 'vnAuth', 'vnToken'];
ngModule.vnComponent('vnUserPopover', {
template: require('./index.html'),

View File

@ -57,5 +57,13 @@ describe('Salix', () => {
expect(controller.companyFk).toBe(4);
});
});
describe('getImageUrl()', () => {
it('should return de url image', () => {
const url = controller.getImageUrl();
expect(url).not.toBeDefined();
});
});
});
});

View File

@ -11,6 +11,10 @@
font-size: 5rem;
color: $color-font-bg-marginal;
}
img {
width: 80px;
border-radius: 50%;
}
& > div {
display: flex;
flex-direction: column;

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB