240 lines
		
	
	
		
			8.9 KiB
		
	
	
	
		
			Ruby
		
	
	
	
	
	
			
		
		
	
	
			240 lines
		
	
	
		
			8.9 KiB
		
	
	
	
		
			Ruby
		
	
	
	
	
	
| require "db/mongo/models/environment/environment"
 | |
| require "db/mongo/models/user"
 | |
| require "db/mongo/models/environment/environments_array"
 | |
| require "json"
 | |
| require "hooks"
 | |
| require "lib/project/type/types_factory"
 | |
| require "exceptions/invalid_record"
 | |
| require "exceptions/record_not_found"
 | |
| #require "db/validators/environment/environments"
 | |
| require "db/validators/project/named_tasks"
 | |
| 
 | |
| module Devops
 | |
|   module Model
 | |
|     class Project
 | |
| 
 | |
|       include Hooks
 | |
|       include Hooks::InstanceHooks
 | |
|       define_hook :before_create
 | |
|       define_hook :after_create
 | |
| 
 | |
|       define_hook :before_delete
 | |
|       define_hook :after_delete
 | |
| 
 | |
|       include ::Mongoid::Document
 | |
|       include ::Mongoid::Timestamps::CreatedInt
 | |
|       include ::ActiveModel::Validations
 | |
| 
 | |
|       #attr_accessor :components
 | |
|       store_in collection: "projects"
 | |
| 
 | |
|       field :_id, as: :'id', overwrite: true, type: String
 | |
|       field :environments, type: EnvironmentsArray, default: ->{ [] }
 | |
|       field :type, type: String
 | |
|       field :owner, type: String
 | |
|       field :project_users, type: Array, default: ->{ [] }
 | |
|       field :archived, type: Boolean
 | |
|       field :description, type: String
 | |
|       field :run_list, type: Array, default: ->{ [] }
 | |
|       field :named_tasks, type: Array, default: ->{ [] }
 | |
| 
 | |
|       MAX_ID_LEN = 100
 | |
