@ -0,0 +1,26 @@
 | 
				
			||||
<%= labelled_fields_for :user_extensions, @user.user_extensions do |user_extension| %>
 | 
				
			||||
 | 
				
			||||
<p style="width:400px;padding-left: 26px;">
 | 
				
			||||
	<%= user_extension.text_field :birthday %>
 | 
				
			||||
</p>
 | 
				
			||||
<p style="width:400px;">
 | 
				
			||||
	<%= user_extension.select :gender, [[l(:label_boy), '1'], [l(:label_girl), '0']] %>
 | 
				
			||||
</p>
 | 
				
			||||
 | 
				
			||||
<p style="width:400px;padding-left: 26px;">
 | 
				
			||||
	<%= user_extension.text_area :brief_introduction %>(少于250字)
 | 
				
			||||
</p>
 | 
				
			||||
<p style="width:400px;padding-left: 26px;">
 | 
				
			||||
	<%= user_extension.text_field :location %>
 | 
				
			||||
</p>
 | 
				
			||||
<p style="width:400px;padding-left: 26px;">
 | 
				
			||||
	<%= user_extension.text_field :occupation %>
 | 
				
			||||
</p>
 | 
				
			||||
<p style="width:400px;padding-left: 26px;">
 | 
				
			||||
	<%= user_extension.text_field :work_experience %>
 | 
				
			||||
</p>
 | 
				
			||||
<p style="width:400px;padding-left: 26px;">
 | 
				
			||||
	<%= user_extension.text_field :zip_code %>
 | 
				
			||||
</p>
 | 
				
			||||
 | 
				
			||||
<% end %>
 | 
				
			||||
@ -0,0 +1,119 @@
 | 
				
			||||
require_relative 'shell_env'
 | 
				
			||||
require_relative 'grack_ldap'
 | 
				
			||||
require_relative 'grack_helpers'
 | 
				
			||||
 | 
				
			||||
