SQLite integration should be complete now

This commit is contained in:
Christoffer Müller Madsen 2017-06-15 02:20:13 +02:00
parent b711f54b84
commit 06eb99c84a
9 changed files with 111 additions and 62 deletions

View File

@ -1,5 +1,4 @@
source 'https://rubygems.org' source 'https://rubygems.org'
gem 'fileutils'
gem 'tty-prompt' gem 'tty-prompt'
gem 'colorize' gem 'colorize'
gem 'sqlite3' gem 'sqlite3'

View File

@ -1,9 +1,9 @@
FROM ubuntu:xenial FROM ubuntu:xenial
RUN apt-get update RUN apt-get update
RUN apt-get install -y emacs-nox ruby openssh-server RUN apt-get install -y emacs-nox openssh-server
RUN apt-get install -y build-essential libsqlite3-dev sqlite3 RUN apt-get install -y ruby ruby-dev build-essential libsqlite3-dev sqlite3
RUN gem install tty-prompt colorize RUN gem install bundler
RUN mkdir /var/run/sshd RUN mkdir /var/run/sshd
# SSH login fix. Otherwise user is kicked off after login # SSH login fix. Otherwise user is kicked off after login

View File

@ -1,3 +1,4 @@
#!/bin/sh #!/bin/sh
cp ../eshell ./ cp ../eshell ./
cp ../Gemfile* ./
docker build -t emacs-collab:latest . docker build -t emacs-collab:latest .

View File

