Makistos
10/28/2013 - 7:59 AM

Checks if the user has right to build the given repository based on his role in Redmine. User must be "Builder" in the corresponding Redmine

Checks if the user has right to build the given repository based on his role in Redmine. User must be "Builder" in the corresponding Redmine project if the Gitorious repository is a Team repo. If it is a User repo, user always has right to build.

Returns: 0 [redmine_login] : User has right to build, [redmine_login] is the login name used in Redmine (not necessarily the same as in Gitorious). 1 : User does not have a right to build the repo. 2-n : Some error occured.

#ci #git #gitorious #redmine #scm #ruby

#!/usr/bin/ruby

require "mysql"

# Paths
$hashed_repository_path = '/var/www/gitorious/repositories/'
$pt_repository_path = '/git'

# Database settings, fix these to correct ones.
$git_host = 'localhost'
$git_dbuser = 'git'
$git_dbpw = 'git'
$git_dbname = 'gitorious_production'

$redmine_host = 'localhost'
$redmine_dbuser = 'redmine'
$redmine_dbpw = 'redmine'
$redmine_dbname = 'redmine'

# Ancestor class for database connectors
class DbConnection
  def initialize(host, user, pw, name)
    @dbConn = Mysql::new(host, user, pw, name)
  end
end

# Class that implements database connectivity to the Gitorious Db
class GitoriousDb < DbConnection

  # Get user email from the users table based on gitorious user name
  def user_email(user_name)
    @query = "SELECT email FROM users WHERE login = '#{user_name}'"
    puts "Email query = #{@query}" if $DEBUG
    @rs = @dbConn.query("#{@query}")
    # Raise error if @rs_email = Nil or num_rows != 1
    @email = @rs.fetch_row
    return @email[0]
  end

  # Repository type from the repository table based on the hashed path
  def repo_type(hashed_path)
    @rs = @dbConn.query("SELECT repo.owner_type FROM repositories repo WHERE hashed_path = '#{hashed_path}'")
    # Raise error if @rs_repo = Nil or num_rows != 1
    @repo_type = @rs.fetch_row
    return @repo_type[0]
  end

  # Converts a hashed path to an unhashed path
  def unhashed_path(hashed_path, base_path)
    @query = "SELECT projects.title, repo.name FROM repositories repo, projects
                        WHERE repo.project_id = projects.id AND
                              repo.hashed_path = '#{hashed_path}'"
    puts "Path query = #{@query}" if $DEBUG
    @rs = @dbConn.query("#{@query}")
    # Raise error if needed
    @fields = @rs.fetch_row
    return "#{base_path}/#{@fields[0]}/#{@fields[1]}.git".gsub(/ /, '_')
    #return "#{fields[0]}/#{fields[1]}"
  end
end

# Class that implements database connectivty to the Redmine Db
class RedmineDb < DbConnection

  # Checks if the user with the given email is defined as a Builder in the
  # given project repository
  def project_builder?(email, repo_path)
    @query = "SELECT roles.name FROM roles, users, repositories repo, members, member_roles
                        WHERE users.mail = '#{email}' AND
                              repo.url = '#{repo_path}' AND
                              members.user_id = users.id AND
                              member_roles.member_id  = members.id AND
                              roles.id = member_roles.role_id AND
                              repo.project_id = members.project_id"
    puts "Project builder query: #{@query}" if $DEBUG
    @rs = @dbConn.query("#{@query}")
    @retval = false
    @rs.each do |res|
      if res[0] == 'Builder'
    @retval = true
      end
    end
    if $DEBUG
      puts "Is_builder = #{@retval}" if $DEBUG
    end
    return @retval
  end

  # Gets the user name based on given email address.
  def login(email)
    @rs = @dbConn.query("SELECT login FROM users WHERE mail = '#{email}'")
    @login = @rs.fetch_row
    return @login[0]
  end
end

# Class holding user information
class User
  attr_accessor :git_login, :email, :redmine_login

  def initialize(user_name)
    self.git_login = user_name
  end
end

# Class holding path information
class RepoPaths
  attr_accessor :clear_path, :hashed_path

  def initialize(path_name)
    self.hashed_path = path_name.gsub(/#{$hashed_repository_path}/, '')
    self.hashed_path.gsub!(/.git$/, '')
  end
end

# Class implementing the "glue" logic for the databases
class CheckPerms

  def initialize()
    @user = User.new(ARGV[0])
    @paths = RepoPaths.new(ARGV[1])
    @git_db = GitoriousDb.new($git_host, $git_dbuser, $git_dbpw, $git_dbname)
    @redmine_db = RedmineDb.new($redmine_host, $redmine_dbuser, $redmine_dbpw, $redmine_dbname)

    @user.email = @git_db.user_email("#{@user.git_login}")
    @user.redmine_login = @redmine_db.login("#{@user.email}")

    @paths.clear_path = @git_db.unhashed_path(@paths.hashed_path, $pt_repository_path)
  end

  private

  # Checks if this user is allowed to build in this repository. Returns true or false.
  def can_build?
    if @git_db.repo_type(@paths.hashed_path) == 'User' || @redmine_db.project_builder?(@user.email, @paths.clear_path)
      return true
    else
      return false
    end
  end

  public

  # Prints access info + Redmin user id if access is granted.
  def print_access
    if can_build?
      puts "0:#{@user.redmine_login}"
    else
      puts "1"
    end
  end
end

####
# Main code

# Read arguments

checkPerms = CheckPerms.new

# Return result
checkPerms.print_access