module Grack
 | 
				
			||||
  class Auth < Rack::Auth::Basic
 | 
				
			||||
    include LDAP
 | 
				
			||||
    include Helpers
 | 
				
			||||
 | 
				
			||||
    attr_accessor :user, :project, :ref, :env
 | 
				
			||||
 | 
				
			||||
    def call(env)
 | 
				
			||||
      @env = env
 | 
				
			||||
      @request = Rack::Request.new(env)
 | 
				
			||||
      @auth = Request.new(env)
 | 
				
			||||
 | 
				
			||||
      # Need this patch due to the rails mount
 | 
				
			||||
      @env['PATH_INFO'] = @request.path
 | 
				
			||||
      @env['SCRIPT_NAME'] = ""
 | 
				
			||||
 | 
				
			||||
      auth!
 | 
				
			||||
    end
 | 
				
			||||
 | 
				
			||||
    private
 | 
				
			||||
 | 
				
			||||
    def auth!
 | 
				
			||||
      return render_not_found unless project
 | 
				
			||||
 | 
				
			||||
      if @auth.provided?
 | 
				
			||||
        return bad_request unless @auth.basic?
 | 
				
			||||
 | 
				
			||||
        # Authentication with username and password
 | 
				
			||||
        login, password = @auth.credentials
 | 
				
			||||
 | 
				
			||||
        @user = authenticate_user(login, password)
 | 
				
			||||
 | 
				
			||||
        if @user
 | 
				
			||||
          Gitlab::ShellEnv.set_env(@user)
 | 
				
			||||
          @env['REMOTE_USER'] = @auth.username
 | 
				
			||||
        else
 | 
				
			||||
          return unauthorized
 | 
				
			||||
        end
 | 
				
			||||
 | 
				
			||||
      else
 | 
				
			||||
        return unauthorized unless project.public
 | 
				
			||||
      end
 | 
				
			||||
 | 
				
			||||
      if authorized_git_request?
 | 
				
			||||
        @app.call(env)
 | 
				
			||||
      else
 | 
				
			||||
        unauthorized
 | 
				
			||||
      end
 | 
				
			||||
    end
 | 
				
			||||
 | 
				
			||||
    def authorized_git_request?
 | 
				
			||||
      # Git upload and receive
 | 
				
			||||
      if @request.get?
 | 
				
			||||
        authorize_request(@request.params['service'])
 | 
				
			||||
      elsif @request.post?
 | 
				
			||||
        authorize_request(File.basename(@request.path))
 | 
				
			||||
      else
 | 
				
			||||
        false
 | 
				
			||||
      end
 | 
				
			||||
    end
 | 
				
			||||
 | 
				
			||||
    def authenticate_user(login, password)
 | 
				
			||||
      user = User.find_by_email(login) || User.find_by_username(login)
 | 
				
			||||
 | 
				
			||||
      # If the provided login was not a known email or username
 | 
				
			||||
      # then user is nil
 | 
				
			||||
      if user.nil? || user.ldap_user?
 | 
				
			||||
        # Second chance - try LDAP authentication
 | 
				
			||||
        return nil unless ldap_conf.enabled
 | 
				
			||||
 | 
				
			||||
        auth = Gitlab::Auth.new
 | 
				
			||||
        auth.ldap_auth(login, password)
 | 
				
			||||
      else
 | 
				
			||||
        return user if user.valid_password?(password)
 | 
				
			||||
      end
 | 
				
			||||
    end
 | 
				
			||||
 | 
				
			||||
    def authorize_request(service)
 | 
				
			||||
      case service
 | 
				
			||||
      when 'git-upload-pack'
 | 
				
			||||
        project.public || can?(user, :download_code, project)
 | 
				
			||||
      when'git-receive-pack'
 | 
				
			||||
        action = if project.protected_branch?(ref)
 | 
				
			||||
                   :push_code_to_protected_branches
 | 
				
			||||
                 else
 | 
				
			||||
                   :push_code
 | 
				
			||||
                 end
 | 
				
			||||
 | 
				
			||||
        can?(user, action, project)
 | 
				
			||||
      else
 | 
				
			||||
        false
 | 
				
			||||
      end
 | 
				
			||||
    end
 | 
				
			||||
 | 
				
			||||
    def project
 | 
				
			||||
      @project ||= project_by_path(@request.path_info)
 | 
				
			||||
    end
 | 
				
			||||
 | 
				
			||||
    def ref
 | 
				
			||||
      @ref ||= parse_ref
 | 
				
			||||
    end
 | 
				
			||||
 | 
				
			||||
    def parse_ref
 | 
				
			||||
      input = if @env["HTTP_CONTENT_ENCODING"] =~ /gzip/
 | 
				
			||||
                Zlib::GzipReader.new(@request.body).read
 | 
				
			||||
              else
 | 
				
			||||
                @request.body.read
 | 
				
			||||
              end
 | 
				
			||||
 | 
				
			||||
      # Need to reset seek point
 | 
				
			||||
      @request.body.rewind
 | 
				
			||||
      /refs\/heads\/([\w\.-]+)/n.match(input.force_encoding('ascii-8bit')).to_a.last
 | 
				
			||||
    end
 | 
				
			||||
  end
 | 
				
			||||
end
 | 
				
			||||
@ -0,0 +1,28 @@
 | 
				
			||||