@ -10,9 +10,11 @@ CREATE TABLE Users (
); );
CREATE TABLE Projects ( CREATE TABLE Projects (
uid INT NOT NULL, uid INT NOT NULL,
name VARCHAR (24) NOT NULL, name VARCHAR (24) NOT NULL,
owner VARCHAR (24) NOT NULL, path VARCHAR (255) NOT NULL,
posixname VARCHAR (32) NOT NULL,
owner VARCHAR (1024),
users VARCHAR (8192), users VARCHAR (8192),
PRIMARY KEY (uid), PRIMARY KEY (uid),

View File

@ -6,7 +6,7 @@ require_relative 'sshkey'
POSIX_NAME_PREFIX = "emacs" POSIX_NAME_PREFIX = "emacs"
USER_LOCATION = "./users/" USER_LOCATION = "./users/"
DATA_PATH = "/home/christoffermadsen/git/emacs-collab/data" DATA_PATH = "./data"
require_relative 'database/sqlite' require_relative 'database/sqlite'
@ -65,13 +65,20 @@ module EmacsCollab
$db.get_project(id) $db.get_project(id)
end end
def self.get_projects
$db.get_projects
end
def self.add_project(project) def self.add_project(project)
$db.add_project(project) $db.add_project(project)
end end
def self.create_project(id) def self.create_project(id)
if get_project(id) then begin
raise DuplicateProjectError, "Project with id #{id} already exists" if get_project(id) then
raise DuplicateProjectError, "Project with id #{id} already exists"
end
rescue EmacsCollab::ProjectNotFoundError => e
end end
if not system("useradd -m #{POSIX_NAME_PREFIX}#{id} -s /usr/bin/eshell") then if not system("useradd -m #{POSIX_NAME_PREFIX}#{id} -s /usr/bin/eshell") then
@ -82,6 +89,7 @@ module EmacsCollab
project.id = id project.id = id
project.path = "/home/#{POSIX_NAME_PREFIX}#{id}" project.path = "/home/#{POSIX_NAME_PREFIX}#{id}"
project.posixname = "#{POSIX_NAME_PREFIX}#{id}" project.posixname = "#{POSIX_NAME_PREFIX}#{id}"
project.uid = /uid=([0-9]+)\(/.match(`id #{project.posixname}`)[1].to_i
FileUtils.mkdir "#{project.path}/.ssh" FileUtils.mkdir "#{project.path}/.ssh"
FileUtils.touch "#{project.path}/.ssh/authorized_keys" FileUtils.touch "#{project.path}/.ssh/authorized_keys"
@ -169,9 +177,9 @@ module EmacsCollab
end end
def self.flush_projects_with_user(user) def self.flush_projects_with_user(user)
$projects.select{|p| p.users.include? user}.each do |p| #$projects.select{|p| p.users.include? user}.each do |p|
p.flush # p.flush
end #end
end end
################################################ ################################################

View File

@ -14,7 +14,6 @@ module EmacsCollab
end end
def get_user(id) def get_user(id)
# TODO
row = @db.execute("SELECT * FROM Users WHERE name = ?", [id])[0] row = @db.execute("SELECT * FROM Users WHERE name = ?", [id])[0]
unless row unless row
raise UserNotFoundError, "User with id #{id} could not be found in database" raise UserNotFoundError, "User with id #{id} could not be found in database"
@ -23,19 +22,19 @@ module EmacsCollab
user = User.new(row[0]) user = User.new(row[0])
user.pw_hash = row[1] user.pw_hash = row[1]
user.salt = row[2] user.salt = row[2]
user.keys = row[3] == nil ? nil : JSON.parse(row[3]) user.keys = row[3] == nil ? Array.new : Marshal.load(row[3])
user user
end end
def get_users def get_users
user_rows = @db.execute("SELECT * FROM Users") rows = @db.execute("SELECT * FROM Users")
user_rows.map do |row| rows.map do |row|
user = User.new(row[0]) user = User.new(row[0])
user.pw_hash = row[1] user.pw_hash = row[1]
user.salt = row[2] user.salt = row[2]
user.keys = row[3] == nil ? nil : JSON.parse(row[3]) user.keys = row[3] == nil ? Array.new : Marshal.load(row[3])
user user
end end
end end
@ -49,11 +48,63 @@ module EmacsCollab
@db.execute("UPDATE Users SET keys = ? WHERE name = ?", @db.execute("UPDATE Users SET keys = ? WHERE name = ?",
[JSON.generate(user.keys),user.id]) [JSON.generate(user.keys),user.id])
end end
def change_user_password(user,hash,salt) def change_user_password(user,hash,salt)
@db.execute("UPDATE Users SET passwd = ?, salt = ? WHERE name = ?", @db.execute("UPDATE Users SET passwd = ?, salt = ? WHERE name = ?",
[hash,salt,user.id]) [hash,salt,user.id])
end end
def get_project(name)
row = @db.execute("SELECT * FROM Projects WHERE name = ?", [name])[0]
unless row
raise EmacsCollab::ProjectNotFoundError, "Project with name #{name} could not be found in database"
end
proj = Project.new()
proj.uid = row[0]
proj.id = row[1]
proj.path = row[2]
proj.posixname = row[3]
proj.owner = row[4]
users = (row[5] == nil ? Array.new : Marshal.load(row[5]))
users.each do |u|
EmacsCollab.get_user_by_id(u.id).keys.each do |k|
proj.add_key(k)
end
end
proj
end
def get_projects
rows = @db.execute("SELECT * FROM Projects")
rows.map do |row|
proj = Project.new()
proj.uid = row[0]
proj.id = row[1]
proj.path = row[2]
proj.posixname = row[3]
proj.owner = row[4]
users = (row[5] == nil ? Array.new : Marshal.load(row[5]))
users.each do |u|
EmacsCollab.get_user_by_id(u).keys.each do |k|
proj.add_key(k)
end
end
proj.users = row[5]
proj
end
end
def add_project(proj)
@db.execute("INSERT INTO Projects (uid,name,path,posixname,owner,users) VALUES (?,?,?,?,?,?)",
[ proj.uid, proj.id, proj.path, proj.posixname, "", Marshal.dump(proj.users) ])
end
def update_project(proj)
@db.execute("UPDATE Projects SET name = ?, path = ?, posixname = ?, owner = ?, users = ? WHERE uid = ?",
[ proj.id, proj.path, proj.posixname, "", Marshal.dump(proj.users), proj.uid ])
end
end end
end end
end end

View File

@ -1,10 +1,11 @@
module EmacsCollab module EmacsCollab
class Project class Project
attr_accessor :id, :path, :posixname, :users attr_accessor :uid, :id, :path, :posixname, :users, :owner
attr_reader :keys attr_reader :keys
def initialize def initialize
@users = [] @users = []
@keys = []
end end
def to_s def to_s
@ -17,36 +18,30 @@ module EmacsCollab
def add_user(user) def add_user(user)
@users << user @users << user
user.keys.each do |key| # TODO: Remove the following comments
add_key(key) #user.keys.each do |key|
end # add_key(key)
#end
flush flush
refresh
end end
def remove_user(user) def remove_user(user)
@user.delete(user) @user.delete(user)
# TODO Make sure to remove the key of the user
flush flush
refresh refresh
end end
def refresh def refresh
@users = File.open("#{@path}/.ssh/users","r") do |f|
f.read.split("\n").map{|id| get_user_by_id(id)}
end
@keys = extract_ssh_pubkeys("#{@path}/.ssh/authorized_keys")
end end
def flush def flush
File.open("#{@path}/.ssh/users","w+") do |user_file| $db.update_project(self)
@users.each do |u|
user_file << "#{u.id}\n" EmacsCollab.get_ssh_keyfile(self,"w+") do |key_file|
end
end
get_ssh_keyfile(self,"w+") do |key_file|
@users.each do |user| @users.each do |user|
user.keys.each do |key| EmacsCollab.get_user_by_id(user).keys.each do |key|
key_file << "#{key.to_s}\n" key_file << "#{key.to_s}\n"
end end
end end
@ -58,4 +53,7 @@ module EmacsCollab
class DuplicateProjectError < StandardError class DuplicateProjectError < StandardError
end end
class ProjectNotFoundError < StandardError
end
end end

View File

@ -10,11 +10,10 @@ module EmacsCollab
def initialize(id) def initialize(id)
@id = id @id = id
@keypath = "#{USER_LOCATION}#{id}" @keypath = "#{USER_LOCATION}#{id}"
refresh_keys
end end
def add_key_from_string(keystring) def add_key_from_string(keystring)
unless valid_pubkey? keystring unless EmacsCollab.valid_pubkey? keystring
raise InvalidSSHPubKey, "Public key not valid" raise InvalidSSHPubKey, "Public key not valid"
end end
ks = keystring.split(" "); ks = keystring.split(" ");
@ -25,31 +24,19 @@ module EmacsCollab
else else
raise DuplicateSSHPubKey, "Public key is already added to user" raise DuplicateSSHPubKey, "Public key is already added to user"
end end
p self
flush flush
refresh_keys EmacsCollab.flush_projects_with_user(self)
flush_projects_with_user(self)
end end
def remove_key(key) def remove_key(key)
@keys.delete(key) @keys.delete(key)
flush flush
refresh_keys EmacsCollab.flush_projects_with_user(self)
flush_projects_with_user(self)
end
def refresh_keys
#File.open(@keypath,"r") do |f|
# @keys = 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 end
def flush def flush
File.open(@keypath,"w+") do |key_file| $db.update_user(self)
@keys.each do |key|
key_file << "#{key.to_s}\n"
end
end
end end
end end

View File

@ -2,6 +2,9 @@ require_relative 'lib/emacscollab'
require 'tty-prompt' require 'tty-prompt'
require 'colorize' require 'colorize'
require_relative 'lib/emacscollab/collab'
require_relative 'lib/emacscollab/sshkey'
$prompt = TTY::Prompt.new $prompt = TTY::Prompt.new
$login = "root" $login = "root"
@ -34,10 +37,10 @@ def keys_user(user)
key = $prompt.ask("Please enter a valid public SSH key", echo: false) key = $prompt.ask("Please enter a valid public SSH key", echo: false)
begin begin
user.add_key_from_string(key) user.add_key_from_string(key)
rescue InvalidSSHPubKey => e rescue EmacsCollab::InvalidSSHPubKey => e
puts e.message.colorize(:red) puts e.message.colorize(:red)
keys_user(user) keys_user(user)
rescue DuplicateSSHPubKey => e rescue EmacsCollab::DuplicateSSHPubKey => e
puts e.message.colorize(:red) puts e.message.colorize(:red)
keys_user(user) keys_user(user)
end end
@ -67,8 +70,8 @@ def project_create
input.validate /\A\w+\Z/ input.validate /\A\w+\Z/
end end
begin begin
create_project(id) EmacsCollab.create_project(id)
rescue DuplicateProjectError => e rescue EmacsCollab::DuplicateProjectError => e
puts e.message.colorize(:red) puts e.message.colorize(:red)
projects projects
end end
@ -77,7 +80,7 @@ end
def project_modify def project_modify
# Currently, it is implied that modify equals changing which users have access # Currently, it is implied that modify equals changing which users have access
project_users($prompt.select("Pick a project", $projects)) project_users($prompt.select("Pick a project", EmacsCollab.get_projects))
end end
def project_users(project) def project_users(project)
@ -90,7 +93,7 @@ def project_users(project)
when :add when :add
choices = EmacsCollab.get_users choices = EmacsCollab.get_users
user = $prompt.select("Pick a user", choices) user = $prompt.select("Pick a user", choices)
project.add_user(user) project.add_user(user.id)
puts "Added user #{user} to #{project}".colorize(:green) puts "Added user #{user} to #{project}".colorize(:green)
when :select when :select
choices = EmacsCollab.get_users choices = EmacsCollab.get_users
@ -99,7 +102,7 @@ def project_users(project)
defaults = [] defaults = []
counter = 1 counter = 1
choices.each do |u| choices.each do |u|
if project.users.include? u then if project.users.include? u.id then
defaults << counter defaults << counter
end end
counter += 1 counter += 1
@ -111,7 +114,7 @@ def project_users(project)
users = $prompt.multi_select("Select users", choices) users = $prompt.multi_select("Select users", choices)
end end
project.users = users project.users = users.map { |u| u.id }
project.flush project.flush
project.refresh project.refresh
end end