|       ID_REGEX = /\A[\w\-\.]{1,#{MAX_ID_LEN}}\z/
 | |
| 
 | |
|       validates_presence_of :id, message: "'id' is undefined"
 | |
|       validates_length_of :id, minimum: 1, maximum: MAX_ID_LEN
 | |
|       validates_format_of :id, with: ID_REGEX, message: "invalid id, it should contains 'a-zA-Z0-9-.' symbols"
 | |
|       validates_uniqueness_of :id, on: :create
 | |
| 
 | |
|       validates_length_of :description, maximum: 500
 | |
| 
 | |
|       validates_presence_of :owner, message: "'owner' is undefined"
 | |
|       validates :named_tasks, proper_named_tasks_format: true
 | |
| 
 | |
| 
 | |
| =begin
 | |
| TODO:
 | |
| 
 | |
|       set_field_validators :named_tasks, [::Validators::FieldValidator::Nil,
 | |
|                                     ::Validators::FieldValidator::FieldType::Array,
 | |
|                                     ::Validators::FieldValidator::NamedTasks]
 | |
| 
 | |
|       set_validators ::Validators::DeployEnv::RunList,
 | |
|                      ::Validators::DeployEnv::DeployEnvs
 | |
| =end
 | |
|       validates_length_of :description, maximum: 500
 | |
| 
 | |
|       #TODO:  self.named_tasks = p["named_tasks"] || []
 | |
|       def initialize hash
 | |
|         raise InvalidRecord.new("Parameter 'id' is not a string") unless hash["id"].is_a?(String)
 | |
|         raise InvalidRecord.new("Parameter 'environments' is not an array") unless hash["environments"].is_a?(Array) or hash["environments"].nil?
 | |
|         raise InvalidRecord.new("Parameter 'run_list' is not an array") unless hash["run_list"].is_a?(Array) or hash["run_list"].nil?
 | |
|         raise InvalidRecord.new("Parameter 'project_users' is not an array") unless hash["project_users"].is_a?(Array) or hash["project_users"].nil?
 | |
|         super(hash)
 | |
|       end
 | |
| 
 | |
|       def self.find_with_environment id, environment
 | |
|         Project.find_by({_id: id, environments:{'$elemMatch' => {id: environment}}})
 | |
|       end
 | |
| 
 | |
|       def self.find_with_category id, environment, category
 | |
|         Project.find_by(
 | |
|           _id: id,
 | |
|           environments: {
 | |
|             '$elemMatch' => {
 | |
|               id: environment,
 | |
|               categories: {'$elemMatch' => {id: category}}
 | |
|             }
 | |
|           }
 | |
|         )
 | |
|       end
 | |
| 
 | |
|       # TODO: extract to handler or parser
 | |
|       def self.list_fields
 | |
|         ['deploy_envs', 'type', 'description', 'named_tasks']
 | |
|       end
 | |
| 
 | |
|       def self.check_user_authorization project_id, env, user_id
 | |
| #        find({'_id' => project_id}).projection({environments:{'$elemMatch' => {id:env}}})
 | |
|         project = find(project_id)
 | |
|         if !project.check_authorization(user_id, env)
 | |
|           raise Devops::Exception::Unauthorized.new("User '#{user_id}' is unauthorized to work with project '#{project_id}' and environment '#{env}'")
 | |
|         end
 | |
|         project
 | |
|       rescue Mongoid::Errors::DocumentNotFound
 | |
|         raise Devops::Exception::RecordNotFound.new("Project with id '#{project_id}' not found")
 | |
|       end
 | |
| 
 | |
|       def environment env
 | |
|         de = self.environments.detect {|e| e.id == env}
 | |
|         raise Devops::Exception::RecordNotFound.new("Project '#{self.id}' does not have deploy environment '#{env}'") if de.nil?
 | |
|         de
 | |
|       end
 | |
| 
 | |
|       def add_environment environment
 | |
|         self.push(environments: environment.to_hash)
 | |
|         DevopsLogger.logger.info("Added environment '#{environment.id}' to project '#{self.id}'")
 | |
|         DevopsLogger.logger.debug("Added environment: #{environment.to_hash.inspect}")
 | |
|       end
 | |
| 
 | |
|       def add_category env, category
 | |
|         env.categories.push category
 | |
|         category_hash = category.to_hash
 | |
|         Project.where('_id' => self.id, 'environments.id' => env.id).push('environments.$.categories' => category_hash)
 | |
|         DevopsLogger.logger.debug("Added category '#{category.id}' to project '#{self.id}' and environment '#{env.id}'")
 | |
|         DevopsLogger.logger.debug("Added category: #{category_hash.inspect}")
 | |
|         category
 | |
|       end
 | |
| 
 | |
|       def delete_category env, category_id
 | |
|         bsize = env.categories.size
 | |
|         env.categories.delete_if{|c| c.id == category_id}
 | |
|         if bsize == env.categories.size
 | |
|           raise Devops::Exception::RecordNotFound.new("Category '#{category_id}' in project '#{id}' and deploy environment '#{env}' does not exist")
 | |
|         else
 | |
|           Project.where({'_id' => self.id, 'environments.id' => env.id}).pull('environments.$.categories' => {'id' => category_id})
 | |
|           DevopsLogger.logger.info("Category '#{category_id}' removed from project '#{self.id}' and environment '#{env.id}'")
 | |
|         end
 | |
|       end
 | |
| 
 | |
|       # user could be a String or an Array of strings.
 | |
|       # if env is nil, add given user(s) to all project's envs,
 | |
|       # otherwise only to specified one.
 | |
|       def add_authorized_user user, env=nil
 | |
|         return if user.nil?
 | |
|         new_users = ( user.is_a?(Array) ? user : [ user ] )
 | |
|         environments = env.nil? ? self.environments : [ self.environment(env) ]
 | |
|         environments.each do |e|
 | |
|           e.add_users new_users
 | |
|           Devops::Db.connector.set_project_environment_field(self.id, e.id, {users: e.users})
 | |
|         end
 | |
|       end
 | |
| 
 | |
|       def remove_authorized_user user, env=nil
 | |
|         return if user.nil?
 | |
|         users = ( user.is_a?(Array) ? user : [ user ] )
 | |
|         environments = env.nil? ? self.environments : [ self.environment(env) ]
 | |
|         environments.each do |e|
 | |
|           e.users = e.users - users
 | |
|           Devops::Db.connector.set_project_environment_field(self.id, e.id, {users: e.users})
 | |
|         end
 | |
|       end
 | |
| 
 | |
|       def check_authorization user_id, env
 | |
|         return true if user_id == self.owner or user_id == User::ROOT_USER_NAME
 | |
|         return true if is_sandbox?
 | |
|         e = self.environment(env)
 | |
|         return e.users.include? user_id
 | |
|       rescue Devops::Exception::RecordNotFound => e
 | |
|         return false
 | |
|       end
 | |
| 
 | |
|       def is_sandbox?
 | |
|         id.start_with?('sandbox-')
 | |
|       end
 | |
| 
 | |
|       def delete_environment env
 | |
|         self.environments.delete_if {|e| e.id == env}
 | |
|         Project.where('_id' => self.id).pull('environments' => {'id' => env})
 | |
|       end
 | |
| 
 | |
|       def to_hash
 | |
|         hash = self.attributes.clone
 | |
|         hash["id"] = hash.delete("_id")
 | |
|         hash.delete('archived') unless hash['archived']
 | |
|         hash
 | |
|       end
 | |
| 
 | |
|       # TODO: why symbols here?
 | |
|       def to_hash_list
 | |
|         {
 | |
|           id: self.id,
 | |
|           description: self.description,
 | |
|           owner: self.owner,
 | |
|           run_list: self.run_list,
 | |
|           project_users: self.project_users,
 | |
|           created_at: self.created_at
 | |
|         }
 | |
|       end
 | |
| 
 | |
|       def deploy_info environment, build_number=nil
 | |
|         {
 | |
|           "use_json_file" => false,
 | |
| #          "run_list" => Set.new.merge(self.run_list).merge(environment.run_list).to_a,
 | |
|           "project" => self.id,
 | |
|           "project_info" => {
 | |
|             "project" => self.id,
 | |
|             "environment" => environment.id,
 | |
|             "deployers" => environment.users
 | |
|           }
 | |
|         }
 | |
|       end
 | |
| 
 | |
| =begin
 | |
|       def extract_servers env, params
 | |
|         @handler.extract_servers(self, env, params)
 | |
|       end
 | |
| 
 | |
|       # maybe it worth to move components functionality to devops-nibr?
 | |
|       #TODO: create validator
 | |
|       def validate_components
 | |
|         raise InvalidRecord.new "Components is not a hash" unless self.components.is_a?(Hash)
 | |
|         self.components.each do |id, c|
 | |
|           raise InvalidRecord.new "Component '#{id}' has no attribute 'fileid'" unless c.key?("fileid")
 | |
|         end
 | |
|       end
 | |
| =end
 | |
| 
 | |
|       # def self.create_roles_response roles
 | |
|       #   return "error in creating roles" unless roles
 | |
|       #   info = ''
 | |
|       #   info += "Project roles '#{roles[:new].join("', '")}' have been automaticaly created" unless roles[:new].nil?
 | |
|       #   info += " Project roles '#{roles[:exist].join("', '")}' weren't created because they exist" unless roles[:exist].nil?
 | |
|       #   info += " Project roles '#{roles[:error].join("', '")}' weren't created because of internal error" unless roles[:error].nil?
 | |
|       #   info
 | |
|       # end
 | |
| 
 | |
|     end
 | |
|   end
 | |
| end
 | 
