0
1
Fork 0

Merge with master

This commit is contained in:
Juan Ferrer Toribio 2017-07-04 08:51:41 +02:00
commit 13e45afc77
25 changed files with 645 additions and 80 deletions

2
debian/control vendored
View File

@ -9,7 +9,7 @@ Vcs-Git: git://www.verdnatura.es/var/git/hedera-web
Package: hedera-web Package: hedera-web
Architecture: all Architecture: all
Depends: apache2, php5-mysql, php5-mcrypt, php5-ssh2, php5-apcu, php-vn-lib, nodejs Depends: apache2, php5-mysql, php5-mcrypt, php5-ldap, php5-ssh2, php5-apcu, php-vn-lib, nodejs
Suggests: php-text-captcha, php5-imap Suggests: php-text-captcha, php5-imap
Section: misc Section: misc
Priority: optional Priority: optional

View File

@ -8,8 +8,7 @@
</db-form> </db-form>
<db-form id="user"> <db-form id="user">
<db-model property="model" id="user-model" updatable="true"> <db-model property="model" id="user-model" updatable="true">
SELECT u.id, u.name, u.recoverPass, SELECT u.id, u.name, u.email, u.recoverPass, c.mail, c.user_id
c.email, c.mail, c.user_id
FROM account.userView u FROM account.userView u
LEFT JOIN customer_view c LEFT JOIN customer_view c
ON u.id = c.user_id ON u.id = c.user_id

View File

@ -7,6 +7,10 @@
,"Clear all": "Netejar tot" ,"Clear all": "Netejar tot"
,"Upload files": "Pujar arxius" ,"Upload files": "Pujar arxius"
,"Waiting for upload": "Esperant per pujar"
,"Uploading file": "Pujant fitxer"
,"Image uploaded": "Imatge pujada"
,"Upload finished successfully": "Imatges pujades correctament" ,"Upload finished successfully": "Imatges pujades correctament"
,"Some errors happened on upload": "Van ocórrer errors en pujar alguna de les imatges" ,"Some errors happened on upload": "Van ocórrer errors en pujar alguna de les imatges"
,"There are no files to upload": "No s'ha seleccionat arxius per pujar" ,"There are no files to upload": "No s'ha seleccionat arxius per pujar"

View File

@ -7,6 +7,10 @@
,"Clear all": "Clear all" ,"Clear all": "Clear all"
,"Upload files": "Upload files" ,"Upload files": "Upload files"
,"Waiting for upload": "Waiting for upload"
,"Uploading file": "Uploading file"
,"Image uploaded": "Image uploaded"
,"Upload finished successfully": "Upload finished successfully" ,"Upload finished successfully": "Upload finished successfully"
,"Some errors happened on upload": "Some errors happened on upload" ,"Some errors happened on upload": "Some errors happened on upload"
,"There are no files to upload": "There are no files to upload" ,"There are no files to upload": "There are no files to upload"

View File

@ -7,6 +7,10 @@
,"Clear all": "Limpiar todo" ,"Clear all": "Limpiar todo"
,"Upload files": "Subir archivos" ,"Upload files": "Subir archivos"
,"Waiting for upload": "Esperando para subir"
,"Uploading file": "Subiendo fichero"
,"Image uploaded": "Imagen subida"
,"Upload finished successfully": "Imágenes subidas correctamente" ,"Upload finished successfully": "Imágenes subidas correctamente"
,"Some errors happened on upload": "Ocurrieron errores al subir alguna de las imágenes" ,"Some errors happened on upload": "Ocurrieron errores al subir alguna de las imágenes"
,"There are no files to upload": "No se han seleccionado archivos para subir" ,"There are no files to upload": "No se han seleccionado archivos para subir"

View File

@ -7,6 +7,10 @@
,"Clear all": "Tout effacer" ,"Clear all": "Tout effacer"
,"Upload files": "Upload Files" ,"Upload files": "Upload Files"
,"Waiting for upload": "En attente de télécharger"
,"Uploading file": "Uploader des fichiers"
,"Image uploaded": "Fichier uploadé"
,"Upload finished successfully": "Les images téléchargées correctement" ,"Upload finished successfully": "Les images téléchargées correctement"
,"Some errors happened on upload": "Des erreurs sont survenues lors du téléchargement des images" ,"Some errors happened on upload": "Des erreurs sont survenues lors du téléchargement des images"
,"There are no files to upload": "Aucun fichier sélectionné pour télécharger" ,"There are no files to upload": "Aucun fichier sélectionné pour télécharger"