module Grack
 | 
				
			||||
  module Helpers
 | 
				
			||||
    def project_by_path(path)
 | 
				
			||||
      if m = /^\/([\w\.\/-]+)\.git/.match(path).to_a
 | 
				
			||||
        path_with_namespace = m.last
 | 
				
			||||
        path_with_namespace.gsub!(/\.wiki$/, '')
 | 
				
			||||
 | 
				
			||||
        Project.find_with_namespace(path_with_namespace)
 | 
				
			||||
      end
 | 
				
			||||
    end
 | 
				
			||||
 | 
				
			||||
    def render_not_found
 | 
				
			||||
      [404, {"Content-Type" => "text/plain"}, ["Not Found"]]
 | 
				
			||||
    end
 | 
				
			||||
 | 
				
			||||
    def can?(object, action, subject)
 | 
				
			||||
      abilities.allowed?(object, action, subject)
 | 
				
			||||
    end
 | 
				
			||||
 | 
				
			||||
    def abilities
 | 
				
			||||
      @abilities ||= begin
 | 
				
			||||
                       abilities = Six.new
 | 
				
			||||
                       abilities << Ability
 | 
				
			||||
                       abilities
 | 
				
			||||
                     end
 | 
				
			||||
    end
 | 
				
			||||
  end
 | 
				
			||||
end
 | 
				
			||||
@ -0,0 +1,24 @@
 | 
				
			||||
require 'omniauth-ldap'
 | 
				
			||||
 | 
				
			||||
module Grack
 | 
				
			||||
  module LDAP
 | 
				
			||||
    def ldap_auth(login, password)
 | 
				
			||||
      # Check user against LDAP backend if user is not authenticated
 | 
				
			||||
      # Only check with valid login and password to prevent anonymous bind results
 | 
				
			||||
      return nil unless ldap_conf.enabled && !login.blank? && !password.blank?
 | 
				
			||||
 | 
				
			||||
      ldap = OmniAuth::LDAP::Adaptor.new(ldap_conf)
 | 
				
			||||
      ldap_user = ldap.bind_as(
 | 
				
			||||
        filter: Net::LDAP::Filter.eq(ldap.uid, login),
 | 
				
			||||
        size: 1,
 | 
				
			||||
        password: password
 | 
				
			||||
      )
 | 
				
			||||
 | 
				
			||||
      User.find_by_extern_uid_and_provider(ldap_user.dn, 'ldap') if ldap_user
 | 
				
			||||
    end
 | 
				
			||||
 | 
				
			||||
    def ldap_conf
 | 
				
			||||
      @ldap_conf ||= Gitlab.config.ldap
 | 
				
			||||
    end
 | 
				
			||||
  end
 | 
				
			||||
end
 | 
				
			||||
@ -0,0 +1,148 @@
 | 
				
			||||
