From 3114c678a4c2585a281bbf3fd8cd1f0e486985ec Mon Sep 17 00:00:00 2001 From: Cayo Puigdefabregas Date: Wed, 6 Apr 2022 12:35:08 +0200 Subject: [PATCH 01/54] add user model fields #3017 --- .../1b61613d1c19_add_new_fields_in_agent.py | 35 ++++++++ ereuse_devicehub/resources/agent/models.py | 86 ++++++++++++------- ereuse_devicehub/resources/user/models.py | 58 ++++++++----- .../ereuse_devicehub/user_profile.html | 73 +++++++++++----- ereuse_devicehub/views.py | 2 + 5 files changed, 182 insertions(+), 72 deletions(-) create mode 100644 ereuse_devicehub/migrations/versions/1b61613d1c19_add_new_fields_in_agent.py diff --git a/ereuse_devicehub/migrations/versions/1b61613d1c19_add_new_fields_in_agent.py b/ereuse_devicehub/migrations/versions/1b61613d1c19_add_new_fields_in_agent.py new file mode 100644 index 00000000..13d71b82 --- /dev/null +++ b/ereuse_devicehub/migrations/versions/1b61613d1c19_add_new_fields_in_agent.py @@ -0,0 +1,35 @@ +"""add new fields in agent + +Revision ID: 1b61613d1c19 +Revises: 8571fb32c912 +Create Date: 2022-04-06 12:23:37.644108 + +""" +import citext +import sqlalchemy as sa +from alembic import context, op + +# revision identifiers, used by Alembic. +revision = '1b61613d1c19' +down_revision = '8571fb32c912' +branch_labels = None +depends_on = None + + +def get_inv(): + INV = context.get_x_argument(as_dictionary=True).get('inventory') + if not INV: + raise ValueError("Inventory value is not specified") + return INV + + +def upgrade(): + op.add_column( + "agent", + sa.Column("last_name", citext.CIText(), nullable=True), + schema=f'{get_inv()}', + ) + + +def downgrade(): + op.drop_column('agent', 'last_name', schema=f'{get_inv()}') diff --git a/ereuse_devicehub/resources/agent/models.py b/ereuse_devicehub/resources/agent/models.py index ab9e073a..4554d227 100644 --- a/ereuse_devicehub/resources/agent/models.py +++ b/ereuse_devicehub/resources/agent/models.py @@ -3,7 +3,9 @@ from operator import attrgetter from uuid import uuid4 from citext import CIText -from sqlalchemy import Column, Enum as DBEnum, ForeignKey, Unicode, UniqueConstraint +from sqlalchemy import Column +from sqlalchemy import Enum as DBEnum +from sqlalchemy import ForeignKey, Unicode, UniqueConstraint from sqlalchemy.dialects.postgresql import UUID from sqlalchemy.ext.declarative import declared_attr from sqlalchemy.orm import backref, relationship, validates @@ -29,6 +31,7 @@ class Agent(Thing): id = Column(UUID(as_uuid=True), primary_key=True, default=uuid4) type = Column(Unicode, nullable=False) name = Column(CIText()) + last_name = Column(CIText()) name.comment = """The name of the organization or person.""" tax_id = Column(Unicode(length=STR_SM_SIZE), check_lower('tax_id')) tax_id.comment = """The Tax / Fiscal ID of the organization, @@ -42,9 +45,15 @@ class Agent(Thing): __table_args__ = ( UniqueConstraint(tax_id, country, name='Registration Number per country.'), UniqueConstraint(tax_id, name, name='One tax ID with one name.'), - db.Index('agent_type', type, postgresql_using='hash') + db.Index('agent_type', type, postgresql_using='hash'), ) + @property + def get_full_name(self): + if self.last_name: + return "{} {}".format(self.name, self.last_name) + return self.name + @declared_attr def __mapper_args__(cls): """Defines inheritance. @@ -63,7 +72,9 @@ class Agent(Thing): @property def actions(self) -> list: # todo test - return sorted(chain(self.actions_agent, self.actions_to), key=attrgetter('created')) + return sorted( + chain(self.actions_agent, self.actions_to), key=attrgetter('created') + ) @validates('name') def does_not_contain_slash(self, _, value: str): @@ -76,15 +87,17 @@ class Agent(Thing): class Organization(JoinedTableMixin, Agent): - default_of = db.relationship(Inventory, - uselist=False, - lazy=True, - backref=backref('org', lazy=True), - # We need to use this as we cannot do Inventory.foreign -> Org - # as foreign keys can only reference to one table - # and we have multiple organization table (one per schema) - foreign_keys=[Inventory.org_id], - primaryjoin=lambda: Organization.id == Inventory.org_id) + default_of = db.relationship( + Inventory, + uselist=False, + lazy=True, + backref=backref('org', lazy=True), + # We need to use this as we cannot do Inventory.foreign -> Org + # as foreign keys can only reference to one table + # and we have multiple organization table (one per schema) + foreign_keys=[Inventory.org_id], + primaryjoin=lambda: Organization.id == Inventory.org_id, + ) def __init__(self, name: str, **kwargs) -> None: super().__init__(**kwargs, name=name) @@ -97,12 +110,17 @@ class Organization(JoinedTableMixin, Agent): class Individual(JoinedTableMixin, Agent): active_org_id = Column(UUID(as_uuid=True), ForeignKey(Organization.id)) - active_org = relationship(Organization, primaryjoin=active_org_id == Organization.id) + + active_org = relationship( + Organization, primaryjoin=active_org_id == Organization.id + ) user_id = Column(UUID(as_uuid=True), ForeignKey(User.id), unique=True) - user = relationship(User, - backref=backref('individuals', lazy=True, collection_class=set), - primaryjoin=user_id == User.id) + user = relationship( + User, + backref=backref('individuals', lazy=True, collection_class=set), + primaryjoin=user_id == User.id, + ) class Membership(Thing): @@ -110,20 +128,29 @@ class Membership(Thing): For example, because the individual works in or because is a member of. """ - id = Column(Unicode(), check_lower('id')) - organization_id = Column(UUID(as_uuid=True), ForeignKey(Organization.id), primary_key=True) - organization = relationship(Organization, - backref=backref('members', collection_class=set, lazy=True), - primaryjoin=organization_id == Organization.id) - individual_id = Column(UUID(as_uuid=True), ForeignKey(Individual.id), primary_key=True) - individual = relationship(Individual, - backref=backref('member_of', collection_class=set, lazy=True), - primaryjoin=individual_id == Individual.id) - def __init__(self, organization: Organization, individual: Individual, id: str = None) -> None: - super().__init__(organization=organization, - individual=individual, - id=id) + id = Column(Unicode(), check_lower('id')) + organization_id = Column( + UUID(as_uuid=True), ForeignKey(Organization.id), primary_key=True + ) + organization = relationship( + Organization, + backref=backref('members', collection_class=set, lazy=True), + primaryjoin=organization_id == Organization.id, + ) + individual_id = Column( + UUID(as_uuid=True), ForeignKey(Individual.id), primary_key=True + ) + individual = relationship( + Individual, + backref=backref('member_of', collection_class=set, lazy=True), + primaryjoin=individual_id == Individual.id, + ) + + def __init__( + self, organization: Organization, individual: Individual, id: str = None + ) -> None: + super().__init__(organization=organization, individual=individual, id=id) __table_args__ = ( UniqueConstraint(id, organization_id, name='One member id per organization.'), @@ -134,6 +161,7 @@ class Person(Individual): """A person in the system. There can be several persons pointing to a real. """ + pass diff --git a/ereuse_devicehub/resources/user/models.py b/ereuse_devicehub/resources/user/models.py index 70f14e00..039a4bf3 100644 --- a/ereuse_devicehub/resources/user/models.py +++ b/ereuse_devicehub/resources/user/models.py @@ -2,37 +2,44 @@ from uuid import uuid4 from flask import current_app as app from flask_login import UserMixin -from sqlalchemy import Column, Boolean, BigInteger, Sequence +from sqlalchemy import BigInteger, Boolean, Column, Sequence from sqlalchemy.dialects.postgresql import UUID from sqlalchemy_utils import EmailType, PasswordType from teal.db import IntEnum from ereuse_devicehub.db import db +from ereuse_devicehub.resources.enums import SessionType from ereuse_devicehub.resources.inventory.model import Inventory from ereuse_devicehub.resources.models import STR_SIZE, Thing -from ereuse_devicehub.resources.enums import SessionType class User(UserMixin, Thing): __table_args__ = {'schema': 'common'} id = Column(UUID(as_uuid=True), default=uuid4, primary_key=True) email = Column(EmailType, nullable=False, unique=True) - password = Column(PasswordType(max_length=STR_SIZE, - onload=lambda **kwargs: dict( - schemes=app.config['PASSWORD_SCHEMES'], - **kwargs - ))) + password = Column( + PasswordType( + max_length=STR_SIZE, + onload=lambda **kwargs: dict( + schemes=app.config['PASSWORD_SCHEMES'], **kwargs + ), + ) + ) token = Column(UUID(as_uuid=True), default=uuid4, unique=True, nullable=False) active = Column(Boolean, default=True, nullable=False) phantom = Column(Boolean, default=False, nullable=False) - inventories = db.relationship(Inventory, - backref=db.backref('users', lazy=True, collection_class=set), - secondary=lambda: UserInventory.__table__, - collection_class=set) + inventories = db.relationship( + Inventory, + backref=db.backref('users', lazy=True, collection_class=set), + secondary=lambda: UserInventory.__table__, + collection_class=set, + ) # todo set restriction that user has, at least, one active db - def __init__(self, email, password=None, inventories=None, active=True, phantom=False) -> None: + def __init__( + self, email, password=None, inventories=None, active=True, phantom=False + ) -> None: """Creates an user. :param email: :param password: @@ -44,8 +51,13 @@ class User(UserMixin, Thing): create during the trade actions """ inventories = inventories or {Inventory.current} - super().__init__(email=email, password=password, inventories=inventories, - active=active, phantom=phantom) + super().__init__( + email=email, + password=password, + inventories=inventories, + active=active, + phantom=phantom, + ) def __repr__(self) -> str: return ''.format(self) @@ -73,8 +85,9 @@ class User(UserMixin, Thing): @property def get_full_name(self): - # TODO(@slamora) create first_name & last_name fields and use - # them to generate user full name + if self.individual: + return self.individual.get_full_name + return self.email def check_password(self, password): @@ -84,9 +97,12 @@ class User(UserMixin, Thing): class UserInventory(db.Model): """Relationship between users and their inventories.""" + __table_args__ = {'schema': 'common'} user_id = db.Column(db.UUID(as_uuid=True), db.ForeignKey(User.id), primary_key=True) - inventory_id = db.Column(db.Unicode(), db.ForeignKey(Inventory.id), primary_key=True) + inventory_id = db.Column( + db.Unicode(), db.ForeignKey(Inventory.id), primary_key=True + ) class Session(Thing): @@ -96,9 +112,11 @@ class Session(Thing): token = Column(UUID(as_uuid=True), default=uuid4, unique=True, nullable=False) type = Column(IntEnum(SessionType), default=SessionType.Internal, nullable=False) user_id = db.Column(db.UUID(as_uuid=True), db.ForeignKey(User.id)) - user = db.relationship(User, - backref=db.backref('sessions', lazy=True, collection_class=set), - collection_class=set) + user = db.relationship( + User, + backref=db.backref('sessions', lazy=True, collection_class=set), + collection_class=set, + ) def __str__(self) -> str: return '{0.token}'.format(self) diff --git a/ereuse_devicehub/templates/ereuse_devicehub/user_profile.html b/ereuse_devicehub/templates/ereuse_devicehub/user_profile.html index 71ab39fa..326f3991 100644 --- a/ereuse_devicehub/templates/ereuse_devicehub/user_profile.html +++ b/ereuse_devicehub/templates/ereuse_devicehub/user_profile.html @@ -27,7 +27,7 @@ -
+
@@ -54,46 +54,73 @@
-
About
-

Sunt est soluta temporibus accusantium neque nam maiores cumque temporibus. Tempora libero non est unde veniam est qui dolor. Ut sunt iure rerum quae quisquam autem eveniet perspiciatis odit. Fuga sequi sed ea saepe at unde.

-
Profile Details
+
+
Account user
+
{{ current_user.email or ''}}
+
+ + {% for u in current_user.individuals %} +
Full Name
-
Kevin Anderson
-
- -
-
Company
-
Lueilwitz, Wisoky and Leuschke
-
- -
-
Job
-
Web Designer
+
{{ u.get_full_name or ''}}
Country
-
USA
-
- -
-
Address
-
A108 Adam Street, New York, NY 535022
+
{{ u.country or ''}}
Phone
-
(436) 486-3538 x29071
+
{{ u.telephone or ''}}
Email
-
k.anderson@example.com
+
{{ u.email or ''}}
+
+
Created
+
{{ u.created.strftime('%H:%M %d-%m-%Y') or ''}}
+
+ +
+
Last login
+
+ {% for s in sessions %} + {{ s }}
+ {% endfor %} +
+
+ + {% if u.active_org %} +
+
Company name
+
{{ u.active_org.name or ''}}
+
+ +
+
Company country
+
{{ u.active_org.country or '' }}
+
+ +
+
Company Phone
+
{{ u.active_org.telephone or '' }}
+
+ +
+
Company Email
+
{{ u.active_org.email or '' }}
+
+ + {% endif %} + {% endfor %} +
diff --git a/ereuse_devicehub/views.py b/ereuse_devicehub/views.py index 0c9b4361..1a2112a2 100644 --- a/ereuse_devicehub/views.py +++ b/ereuse_devicehub/views.py @@ -50,8 +50,10 @@ class UserProfileView(View): template_name = 'ereuse_devicehub/user_profile.html' def dispatch_request(self): + sessions = {s.created.strftime('%H:%M %d-%m-%Y') for s in current_user.sessions} context = { 'current_user': current_user, + 'sessions': sessions, 'version': __version__, } return flask.render_template(self.template_name, **context) From 9f8465902683c1e60fc250ecd32ab82680c43116 Mon Sep 17 00:00:00 2001 From: Cayo Puigdefabregas Date: Wed, 6 Apr 2022 13:49:15 +0200 Subject: [PATCH 02/54] clean white space --- ereuse_devicehub/resources/agent/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ereuse_devicehub/resources/agent/models.py b/ereuse_devicehub/resources/agent/models.py index 4554d227..36d7fcd8 100644 --- a/ereuse_devicehub/resources/agent/models.py +++ b/ereuse_devicehub/resources/agent/models.py @@ -34,7 +34,7 @@ class Agent(Thing): last_name = Column(CIText()) name.comment = """The name of the organization or person.""" tax_id = Column(Unicode(length=STR_SM_SIZE), check_lower('tax_id')) - tax_id.comment = """The Tax / Fiscal ID of the organization, + tax_id.comment = """The Tax / Fiscal ID of the organization, e.g. the TIN in the US or the CIF/NIF in Spain. """ country = Column(DBEnum(enums.Country)) From d1310a67bfa6ca5e87f80e3658385eac889113cf Mon Sep 17 00:00:00 2001 From: Cayo Puigdefabregas Date: Wed, 6 Apr 2022 13:50:08 +0200 Subject: [PATCH 03/54] add profile form --- ereuse_devicehub/forms.py | 36 ++++++- .../ereuse_devicehub/user_profile.html | 101 ++---------------- ereuse_devicehub/views.py | 4 +- 3 files changed, 47 insertions(+), 94 deletions(-) diff --git a/ereuse_devicehub/forms.py b/ereuse_devicehub/forms.py index d88c9cf1..dca1044c 100644 --- a/ereuse_devicehub/forms.py +++ b/ereuse_devicehub/forms.py @@ -1,9 +1,19 @@ from flask_wtf import FlaskForm from werkzeug.security import generate_password_hash -from wtforms import BooleanField, EmailField, PasswordField, validators +from wtforms import ( + BooleanField, + EmailField, + PasswordField, + SelectField, + StringField, + validators, +) +from ereuse_devicehub.enums import Country from ereuse_devicehub.resources.user.models import User +COUNTRY = [(x.name, x.value) for x in Country] + class LoginForm(FlaskForm): email = EmailField('Email Address', [validators.Length(min=6, max=35)]) @@ -59,3 +69,27 @@ class LoginForm(FlaskForm): self.form_errors.append(self.error_messages['inactive']) return user.is_active + + +class ProfileForm(FlaskForm): + name = StringField( + 'First name', + [validators.Length(min=2, max=35)], + render_kw={'class': "form-control"}, + ) + last_name = StringField( + 'Last name', + [validators.Length(min=2, max=35)], + render_kw={'class': "form-control"}, + ) + email = StringField( + 'Email Address', + [validators.Length(min=6, max=35)], + render_kw={'class': "form-control"}, + ) + telephone = StringField( + 'Phone', [validators.Length(min=6, max=35)], render_kw={'class': "form-control"} + ) + country = SelectField( + 'Country', choices=COUNTRY, default="es", render_kw={'class': "form-select"} + ) diff --git a/ereuse_devicehub/templates/ereuse_devicehub/user_profile.html b/ereuse_devicehub/templates/ereuse_devicehub/user_profile.html index 326f3991..4b6468ba 100644 --- a/ereuse_devicehub/templates/ereuse_devicehub/user_profile.html +++ b/ereuse_devicehub/templates/ereuse_devicehub/user_profile.html @@ -126,102 +126,19 @@
-
+ + {% for f in profile_form %} + {% if f == profile_form.csrf_token %} + {{ f }} + {% else %}
- +
- Profile -
- - -
+ {{ f }}
- -
- -
- -
-
- -
- -
- -
-
- -
- -
- -
-
- -
- -
- -
-
- -
- -
- -
-
- -
- -
- -
-
- -
- -
- -
-
- -
- -
- -
-
- -
- -
- -
-
- -
- -
- -
-
- -
- -
- -
-
- -
- -
- -
-
- + {% endif %} + {% endfor %}
diff --git a/ereuse_devicehub/views.py b/ereuse_devicehub/views.py index 1a2112a2..f6ed21f4 100644 --- a/ereuse_devicehub/views.py +++ b/ereuse_devicehub/views.py @@ -4,7 +4,7 @@ from flask.views import View from flask_login import current_user, login_required, login_user, logout_user from ereuse_devicehub import __version__ -from ereuse_devicehub.forms import LoginForm +from ereuse_devicehub.forms import LoginForm, ProfileForm from ereuse_devicehub.resources.user.models import User from ereuse_devicehub.utils import is_safe_url @@ -50,11 +50,13 @@ class UserProfileView(View): template_name = 'ereuse_devicehub/user_profile.html' def dispatch_request(self): + form = ProfileForm() sessions = {s.created.strftime('%H:%M %d-%m-%Y') for s in current_user.sessions} context = { 'current_user': current_user, 'sessions': sessions, 'version': __version__, + 'profile_form': form, } return flask.render_template(self.template_name, **context) From 1820b15255c22379d10a643acb2211590bd4f47c Mon Sep 17 00:00:00 2001 From: Cayo Puigdefabregas Date: Mon, 11 Apr 2022 17:16:20 +0200 Subject: [PATCH 04/54] save data profile --- ereuse_devicehub/forms.py | 24 +++++++++++++++++++ .../ereuse_devicehub/user_profile.html | 9 ++++++- ereuse_devicehub/views.py | 17 +++++++++++-- 3 files changed, 47 insertions(+), 3 deletions(-) diff --git a/ereuse_devicehub/forms.py b/ereuse_devicehub/forms.py index dca1044c..1bfd7907 100644 --- a/ereuse_devicehub/forms.py +++ b/ereuse_devicehub/forms.py @@ -1,3 +1,4 @@ +from flask import g from flask_wtf import FlaskForm from werkzeug.security import generate_password_hash from wtforms import ( @@ -9,6 +10,7 @@ from wtforms import ( validators, ) +from ereuse_devicehub.db import db from ereuse_devicehub.enums import Country from ereuse_devicehub.resources.user.models import User @@ -93,3 +95,25 @@ class ProfileForm(FlaskForm): country = SelectField( 'Country', choices=COUNTRY, default="es", render_kw={'class': "form-select"} ) + + def __init__(self, *args, **kwargs): + user = kwargs.pop('user', None) + super().__init__(*args, **kwargs) + if user: + self.name.data = user.name + self.last_name.data = user.last_name + self.email.data = user.email + self.telephone.data = user.telephone + self.country.data = user.country + + def save(self, commit=True): + agent = g.user.individual + agent.name = self.name.data + agent.last_name = self.last_name.data + agent.email = self.email.data + agent.telephone = self.telephone.data + agent.country = self.country.data + + db.session.add(agent) + if commit: + db.session.commit() diff --git a/ereuse_devicehub/templates/ereuse_devicehub/user_profile.html b/ereuse_devicehub/templates/ereuse_devicehub/user_profile.html index 4b6468ba..dba8db62 100644 --- a/ereuse_devicehub/templates/ereuse_devicehub/user_profile.html +++ b/ereuse_devicehub/templates/ereuse_devicehub/user_profile.html @@ -135,6 +135,13 @@
{{ f }} + {% if f.errors %} +

+ {% for error in f.errors %} + {{ error }}
+ {% endfor %} +

+ {% endif %}
{% endif %} @@ -149,7 +156,7 @@
- +
diff --git a/ereuse_devicehub/views.py b/ereuse_devicehub/views.py index f6ed21f4..682d858d 100644 --- a/ereuse_devicehub/views.py +++ b/ereuse_devicehub/views.py @@ -1,9 +1,10 @@ import flask -from flask import Blueprint +from flask import Blueprint, request from flask.views import View from flask_login import current_user, login_required, login_user, logout_user -from ereuse_devicehub import __version__ +from ereuse_devicehub import __version__, messages +from ereuse_devicehub.db import db from ereuse_devicehub.forms import LoginForm, ProfileForm from ereuse_devicehub.resources.user.models import User from ereuse_devicehub.utils import is_safe_url @@ -46,11 +47,15 @@ class LogoutView(View): class UserProfileView(View): + methods = ['GET', 'POST'] decorators = [login_required] template_name = 'ereuse_devicehub/user_profile.html' def dispatch_request(self): form = ProfileForm() + if request.method == 'GET': + form = ProfileForm(user=current_user.individual) + sessions = {s.created.strftime('%H:%M %d-%m-%Y') for s in current_user.sessions} context = { 'current_user': current_user, @@ -58,6 +63,14 @@ class UserProfileView(View): 'version': __version__, 'profile_form': form, } + + if form.validate_on_submit(): + form.save(commit=False) + messages.success('Modify user Profile datas successfully!') + elif form.errors: + messages.error('Error modify user Profile data!') + + db.session.commit() return flask.render_template(self.template_name, **context) From 9d4ca5a2dcc21188b904457d19a6a67573ec9818 Mon Sep 17 00:00:00 2001 From: Cayo Puigdefabregas Date: Mon, 11 Apr 2022 19:48:59 +0200 Subject: [PATCH 05/54] change password --- ereuse_devicehub/forms.py | 43 +++++++++++++++++++ .../ereuse_devicehub/user_profile.html | 37 ++++++++-------- ereuse_devicehub/views.py | 26 +++++++++-- 3 files changed, 83 insertions(+), 23 deletions(-) diff --git a/ereuse_devicehub/forms.py b/ereuse_devicehub/forms.py index 1bfd7907..9789a06e 100644 --- a/ereuse_devicehub/forms.py +++ b/ereuse_devicehub/forms.py @@ -117,3 +117,46 @@ class ProfileForm(FlaskForm): db.session.add(agent) if commit: db.session.commit() + + +class PasswordForm(FlaskForm): + password = PasswordField( + 'Current Password', + [validators.DataRequired()], + render_kw={'class': "form-control"}, + ) + newpassword = PasswordField( + 'New Password', + [validators.DataRequired()], + render_kw={'class': "form-control"}, + ) + renewpassword = PasswordField( + 'Re-enter New Password', + [validators.DataRequired()], + render_kw={'class': "form-control"}, + ) + + def validate(self, extra_validators=None): + is_valid = super().validate(extra_validators) + + if not is_valid: + return False + + if not g.user.check_password(self.password.data): + self.password.errors = ['Incorrect password'] + return False + + if self.newpassword.data != self.renewpassword.data: + self.newpassword.errors = ['Is not the same password'] + self.renewpassword.errors = ['Is not the same password'] + return False + + return True + + def save(self, commit=True): + g.user.password = generate_password_hash(self.newpassword.data) + + db.session.add(g.user) + if commit: + db.session.commit() + return diff --git a/ereuse_devicehub/templates/ereuse_devicehub/user_profile.html b/ereuse_devicehub/templates/ereuse_devicehub/user_profile.html index dba8db62..782b92c8 100644 --- a/ereuse_devicehub/templates/ereuse_devicehub/user_profile.html +++ b/ereuse_devicehub/templates/ereuse_devicehub/user_profile.html @@ -132,7 +132,7 @@ {{ f }} {% else %}
- +
{{ f }} {% if f.errors %} @@ -197,29 +197,26 @@
- - + + {% for f in password_form %} + {% if f == password_form.csrf_token %} + {{ f }} + {% else %}
- +
- + {{ f }} + {% if f.errors %} +

+ {% for error in f.errors %} + {{ error }}
+ {% endfor %} +

+ {% endif %}
- -
- -
- -
-
- -
- -
- -
-
- + {% endif %} + {% endfor %}
diff --git a/ereuse_devicehub/views.py b/ereuse_devicehub/views.py index 682d858d..bdbea6ae 100644 --- a/ereuse_devicehub/views.py +++ b/ereuse_devicehub/views.py @@ -5,7 +5,7 @@ from flask_login import current_user, login_required, login_user, logout_user from ereuse_devicehub import __version__, messages from ereuse_devicehub.db import db -from ereuse_devicehub.forms import LoginForm, ProfileForm +from ereuse_devicehub.forms import LoginForm, PasswordForm, ProfileForm from ereuse_devicehub.resources.user.models import User from ereuse_devicehub.utils import is_safe_url @@ -62,18 +62,38 @@ class UserProfileView(View): 'sessions': sessions, 'version': __version__, 'profile_form': form, + 'password_form': PasswordForm(), } if form.validate_on_submit(): form.save(commit=False) messages.success('Modify user Profile datas successfully!') + db.session.commit() elif form.errors: - messages.error('Error modify user Profile data!') + messages.error('Error modifying user Profile data!') + + return flask.render_template(self.template_name, **context) + + +class UserPasswordView(View): + methods = ['POST'] + decorators = [login_required] + + def dispatch_request(self): + form = PasswordForm() + # import pdb; pdb.set_trace() + db.session.commit() + if form.validate_on_submit(): + form.save(commit=False) + messages.success('Reset user password successfully!') + else: + messages.error('Error modifying user password!') db.session.commit() - return flask.render_template(self.template_name, **context) + return flask.redirect(flask.url_for('core.user-profile')) core.add_url_rule('/login/', view_func=LoginView.as_view('login')) core.add_url_rule('/logout/', view_func=LogoutView.as_view('logout')) core.add_url_rule('/profile/', view_func=UserProfileView.as_view('user-profile')) +core.add_url_rule('/set_password/', view_func=UserPasswordView.as_view('set-password')) From cb1f4377d6f52f6b4fa56e52b3af362437c3e296 Mon Sep 17 00:00:00 2001 From: RubenPX Date: Tue, 12 Apr 2022 12:44:24 +0200 Subject: [PATCH 06/54] Fix button spacing --- ereuse_devicehub/templates/inventory/device_list.html | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/ereuse_devicehub/templates/inventory/device_list.html b/ereuse_devicehub/templates/inventory/device_list.html index b1c45382..47d4c382 100644 --- a/ereuse_devicehub/templates/inventory/device_list.html +++ b/ereuse_devicehub/templates/inventory/device_list.html @@ -72,7 +72,7 @@
-
-{% endblock body %} +{% endblock body %} \ No newline at end of file From d985744fb82edacc3a1cfddcd1141b8c4412b665 Mon Sep 17 00:00:00 2001 From: RubenPX Date: Tue, 12 Apr 2022 13:19:56 +0200 Subject: [PATCH 11/54] fix device list padding --- ereuse_devicehub/templates/inventory/device_list.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ereuse_devicehub/templates/inventory/device_list.html b/ereuse_devicehub/templates/inventory/device_list.html index cdf2c5e3..34f1fdd6 100644 --- a/ereuse_devicehub/templates/inventory/device_list.html +++ b/ereuse_devicehub/templates/inventory/device_list.html @@ -69,7 +69,7 @@ {% endif %} -
+
-
- - -
- -
- -
-
- - -
-
- - -
-
- - -
-
- - -
-
-
- -
- -
-
- -
-
From 4e19b9233ba49c58e3d38206ae628d2192ce97fe Mon Sep 17 00:00:00 2001 From: Cayo Puigdefabregas Date: Wed, 13 Apr 2022 19:11:23 +0200 Subject: [PATCH 20/54] validate email is unique --- ereuse_devicehub/forms.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/ereuse_devicehub/forms.py b/ereuse_devicehub/forms.py index 7dddf884..2ae69094 100644 --- a/ereuse_devicehub/forms.py +++ b/ereuse_devicehub/forms.py @@ -12,6 +12,7 @@ from wtforms import ( ) from ereuse_devicehub.db import db +from ereuse_devicehub.resources.agent.models import Agent from ereuse_devicehub.resources.user.models import User COUNTRY = [(x.name, x.value) for x in Country] @@ -101,6 +102,21 @@ class ProfileForm(FlaskForm): if user.country: self.country.data = user.country.name + def validate(self, extra_validators=None): + is_valid = super().validate(extra_validators) + + if not is_valid: + return False + + # import pdb; pdb.set_trace() + email = self.email.data + if email != g.user.individual.email: + if Agent.query.filter_by(email=email).first(): + self.email.errors = ['You can not use this email.'] + return False + + return True + def save(self, commit=True): agent = g.user.individual agent.name = self.name.data From d870d254f1979f1fc8564b73d93a014edbb46580 Mon Sep 17 00:00:00 2001 From: Cayo Puigdefabregas Date: Wed, 13 Apr 2022 19:12:12 +0200 Subject: [PATCH 21/54] drop pdbs --- ereuse_devicehub/forms.py | 1 - 1 file changed, 1 deletion(-) diff --git a/ereuse_devicehub/forms.py b/ereuse_devicehub/forms.py index 2ae69094..4c614c95 100644 --- a/ereuse_devicehub/forms.py +++ b/ereuse_devicehub/forms.py @@ -108,7 +108,6 @@ class ProfileForm(FlaskForm): if not is_valid: return False - # import pdb; pdb.set_trace() email = self.email.data if email != g.user.individual.email: if Agent.query.filter_by(email=email).first(): From 154362613e4c92e47cacda7a4c68eb5376ed91f9 Mon Sep 17 00:00:00 2001 From: RubenPX Date: Wed, 20 Apr 2022 11:53:51 +0200 Subject: [PATCH 22/54] fix trade lots modal --- ereuse_devicehub/templates/inventory/device_list.html | 1 + 1 file changed, 1 insertion(+) diff --git a/ereuse_devicehub/templates/inventory/device_list.html b/ereuse_devicehub/templates/inventory/device_list.html index c7e8c133..10305ac4 100644 --- a/ereuse_devicehub/templates/inventory/device_list.html +++ b/ereuse_devicehub/templates/inventory/device_list.html @@ -78,6 +78,7 @@ Lots +
-{% endblock body %} \ No newline at end of file +{% endblock body %} diff --git a/ereuse_devicehub/templates/inventory/addDevicestag.html b/ereuse_devicehub/templates/inventory/addDevicestag.html index 51938211..bb02c221 100644 --- a/ereuse_devicehub/templates/inventory/addDevicestag.html +++ b/ereuse_devicehub/templates/inventory/addDevicestag.html @@ -3,14 +3,14 @@ + +