95 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			Ruby
		
	
	
	
	
	
			
		
		
	
	
			95 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			Ruby
		
	
	
	
	
	
| require "mongoid"
 | |
| require_relative "role"
 | |
| 
 | |
| module Devops
 | |
|   module Model
 | |
|     class User
 | |
| 
 | |
|       include ::Mongoid::Document
 | |
|       include ::Mongoid::Timestamps::CreatedInt
 | |
|       include ::ActiveModel::Validations
 | |
| 
 | |
|       store_in collection: "users"
 | |
| 
 | |
|       ROOT_USER_NAME = 'root'
 | |
|       ROOT_PASSWORD = 'super_user'
 | |
|       USER_NAME_REGEX = /[\w-]+/
 | |
| 
 | |
|       ALL_POLICIES_KEY = 'all'
 | |
| 
 | |
|       field :_id, as: :'id', overwrite: true, type: String
 | |
|       field :password, type: String
 | |
|       field :email, type: String
 | |
|       field :roles, type: Array, default: ->{ [] }
 | |
| 
 | |
|       validates_presence_of :id, message: "'id' is undefined"
 | |
|       validates_length_of :id, minimum: 1, maximum: 100
 | |
|       validates_format_of :id, with: USER_NAME_REGEX, message: "invalid id, it should contains '_a-zA-Z0-9-.' symbols"
 | |
|       validates_uniqueness_of :id, on: :create
 | |
| 
 | |
|       validates_presence_of :password, message: "'password' is undefined"
 | |
|       validates_length_of :password, maximum: 31, minimum: 5
 | |
| 
 | |
|       validates_format_of :email, with: /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\z/i, message: "Invalid email"
 | |
| 
 | |
|       validate :validate_roles
 | |
| 
 | |
|       def initialize hash
 | |
|         raise InvalidRecord.new("Parameter 'id' is not a string") unless hash["id"].is_a?(String)
 | |
|         raise InvalidRecord.new("Parameter 'password' is not a string") unless hash["password"].is_a?(String)
 | |
|         raise InvalidRecord.new("Parameter 'email' is not a string") unless hash["email"].is_a?(String)
 | |
|         raise InvalidRecord.new("Parameter 'roles' is not an array") unless hash["roles"].is_a?(Array)
 | |
|         super(hash)
 | |
|       end
 | |
| 
 | |
|       def validate_roles
 | |
|         dbroles = Role.in({'_id' => self.roles})
 | |
|         dbroles = dbroles.map{|r| r.id}
 | |
|         buf = self.roles - dbroles
 | |
|         unless buf.empty?
 | |
|           errors.add(:roles, "Invalid roles: #{buf.join(', ')}")
 | |
|         end
 | |
|       end
 | |
| 
 | |
|       def self.create_root
 | |
|         unless Role.where(:id => Role::SUPER_USER_ROLE).exists?
 | |
|           role = Role.new({'id' => Role::SUPER_USER_ROLE, 'name' => Role::SUPER_USER_ROLE, 'description' => "All policies", 'policies' => ['all']})
 | |
|           role.save!
 | |
|           DevopsLogger.logger.info("Role '#{Role::SUPER_USER_ROLE}' has been created")
 | |
|         end
 | |
|         unless User.where(:id => ROOT_USER_NAME).exists?
 | |
|           root = Devops::Model::User.new({'id' => ROOT_USER_NAME, 'password' => ROOT_PASSWORD, 'email' => "#{ROOT_USER_NAME}@host.ru", 'roles' => []})
 | |
|           root.save!
 | |
|           DevopsLogger.logger.info("User '#{ROOT_USER_NAME}' has been created")
 | |
|           root
 | |
|         end
 | |
|       end
 | |
| 
 | |
|       def self.auth login, password
 | |
|         User.find_by({id: login, password: password})
 | |
|       rescue Mongoid::Errors::DocumentNotFound
 | |
|         nil
 | |
|       end
 | |
| 
 | |
|       def to_hash
 | |
|         hash = self.attributes
 | |
|         hash.delete("password")
 | |
|         hash["id"] = hash.delete("_id")
 | |
|         hash
 | |
|       end
 | |
| 
 | |
|       def check_policy policy
 | |
|         return true if self.id == ROOT_USER_NAME
 | |
|         policies = Set.new
 | |
|         Devops::Model::Role.find(self.roles).each{|r| policies.merge(r.policies)}
 | |
|         return true if policies.include?(ALL_POLICIES_KEY)
 | |
|         raise Devops::Exception::Unauthorized.new("Access denied for user '#{self.id}'") unless policies.include?(policy.to_s)
 | |
|         true
 | |
|       rescue Mongoid::Errors::DocumentNotFound
 | |
|         raise Devops::Exception::Unauthorized.new("Access denied for user '#{self.id}', no roles with policy '#{policy}' found")
 | |
|       end
 | |
| 
 | |
|     end
 | |
|   end
 | |
| end
 | 