module Gitlab
 | 
				
			||||
  class Shell
 | 
				
			||||
    class AccessDenied < StandardError; end
 | 
				
			||||
 | 
				
			||||
    # Init new repository
 | 
				
			||||
    #
 | 
				
			||||
    # name - project path with namespace
 | 
				
			||||
    #
 | 
				
			||||
    # Ex.
 | 
				
			||||
    #   add_repository("gitlab/gitlab-ci")
 | 
				
			||||
    #
 | 
				
			||||
    def add_repository(name)
 | 
				
			||||
      system "#{gitlab_shell_user_home}/gitlab-shell/bin/gitlab-projects", "add-project", "#{name}.git"
 | 
				
			||||
    end
 | 
				
			||||
 | 
				
			||||
    # Import repository
 | 
				
			||||
    #
 | 
				
			||||
    # name - project path with namespace
 | 
				
			||||
    #
 | 
				
			||||
    # Ex.
 | 
				
			||||
    #   import_repository("gitlab/gitlab-ci", "https://github.com/randx/six.git")
 | 
				
			||||
    #
 | 
				
			||||
    def import_repository(name, url)
 | 
				
			||||
      system "#{gitlab_shell_user_home}/gitlab-shell/bin/gitlab-projects", "import-project", "#{name}.git", url
 | 
				
			||||
    end
 | 
				
			||||
 | 
				
			||||
    # Move repository
 | 
				
			||||
    #
 | 
				
			||||
    # path - project path with namespace
 | 
				
			||||
    # new_path - new project path with namespace
 | 
				
			||||
    #
 | 
				
			||||
    # Ex.
 | 
				
			||||
    #   mv_repository("gitlab/gitlab-ci", "randx/gitlab-ci-new.git")
 | 
				
			||||
    #
 | 
				
			||||
    def mv_repository(path, new_path)
 | 
				
			||||
      system "#{gitlab_shell_user_home}/gitlab-shell/bin/gitlab-projects", "mv-project", "#{path}.git", "#{new_path}.git"
 | 
				
			||||
    end
 | 
				
			||||
 | 
				
			||||
    # Fork repository to new namespace
 | 
				
			||||
    #
 | 
				
			||||
    # path - project path with namespace
 | 
				
			||||
    # fork_namespace - namespace for forked project
 | 
				
			||||
    #
 | 
				
			||||
    # Ex.
 | 
				
			||||
    #  fork_repository("gitlab/gitlab-ci", "randx")
 | 
				
			||||
    #
 | 
				
			||||
    def fork_repository(path, fork_namespace)
 | 
				
			||||
      system "#{gitlab_shell_user_home}/gitlab-shell/bin/gitlab-projects", "fork-project", "#{path}.git", fork_namespace
 | 
				
			||||
    end
 | 
				
			||||
 | 
				
			||||
    # Remove repository from file system
 | 
				
			||||
    #
 | 
				
			||||
    # name - project path with namespace
 | 
				
			||||
    #
 | 
				
			||||
    # Ex.
 | 
				
			||||
    #   remove_repository("gitlab/gitlab-ci")
 | 
				
			||||
    #
 | 
				
			||||
    def remove_repository(name)
 | 
				
			||||
      system "#{gitlab_shell_user_home}/gitlab-shell/bin/gitlab-projects", "rm-project", "#{name}.git"
 | 
				
			||||
    end
 | 
				
			||||
 | 
				
			||||
    # Add new key to gitlab-shell
 | 
				
			||||
    #
 | 
				
			||||
    # Ex.
 | 
				
			||||
    #   add_key("key-42", "sha-rsa ...")
 | 
				
			||||
    #
 | 
				
			||||
    def add_key(key_id, key_content)
 | 
				
			||||
      system "#{gitlab_shell_user_home}/gitlab-shell/bin/gitlab-keys", "add-key", key_id, key_content
 | 
				
			||||
    end
 | 
				
			||||
 | 
				
			||||
    # Remove ssh key from gitlab shell
 | 
				
			||||
    #
 | 
				
			||||
    # Ex.
 | 
				
			||||
    #   remove_key("key-342", "sha-rsa ...")
 | 
				
			||||
    #
 | 
				
			||||
    def remove_key(key_id, key_content)
 | 
				
			||||
      system "#{gitlab_shell_user_home}/gitlab-shell/bin/gitlab-keys", "rm-key", key_id, key_content
 | 
				
			||||
    end
 | 
				
			||||
 | 
				
			||||
    # Add empty directory for storing repositories
 | 
				
			||||
    #
 | 
				
			||||
    # Ex.
 | 
				
			||||
    #   add_namespace("gitlab")
 | 
				
			||||
    #
 | 
				
			||||
    def add_namespace(name)
 | 
				
			||||
      FileUtils.mkdir(full_path(name), mode: 0770) unless exists?(name)
 | 
				
			||||
    end
 | 
				
			||||
 | 
				
			||||
    # Remove directory from repositories storage
 | 
				
			||||
    # Every repository inside this directory will be removed too
 | 
				
			||||
    #
 | 
				
			||||
    # Ex.
 | 
				
			||||
    #   rm_namespace("gitlab")
 | 
				
			||||
    #
 | 
				
			||||
    def rm_namespace(name)
 | 
				
			||||
      FileUtils.rm_r(full_path(name), force: true)
 | 
				
			||||
    end
 | 
				
			||||
 | 
				
			||||
    # Move namespace directory inside repositories storage
 | 
				
			||||
    #
 | 
				
			||||
    # Ex.
 | 
				
			||||
    #   mv_namespace("gitlab", "gitlabhq")
 | 
				
			||||
    #
 | 
				
			||||
    def mv_namespace(old_name, new_name)
 | 
				
			||||
      return false if exists?(new_name) || !exists?(old_name)
 | 
				
			||||
 | 
				
			||||
      FileUtils.mv(full_path(old_name), full_path(new_name))
 | 
				
			||||
    end
 | 
				
			||||
 | 
				
			||||
    # Remove GitLab Satellites for provided path (namespace or repo dir)
 | 
				
			||||
    #
 | 
				
			||||
    # Ex.
 | 
				
			||||
    #   rm_satellites("gitlab")
 | 
				
			||||
    #
 | 
				
			||||
    #   rm_satellites("gitlab/gitlab-ci.git")
 | 
				
			||||
    #
 | 
				
			||||
    def rm_satellites(path)
 | 
				
			||||
      raise ArgumentError.new("Path can't be blank") if path.blank?
 | 
				
			||||
 | 
				
			||||
      satellites_path = File.join(Gitlab.config.satellites.path, path)
 | 
				
			||||
      FileUtils.rm_r(satellites_path, force: true)
 | 
				
			||||
    end
 | 
				
			||||
 | 
				
			||||
    def url_to_repo path
 | 
				
			||||
      Gitlab.config.gitlab_shell.ssh_path_prefix + "#{path}.git"
 | 
				
			||||
    end
 | 
				
			||||
 | 
				
			||||
    protected
 | 
				
			||||
 | 
				
			||||
    def gitlab_shell_user_home
 | 
				
			||||
      File.expand_path("~#{Gitlab.config.gitlab_shell.ssh_user}")
 | 
				
			||||
    end
 | 
				
			||||
 | 
				
			||||
    def repos_path
 | 
				
			||||
      Gitlab.config.gitlab_shell.repos_path
 | 
				
			||||
    end
 | 
				
			||||
 | 
				
			||||
    def full_path(dir_name)
 | 
				
			||||
      raise ArgumentError.new("Directory name can't be blank") if dir_name.blank?
 | 
				
			||||
 | 
				
			||||
      File.join(repos_path, dir_name)
 | 
				
			||||
    end
 | 
				
			||||
 | 
				
			||||
    def exists?(dir_name)
 | 
				
			||||
      File.exists?(full_path(dir_name))
 | 
				
			||||
    end
 | 
				
			||||
  end
 | 
				
			||||
