diff --git a/app/roles/account.rb b/app/roles/account.rb
index 63a9b5c51bf921454df661636fa02aa1b2c89915..b8c445a3d5866e37ac79c4378759d859e698c54f 100644
--- a/app/roles/account.rb
+++ b/app/roles/account.rb
@@ -1,6 +1,13 @@
-module Account 
+module Account
+  # Returns a string for use as a Gitolite user identifier
+  #
+  # Note that Gitolite 2.x requires the following pattern for users:
+  #
+  #   ^@?[0-9a-zA-Z][0-9a-zA-Z._\@+-]*$
   def identifier
-    email.gsub /[^[:alnum:]]/, "_"
+    # Replace non-word chars with underscores, then make sure it starts with
+    # valid chars
+    email.gsub(/\W/, '_').gsub(/\A([\W\_])+/, '')
   end
 
   def is_admin?
diff --git a/spec/factories.rb b/spec/factories.rb
index 2e4acf394614c9514de316e64dd74dde5c8aa046..a8b3bc57d3fdd9f7d94245ceed647707ab7b7c3a 100644
--- a/spec/factories.rb
+++ b/spec/factories.rb
@@ -28,7 +28,7 @@ FactoryGirl.define do
     email { Faker::Internet.email }
     name
     password "123456"
-    password_confirmation "123456"
+    password_confirmation { password }
 
     trait :admin do
       admin true
diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb
index ca34f07df7f005f783f51e141546a4aa9b58e4c3..081767543e2f1ed355a50cd98a82b5cb401d13bf 100644
--- a/spec/models/user_spec.rb
+++ b/spec/models/user_spec.rb
@@ -31,36 +31,46 @@ describe User do
     it { should respond_to(:private_token) }
   end
 
-  it "should return valid identifier" do
-    user = User.new(email: "test@mail.com")
-    user.identifier.should == "test_mail_com"
-  end
+  describe '#identifier' do
+    it "should return valid identifier" do
+      user = build(:user, email: "test@mail.com")
+      user.identifier.should == "test_mail_com"
+    end
 
-  it "should return identifier without + sign" do
-    user = User.new(email: "test+foo@mail.com")
-    user.identifier.should == "test_foo_mail_com"
-  end
+    it "should return identifier without + sign" do
+      user = build(:user, email: "test+foo@mail.com")
+      user.identifier.should == "test_foo_mail_com"
+    end
 
-  it "should execute callback when force_random_password specified" do
-    user = User.new(email: "test@mail.com", force_random_password: true)
-    user.should_receive(:generate_password)
-    user.save
+    it "should conform to Gitolite's required identifier pattern" do
+      user = build(:user, email: "_test@example.com")
+      user.identifier.should == 'test_example_com'
+    end
   end
 
-  it "should not generate password by default" do
-    user = Factory(:user, password: 'abcdefg', password_confirmation: 'abcdefg')
-    user.password.should == 'abcdefg'
-  end
+  describe '#generate_password' do
+    it "should execute callback when force_random_password specified" do
+      user = build(:user, force_random_password: true)
+      user.should_receive(:generate_password)
+      user.save
+    end
+
+    it "should not generate password by default" do
+      user = create(:user, password: 'abcdefg')
+      user.password.should == 'abcdefg'
+    end
 
-  it "should generate password when forcing random password" do
-    Devise.stub(:friendly_token).and_return('123456789')
-    user = User.create(email: "test1@mail.com", force_random_password: true)
-    user.password.should == user.password_confirmation
-    user.password.should == '12345678'
+    it "should generate password when forcing random password" do
+      Devise.stub(:friendly_token).and_return('123456789')
+      user = create(:user, password: 'abcdefg', force_random_password: true)
+      user.password.should == '12345678'
+    end
   end
 
-  it "should have authentication token" do
-    user = Factory(:user)
-    user.authentication_token.should_not == ""
+  describe 'authentication token' do
+    it "should have authentication token" do
+      user = Factory(:user)
+      user.authentication_token.should_not be_blank
+    end
   end
 end