From 06eb99c84a2a29b84edefaa2e3a9aaa7b2d887ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoffer=20M=C3=BCller=20Madsen?= Date: Thu, 15 Jun 2017 02:20:13 +0200 Subject: [PATCH] SQLite integration should be complete now --- Gemfile | 1 - docker/Dockerfile | 6 +-- docker/build.sh | 1 + init_sql_db.sql | 8 ++-- lib/emacscollab/collab.rb | 20 +++++++--- lib/emacscollab/database/sqlite.rb | 63 +++++++++++++++++++++++++++--- lib/emacscollab/project.rb | 32 +++++++-------- lib/emacscollab/user.rb | 23 +++-------- prompt.rb | 19 +++++---- 9 files changed, 111 insertions(+), 62 deletions(-) diff --git a/Gemfile b/Gemfile index 43a2066..eb04a96 100644 --- a/Gemfile +++ b/Gemfile @@ -1,5 +1,4 @@ source 'https://rubygems.org' -gem 'fileutils' gem 'tty-prompt' gem 'colorize' gem 'sqlite3' diff --git a/docker/Dockerfile b/docker/Dockerfile index 75f830d..9534a1a 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -1,9 +1,9 @@ FROM ubuntu:xenial RUN apt-get update -RUN apt-get install -y emacs-nox ruby openssh-server -RUN apt-get install -y build-essential libsqlite3-dev sqlite3 -RUN gem install tty-prompt colorize +RUN apt-get install -y emacs-nox openssh-server +RUN apt-get install -y ruby ruby-dev build-essential libsqlite3-dev sqlite3 +RUN gem install bundler RUN mkdir /var/run/sshd # SSH login fix. Otherwise user is kicked off after login diff --git a/docker/build.sh b/docker/build.sh index e59ae48..3e984dd 100755 --- a/docker/build.sh +++ b/docker/build.sh @@ -1,3 +1,4 @@ #!/bin/sh cp ../eshell ./ +cp ../Gemfile* ./ docker build -t emacs-collab:latest . diff --git a/init_sql_db.sql b/init_sql_db.sql index 7035e57..cf170dd 100644 --- a/init_sql_db.sql +++ b/init_sql_db.sql @@ -10,9 +10,11 @@ CREATE TABLE Users ( ); CREATE TABLE Projects ( - uid INT NOT NULL, - name VARCHAR (24) NOT NULL, - owner VARCHAR (24) NOT NULL, + uid INT NOT NULL, + name VARCHAR (24) NOT NULL, + path VARCHAR (255) NOT NULL, + posixname VARCHAR (32) NOT NULL, + owner VARCHAR (1024), users VARCHAR (8192), PRIMARY KEY (uid), diff --git a/lib/emacscollab/collab.rb b/lib/emacscollab/collab.rb index 82b3d00..a273705 100644 --- a/lib/emacscollab/collab.rb +++ b/lib/emacscollab/collab.rb @@ -6,7 +6,7 @@ require_relative 'sshkey' POSIX_NAME_PREFIX = "emacs" USER_LOCATION = "./users/" -DATA_PATH = "/home/christoffermadsen/git/emacs-collab/data" +DATA_PATH = "./data" require_relative 'database/sqlite' @@ -65,13 +65,20 @@ module EmacsCollab $db.get_project(id) end + def self.get_projects + $db.get_projects + end + def self.add_project(project) $db.add_project(project) end def self.create_project(id) - if get_project(id) then - raise DuplicateProjectError, "Project with id #{id} already exists" + begin + if get_project(id) then + raise DuplicateProjectError, "Project with id #{id} already exists" + end + rescue EmacsCollab::ProjectNotFoundError => e end if not system("useradd -m #{POSIX_NAME_PREFIX}#{id} -s /usr/bin/eshell") then @@ -82,6 +89,7 @@ module EmacsCollab project.id = id project.path = "/home/#{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.touch "#{project.path}/.ssh/authorized_keys" @@ -169,9 +177,9 @@ module EmacsCollab end def self.flush_projects_with_user(user) - $projects.select{|p| p.users.include? user}.each do |p| - p.flush - end + #$projects.select{|p| p.users.include? user}.each do |p| + # p.flush + #end end ################################################ diff --git a/lib/emacscollab/database/sqlite.rb b/lib/emacscollab/database/sqlite.rb index 5aa432a..d57b6c8 100644 --- a/lib/emacscollab/database/sqlite.rb +++ b/lib/emacscollab/database/sqlite.rb @@ -14,7 +14,6 @@ module EmacsCollab end def get_user(id) - # TODO row = @db.execute("SELECT * FROM Users WHERE name = ?", [id])[0] unless row raise UserNotFoundError, "User with id #{id} could not be found in database" @@ -23,19 +22,19 @@ module EmacsCollab user = User.new(row[0]) user.pw_hash = row[1] 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 end 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.pw_hash = row[1] 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 end end @@ -49,11 +48,63 @@ module EmacsCollab @db.execute("UPDATE Users SET keys = ? WHERE name = ?", [JSON.generate(user.keys),user.id]) end - + def change_user_password(user,hash,salt) @db.execute("UPDATE Users SET passwd = ?, salt = ? WHERE name = ?", [hash,salt,user.id]) 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 diff --git a/lib/emacscollab/project.rb b/lib/emacscollab/project.rb index 9e4c7ae..85203a0 100644 --- a/lib/emacscollab/project.rb +++ b/lib/emacscollab/project.rb @@ -1,10 +1,11 @@ module EmacsCollab class Project - attr_accessor :id, :path, :posixname, :users + attr_accessor :uid, :id, :path, :posixname, :users, :owner attr_reader :keys def initialize @users = [] + @keys = [] end def to_s @@ -17,36 +18,30 @@ module EmacsCollab def add_user(user) @users << user - user.keys.each do |key| - add_key(key) - end + # TODO: Remove the following comments + #user.keys.each do |key| + # add_key(key) + #end flush - refresh end def remove_user(user) @user.delete(user) + # TODO Make sure to remove the key of the user flush refresh end 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 def flush - File.open("#{@path}/.ssh/users","w+") do |user_file| - @users.each do |u| - user_file << "#{u.id}\n" - end - end - - get_ssh_keyfile(self,"w+") do |key_file| + $db.update_project(self) + + EmacsCollab.get_ssh_keyfile(self,"w+") do |key_file| @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" end end @@ -58,4 +53,7 @@ module EmacsCollab class DuplicateProjectError < StandardError end + class ProjectNotFoundError < StandardError + end + end diff --git a/lib/emacscollab/user.rb b/lib/emacscollab/user.rb index 32d60f2..31b290f 100644 --- a/lib/emacscollab/user.rb +++ b/lib/emacscollab/user.rb @@ -10,11 +10,10 @@ module EmacsCollab def initialize(id) @id = id @keypath = "#{USER_LOCATION}#{id}" - refresh_keys end def add_key_from_string(keystring) - unless valid_pubkey? keystring + unless EmacsCollab.valid_pubkey? keystring raise InvalidSSHPubKey, "Public key not valid" end ks = keystring.split(" "); @@ -25,31 +24,19 @@ module EmacsCollab else raise DuplicateSSHPubKey, "Public key is already added to user" end - + p self flush - refresh_keys - flush_projects_with_user(self) + EmacsCollab.flush_projects_with_user(self) end def remove_key(key) @keys.delete(key) flush - refresh_keys - 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 + EmacsCollab.flush_projects_with_user(self) end def flush - File.open(@keypath,"w+") do |key_file| - @keys.each do |key| - key_file << "#{key.to_s}\n" - end - end + $db.update_user(self) end end diff --git a/prompt.rb b/prompt.rb index b659751..2519f16 100644 --- a/prompt.rb +++ b/prompt.rb @@ -2,6 +2,9 @@ require_relative 'lib/emacscollab' require 'tty-prompt' require 'colorize' +require_relative 'lib/emacscollab/collab' +require_relative 'lib/emacscollab/sshkey' + $prompt = TTY::Prompt.new $login = "root" @@ -34,10 +37,10 @@ def keys_user(user) key = $prompt.ask("Please enter a valid public SSH key", echo: false) begin user.add_key_from_string(key) - rescue InvalidSSHPubKey => e + rescue EmacsCollab::InvalidSSHPubKey => e puts e.message.colorize(:red) keys_user(user) - rescue DuplicateSSHPubKey => e + rescue EmacsCollab::DuplicateSSHPubKey => e puts e.message.colorize(:red) keys_user(user) end @@ -67,8 +70,8 @@ def project_create input.validate /\A\w+\Z/ end begin - create_project(id) - rescue DuplicateProjectError => e + EmacsCollab.create_project(id) + rescue EmacsCollab::DuplicateProjectError => e puts e.message.colorize(:red) projects end @@ -77,7 +80,7 @@ end def project_modify # 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 def project_users(project) @@ -90,7 +93,7 @@ def project_users(project) when :add choices = EmacsCollab.get_users user = $prompt.select("Pick a user", choices) - project.add_user(user) + project.add_user(user.id) puts "Added user #{user} to #{project}".colorize(:green) when :select choices = EmacsCollab.get_users @@ -99,7 +102,7 @@ def project_users(project) defaults = [] counter = 1 choices.each do |u| - if project.users.include? u then + if project.users.include? u.id then defaults << counter end counter += 1 @@ -111,7 +114,7 @@ def project_users(project) users = $prompt.multi_select("Select users", choices) end - project.users = users + project.users = users.map { |u| u.id } project.flush project.refresh end