end
 | 
				
			||||
@ -0,0 +1,12 @@
 | 
				
			||||
# == GitLab Shell mixin
 | 
				
			||||
#
 | 
				
			||||
# Provide a shortcut to Gitlab::Shell instance by gitlab_shell
 | 
				
			||||
#
 | 
				
			||||
module Gitlab
 | 
				
			||||
  module ShellAdapter
 | 
				
			||||
    def gitlab_shell
 | 
				
			||||
      Gitlab::Shell.new
 | 
				
			||||
    end
 | 
				
			||||
  end
 | 
				
			||||
end
 | 
				
			||||
 | 
				
			||||
@ -0,0 +1,17 @@
 | 
				
			||||
module Gitlab
 | 
				
			||||
  # This module provide 2 methods
 | 
				
			||||
  # to set specific ENV variabled for GitLab Shell
 | 
				
			||||
  module ShellEnv
 | 
				
			||||
    extend self
 | 
				
			||||
 | 
				
			||||
    def set_env(user)
 | 
				
			||||
      # Set GL_ID env variable
 | 
				
			||||
      ENV['GL_ID'] = "user-#{user.id}"
 | 
				
			||||
    end
 | 
				
			||||
 | 
				
			||||
    def reset_env
 | 
				
			||||
      # Reset GL_ID env variable
 | 
				
			||||
      ENV['GL_ID'] = nil
 | 
				
			||||
    end
 | 
				
			||||
  end
 | 
				
			||||
end
 | 
				
			||||
| 
		 Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 2.8 KiB  | 
| 
		 Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 2.8 KiB  | 
| 
		 Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 2.8 KiB  | 
| 
		 Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 2.8 KiB  |