diff --git a/branch.sql b/branch.sql new file mode 100644 index 0000000000..602ecd7e4b --- /dev/null +++ b/branch.sql @@ -0,0 +1,30 @@ +BEGIN; + CREATE TYPE email_address_with_confirmation AS + ( + address text, + confirmed boolean + ); + + ALTER TABLE participants ADD email email_address_with_confirmation + DEFAULT NULL; + + CREATE TABLE emails + ( id serial PRIMARY KEY + , email email_address_with_confirmation NOT NULL + , ctime timestamp with time zone NOT NULL + DEFAULT CURRENT_TIMESTAMP + , participant text NOT NULL + REFERENCES participants + ON UPDATE CASCADE + ON DELETE RESTRICT + ); + + + CREATE RULE log_email_changes AS ON UPDATE + TO participants WHERE (OLD.email IS NULL AND NOT NEW.email IS NULL) + OR (NEW.email IS NULL AND NOT OLD.email IS NULL) + OR NEW.email <> OLD.email + DO INSERT INTO emails (email, participant) + VALUES (NEW.email, OLD.username); + +END; diff --git a/gittip/models/email_address_with_confirmation.py b/gittip/models/email_address_with_confirmation.py new file mode 100644 index 0000000000..9996e87e6a --- /dev/null +++ b/gittip/models/email_address_with_confirmation.py @@ -0,0 +1,6 @@ +from postgres.orm import Model + + +class EmailAddressWithConfirmation(Model): + + typname = "email_address_with_confirmation" diff --git a/gittip/models/participant.py b/gittip/models/participant.py index f19aa0225d..e7585c00de 100644 --- a/gittip/models/participant.py +++ b/gittip/models/participant.py @@ -314,6 +314,13 @@ def change_username(self, suggested): return suggested + def update_email(self, email, confirmed=False): + with self.db.get_cursor() as c: + add_event(c, 'participant', dict(id=self.id, action='set', values=dict(current_email=email))) + c.one("UPDATE participants SET email = ROW(%s, %s) WHERE username=%s RETURNING id" + , (email, confirmed, self.username) + ) + self.set_attributes(email=(email, confirmed)) def update_goal(self, goal): typecheck(goal, (Decimal, None)) diff --git a/gittip/wireup.py b/gittip/wireup.py index fc1ec0faad..74412c6c91 100644 --- a/gittip/wireup.py +++ b/gittip/wireup.py @@ -19,6 +19,7 @@ from gittip.models.account_elsewhere import AccountElsewhere from gittip.models.community import Community from gittip.models.participant import Participant +from gittip.models.email_address_with_confirmation import EmailAddressWithConfirmation from gittip.models import GittipDB @@ -35,6 +36,7 @@ def db(env): db.register_model(Community) db.register_model(AccountElsewhere) db.register_model(Participant) + db.register_model(EmailAddressWithConfirmation) return db diff --git a/js/gittip/profile.js b/js/gittip/profile.js index 4c0b609672..6cc3d1e68b 100644 --- a/js/gittip/profile.js +++ b/js/gittip/profile.js @@ -356,4 +356,57 @@ Gittip.profile.init = function() { return false; }); + + // Wire up email address input. + // ============================ + $('.email').on("click", ".toggle-email", function() + { + $('.email').toggle(); + $('input.email').focus(); + }); + + // Wire up email form. + $('.email-submit') + .on('click', '[type=submit]', function () { + var $this = $(this); + + $this.text('Saving...'); + + function success(data) { + $('.email-address').text(data.email); + $('.email').toggle(); + if (data.email === '') { + html = "None" + html += ""; + } else { + html = "" + data.email + ""; + html += ""; + } + $('div.email').html(html); + $this.text('Save'); + } + + $.ajax({ + url: "email.json", + type: "POST", + dataType: 'json', + success: success, + error: function (data) { + $this.text('Save'); + Gittip.notification('Failed to save your email address. ' + + 'Please try again.', 'error'); + }, + data: { + email: $('input.email').val() + } + } + ) + + return false; + }) + .on('click', '[type=cancel]', function () { + $('.email').toggle(); + + return false; + }); }; diff --git a/scss/modules.scss b/scss/modules.scss index aee58e018a..37847c83d7 100644 --- a/scss/modules.scss +++ b/scss/modules.scss @@ -80,7 +80,7 @@ a.mini-user:hover { float: right; margin-top: -13px; } - .auth-button, .account-delete, .toggle-bitcoin { + .auth-button, .account-delete, .toggle-bitcoin, .toggle-email { float: right; margin-top: -13px; } diff --git a/scss/profile-edit.scss b/scss/profile-edit.scss index 0dd41a1a1a..10cb87efd7 100644 --- a/scss/profile-edit.scss +++ b/scss/profile-edit.scss @@ -57,7 +57,7 @@ } } } - .bitcoin-submit { + .email-submit, .bitcoin-submit { .address input { width: 100%; margin: 5px 0; diff --git a/templates/connected-accounts.html b/templates/connected-accounts.html index b624b47d1e..9487d21d1c 100644 --- a/templates/connected-accounts.html +++ b/templates/connected-accounts.html @@ -10,6 +10,46 @@