Skip to content
This repository has been archived by the owner on Apr 28, 2020. It is now read-only.

Create Name model for usernames #265

Merged
merged 6 commits into from
Oct 1, 2018
Merged

Create Name model for usernames #265

merged 6 commits into from
Oct 1, 2018

Conversation

jace
Copy link
Member

@jace jace commented Sep 28, 2018

Merges name from User and Organization models into a single table, thereby fulfilling the unification requirement described in #91 and #232.

@jace jace requested a review from iambibhas September 28, 2018 23:03
@jace
Copy link
Member Author

jace commented Sep 28, 2018

This change also fixes username validation in the models, in the process exposing some bugs in the unit tests. These have now been corrected.


class SharedNameMixin(object):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is this model for?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not a model. It offers the name property that makes the relationship behave like a string in both User and Organization.

@@ -51,7 +51,7 @@ def validate_old_password(self, field):

class ProfileForm(forms.Form):
fullname = forms.StringField(__("Full name"),
validators=[forms.validators.DataRequired(), forms.validators.Length(max=80)])
validators=[forms.validators.DataRequired(), forms.validators.Length(max=63)])
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why the length restriction on full name? Username is created from it?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DNS labels are restricted to 63 characters. Any longer and Talkfunnel's subdomains will break.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No I know that and get the limit for username. full name is never used on url, right?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Whoops, validator needed to be on the other field.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed this and a bunch of other issues. Organization views were all broken.

jace added 2 commits October 1, 2018 00:50

@name.expression
def name(cls):
return db.select([Name.name]).where(Name.user_id == cls.id).label('name')
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This query is super inefficient. What it generates (with explicit column names instead of *):

SELECT * FROM "user" WHERE (SELECT name.name FROM name WHERE name.user_id = "user".id) = '<param>'

EXPLAIN output:

                                      QUERY PLAN
--------------------------------------------------------------------------------------
 Seq Scan on "user"  (cost=0.00..478332.40 rows=287 width=605)
   Filter: (((SubPlan 1))::text = '<param>'::text)
   SubPlan 1
     ->  Index Scan using name_user_id_key on name  (cost=0.29..8.31 rows=1 width=10)
           Index Cond: (user_id = "user".id)
(5 rows)

To avoid the sequential scan, we may have to write a custom comparator instead of using this expression.

return True
@name.expression
def name(cls):
return db.select([Name.name]).where(Name.org_id == cls.id).label('name')
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same problem here.

@jace
Copy link
Member Author

jace commented Oct 1, 2018

After having tried the custom comparator approach, I've found that there is no way to invisibly insert a join condition. Whoever is performing the query must (a) perform the join, or (b) call with_transformation as described in the documentation. Since our problem is that organization views use load_models, which isn't aware of these things, the best approach seems to be to deprecate use of load_models and use ClassView with a custom loader.

I'm therefore merging this PR as is, and will pursue ClassView in a separate PR.

@jace jace merged commit d8ef02f into master Oct 1, 2018
@jace jace deleted the username branch October 1, 2018 12:12
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants