Merge pull request 'test' (!48) from test into dev
gitea/hedera-web/pipeline/head This commit looks good Details

Reviewed-on: #48
This commit is contained in:
Juan Ferrer 2024-02-15 12:32:01 +00:00
commit 4d8a67f499
39 changed files with 436 additions and 230 deletions

2
Jenkinsfile vendored
View File

@ -38,7 +38,7 @@ pipeline {
}
agent {
docker {
image 'registry.verdnatura.es/debuild:2.21.3-vn2'
image 'registry.verdnatura.es/debuild:2.23.4-vn1'
registryUrl 'https://registry.verdnatura.es/'
registryCredentialsId 'docker-registry'
args '-v /mnt/appdata/reprepro:/reprepro'

2
debian/changelog vendored
View File

@ -1,4 +1,4 @@
hedera-web (23.6.14) stable; urgency=low
hedera-web (23.40.6) stable; urgency=low
* Initial Release.

2
debian/links vendored
View File

@ -1,3 +1,3 @@
usr/share/hedera-web/hedera-web.php usr/bin/hedera-web.php
etc/hedera-web/apache.conf etc/apache2/conf-available/hedera-web.conf
etc/hedera-web/php.ini etc/php/7.0/apache2/conf.d/99-hedera-web.ini
etc/hedera-web/php.ini etc/php/8.2/apache2/conf.d/99-hedera-web.ini

View File

@ -7,79 +7,7 @@ export default new Class({
activate() {
this.$.userModel.setInfo('c', 'myClient', 'hedera');
this.$.userModel.setInfo('u', 'myUser', 'account');
if (this.hash.$.verificationToken)
this.onPassChangeClick();
}
,onPassChangeClick() {
this.$.oldPassword.value = '';
this.$.newPassword.value = '';
this.$.repeatPassword.value = '';
var verificationToken = this.hash.$.verificationToken;
this.$.oldPassword.style.display = verificationToken ? 'none' : 'block';
this.$.changePassword.show();
if (verificationToken)
this.$.newPassword.focus();
else
this.$.oldPassword.focus();
}
,async onPassModifyClick() {
const form = this.$.changePassword.node;
Vn.Node.disableInputs(form);
try {
const oldPassword = this.$.oldPassword.value;
const newPassword = this.$.newPassword.value;
const repeatedPassword = this.$.repeatPassword.value;
try {
if (newPassword == '' && repeatedPassword == '')
throw new Error(_('Passwords empty'));
if (newPassword !== repeatedPassword)
throw new Error(_('Passwords doesn\'t match'));
} catch (err) {
return Htk.Toast.showError(err.message);
}
const verificationToken = this.hash.$.verificationToken;
const params = {newPassword};
try {
if (verificationToken) {
params.verificationToken = verificationToken;
await this.conn.send('user/restore-password', params);
} else {
let userId = this.gui.user.id;
params.oldPassword = oldPassword;
await this.conn.patch(
`Accounts/${userId}/changePassword`, params);
}
} catch(err) {
Htk.Toast.showError(err.message);
if (verificationToken)
this.$.newPassword.select();
else
this.$.oldPassword.select();
return;
}
this.hash.unset('verificationToken');
await this.conn.open(this.gui.user.name, newPassword);
this.$.changePassword.hide();
} finally {
Vn.Node.disableInputs(form, false);
}
Htk.Toast.showMessage(_('Password changed!'));
}
,onPassInfoClick() {
this.$.passwordInfo.show();
this.$.changePassword.conn = this.conn
this.$.changePassword.user = this.gui.user
}
});

View File

@ -1,11 +1,5 @@
<vn>
<vn-group>
<db-form v-model="passwordForm">
<db-model property="model">
SELECT length, nAlpha, nUpper, nDigits, nPunct
FROM account.userPassword
</db-model>
</db-form>
<db-form id="user-form">
<db-model property="model" id="user-model" updatable="true">
SELECT u.id, u.name, u.email, u.nickname,
@ -27,7 +21,7 @@
<htk-bar-button
icon="lock_reset"
tip="_Change password"
on-click="this.onPassChangeClick()"/>
on-click="this.$.changePassword.open()"/>
</div>
<div id="form" class="conf">
<div class="form box vn-w-sm vn-pa-lg">
@ -74,64 +68,5 @@
</div>
</div>
</div>
<htk-popup
id="change-password"
modal="true">
<div property="child-node" class="htk-dialog vn-w-xs vn-pa-lg">
<div class="form">
<h5 class="vn-mb-md">
<t>Change password</t>
</h5>
<input
id="old-password"
type="password"
placeholder="_Old password"/>
<input
id="new-password"
type="password"
placeholder="_New password"
autocomplete="new-password"/>
<input
id="repeat-password"
type="password"
placeholder="_Repeat password"
autocomplete="new-password"/>
</div>
<div class="button-bar">
<button class="thin" on-click="this.onPassModifyClick()">
<t>Modify</t>
</button>
<button class="thin" on-click="this.onPassInfoClick()">
<t>Requirements</t>
</button>
<div class="clear"/>
</div>
</div>
</htk-popup>
<htk-popup
id="password-info"
modal="true">
<div property="child-node" class="htk-dialog pass-info vn-w-xs vn-pa-lg">
<h5 class="vn-mb-md">
<t>Password requirements</t>
</h5>
<ul>
<li>
{{passwordForm.length}} <t>characters long</t>
</li>
<li>
{{passwordForm.nAlpha}} <t>alphabetic characters</t>
</li>
<li>
{{passwordForm.nUpper}} <t>capital letters</t>
</li>
<li>
{{passwordForm.nDigits}} <t>digits</t>
</li>
<li>
{{passwordForm.nPunct}} <t>symbols</t>
</li>
</ul>
</div>
</htk-popup>
<htk-change-password id="change-password"/>
</vn>

View File

@ -7,8 +7,8 @@ export default new Class({
,activate() {
if (!this.hash.$.to)
this.hash.assign({
from: new Date(),
to: new Date()
from: Date.vnNew(),
to: Date.vnNew()
});
}
});

View File

@ -14,7 +14,7 @@ export default new Class({
,refreshCaptcha() {
params = {
srv: 'rest:misc/captcha',
stamp: new Date().getTime()
stamp: Date.vnNew().getTime()
};
this.$.captchaImg.src = '?'+ Vn.Url.makeUri(params);
}

View File

@ -13,7 +13,8 @@ BecauseOurSalesDep: >-
Pour nos professionnels de service commercial qui sera toujours de trouver une
solution à vos besoins.
BecauseOurWorkShop: Parce que nous avons un atelier de couture pour aider.
BecauseWeHaveWhatYouNeed: Parce que nous avons ce que vous avez besoin quand vous en avez besoin ...
BecauseWeHaveWhatYouNeed: >-
Parce que nous avons ce que vous avez besoin quand vous en avez besoin ...
AboutDesc: >-
Nous sommes une société spécialisée dans le commerce de gros et de la
distribution d'une large gamme d'accessoires, des verts et des fleurs à des
@ -31,6 +32,6 @@ AboutDisp: >-
Mercaflor - Mercavalencia (Valencia) qui effectuent des ventes directes
seulement.
AboutOrder: >-
Vous pouvez faire vos commandes et réservations par téléphone au +33 781 533
900, en ligne grâce à notre site Internet ou directement dans nos
Vous pouvez faire vos commandes et réservations par téléphone au +33 783 285
437, en ligne grâce à notre site Internet ou directement dans nos
installations.

View File

@ -203,6 +203,12 @@ const Catalog = new Class({
this.hideMenu();
}
,itemRenderer(builder, form) {
var minQuantity = builder.$.minQuantity;
minQuantity.style.display = form.$.minQuantity
? 'block' : 'hidden';
}
,realmRenderer(builder, form) {
var link = builder.$.link;
link.href = this.hash.make({
@ -273,6 +279,8 @@ const Catalog = new Class({
orderId: this.orderId
});
this.$.cardPopup.show(event.currentTarget);
this.$.cardMinQuantity.style.display = form.$.minQuantity
? 'block' : 'none';
}
,onAddLotClick(column, value, row) {
@ -317,7 +325,7 @@ const Catalog = new Class({
}
if (amountSum > 0) {
this.conn.execQuery(sql);
await this.conn.execQuery(sql);
var itemName = this.$.$card.get('item');
Htk.Toast.showMessage(

View File

@ -46,3 +46,4 @@ NoMoreAmountAvailable: No hi ha més quantitat disponible
MinimalGrouping: Empaquetat mínim
Available: Disponible
GroupingPrice: Preu per grup
MinimalQuantity: Quantitat mínima

View File

@ -46,3 +46,4 @@ NoMoreAmountAvailable: No more amount available
MinimalGrouping: Minimal packing
Available: Available
GroupingPrice: Price per group
MinimalQuantity: Minimal quantity

View File

@ -46,3 +46,4 @@ NoMoreAmountAvailable: No hay más cantidad disponible
MinimalGrouping: Empaquetado mínimo
Available: Disponible
GroupingPrice: Precio per grupo
MinimalQuantity: Cantidad mínima

View File

@ -46,3 +46,4 @@ NoMoreAmountAvailable: Pas plus disponible
MinimalGrouping: Emballage minimal
Available: Disponible
GroupingPrice: Prix par groupe
MinimalQuantity: Quantité minimum

View File

@ -46,3 +46,4 @@ NoMoreAmountAvailable: Não há mais quantidade disponível
MinimalGrouping: Embalagem mínima
Available: Disponível
GroupingPrice: Preço por grupo
MinimalQuantity: Quantidade mínima

View File

@ -192,6 +192,25 @@
margin: 0;
margin-bottom: 1px;
}
& > .min-quantity {
bottom: 32px;
right: 0;
}
}
.min-quantity {
position: absolute;
display: none;
bottom: 30px;
right: 0;
font-size: .8rem;
color: #a44;
cursor: pointer;
& > span {
font-size: 16px;
vertical-align: middle;
}
}
/* Tags */
@ -266,7 +285,7 @@
flex: auto;
overflow: hidden;
margin: 10px;
height: 170px;
height: 185px;
& > h2 {
max-height: 3rem;
@ -351,6 +370,7 @@
& > .top {
padding: 14px;
position: relative;
& > .item-info {
margin-left: 126px;
@ -371,6 +391,11 @@
margin-top: 15px 0;
font-size: .9rem;
}
& > .min-quantity {
bottom: 0;
right: 0;
padding: 14px;
}
}
& > .lots-grid {
border-top: 1px solid #DDD;

View File

@ -115,8 +115,9 @@
WHERE #filter;
CALL myOrder_calcCatalogFull(#orderId);
SELECT i.id, i.longName item, i.subName,
i.tag5, i.value5, i.tag6, i.value6, i.tag7, i.value7,
i.relevancy, i.size, i.category,
i.tag5, i.value5, i.tag6, i.value6,
i.tag7, i.value7, i.tag8, i.value8,
i.relevancy, i.size, i.category, i.minQuantity,
k.name ink, p.name producer, o.name origin,
b.available, b.price, b.`grouping`,
i.image, im.updated
@ -148,7 +149,8 @@
id="grid-view"
empty-message="_Choose filter from right menu"
form-id="item"
model="items">
model="items"
renderer="itemRenderer">
<custom>
<div
id="item-box"
@ -186,6 +188,10 @@
<td>{{item.tag7}}</td>
<td>{{item.value7}}</td>
</tr>
<tr>
<td>{{item.tag8}}</td>
<td>{{item.value8}}</td>
</tr>
</table>
<div class="available-price">
<span class="grouping" title="_MinimalGrouping">
@ -198,6 +204,12 @@
{{Vn.Value.format(item.price, '%.02d€')}}
</span>
</div>
<div id="min-quantity" class="min-quantity" title="_MinimalQuantity">
<span class="htk-icon material-symbols-rounded">
production_quantity_limits
</span>
{{item.minQuantity}}
</div>
</div>
</div>
</custom>
@ -456,6 +468,12 @@
</tr>
</custom>
</htk-repeater>
<div id="card-min-quantity" class="min-quantity" title="_MinimalQuantity">
<span class="htk-icon material-symbols-rounded">
production_quantity_limits
</span>
{{card.minQuantity}}
</div>
</div>
<htk-grid class="lots-grid" show-header="false">
<db-model

View File

@ -8,7 +8,7 @@ export default new Class({
this.autoStepLocked = true;
this.$.assistant.stepsIndex = this.agencySteps;
this.today = new Date();
this.today = Date.vnNew();
this.today.setHours(0, 0, 0, 0);
},
@ -22,8 +22,8 @@ export default new Class({
let date;
const row = orderForm.$ || defaultsForm.$ || {};
if (!date || date.getTime() < (new Date()).getTime()) {
date = new Date();
if (!date || date.getTime() < (Date.vnNew()).getTime()) {
date = Date.vnNew();
date.setHours(0, 0, 0, 0);
let addDays = 0;

View File

@ -6,7 +6,7 @@ export default new Class({
activate() {
this.$.lot.assign({
date: new Date(),
date: Date.vnNew(),
useIds: false
});
},

View File

@ -65,3 +65,20 @@ Account: Compte
Addresses: Adreces
Load an order: Si us plau carrega una comanda pendent a la cistella o en comença una de nova
Old password: Contrasenya antiga
New password: Nova contrasenya
Repeat password: Repetir contrasenya
Requirements: Requisits
Modify: Modificar
Password requirements: Requisits de contrasenya
characters long: caràcters de longitud
alphabetic characters: caràcters alfabètics
capital letters: majúscules
digits: dígits
symbols: símbols
Password changed!: Contrasenya modificada!
Password doesn't meet the requirements: ''
Passwords doesn't match: Les contrasenyes no coincideixen!
Passwords empty: Les contrasenyes en blanc
Change password: Canvia la contrasenya

View File

@ -65,3 +65,22 @@ Account: Cuenta
Addresses: Direcciones
Load an order: Por favor carga un pedido pendiente en la cesta o empieza uno nuevo
Old password: Contaseña antigua
New password: Nueva contraseña
Repeat password: Repetir contraseña
Requirements: Requisitos
Modify: Modificar
Password requirements: Requisitos de constraseña
characters long: carácteres de longitud
alphabetic characters: carácteres alfabéticos
capital letters: letras mayúsculas
digits: dígitos
symbols: 'símbolos. Ej: $%&.'
Password changed!: ¡Contraseña modificada!
Password doesn't meet the requirements: >-
La nueva contraseña no reune los requisitos de seguridad necesarios, pulsa en
info para más detalle
Passwords doesn't match: ¡Las contraseñas no coinciden!
Passwords empty: Contraseña vacía
Change password: Cambiar contraseña

View File

@ -5,7 +5,7 @@ Remind me: Retenir mon mot de passe
Log in as guest: Entrez en tant qu'invité
Login: Se connecter
Login mail: info@verdnatura.es
Login phone: +33 781 533 900
Login phone: +33 783 285 437
Password forgotten? Push here: Vous avez oublié votre mot de passe?
Yet you are not a customer?: Vous n'êtes pas encore client?
Sign up: S'inscrire
@ -65,3 +65,20 @@ Account: Compte
Addresses: Adresses
Load an order: Veuillez télécharger une commande en attente dans le panier ou en démarrer une nouvelle
Old password: Ancien mot de passe
New password: Nouveau mot de passe
Repeat password: Répéter le mot de passe
Requirements: Exigences
Modify: Modifier
Password requirements: Mot de passe exigences
characters long: Longs caractères
alphabetic characters: les caractères alphabétiques
capital letters: lettres majuscules
digits: chiffres
symbols: 'symboles. Ej: $%&.'
Password changed!: Mot de passe modifié!
Password doesn't meet the requirements: ''
Passwords doesn't match: Les mots de passe ne correspondent pas!
Passwords empty: ''
Change password: Changer le mot de passe

View File

@ -63,3 +63,20 @@ Account: Conta
Addresses: Moradas
Load an order: Carregue um pedido pendente no carrinho ou inicie um novo
Old password: Palavra-passe antiga
New password: Nova Palavra-passe
Repeat password: Repetir Palavra-passe
Requirements: Requisitos
Modify: Modificar
Password requirements: Requisitos de Palavra-passe
characters long: caracteres
alphabetic characters: caracteres alfabéticos
capital letters: letras maiúsculas
digits: dígitos
symbols: 'símbolos. Ej: $%&.'
Password changed!: Palavra-passe Modificada!
Password doesn't meet the requirements: Palavra-passe não atende aos requisitos
Passwords doesn't match: As Palavras-Passe não coincidem!
Passwords empty: Palavra-passe vazia
Change password: Mudar Palavra-passe

View File

@ -26,6 +26,12 @@ module.exports = new Class({
self._onSubmit();
return false;
};
if(this.hash.$.verificationToken){
this.$.changePassword.conn = this.conn;
this.$.changePassword.token = this.hash.$.verificationToken;
this.$.changePassword.open();
}
}
,_onConnLoadChange(conn, isLoading) {
@ -94,7 +100,11 @@ module.exports = new Class({
return;
}
await this._conn.send('user/recover-password', {recoverUser});
await this.conn.post('VnUsers/recoverPassword', {
user: recoverUser,
app: 'hedera'
});
Htk.Toast.showMessage(_('A mail has been sent wich you can recover your password'));
}
});

View File

@ -54,4 +54,5 @@
</div>
</div>
</div>
<htk-change-password id="change-password"/>
</vn>

View File

@ -141,7 +141,7 @@ module.exports = new Class({
}
,goToCurrentMonth() {
var date = new Date();
var date = Date.vnNew();
this.goToMonth(date.getFullYear(), date.getMonth());
}
@ -179,7 +179,7 @@ module.exports = new Class({
// Marks the current day
var today = new Date();
var today = Date.vnNew();
if (this.year == today.getFullYear()
&& this.month == today.getMonth()) {

View File

@ -0,0 +1,111 @@
var Component = require('vn/component');
var Toast = require('../toast');
var Tpl = require('./ui.xml').default;
/**
* A change password popup.
*/
module.exports = new Class({
Extends: Component,
Tag: 'htk-change-password',
Properties: {
/**
* The token url.
*/
token: {
type: String
,set(value) {
this._token = value;
}
,get() {
return this._token;
}
},
conn: {
type: Db.Connection
,set(x) {
this._conn = x
}
,get() {
return this._conn;
}
},
user: {
type: Object
}
},
initialize(props) {
Component.prototype.initialize.call(this, props);
},
async open() {
this.passwordForm = await this.conn.get('UserPasswords/findOne')
this.loadTemplateFromString(Tpl);
this.$.oldPassword.value = '';
this.$.newPassword.value = '';
this.$.repeatPassword.value = '';
this.$.oldPassword.style.display = this.token ? 'none' : 'block';
this.$.changePassword.open();
if (this.token)
this.$.newPassword.focus();
else
this.$.oldPassword.focus();
},
async onPassModifyClick() {
const form = this.$.changePassword.node;
Vn.Node.disableInputs(form);
try {
const oldPassword = this.$.oldPassword.value;
const newPassword = this.$.newPassword.value;
const repeatedPassword = this.$.repeatPassword.value;
try {
if (newPassword == '' && repeatedPassword == '')
throw new Error(_('Passwords empty'));
if (newPassword !== repeatedPassword)
throw new Error(_('Passwords doesn\'t match'));
} catch (err) {
return Toast.showError(err.message);
}
const params = {newPassword};
try {
if (this.token) {
const headers = {
Authorization: this.token
};
await this.conn.post('VnUsers/reset-password', params, {headers});
} else {
params.userId = this.user.id;
params.oldPassword = oldPassword;
await this.conn.patch(`Accounts/change-password`, params);
}
} catch(err) {
Toast.showError(err.message);
if (this.token)
this.$.newPassword.select();
else
this.$.oldPassword.select();
return;
}
if(this.user)
await this.conn.open(this.user.name, newPassword);
this.$.changePassword.hide();
} finally {
Vn.Node.disableInputs(form, false);
}
Toast.showMessage(_('Password changed!'));
}
});

View File

@ -0,0 +1,62 @@
<vn>
<htk-popup
id="change-password"
modal="true">
<div property="child-node" class="htk-dialog vn-w-xs vn-pa-lg">
<div class="form">
<h5 class="vn-mb-md">
<t>Change password</t>
</h5>
<input
id="old-password"
type="password"
placeholder="_Old password"/>
<input
id="new-password"
type="password"
placeholder="_New password"
autocomplete="new-password"/>
<input
id="repeat-password"
type="password"
placeholder="_Repeat password"
autocomplete="new-password"/>
</div>
<div class="button-bar">
<button class="thin" on-click="this.onPassModifyClick()">
<t>Modify</t>
</button>
<button class="thin" on-click="this.$.passwordInfo.show()">
<t>Requirements</t>
</button>
<div class="clear"/>
</div>
</div>
</htk-popup>
<htk-popup
id="password-info"
modal="true">
<div property="child-node" class="htk-dialog pass-info vn-w-xs vn-pa-lg">
<h5 class="vn-mb-md">
<t>Password requirements</t>
</h5>
<ul>
<li>
{{this.passwordForm.length}} <t>characters long</t>
</li>
<li>
{{this.passwordForm.nAlpha}} <t>alphabetic characters</t>
</li>
<li>
{{this.passwordForm.nUpper}} <t>capital letters</t>
</li>
<li>
{{this.passwordForm.nDigits}} <t>digits</t>
</li>
<li>
{{this.passwordForm.nPunct}} <t>symbols</t>
</li>
</ul>
</div>
</htk-popup>
</vn>

View File

@ -19,6 +19,7 @@ Htk = module.exports = {
,List : require('./list')
,Field : require('./field')
,Column : require('./column')
,ChangePassword : require('./change-password')
};
var Fields = {

View File

@ -192,7 +192,7 @@ module.exports = new Class({
}
,_onFileUpload(cell) {
this._stamp = new Date().getTime();
this._stamp = Date.vnNew().getTime();
this._refreshSrc(cell);
this.popup.hide();
}

View File

@ -3,69 +3,61 @@
*/
module.exports =
{
set: function (key, value, days)
{
set: function(key, value, days) {
var strCookie = key + '=' + value + ';';
if (days != undefined)
{
var date = new Date ();
date.setTime (date.getTime () + days * 86400000);
strCookie += 'expires=' + date.toGMTString ();
if (days != undefined) {
var date = Date.vnNew();
date.setTime(date.getTime() + days * 86400000);
strCookie += 'expires=' + date.toGMTString();
}
document.cookie = strCookie;
}
,unset: function (key)
{
this.set (key, '', -1);
,unset: function(key) {
this.set(key, '', -1);
}
,get: function (key)
{
var cookie = new String (document.cookie);
var start = cookie.indexOf (key + '=');
,get: function(key) {
var cookie = new String(document.cookie);
var start = cookie.indexOf(key + '=');
if (start != -1)
{
if (start != -1) {
var end;
start += key.length + 1;
end = cookie.indexOf (';', start);
end = cookie.indexOf(';', start);
if (end > 0)
return cookie.substring (start, end);
return cookie.substring(start, end);
else
return cookie.substring (start);
return cookie.substring(start);
}
return null;
}
,getInt: function (key)
{
var value = this.get (key);
,getInt: function(key) {
var value = this.get(key);
if (value != null)
return parseInt (value);
return parseInt(value);
return null;
}
,getFloat: function (key)
{
var value = this.get (key);
,getFloat: function(key) {
var value = this.get(key);
if (value != null)
return parseFloat (value);
return parseFloat(value);
return null;
}
,check: function (key)
{
return this.get (key) != null;
,check: function(key) {
return this.get(key) != null;
}
};

View File

@ -6,6 +6,22 @@ Date.prototype.clone = function() {
return new Date(this.getTime());
}
Date.vnUTC = () => {
const env = process.env.NODE_ENV;
if (!env || env === 'development')
return new Date(Date.UTC(2001, 0, 1, 11));
return new Date();
};
Date.vnNew = () => {
return new Date(Date.vnUTC());
};
Date.vnNow = () => {
return new Date(Date.vnUTC()).getTime();
};
module.exports =
{
WDays: [

View File

@ -85,6 +85,7 @@ module.exports = new Class({
const config = {
headers: {'Authorization': token}
};
await this.send('user/logout', null, config);
await this.post('Accounts/logout', null, config);
}
},
@ -139,15 +140,16 @@ module.exports = new Class({
/*
* Called when REST response is received.
*/
async sendWithUrl(method, url, params) {
return this.request({
async sendWithUrl(method, url, params, config) {
config = Object.assign({}, config, {
method,
url,
data: Vn.Url.makeUri(params),
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
data: Vn.Url.makeUri(params)
});
config.headers = Object.assign({}, config.headers, {
'Content-Type': 'application/x-www-form-urlencoded'
});
return this.request(config);
},
async get(url, config) {

View File

@ -1,6 +1,6 @@
{
"name": "hedera-web",
"version": "23.6.14",
"version": "23.40.6",
"description": "Verdnatura web page",
"license": "GPL-3.0",
"repository": {
@ -42,7 +42,8 @@
"scripts": {
"front": "webpack serve --open",
"back": "cd ../salix && gulp backOnly",
"db": "cd ../vn-database && myvc run",
"php": "php -S 127.0.0.1:3001 -t . index.php",
"db": "cd ../vn-database && myt run",
"build": "rm -rf build/ ; webpack",
"clean": "rm -rf build/"
}

View File

@ -1,6 +1,7 @@
<?php
use Vn\Lib;
use Vn\Lib\Locale;
use Vn\Web\Security;
use Vn\Lib\Type;
@ -36,13 +37,17 @@ class Query extends Vn\Web\JsonRequest {
while ($db->moreResults() && $db->nextResult());
if ($db->checkWarnings()
&&($result = $db->query('SHOW WARNINGS'))) {
$sql = 'SELECT `description`, @warn `code`
FROM `message` WHERE `code` = @warn';
&& ($result = $db->query('SHOW WARNINGS'))) {
$sql =
'SELECT IFNULL(i.`description`, m.`description`) `description`, @warn `code`
FROM `message` m
LEFT JOIN `messageI18n` i
ON i.`code` = m.`code` AND i.lang = #
WHERE m.`code` = @warn';
while ($row = $result->fetch_object()) {
if ($row->Code == 1265
&&($warning = $db->getObject($sql)))
&& ($warning = $db->getObject($sql, [Locale::get()])))
trigger_error("{$warning->code}: {$warning->description}", E_USER_WARNING);
else
trigger_error("{$row->Code}: {$row->Message}", E_USER_WARNING);

View File

@ -18,7 +18,7 @@ class Segment {
switch ($type) {
case Type::DATE:
$tmp = new Date();
$tmp = Date.vnNew();
$tmp->setDate(substr($v, 0, 4), substr($v, 4, 2), substr($v, 6, 2));
return $tmp;
case Type::TIME:

7
rest/user/logout.php Normal file
View File

@ -0,0 +1,7 @@
<?php
class Logout extends Vn\Web\JsonRequest {
function run($db) {
$_SESSION['user'] = null;
}
}

View File

@ -5,6 +5,7 @@ namespace Vn\Web;
require_once 'libphp-phpmailer/autoload.php';
use Vn\Lib\UserException;
use PHPMailer\PHPMailer\PHPMailer;
class Mailer {
private $conf;
@ -19,7 +20,7 @@ class Mailer {
function createObject($mailTo, $body, $subject) {
$conf = $this->conf;
$mail = new \PHPMailer();
$mail = new PHPMailer();
$mail->isSMTP();
$mail->Host = $conf->host;

View File

@ -54,8 +54,12 @@ class RestService extends Service {
if ($e->getCode() == 1644) {
$eMessage = $e->getMessage();
$tMessage = $db->getValue(
'SELECT `description` FROM `messageL10n` WHERE `code` = #',
[$eMessage]
'SELECT IFNULL(i.`description`, m.`description`) `description`
FROM `message` m
LEFT JOIN `messageI18n` i
ON i.`code` = m.`code` AND i.lang = #
WHERE m.`code` = #',
[Locale::get(), $eMessage]
);
if (!$tMessage) $tMessage = $eMessage;
throw new Lib\UserException($tMessage, $eMessage);

View File

@ -158,8 +158,10 @@ abstract class Service {
[$token]
);
if (!$userId)
if (!$userId) {
$_SESSION['user'] = null;
throw new SessionExpiredException();
}
$anonymousUser = FALSE;
$user = $db->getValue(
@ -175,9 +177,11 @@ abstract class Service {
[$user]
);
if (!$isActive)
if (!$isActive) {
$_SESSION['user'] = null;
throw new UserDisabledException();
}
}
$db->query('CALL account.myUser_loginWithName(#)', [$user]);
@ -187,7 +191,6 @@ abstract class Service {
$_SESSION['user'] = $user;
// Registering the user access
if (isset($_SESSION['access']) && $userChanged)
$db->query(
'CALL visitUser_new(#, #)',