Add message file loading and validation

This commit is contained in:
Eric Budd 2018-01-24 01:01:56 -05:00
parent 4272f288a7
commit 8d784900dd
1 changed files with 60 additions and 7 deletions

67
iris.rb
View File

@ -2,12 +2,16 @@
#TODO: Validate author with file owner #TODO: Validate author with file owner
#TODO: Create struct to firm up message payload #TODO: Create struct to firm up message payload
#TODO: Common message file location for the security-concious?
#TODO: Check for proper file permissions on message file
#TODO: Use ENV for rows and cols of display?
require 'time' require 'time'
require 'base64' require 'base64'
require 'digest' require 'digest'
require 'socket' require 'socket'
require 'json' require 'json'
require 'etc'
class Config class Config
CONFIG_FILE = "#{ENV['HOME']}/.iris.config.json" CONFIG_FILE = "#{ENV['HOME']}/.iris.config.json"
@ -18,41 +22,90 @@ class Config
AUTHOR = "#{USER}@#{HOSTNAME}" AUTHOR = "#{USER}@#{HOSTNAME}"
def self.get(filepath = CONFIG_FILE) def self.get(filepath = CONFIG_FILE)
return @loaded_config if @loaded_config return @@loaded_config if @@loaded_config
if !File.exists?(filepath) if !File.exists?(filepath)
File.write(filepath, '{}') File.write(filepath, '{}')
return @loaded_config = {} return @@loaded_config = {}
end
return @@loaded_config = JSON.load(filepath)
end
def self.load_corpus
@@message_corpus ||= (`ls /home/**/.iris.config.json`).split("\n")
end
end
class IrisFile
def self.load_messages(filepath = Config::MESSAGE_FILE)
# TODO create file for current user
return [] unless File.exists?(filepath)
# TODO gracefully handle non-json files
payload = JSON.parse(File.read(filepath))
raise 'Invalid File!' unless payload.is_a?(Array)
uid = File.stat(filepath).uid
username = Etc.getpwuid(uid).name
p username
payload.map do |message_json|
new_message = Message.load(message_json)
new_message.validate_user(username)
new_message
end end
return @loaded_config = JSON.load(filepath)
end end
end end
class Message class Message
FILE_FORMAT = 'v2' FILE_FORMAT = 'v2'
attr_reader :timestamp, :hash, :edit_hash, :author, :parent, :message attr_reader :timestamp, :hash, :edit_hash, :author, :parent, :message, :errors
def initialize(message, author = Config::AUTHOR, parent = nil, timestamp = Time.now.utc.iso8601, edit_hash = nil) def initialize(message, author = Config::AUTHOR, parent = nil, timestamp = Time.now.utc.iso8601, edit_hash = nil)
@parent = parent @parent = parent
@author = author @author = author
@timestamp = timestamp @timestamp = timestamp
@message = message @message = message
@errors = []
end end
def self.load(payload) def self.load(payload)
data = JSON.parse(payload) data = payload if payload.is_a?(Hash)
# hash, edit_hash, timestamp, parent, author, *message = payload.split(FIELD_SEPARATOR) data = JSON.parse(payload) if payload.is_a?(String)
loaded_message = self.new(data['data']['message'], data['data']['author'], data['data']['parent'], data['data']['timestamp'], data['edit_hash']) loaded_message = self.new(data['data']['message'], data['data']['author'], data['data']['parent'], data['data']['timestamp'], data['edit_hash'])
raise 'Broken hash!' unless loaded_message.hash == data['hash'] loaded_message.validate_hash(data['hash'])
loaded_message loaded_message
end end
def validate_user(username)
@errors << 'Unvalidatable; could not parse username' if username.nil?
@errors << 'Unvalidatable; username is empty' if username.empty?
user_regex = Regexp.new("(.*)@#{Config::HOSTNAME}$")
author_name = user_regex.match(author)[1]
@errors << "Bad username: got #{author}'s message from #{username}'s message file." unless author_name == username
end
def validate_hash(test_hash)
if hash != test_hash
@errors << "Broken hash: expected '#{hash}', got '#{test_hash}'"
end
end
def valid?
@errors.empty?
end
def hash(payload = nil) def hash(payload = nil)
payload ||= unconfirmed_payload.to_json payload ||= unconfirmed_payload.to_json
Base64.encode64(Digest::SHA1.digest(payload)) Base64.encode64(Digest::SHA1.digest(payload))
end end
def is_topic?
parent.nil?
end
def to_json def to_json
{ {
hash: hash, hash: hash,