Commit 2e3f250d4516c92adce5511747419d7f1fe04b97
1 parent
dba98240
Exists in
spb-stable
and in
3 other branches
Add website url to user
Showing
14 changed files
with
94 additions
and
9 deletions
Show diff stats
CHANGELOG
| @@ -16,6 +16,7 @@ v 6.5.0 | @@ -16,6 +16,7 @@ v 6.5.0 | ||
| 16 | - Use jquery timeago plugin | 16 | - Use jquery timeago plugin |
| 17 | - Fix 500 error for rdoc files | 17 | - Fix 500 error for rdoc files |
| 18 | - Ability to customize merge commit message (sponsored by Say Media) | 18 | - Ability to customize merge commit message (sponsored by Say Media) |
| 19 | + - Add website url to user profile | ||
| 19 | 20 | ||
| 20 | v6.4.3 | 21 | v6.4.3 |
| 21 | - Don't use unicorn worker killer if PhusionPassenger is defined | 22 | - Don't use unicorn worker killer if PhusionPassenger is defined |
app/models/user.rb
| @@ -41,7 +41,8 @@ | @@ -41,7 +41,8 @@ | ||
| 41 | # confirmed_at :datetime | 41 | # confirmed_at :datetime |
| 42 | # confirmation_sent_at :datetime | 42 | # confirmation_sent_at :datetime |
| 43 | # unconfirmed_email :string(255) | 43 | # unconfirmed_email :string(255) |
| 44 | -# hide_no_ssh_key :boolean default(FALSE), not null | 44 | +# hide_no_ssh_key :boolean default(FALSE) |
| 45 | +# website_url :string(255) default(""), not null | ||
| 45 | # | 46 | # |
| 46 | 47 | ||
| 47 | require 'carrierwave/orm/activerecord' | 48 | require 'carrierwave/orm/activerecord' |
| @@ -52,7 +53,7 @@ class User < ActiveRecord::Base | @@ -52,7 +53,7 @@ class User < ActiveRecord::Base | ||
| 52 | :recoverable, :rememberable, :trackable, :validatable, :omniauthable, :confirmable, :registerable | 53 | :recoverable, :rememberable, :trackable, :validatable, :omniauthable, :confirmable, :registerable |
| 53 | 54 | ||
| 54 | attr_accessible :email, :password, :password_confirmation, :remember_me, :bio, :name, :username, | 55 | attr_accessible :email, :password, :password_confirmation, :remember_me, :bio, :name, :username, |
| 55 | - :skype, :linkedin, :twitter, :color_scheme_id, :theme_id, :force_random_password, | 56 | + :skype, :linkedin, :twitter, :website_url, :color_scheme_id, :theme_id, :force_random_password, |
| 56 | :extern_uid, :provider, :password_expires_at, :avatar, :hide_no_ssh_key, | 57 | :extern_uid, :provider, :password_expires_at, :avatar, :hide_no_ssh_key, |
| 57 | as: [:default, :admin] | 58 | as: [:default, :admin] |
| 58 | 59 | ||
| @@ -424,4 +425,14 @@ class User < ActiveRecord::Base | @@ -424,4 +425,14 @@ class User < ActiveRecord::Base | ||
| 424 | order('id DESC').limit(1000). | 425 | order('id DESC').limit(1000). |
| 425 | update_all(updated_at: Time.now) | 426 | update_all(updated_at: Time.now) |
| 426 | end | 427 | end |
| 428 | + | ||
| 429 | + def full_website_url | ||
| 430 | + return "http://#{website_url}" if website_url !~ /^https?:\/\// | ||
| 431 | + | ||
| 432 | + website_url | ||
| 433 | + end | ||
| 434 | + | ||
| 435 | + def short_website_url | ||
| 436 | + website_url.gsub(/https?:\/\//, '') | ||
| 437 | + end | ||
| 427 | end | 438 | end |
app/views/admin/users/_form.html.haml
| @@ -80,6 +80,9 @@ | @@ -80,6 +80,9 @@ | ||
| 80 | .form-group | 80 | .form-group |
| 81 | = f.label :twitter, class: 'control-label' | 81 | = f.label :twitter, class: 'control-label' |
| 82 | .col-sm-10= f.text_field :twitter, class: 'form-control' | 82 | .col-sm-10= f.text_field :twitter, class: 'form-control' |
| 83 | + .form-group | ||
| 84 | + = f.label :website_url, class: 'control-label' | ||
| 85 | + .col-sm-10= f.text_field :website_url, class: 'form-control' | ||
| 83 | 86 | ||
| 84 | .form-actions | 87 | .form-actions |
| 85 | - if @user.new_record? | 88 | - if @user.new_record? |
app/views/profiles/show.html.haml
| @@ -47,6 +47,9 @@ | @@ -47,6 +47,9 @@ | ||
| 47 | = f.label :twitter, class: "control-label" | 47 | = f.label :twitter, class: "control-label" |
| 48 | .col-sm-10= f.text_field :twitter, class: "form-control" | 48 | .col-sm-10= f.text_field :twitter, class: "form-control" |
| 49 | .form-group | 49 | .form-group |
| 50 | + = f.label :website_url, class: "control-label" | ||
| 51 | + .col-sm-10= f.text_field :website_url, class: "form-control" | ||
| 52 | + .form-group | ||
| 50 | = f.label :bio, class: "control-label" | 53 | = f.label :bio, class: "control-label" |
| 51 | .col-sm-10 | 54 | .col-sm-10 |
| 52 | = f.text_area :bio, rows: 6, class: "form-control", maxlength: 250 | 55 | = f.text_area :bio, rows: 6, class: "form-control", maxlength: 250 |
app/views/users/_profile.html.haml
| @@ -17,6 +17,10 @@ | @@ -17,6 +17,10 @@ | ||
| 17 | %li | 17 | %li |
| 18 | %span.light Twitter: | 18 | %span.light Twitter: |
| 19 | %strong= link_to user.twitter, "http://www.twitter.com/#{user.twitter}" | 19 | %strong= link_to user.twitter, "http://www.twitter.com/#{user.twitter}" |
| 20 | + - unless user.website_url.blank? | ||
| 21 | + %li | ||
| 22 | + %span.light Website url: | ||
| 23 | + %strong= link_to user.short_website_url, user.full_website_url | ||
| 20 | - unless user.bio.blank? | 24 | - unless user.bio.blank? |
| 21 | %li | 25 | %li |
| 22 | %span.light Bio: | 26 | %span.light Bio: |
db/schema.rb
| @@ -11,7 +11,7 @@ | @@ -11,7 +11,7 @@ | ||
| 11 | # | 11 | # |
| 12 | # It's strongly recommended that you check this file into your version control system. | 12 | # It's strongly recommended that you check this file into your version control system. |
| 13 | 13 | ||
| 14 | -ActiveRecord::Schema.define(version: 20131217102743) do | 14 | +ActiveRecord::Schema.define(version: 20140116231608) do |
| 15 | 15 | ||
| 16 | create_table "broadcast_messages", force: true do |t| | 16 | create_table "broadcast_messages", force: true do |t| |
| 17 | t.text "message", null: false | 17 | t.text "message", null: false |
| @@ -301,6 +301,7 @@ ActiveRecord::Schema.define(version: 20131217102743) do | @@ -301,6 +301,7 @@ ActiveRecord::Schema.define(version: 20131217102743) do | ||
| 301 | t.datetime "confirmation_sent_at" | 301 | t.datetime "confirmation_sent_at" |
| 302 | t.string "unconfirmed_email" | 302 | t.string "unconfirmed_email" |
| 303 | t.boolean "hide_no_ssh_key", default: false | 303 | t.boolean "hide_no_ssh_key", default: false |
| 304 | + t.string "website_url", default: "", null: false | ||
| 304 | end | 305 | end |
| 305 | 306 | ||
| 306 | add_index "users", ["admin"], name: "index_users_on_admin", using: :btree | 307 | add_index "users", ["admin"], name: "index_users_on_admin", using: :btree |
doc/api/session.md
| @@ -26,6 +26,7 @@ __You can login with both GitLab and LDAP credentials now__ | @@ -26,6 +26,7 @@ __You can login with both GitLab and LDAP credentials now__ | ||
| 26 | "skype": "", | 26 | "skype": "", |
| 27 | "linkedin": "", | 27 | "linkedin": "", |
| 28 | "twitter": "", | 28 | "twitter": "", |
| 29 | + "website_url": "", | ||
| 29 | "dark_scheme": false, | 30 | "dark_scheme": false, |
| 30 | "theme_id": 1, | 31 | "theme_id": 1, |
| 31 | "is_admin": false, | 32 | "is_admin": false, |
doc/api/users.md
| @@ -20,6 +20,7 @@ GET /users | @@ -20,6 +20,7 @@ GET /users | ||
| 20 | "skype": "", | 20 | "skype": "", |
| 21 | "linkedin": "", | 21 | "linkedin": "", |
| 22 | "twitter": "", | 22 | "twitter": "", |
| 23 | + "website_url": "", | ||
| 23 | "extern_uid": "john.smith", | 24 | "extern_uid": "john.smith", |
| 24 | "provider": "provider_name", | 25 | "provider": "provider_name", |
| 25 | "theme_id": 1, | 26 | "theme_id": 1, |
| @@ -38,6 +39,7 @@ GET /users | @@ -38,6 +39,7 @@ GET /users | ||
| 38 | "skype": "", | 39 | "skype": "", |
| 39 | "linkedin": "", | 40 | "linkedin": "", |
| 40 | "twitter": "", | 41 | "twitter": "", |
| 42 | + "website_url": "", | ||
| 41 | "extern_uid": "jack.smith", | 43 | "extern_uid": "jack.smith", |
| 42 | "provider": "provider_name", | 44 | "provider": "provider_name", |
| 43 | "theme_id": 1, | 45 | "theme_id": 1, |
| @@ -74,6 +76,7 @@ Parameters: | @@ -74,6 +76,7 @@ Parameters: | ||
| 74 | "skype": "", | 76 | "skype": "", |
| 75 | "linkedin": "", | 77 | "linkedin": "", |
| 76 | "twitter": "", | 78 | "twitter": "", |
| 79 | + "website_url": "", | ||
| 77 | "extern_uid": "john.smith", | 80 | "extern_uid": "john.smith", |
| 78 | "provider": "provider_name", | 81 | "provider": "provider_name", |
| 79 | "theme_id": 1, | 82 | "theme_id": 1, |
| @@ -102,6 +105,7 @@ Parameters: | @@ -102,6 +105,7 @@ Parameters: | ||
| 102 | + `skype` (optional) - Skype ID | 105 | + `skype` (optional) - Skype ID |
| 103 | + `linkedin` (optional) - Linkedin | 106 | + `linkedin` (optional) - Linkedin |
| 104 | + `twitter` (optional) - Twitter account | 107 | + `twitter` (optional) - Twitter account |
| 108 | ++ `website_url` (optional) - Website url | ||
| 105 | + `projects_limit` (optional) - Number of projects user can create | 109 | + `projects_limit` (optional) - Number of projects user can create |
| 106 | + `extern_uid` (optional) - External UID | 110 | + `extern_uid` (optional) - External UID |
| 107 | + `provider` (optional) - External provider name | 111 | + `provider` (optional) - External provider name |
| @@ -127,6 +131,7 @@ Parameters: | @@ -127,6 +131,7 @@ Parameters: | ||
| 127 | + `skype` - Skype ID | 131 | + `skype` - Skype ID |
| 128 | + `linkedin` - Linkedin | 132 | + `linkedin` - Linkedin |
| 129 | + `twitter` - Twitter account | 133 | + `twitter` - Twitter account |
| 134 | ++ `website_url` - Website url | ||
| 130 | + `projects_limit` - Limit projects each user can create | 135 | + `projects_limit` - Limit projects each user can create |
| 131 | + `extern_uid` - External UID | 136 | + `extern_uid` - External UID |
| 132 | + `provider` - External provider name | 137 | + `provider` - External provider name |
| @@ -174,6 +179,7 @@ GET /user | @@ -174,6 +179,7 @@ GET /user | ||
| 174 | "skype": "", | 179 | "skype": "", |
| 175 | "linkedin": "", | 180 | "linkedin": "", |
| 176 | "twitter": "", | 181 | "twitter": "", |
| 182 | + "website_url": "", | ||
| 177 | "theme_id": 1, | 183 | "theme_id": 1, |
| 178 | "color_scheme_id": 2, | 184 | "color_scheme_id": 2, |
| 179 | "is_admin": false, | 185 | "is_admin": false, |
features/profile/profile.feature
| @@ -8,8 +8,8 @@ Feature: Profile | @@ -8,8 +8,8 @@ Feature: Profile | ||
| 8 | 8 | ||
| 9 | Scenario: I edit profile | 9 | Scenario: I edit profile |
| 10 | Given I visit profile page | 10 | Given I visit profile page |
| 11 | - Then I change my contact info | ||
| 12 | - And I should see new contact info | 11 | + Then I change my profile info |
| 12 | + And I should see new profile info | ||
| 13 | 13 | ||
| 14 | Scenario: I change my password without old one | 14 | Scenario: I change my password without old one |
| 15 | Given I visit profile password page | 15 | Given I visit profile password page |
features/steps/profile/profile.rb
| @@ -6,18 +6,20 @@ class Profile < Spinach::FeatureSteps | @@ -6,18 +6,20 @@ class Profile < Spinach::FeatureSteps | ||
| 6 | page.should have_content "Profile settings" | 6 | page.should have_content "Profile settings" |
| 7 | end | 7 | end |
| 8 | 8 | ||
| 9 | - step 'I change my contact info' do | 9 | + step 'I change my profile info' do |
| 10 | fill_in "user_skype", with: "testskype" | 10 | fill_in "user_skype", with: "testskype" |
| 11 | fill_in "user_linkedin", with: "testlinkedin" | 11 | fill_in "user_linkedin", with: "testlinkedin" |
| 12 | fill_in "user_twitter", with: "testtwitter" | 12 | fill_in "user_twitter", with: "testtwitter" |
| 13 | + fill_in "user_website_url", with: "testurl" | ||
| 13 | click_button "Save changes" | 14 | click_button "Save changes" |
| 14 | @user.reload | 15 | @user.reload |
| 15 | end | 16 | end |
| 16 | 17 | ||
| 17 | - step 'I should see new contact info' do | 18 | + step 'I should see new profile info' do |
| 18 | @user.skype.should == 'testskype' | 19 | @user.skype.should == 'testskype' |
| 19 | @user.linkedin.should == 'testlinkedin' | 20 | @user.linkedin.should == 'testlinkedin' |
| 20 | @user.twitter.should == 'testtwitter' | 21 | @user.twitter.should == 'testtwitter' |
| 22 | + @user.website_url.should == 'testurl' | ||
| 21 | end | 23 | end |
| 22 | 24 | ||
| 23 | step 'I change my avatar' do | 25 | step 'I change my avatar' do |
lib/api/entities.rb
| 1 | module API | 1 | module API |
| 2 | module Entities | 2 | module Entities |
| 3 | class User < Grape::Entity | 3 | class User < Grape::Entity |
| 4 | - expose :id, :username, :email, :name, :bio, :skype, :linkedin, :twitter, | 4 | + expose :id, :username, :email, :name, :bio, :skype, :linkedin, :twitter, :website_url, |
| 5 | :theme_id, :color_scheme_id, :state, :created_at, :extern_uid, :provider | 5 | :theme_id, :color_scheme_id, :state, :created_at, :extern_uid, :provider |
| 6 | expose :is_admin?, as: :is_admin | 6 | expose :is_admin?, as: :is_admin |
| 7 | expose :can_create_group?, as: :can_create_group | 7 | expose :can_create_group?, as: :can_create_group |
lib/api/users.rb
| @@ -36,6 +36,7 @@ module API | @@ -36,6 +36,7 @@ module API | ||
| 36 | # skype - Skype ID | 36 | # skype - Skype ID |
| 37 | # linkedin - Linkedin | 37 | # linkedin - Linkedin |
| 38 | # twitter - Twitter account | 38 | # twitter - Twitter account |
| 39 | + # website_url - Website url | ||
| 39 | # projects_limit - Number of projects user can create | 40 | # projects_limit - Number of projects user can create |
| 40 | # extern_uid - External authentication provider UID | 41 | # extern_uid - External authentication provider UID |
| 41 | # provider - External provider | 42 | # provider - External provider |
| @@ -67,6 +68,7 @@ module API | @@ -67,6 +68,7 @@ module API | ||
| 67 | # skype - Skype ID | 68 | # skype - Skype ID |
| 68 | # linkedin - Linkedin | 69 | # linkedin - Linkedin |
| 69 | # twitter - Twitter account | 70 | # twitter - Twitter account |
| 71 | + # website_url - Website url | ||
| 70 | # projects_limit - Limit projects each user can create | 72 | # projects_limit - Limit projects each user can create |
| 71 | # extern_uid - External authentication provider UID | 73 | # extern_uid - External authentication provider UID |
| 72 | # provider - External provider | 74 | # provider - External provider |
| @@ -78,7 +80,7 @@ module API | @@ -78,7 +80,7 @@ module API | ||
| 78 | put ":id" do | 80 | put ":id" do |
| 79 | authenticated_as_admin! | 81 | authenticated_as_admin! |
| 80 | 82 | ||
| 81 | - attrs = attributes_for_keys [:email, :name, :password, :skype, :linkedin, :twitter, :projects_limit, :username, :extern_uid, :provider, :bio, :can_create_group, :admin] | 83 | + attrs = attributes_for_keys [:email, :name, :password, :skype, :linkedin, :twitter, :website_url, :projects_limit, :username, :extern_uid, :provider, :bio, :can_create_group, :admin] |
| 82 | user = User.find(params[:id]) | 84 | user = User.find(params[:id]) |
| 83 | not_found!("User not found") unless user | 85 | not_found!("User not found") unless user |
| 84 | 86 |
spec/models/user_spec.rb
| @@ -41,6 +41,8 @@ | @@ -41,6 +41,8 @@ | ||
| 41 | # confirmed_at :datetime | 41 | # confirmed_at :datetime |
| 42 | # confirmation_sent_at :datetime | 42 | # confirmation_sent_at :datetime |
| 43 | # unconfirmed_email :string(255) | 43 | # unconfirmed_email :string(255) |
| 44 | +# hide_no_ssh_key :boolean default(FALSE) | ||
| 45 | +# website_url :string(255) default(""), not null | ||
| 44 | # | 46 | # |
| 45 | 47 | ||
| 46 | require 'spec_helper' | 48 | require 'spec_helper' |
| @@ -293,4 +295,48 @@ describe User do | @@ -293,4 +295,48 @@ describe User do | ||
| 293 | user.avatar_type.should == ["only images allowed"] | 295 | user.avatar_type.should == ["only images allowed"] |
| 294 | end | 296 | end |
| 295 | end | 297 | end |
| 298 | + | ||
| 299 | + describe '#full_website_url' do | ||
| 300 | + let(:user) { create(:user) } | ||
| 301 | + | ||
| 302 | + it 'begins with http if website url omits it' do | ||
| 303 | + user.website_url = 'test.com' | ||
| 304 | + | ||
| 305 | + expect(user.full_website_url).to eq 'http://test.com' | ||
| 306 | + end | ||
| 307 | + | ||
| 308 | + it 'begins with http if website url begins with http' do | ||
| 309 | + user.website_url = 'http://test.com' | ||
| 310 | + | ||
| 311 | + expect(user.full_website_url).to eq 'http://test.com' | ||
| 312 | + end | ||
| 313 | + | ||
| 314 | + it 'begins with https if website url begins with https' do | ||
| 315 | + user.website_url = 'https://test.com' | ||
| 316 | + | ||
| 317 | + expect(user.full_website_url).to eq 'https://test.com' | ||
| 318 | + end | ||
| 319 | + end | ||
| 320 | + | ||
| 321 | + describe '#short_website_url' do | ||
| 322 | + let(:user) { create(:user) } | ||
| 323 | + | ||
| 324 | + it 'does not begin with http if website url omits it' do | ||
| 325 | + user.website_url = 'test.com' | ||
| 326 | + | ||
| 327 | + expect(user.short_website_url).to eq 'test.com' | ||
| 328 | + end | ||
| 329 | + | ||
| 330 | + it 'does not begin with http if website url begins with http' do | ||
| 331 | + user.website_url = 'http://test.com' | ||
| 332 | + | ||
| 333 | + expect(user.short_website_url).to eq 'test.com' | ||
| 334 | + end | ||
| 335 | + | ||
| 336 | + it 'does not begin with https if website url begins with https' do | ||
| 337 | + user.website_url = 'https://test.com' | ||
| 338 | + | ||
| 339 | + expect(user.short_website_url).to eq 'test.com' | ||
| 340 | + end | ||
| 341 | + end | ||
| 296 | end | 342 | end |