View File

@ -7,6 +7,10 @@
,"Clear all": "Clear all" ,"Clear all": "Clear all"
,"Upload files": "Upload files" ,"Upload files": "Upload files"
,"Waiting for upload": "Waiting for upload"
,"Uploading file": "Uploading file"
,"Image uploaded": "Image uploaded"
,"Upload finished successfully": "Upload finished successfully" ,"Upload finished successfully": "Upload finished successfully"
,"Some errors happened on upload": "Some errors happened on upload" ,"Some errors happened on upload": "Some errors happened on upload"
,"There are no files to upload": "There are no files to upload" ,"There are no files to upload": "There are no files to upload"

View File

@ -7,6 +7,10 @@
,"Clear all": "Clear All" ,"Clear all": "Clear All"
,"Upload files": "Fazer upload de arquivos" ,"Upload files": "Fazer upload de arquivos"
,"Waiting for upload": "Esperando para enviar"
,"Uploading file": "Enviando arquivo"
,"Image uploaded": "Arquivo enviado"
,"Upload finished successfully": "Upload concluído com sucesso" ,"Upload finished successfully": "Upload concluído com sucesso"
,"Some errors happened on upload": "Ocurrieron erros ao subir alguma das imagens" ,"Some errors happened on upload": "Ocurrieron erros ao subir alguma das imagens"
,"There are no files to upload": "Não há arquivos selecionados para upload" ,"There are no files to upload": "Não há arquivos selecionados para upload"

View File

@ -1,3 +1,11 @@
(function() {
var Status = {
NONE : 0
,WAITING : 1
,UPLOADING : 2
,UPLOADED : 3
};
Hedera.Photos = new Class Hedera.Photos = new Class
({ ({
@ -5,6 +13,8 @@ Hedera.Photos = new Class
,filesData: [] ,filesData: []
,uploadCount: 0 ,uploadCount: 0
,errors: false ,errors: false
,uploadQueue: []
,isUploading: false
,activate: function () ,activate: function ()
{ {
@ -46,17 +56,16 @@ Hedera.Photos = new Class
name.value = getFileName (file.name); name.value = getFileName (file.name);
div.appendChild (name); div.appendChild (name);
var status = doc.createElement ('span'); var statusNode = doc.createElement ('span');
status.className = 'status'; statusNode.className = 'status';
div.appendChild (status); div.appendChild (statusNode);
var fileData = { var fileData = {
div: div, div: div,
file: file, file: file,
name: name, name: name,
status: status, statusNode: statusNode,
sent: false, status: Status.NONE
loading : false
}; };
this.filesData.push (fileData); this.filesData.push (fileData);
button.value = fileData; button.value = fileData;
@ -67,68 +76,88 @@ Hedera.Photos = new Class
,onUploadClick: function () ,onUploadClick: function ()
{ {
var filesData = this.filesData; var filesData = this.filesData;
var formData = new FormData();
var count = 0; var count = 0;
for (var i = 0; i < filesData.length; i++) for (var i = 0; i < filesData.length; i++)
{ {
var fileData = filesData[i]; var fileData = filesData[i];
if (!(fileData.sent || fileData.loading)) if (fileData.status === Status.NONE)
{ {
formData.append ('image', fileData.file); this.setImageStatus (
formData.append ('name', fileData.name.value); fileData, Status.WAITING, 'cloud-upload', _('Waiting for upload'));
formData.append ('schema', this.$('schema').value); fileData.name.disabled = true;
formData.append ('srv', 'json:image/upload'); this.uploadQueue.push (fileData);
this.conn.sendFormData (formData,
this.onFileUpload.bind (this, fileData));
fileData.loading = true;
this.uploadCount++;
count++; count++;
} }
} }
if (count === 0) if (count === 0)
Htk.Toast.showWarning (_('There are no files to upload')); Htk.Toast.showWarning (_('There are no files to upload'));
else
this.uploadNextFile ();
}
,uploadNextFile: function ()
{
if (this.isUploading)
return;
this.isUploading = true;
var fileData = this.uploadQueue.shift ();
this.setImageStatus (
fileData, Status.UPLOADING, 'upload', _('Uploading file'));
var formData = new FormData();
formData.append ('image', fileData.file);
formData.append ('name', fileData.name.value);
formData.append ('schema', this.$('schema').value);
formData.append ('srv', 'json:image/upload');
this.conn.sendFormData (formData,
this.onFileUpload.bind (this, fileData));
} }
,onFileUpload: function (fileData, data, error) ,onFileUpload: function (fileData, data, error)
{ {
fileData.loading = false; this.isUploading = false;
if (data) if (data)
{ {
var iconName = 'ok'; this.setImageStatus (
var title = _('ImageAdded'); fileData, Status.UPLOADED, 'ok', _('Image uploaded'));
fileData.sent = true;
fileData.name.disabled = true;
} }
else else
{ {
var iconName = 'error'; this.setImageStatus (
var title = error.message; fileData, Status.NONE, 'error', error.message);
fileData.name.disabled = false;
this.errors = true; this.errors = true;
} }
var status = fileData.status; if (this.uploadQueue.length === 0)
Vn.Node.removeChilds (status);
var icon = new Htk.Icon ({icon: iconName});
status.appendChild (icon.node);
status.title = title;
this.uploadCount--;
if (this.uploadCount === 0)
{ {
if (!this.errors) if (this.errors)
Htk.Toast.showMessage (_('Upload finished successfully'));
else
Htk.Toast.showError (_('Some errors happened on upload')); Htk.Toast.showError (_('Some errors happened on upload'));
else
Htk.Toast.showMessage (_('Upload finished successfully'));
this.errors = false; this.errors = false;
} }
else
this.uploadNextFile ();
}
,setImageStatus: function (fileData, status, icon, title)
{
fileData.status = status;
var statusNode = fileData.statusNode;
Vn.Node.removeChilds (statusNode);
var iconNode = new Htk.Icon ({icon: icon});
statusNode.appendChild (iconNode.node);
statusNode.title = title ? title : '';
} }
,onFileRemove: function (button) ,onFileRemove: function (button)
@ -202,3 +231,5 @@ function getFileName (path)
return path.substr (barIndex, dotIndex); return path.substr (barIndex, dotIndex);
} }
})();

View File

@ -31,6 +31,7 @@
,"Origin": "Origen" ,"Origin": "Origen"
,"Category": "Categoria" ,"Category": "Categoria"
,"Remove filters": "Esborrar filtres" ,"Remove filters": "Esborrar filtres"
,"Relevancy": "Rellevància"
,"Price": "Precio" ,"Price": "Precio"
,"Amount": "Quantitat" ,"Amount": "Quantitat"

View File

@ -31,6 +31,7 @@
,"Origin": "Origin" ,"Origin": "Origin"
,"Category": "Category" ,"Category": "Category"
,"Remove filters": "Remove filters" ,"Remove filters": "Remove filters"
,"Relevancy": "Relevance"
,"Price": "Price" ,"Price": "Price"
,"Amount": "Amount" ,"Amount": "Amount"

View File

@ -40,8 +40,9 @@
,"Higher price": "Precio más alto" ,"Higher price": "Precio más alto"
,"Lower size": "Medida más pequeña" ,"Lower size": "Medida más pequeña"
,"Higher size": "Medida más grande" ,"Higher size": "Medida más grande"
,", %.0d Units": ", %.0d Unidades" ,"Relevancy": "Relevancia"
,", %.0d Units": ", %.0d Unidades"
,"from": "desde" ,"from": "desde"
,"from %.2d€": "desde %.2d€" ,"from %.2d€": "desde %.2d€"
,"AddToBasket": "Añadir artículo" ,"AddToBasket": "Añadir artículo"

View File

@ -31,6 +31,7 @@
,"Origin": "Origine" ,"Origin": "Origine"
,"Category": "Catégorie" ,"Category": "Catégorie"
,"Remove filters": "Retirer les filtres" ,"Remove filters": "Retirer les filtres"
,"Relevancy": "Pertinence"
,"Price": "Prix" ,"Price": "Prix"
,"Amount": "Quantité" ,"Amount": "Quantité"

View File

@ -31,6 +31,7 @@
,"Origin": "Origin" ,"Origin": "Origin"
,"Category": "Category" ,"Category": "Category"
,"Remove filters": "Remove filters" ,"Remove filters": "Remove filters"
,"Relevancy": "хамаарал"
,"Price": "Price" ,"Price": "Price"
,"Amount": "Amount" ,"Amount": "Amount"

View File

@ -31,6 +31,7 @@
,"Origin": "Orígem" ,"Origin": "Orígem"
,"Category": "Categoria" ,"Category": "Categoria"
,"Remove filters": "Eliminar filtros" ,"Remove filters": "Eliminar filtros"
,"Relevancy": "Relevância"
,"Price": "Preço" ,"Price": "Preço"
,"Amount": "Quantidade" ,"Amount": "Quantidade"

View File

@ -54,7 +54,7 @@
LEFT JOIN vn_locale.color_view c ON c.color_id = a.Color LEFT JOIN vn_locale.color_view c ON c.color_id = a.Color
LEFT JOIN vn_locale.origin_view o ON o.origin_id = a.id_origen LEFT JOIN vn_locale.origin_view o ON o.origin_id = a.id_origen
WHERE b.available > 0 WHERE b.available > 0
ORDER BY a.Article, a.Medida ORDER BY a.relevancy DESC, a.Article, a.Medida
LIMIT 40; LIMIT 40;
</db-model> </db-model>
<db-form id="basket" on-ready="onBasketReady"> <db-form id="basket" on-ready="onBasketReady">
@ -298,7 +298,10 @@
<div id="order" class="order"> <div id="order" class="order">
<h2><t>Order by</t></h2> <h2><t>Order by</t></h2>
<select on-change="onOrderChange"> <select on-change="onOrderChange">
<option value="A|Article" selected="true"> <option value="D|relevancy" selected="true">
<t>Relevancy</t>
</option>
<option value="A|Article">
<t>Name</t> <t>Name</t>
</option> </option>
<option value="A|price"> <option value="A|price">

View File

@ -0,0 +1,62 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
height="16"
viewBox="0 0 16 16"
width="16"
version="1.1"
id="svg6"
sodipodi:docname="cloud-upload.svg"
style="fill:#000000"
inkscape:version="0.92.1 r15371">
<metadata
id="metadata12">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs10" />
<sodipodi:namedview
pagecolor="#000000"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1016"
id="namedview8"
showgrid="false"
inkscape:zoom="9.8333333"
inkscape:cx="-18.305085"
inkscape:cy="11.59322"
inkscape:window-x="1920"
inkscape:window-y="27"
inkscape:window-maximized="1"
inkscape:current-layer="svg6" />
<path
d="M 0,-8 H 24 V 16 H 0 Z"
id="path2"
inkscape:connector-curvature="0"
style="fill:none" />
<path
d="M 11.98125,6.9383334 C 11.612917,5.0695833 9.971667,3.6666667 8,3.6666667 6.4345833,3.6666667 5.075,4.555 4.3979167,5.855 2.7675,6.0283334 1.5,7.4095833 1.5,9.0833334 1.5,10.87625 2.9570833,12.333333 4.75,12.333333 h 7.041667 c 1.495,0 2.708333,-1.213333 2.708333,-2.7083329 0,-1.43 -1.110417,-2.5891668 -2.51875,-2.6866667 z M 9.083333,8.5416667 V 10.708333 H 6.9166667 V 8.5416667 h -1.625 L 8,5.8333333 10.708333,8.5416667 Z"
id="path4"
inkscape:connector-curvature="0"
style="stroke-width:0.54166669;fill:#ffffff;fill-opacity:1" />
</svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

@ -0,0 +1,62 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
height="16"
viewBox="0 0 16 16"
width="16"
version="1.1"
id="svg6"
sodipodi:docname="upload.svg"
style="fill:#000000"
inkscape:version="0.92.1 r15371">
<metadata
id="metadata12">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs10" />
<sodipodi:namedview
pagecolor="#000000"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1016"
id="namedview8"
showgrid="false"
inkscape:zoom="9.8333333"
inkscape:cx="-18.101695"
inkscape:cy="11.18644"
inkscape:window-x="1920"
inkscape:window-y="27"
inkscape:window-maximized="1"
inkscape:current-layer="svg6" />
<path
d="M 0,-8 H 24 V 16 H 0 Z"
id="path2"
inkscape:connector-curvature="0"
style="fill:none" />
<path
d="M 5.7058832,11.441177 H 10.294123 V 6.8529413 H 13.35294 L 8.000008,1.5 2.64706,6.8529413 H 5.7058832 Z M 2.64706,12.970587 H 13.35294 V 14.5 H 2.64706 Z"
id="path4"
inkscape:connector-curvature="0"
style="stroke-width:0.76470536;fill:#ffffff;fill-opacity:1" />
</svg>

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

@ -0,0 +1,143 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
sodipodi:docname="clean.svg"
inkscape:export-filename="/home/sam/dev/RESOURCES/gnome-icon-theme-symbolic/src/gnome-stencils.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90"
height="16"
id="svg7384"
version="1.1"
inkscape:version="0.48.5 r10040"
width="16">
<metadata
id="metadata90">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title>Gnome Symbolic Icon Theme</dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<sodipodi:namedview
inkscape:bbox-nodes="false"
inkscape:bbox-paths="true"
bordercolor="#666666"
borderopacity="1"
inkscape:current-layer="layer12"
inkscape:cx="-150.83074"
inkscape:cy="80.67304"
gridtolerance="10"
inkscape:guide-bbox="true"
guidetolerance="10"
id="namedview88"
inkscape:object-nodes="false"
inkscape:object-paths="false"
objecttolerance="10"
pagecolor="#3a3b39"
inkscape:pageopacity="1"
inkscape:pageshadow="2"
showborder="false"
showgrid="false"
showguides="true"
inkscape:snap-bbox="true"
inkscape:snap-bbox-midpoints="false"
inkscape:snap-global="true"
inkscape:snap-grids="true"
inkscape:snap-nodes="true"
inkscape:snap-others="false"
inkscape:snap-to-guides="true"
inkscape:window-height="1014"
inkscape:window-maximized="1"
inkscape:window-width="1920"
inkscape:window-x="1920"
inkscape:window-y="27"
inkscape:zoom="2.0429688">
<inkscape:grid
dotted="false"
empspacing="2"
enabled="true"
id="grid4866"
originx="60px"
originy="550px"
snapvisiblegridlinesonly="true"
spacingx="1px"
spacingy="1px"
type="xygrid"
visible="true" />
</sodipodi:namedview>
<title
id="title9167">Gnome Symbolic Icon Theme</title>
<defs
id="defs7386" />
<g
inkscape:groupmode="layer"
id="layer9"
inkscape:label="status"
style="display:inline"
transform="translate(-181.0002,-767)" />
<g
inkscape:groupmode="layer"
id="layer10"
inkscape:label="devices"
style="display:inline"
transform="translate(-181.0002,-767)" />
<g
inkscape:groupmode="layer"
id="layer11"
inkscape:label="apps"
transform="translate(-181.0002,-767)" />
<g
inkscape:groupmode="layer"
id="layer13"
inkscape:label="places"
style="display:inline"
transform="translate(-181.0002,-767)" />
<g
inkscape:groupmode="layer"
id="layer14"
inkscape:label="mimetypes"
transform="translate(-181.0002,-767)" />
<g
inkscape:groupmode="layer"
id="layer15"
inkscape:label="emblems"
style="display:inline"
transform="translate(-181.0002,-767)" />
<g
inkscape:groupmode="layer"
id="g71291"
inkscape:label="emotes"
style="display:inline"
transform="translate(-181.0002,-767)" />
<g
inkscape:groupmode="layer"
id="g4953"
inkscape:label="categories"
style="display:inline"
transform="translate(-181.0002,-767)" />
<g
inkscape:groupmode="layer"
id="layer12"
inkscape:label="actions"
style="display:inline"
transform="translate(-181.0002,-767)">
<path
inkscape:connector-curvature="0"
d="m 191.0002,769 6,6 -6,6 -9.0353,0 c -0.53033,-0.0221 -0.9647,-0.49177 -0.9647,-1 l 0,-10 c 0,-0.53079 0.34561,-1 1.0089,-1 l 8.9911,0 z m -1,3 -1,0 c -0.0104,-1.2e-4 -0.0208,-4.6e-4 -0.0313,0 -0.25495,0.0112 -0.50987,0.12858 -0.6875,0.3125 l -1.2812,1.28125 -1.3125,-1.28125 C 185.42208,772.082 185.24103,772.007 185.0002,772 l -1,0 0,1 c 0,0.28647 0.0343,0.55065 0.25,0.75 l 1.28125,1.28125 -1.25,1.25 c -0.18819,0.18817 -0.28124,0.45345 -0.28125,0.71875 l 0,1 1,0 c 0.2653,-10e-6 0.53059,-0.0931 0.71875,-0.28125 l 1.28125,-1.28125 1.28125,1.28125 C 188.46961,777.90694 188.73491,778 189.0002,778 l 1,0 0,-1 c 0,-0.26529 -0.0931,-0.53058 -0.28125,-0.71875 l -1.28125,-1.25 1.28125,-1.28125 c 0.21074,-0.19463 0.30316,-0.46925 0.28125,-0.75 l 0,-1 z"
id="path43079"
sodipodi:nodetypes="ccccccccccsccccccccccccccccccccccc"
style="color:#000000;fill:#666666;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.9 KiB

View File

@ -0,0 +1,62 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
height="16"
viewBox="0 0 16 16"
width="16"
version="1.1"
id="svg6"
sodipodi:docname="cloud-upload.svg"
style="fill:#000000"
inkscape:version="0.92.1 r15371">
<metadata
id="metadata12">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs10" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1016"
id="namedview8"
showgrid="false"
inkscape:zoom="9.8333333"
inkscape:cx="12.20339"
inkscape:cy="12"
inkscape:window-x="1920"
inkscape:window-y="27"
inkscape:window-maximized="1"
inkscape:current-layer="svg6" />
<path
d="M 0,-8 H 24 V 16 H 0 Z"
id="path2"
inkscape:connector-curvature="0"
style="fill:none" />
<path
d="M 11.98125,6.9383334 C 11.612917,5.0695833 9.971667,3.6666667 8,3.6666667 6.4345833,3.6666667 5.075,4.555 4.3979167,5.855 2.7675,6.0283334 1.5,7.4095833 1.5,9.0833334 1.5,10.87625 2.9570833,12.333333 4.75,12.333333 h 7.041667 c 1.495,0 2.708333,-1.213333 2.708333,-2.7083329 0,-1.43 -1.110417,-2.5891668 -2.51875,-2.6866667 z M 9.083333,8.5416667 V 10.708333 H 6.9166667 V 8.5416667 h -1.625 L 8,5.8333333 10.708333,8.5416667 Z"
id="path4"
inkscape:connector-curvature="0"
style="stroke-width:0.54166669;fill:#666666;fill-opacity:1" />
</svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

@ -0,0 +1,62 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
height="16"
viewBox="0 0 16 16"
width="16"
version="1.1"
id="svg6"
sodipodi:docname="upload.svg"
style="fill:#000000"
inkscape:version="0.92.1 r15371">
<metadata
id="metadata12">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs10" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1016"
id="namedview8"
showgrid="false"
inkscape:zoom="9.8333333"
inkscape:cx="12.40678"
inkscape:cy="11.59322"
inkscape:window-x="1920"
inkscape:window-y="27"
inkscape:window-maximized="1"
inkscape:current-layer="svg6" />
<path
d="M 0,-8 H 24 V 16 H 0 Z"
id="path2"
inkscape:connector-curvature="0"
style="fill:none" />
<path
d="M 5.7058832,11.441177 H 10.294123 V 6.8529413 H 13.35294 L 8.000008,1.5 2.64706,6.8529413 H 5.7058832 Z M 2.64706,12.970587 H 13.35294 V 14.5 H 2.64706 Z"
id="path4"
inkscape:connector-curvature="0"
style="stroke-width:0.76470536;fill:#666666;fill-opacity:1" />
</svg>

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

@ -2,7 +2,20 @@
class Account class Account
{ {
static function sync ($db, $user, $password = NULL) static function trySync ($db, $user, $password = NULL)
{
$isSync = $db->getValue (
'SELECT sync FROM account.user WHERE name = #',
[$user]
);
if ($isSync)
return;
self::sync ($db, $user, $password);
}
static function sync ($db, $user, $password = NULL, $force = TRUE)
{ {
$hasAccount = $db->getValue ( $hasAccount = $db->getValue (
'SELECT COUNT(*) > 0 'SELECT COUNT(*) > 0
@ -12,54 +25,135 @@ class Account
[$user] [$user]
); );
if (!$hasAccount) if ($hasAccount)
{
self::ldapSync ($db, $user, $password);
self::sambaSync ($db, $user, $password);
}
$db->query (
'UPDATE account.user SET sync = TRUE WHERE name = #',
[$user]
);
}
/**
* Synchronizes the user credentials in the LDAP server.
*/
static function ldapSync ($db, $user, $password)
{
if (empty ($password))
return; return;
$conf = $db->getRow ( // Gets LDAP configuration parameters
'SELECT sambaHost, homesHost, sshUser, sshPass
FROM account.accountConfig'
);
$sshPass = base64_decode ($conf['sshPass']);
$samba = new SshConnection ($conf['sambaHost'] $conf = $db->getObject (
,$conf['sshUser'] 'SELECT host, rdn, password, baseDn, filter
,$sshPass FROM account.ldapConfig');
);
$homes = new SshConnection ($conf['homesHost'] // Connects an authenticates against server
,$conf['sshUser']
,$sshPass $ds = ldap_connect ($conf->host);
if (!$ds)
throw new Exception ("Can't connect to LDAP server: ". ldapError ($ds));
ldap_set_option($ds, LDAP_OPT_PROTOCOL_VERSION, 3);
$bind = ldap_bind ($ds, $conf->rdn, base64_decode ($conf->password));
if (!$bind)
throw new Exception ("Authentication failed on LDAP server: ". ldapError ($ds));
// Search the user entry
$res = ldap_search ($ds, $conf->baseDn, "(&(uid=$user)($conf->filter))");
if (!$res)
throw new Exception ("Can't get the LDAP entry: ". ldapError ($ds));
$dn = "uid=$user,{$conf->baseDn}";
$entry = ldap_first_entry ($ds, $res);
if ($entry)
{
$info = ['userPassword' => sshaEncode ($password)];
ldap_modify ($ds, $dn, $info);
}
else
{
$info = [
'objectClass' => ['account', 'simpleSecurityObject', 'top'],
'uid' => $user,
'userPassword' => sshaEncode ($password)
];
ldap_add ($ds, $dn, $info);
}
ldap_unbind ($ds);
}
/**
* Synchronizes the user credentials in the Samba server.
*/
static function sambaSync ($db, $user, $password)
{
$conf = $db->getObject (
'SELECT host, sshUser, sshPass, domain, uidBase
FROM account.sambaConfig'
); );
$escUser = SshConnection::escape ($user); $samba = new SshConnection ($conf->host
,$conf->sshUser
,base64_decode ($conf->sshPass)
);
$scriptDir = '/mnt/cluster/scripts';
// Creates the Samba user and initializes it's home directory // Creates the Samba user and initializes it's home directory
$userId = $db->getValue ( $userId = $db->getValue (
'SELECT id FROM account.user WHERE name = #', [$user]); 'SELECT id FROM account.user WHERE name = #', [$user]);
$accConf = $db->getRow (
'SELECT uidBase, domain FROM account.accountConfig');
$escUid = SshConnection::escape ($accConf['uidBase'] + $userId); $samba->exec ("$scriptDir/create-user.sh %s %s %s"
$escMail = SshConnection::escape ("$user@{$accConf['domain']}"); ,$user
,$conf->uidBase + $userId
$samba->exec ( ,"$user@{$conf->domain}"
"/mnt/cluster/scripts/create-user.sh $escUser $escUid $escMail"); );
$homes->exec (
"/mnt/storage/scripts/create-user.sh $escUser");
// Syncronizes the Samba password // Syncronizes the Samba password
if (empty ($password)) if (empty ($password))
return; return;
$escPassword = SshConnection::escape ($password); $samba->exec ("$scriptDir/set-password.sh %s %s"
$samba->exec ( ,$user
"/mnt/cluster/scripts/set-password.sh $escUser $escPassword"); ,$password
);
new SshConnection ($conf['homesHost'], $user, $password);
} }
} }
function ldapError ($ds)
{
return ldap_errno ($ds) .': '. ldap_error ($ds);
}
function sshaEncode ($value)
{
mt_srand ((double) microtime () * 1000000);
$salt = pack ('CCCC', mt_rand (), mt_rand (), mt_rand (), mt_rand ());
$hash = '{SSHA}' . base64_encode (pack ('H*', sha1 ($value . $salt)) . $salt);
return $hash;
}
function sshaVerify ($hash, $value)
{
$ohash = base64_decode (substr ($hash, 6));
$osalt = substr ($ohash, 20);
$ohash = substr ($ohash, 0, 20);
$nhash = pack ('H*', sha1 ($value . $osalt));
return $ohash == $nhash;
}
class SshConnection class SshConnection
{ {
var $connection; var $connection;
@ -87,6 +181,14 @@ class SshConnection
*/ */
function exec ($command) function exec ($command)
{ {
$nargs = func_num_args ();
$args = func_get_args ();
for ($i = 1; $i < $nargs; $i++)
$args[$i] = self::escape ($args[$i]);
$command = call_user_func_array ('sprintf', $args);
error_log ($command);
return ssh2_exec ($this->connection, $command); return ssh2_exec ($this->connection, $command);
} }

View File

@ -1,9 +1,19 @@
<?php <?php
include __DIR__.'/account.php';
class Login extends Vn\Web\JsonRequest class Login extends Vn\Web\JsonRequest
{ {
function run ($db) function run ($db)
{ {
try {
Account::trySync ($db
,strtolower ($_POST['user'])
,$_POST['password']
);
}
catch (Exception $e) {}
$token = $this->service->createToken ( $token = $this->service->createToken (
$_SESSION['user'], $_SESSION['user'],
!empty ($_POST['remember']) !empty ($_POST['remember'])

View File

@ -9,14 +9,11 @@ class RecoverPassword extends Vn\Web\JsonRequest
function run ($db) function run ($db)
{ {
$user = $db->getRow ( $user = $db->getRow (
'SELECT c.`e-mail` mail, u.active 'SELECT email, active FROM account.user WHERE name = #',
FROM vn2008.Clientes c
JOIN account.user u ON u.id = c.Id_Cliente
WHERE u.name = #',
[$_REQUEST['recoverUser']] [$_REQUEST['recoverUser']]
); );
if (!($user['active'] && $user['mail'])) if (!($user['active'] && $user['email']))
return TRUE; return TRUE;
$service = $this->service; $service = $this->service;
@ -24,7 +21,7 @@ class RecoverPassword extends Vn\Web\JsonRequest
$url = $service->getUrl () ."#!form=account/conf&token=$token"; $url = $service->getUrl () ."#!form=account/conf&token=$token";
$report = new Vn\Web\Report ($db, 'recover-password', ['url' => $url]); $report = new Vn\Web\Report ($db, 'recover-password', ['url' => $url]);
$report->sendMail ($user['mail']); $report->sendMail ($user['email']);
return TRUE; return TRUE;
} }

View File

@ -52,6 +52,8 @@ class RestService extends Service
Locale::addPath ('rest/'. dirname ($_REQUEST['method'])); Locale::addPath ('rest/'. dirname ($_REQUEST['method']));
$res = NULL;
try { try {
$res = $method->run ($methodDb); $res = $method->run ($methodDb);
} }