2017-06-04 18:42:43 +00:00
|
|
|
require 'fileutils'
|
|
|
|
require 'scrypt'
|
|
|
|
require_relative 'user'
|
|
|
|
require_relative 'project'
|
|
|
|
require_relative 'sshkey'
|
|
|
|
|
|
|
|
POSIX_NAME_PREFIX = "emacs"
|
|
|
|
USER_LOCATION = "./users/"
|
2017-06-15 00:20:13 +00:00
|
|
|
DATA_PATH = "./data"
|
2017-06-04 18:42:43 +00:00
|
|
|
|
|
|
|
|
|
|
|
require_relative 'database/sqlite'
|
|
|
|
$db = EmacsCollab::Database::SQLite.new "test"
|
|
|
|
|
|
|
|
module EmacsCollab
|
|
|
|
|
|
|
|
# TODO: Fix this weird definition
|
|
|
|
|
|
|
|
#####################
|
|
|
|
# User manipulation #
|
|
|
|
#####################
|
|
|
|
|
|
|
|
def self.create_user(id)
|
|
|
|
user = User.new(id)
|
|
|
|
add_user(user)
|
|
|
|
end
|
|
|
|
|
|
|
|
def self.add_user(user)
|
|
|
|
$db.add_user(user)
|
|
|
|
end
|
|
|
|
|
|
|
|
def self.get_user_by_id(id)
|
|
|
|
$db.get_user(id)
|
|
|
|
end
|
|
|
|
|
2017-06-14 22:45:15 +00:00
|
|
|
def self.get_users
|
|
|
|
$db.get_users
|
|
|
|
end
|
|
|
|
|
2017-06-04 18:42:43 +00:00
|
|
|
def self.change_user_password(id,password)
|
|
|
|
user = get_user_by_id(id)
|
|
|
|
|
|
|
|
hash, salt = salthash_password(password)
|
|
|
|
$db.change_user_password(user, hash, salt)
|
|
|
|
end
|
|
|
|
|
|
|
|
def self.check_password(id, password)
|
|
|
|
user = get_user_by_id(id)
|
|
|
|
|
|
|
|
hash = salthash_password(password, user.salt)[0]
|
|
|
|
|
|
|
|
user.pw_hash == hash
|
|
|
|
end
|
|
|
|
|
|
|
|
def self.salthash_password(password, salt = SCrypt::Engine.generate_salt)
|
|
|
|
hash = SCrypt::Engine.hash_secret(password,salt)
|
|
|
|
return hash, salt
|
|
|
|
end
|
|
|
|
|
|
|
|
########################
|
|
|
|
# Project manipulation #
|
|
|
|
########################
|
|
|
|
|
|
|
|
def self.get_project(id)
|
|
|
|
$db.get_project(id)
|
|
|
|
end
|
|
|
|
|
2017-06-15 00:20:13 +00:00
|
|
|
def self.get_projects
|
|
|
|
$db.get_projects
|
|
|
|
end
|
|
|
|
|
2017-06-04 18:42:43 +00:00
|
|
|
def self.add_project(project)
|
|
|
|
$db.add_project(project)
|
|
|
|
end
|
|
|
|
|
|
|
|
def self.create_project(id)
|
2017-06-15 00:20:13 +00:00
|
|
|
begin
|
|
|
|
if get_project(id) then
|
|
|
|
raise DuplicateProjectError, "Project with id #{id} already exists"
|
|
|
|
end
|
|
|
|
rescue EmacsCollab::ProjectNotFoundError => e
|
2017-06-04 18:42:43 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
if not system("useradd -m #{POSIX_NAME_PREFIX}#{id} -s /usr/bin/eshell") then
|
|
|
|
raise "Project creation failed"
|
|
|
|
end
|
|
|
|
|
|
|
|
project = Project.new
|
|
|
|
project.id = id
|
|
|
|
project.path = "/home/#{POSIX_NAME_PREFIX}#{id}"
|
|
|
|
project.posixname = "#{POSIX_NAME_PREFIX}#{id}"
|
2017-06-15 00:20:13 +00:00
|
|
|
project.uid = /uid=([0-9]+)\(/.match(`id #{project.posixname}`)[1].to_i
|
2017-06-04 18:42:43 +00:00
|
|
|
|
|
|
|
FileUtils.mkdir "#{project.path}/.ssh"
|
|
|
|
FileUtils.touch "#{project.path}/.ssh/authorized_keys"
|
|
|
|
FileUtils.touch "#{project.path}/.ssh/users"
|
|
|
|
FileUtils.chown_R project.posixname, project.posixname, "#{project.path}/.ssh"
|
|
|
|
|
|
|
|
add_project(project)
|
|
|
|
|
|
|
|
project
|
|
|
|
end
|
|
|
|
|
|
|
|
def self.remove_project(project)
|
|
|
|
system("userdel -r #{project.posixname}")
|
|
|
|
$db.remove_project(project)
|
|
|
|
end
|
|
|
|
|
|
|
|
def self.load_project_from_posix_name(posix_name)
|
|
|
|
project = Project.new
|
|
|
|
project.id = posix_name[POSIX_NAME_PREFIX.length..-1]
|
|
|
|
project.path = "/home/#{posix_name}"
|
|
|
|
project.posixname = posix_name
|
|
|
|
project
|
|
|
|
end
|
|
|
|
|
|
|
|
####################
|
|
|
|
# Key manipulation #
|
|
|
|
####################
|
|
|
|
|
|
|
|
def self.get_ssh_keyfile(project,mode,&block)
|
|
|
|
file = File.open("#{project.path}/.ssh/authorized_keys",mode)
|
|
|
|
return file unless block_given?
|
|
|
|
yield(file)
|
|
|
|
ensure
|
|
|
|
file.close
|
|
|
|
end
|
|
|
|
|
|
|
|
def self.get_ssh_pubkeys(project)
|
|
|
|
extract_ssh_pubkeys("#{project.path}/.ssh/authorized_keys")
|
|
|
|
end
|
|
|
|
|
|
|
|
def self.valid_pubkey?(key)
|
|
|
|
IO.popen("ssh-keygen -qlf -","r+") do |io|
|
|
|
|
io.write key.to_s
|
|
|
|
io.close_write
|
|
|
|
io.read
|
|
|
|
end
|
|
|
|
if $?.to_i == 0
|
|
|
|
true
|
|
|
|
else
|
|
|
|
false
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def self.extract_ssh_pubkeys(file)
|
|
|
|
File.open(file,"r") do |f|
|
|
|
|
f.read.split("\n").select{ |line| line[0..2] == "ssh" }.map{ |ks| k = ks.split(" "); SSHKey.new(k[0][4..6], k[1], k[2]) }
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
################
|
|
|
|
|
|
|
|
|
|
|
|
###########
|
|
|
|
# Project $DB #
|
|
|
|
###########
|
|
|
|
|
|
|
|
def self.reload_projects_from_passwd
|
|
|
|
$projects = []
|
|
|
|
`cut -d: -f1 /etc/passwd`.split("\n").
|
|
|
|
select{|u| u.start_with? POSIX_NAME_PREFIX}.
|
|
|
|
map{|u| load_project_from_posix_name(u)}.
|
|
|
|
each{|u| add_project(u)}
|
|
|
|
$projects.each{|p| p.refresh}
|
|
|
|
end
|
|
|
|
|
|
|
|
def self.reload_users_from_dir
|
|
|
|
`ls -1 #{USER_LOCATION}`.split("\n").
|
|
|
|
map{|u| User.new(u)}.
|
|
|
|
each{|u| add_user(u.id)}
|
|
|
|
end
|
|
|
|
|
|
|
|
def self.flush_all_to_disk
|
|
|
|
$users.each {|u| u.flush}
|
|
|
|
$projects.each {|p| p.flush}
|
|
|
|
end
|
|
|
|
|
|
|
|
def self.flush_projects_with_user(user)
|
2017-06-15 00:20:13 +00:00
|
|
|
#$projects.select{|p| p.users.include? user}.each do |p|
|
|
|
|
# p.flush
|
|
|
|
#end
|
2017-06-04 18:42:43 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
################################################
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
#reload_users_from_dir
|
|
|
|
#reload_projects_from_passwd
|
|
|
|
|
|
|
|
#remove_project 5
|
|
|
|
#create_project 3
|
|
|
|
#add_ssh_pubkey(get_project(3), "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC7ZKN2fKcUQUaQqDjNCQQBSdqBVGX7lprNCJmceDBfybhbnuZJ8KvzJJIJIIbzqheW5BVCfkWJY6OgkpAumLWSRCS5n2+AnDHwQgpKDS93OeV+9/kattVtsVUBZaghymyJ2UfA0r918dkxcT9SZbNSl9raiDUUmj3JY8UM219BQP7BRqoZ6e/YZz9lO7ORy6yQT6fIMaVOaZcoDPr6oyNJfadm9POvS/Wl63onoRI9dzpHQG9RuHCcUhHJhkGtzY7GeRWc85WqA9Q4vYo0SK5Je9BG1cvAAVTfV+eYEJEiSDMwWj60roH0C3/ipmzxD/kWqg6YBJWL+XAyQkDnmbuD christoffermadsen@strawberry.thedevcave.net")
|