add file transfer feature and add more jwt functionality

This commit is contained in:
Joseph.Roy 2023-12-14 17:30:29 +00:00
parent 894b2af373
commit 29c8bb368f
6 changed files with 146 additions and 86 deletions

View File

@ -12,5 +12,7 @@ gem 'sqlite3'
gem 'bcrypt'
gem 'securerandom'
gem 'json'
gem 'multipart-post'
# bundle install

View File

@ -2,6 +2,7 @@
require_relative "initialize_database"
require_relative "database_queries"
require_relative "cryptography"
require_relative "tokens"
require 'sinatra'
@ -9,6 +10,10 @@ require 'json'
require 'sqlite3'
require 'jwt'
TOKEN_SECRET = 'WChX-tQWbGbj_pGJQREoFAZGC9JWh58KSk8O7KPj-P8Nd-J88g3eSFDVuNe6zddj0ZB3yxjm_IuPNPyLhiSnxlWHImqXR6ajh3OzrzYm0bNb3f5C4IAScphyEdAfYGMcM-HvYOXxxxp5u5mryfiV3JH1CTqL1CzGyO8df7zUpRKXEXZ5SKmUvhfLU0XKCR_28FAZUgPCAi3GywkDDsH0by68j33BU5cnMT8KiEkHOX4wVUVDQc85_AuE7fN3ji_WkhnDCSLXU9dBCcXM3ziFFeX0RbvIRDG0vKdzwt4TOr4Jws7NP9w11GrUGDFKARZqvT7FTxwxO3MM-mmjb2xyGg'
set :public_folder, DATA_LOCATION + FILE_STORAGE_LOCATION
#puts generate_random_string(256)
@ -68,11 +73,9 @@ post '/auth/reauthenticate' do
reauth_token = Regexp.last_match(1)
hmac_secret = 'WChX-tQWbGbj_pGJQREoFAZGC9JWh58KSk8O7KPj-P8Nd-J88g3eSFDVuNe6zddj0ZB3yxjm_IuPNPyLhiSnxlWHImqXR6ajh3OzrzYm0bNb3f5C4IAScphyEdAfYGMcM-HvYOXxxxp5u5mryfiV3JH1CTqL1CzGyO8df7zUpRKXEXZ5SKmUvhfLU0XKCR_28FAZUgPCAi3GywkDDsH0by68j33BU5cnMT8KiEkHOX4wVUVDQc85_AuE7fN3ji_WkhnDCSLXU9dBCcXM3ziFFeX0RbvIRDG0vKdzwt4TOr4Jws7NP9w11GrUGDFKARZqvT7FTxwxO3MM-mmjb2xyGg'
begin
# Verify the token using the secret key
decoded_token = JWT.decode(reauth_token, hmac_secret, true, algorithm: 'HS256')
decoded_token = JWT.decode(reauth_token, TOKEN_SECRET, true, algorithm: 'HS256')
# At this point, the token is valid
# You can access the claims inside the 'decoded_token' variable
@ -82,71 +85,47 @@ post '/auth/reauthenticate' do
# Your reauthentication logic here...
# Return a response (replace with your own logic)
{ reply: get_jwt(uid) }.to_json
{ jwt: get_jwt(uid) }.to_json
rescue JWT::DecodeError
status 401
return { reply: 'Unauthorized Access. Invalid token.' }.to_json
end
end
def get_reauth_jwt (user_id)
#claims = get_claims user_id
post '/upload' do
payload = {
sub: 'reauthentication' ,
admin: check_if_user_is_admin(user_id),
iss: 'roysathome.net',
uid: user_id, #Example id
iat: Time.now.to_i,
exp: Time.now.to_i + 3600
}
authorization_header = request.env['HTTP_AUTHORIZATION']
hmac_secret = 'WChX-tQWbGbj_pGJQREoFAZGC9JWh58KSk8O7KPj-P8Nd-J88g3eSFDVuNe6zddj0ZB3yxjm_IuPNPyLhiSnxlWHImqXR6ajh3OzrzYm0bNb3f5C4IAScphyEdAfYGMcM-HvYOXxxxp5u5mryfiV3JH1CTqL1CzGyO8df7zUpRKXEXZ5SKmUvhfLU0XKCR_28FAZUgPCAi3GywkDDsH0by68j33BU5cnMT8KiEkHOX4wVUVDQc85_AuE7fN3ji_WkhnDCSLXU9dBCcXM3ziFFeX0RbvIRDG0vKdzwt4TOr4Jws7NP9w11GrUGDFKARZqvT7FTxwxO3MM-mmjb2xyGg'
return JWT.encode payload, hmac_secret, 'HS256'
#data: {time: 'now', help: 'no'}.to_json
unless authorization_header && authorization_header.match(/^Bearer (.+)/)
status 401
return { reply: 'Unauthorized Access. Token missing or invalid.' }.to_json
end
def get_jwt (user_id)
claims = get_claims user_id
token = Regexp.last_match(1)
payload = {
sub: 'authentication' ,
admin: check_if_user_is_admin(user_id),
iss: 'roysathome.net',
uid: user_id, #Example id
iat: Time.now.to_i,
exp: Time.now.to_i + 60,
claims: claims
}
begin
# Verify the token using the secret key
decoded_token = JWT.decode(token, TOKEN_SECRET, true, algorithm: 'HS256')
hmac_secret = 'WChX-tQWbGbj_pGJQREoFAZGC9JWh58KSk8O7KPj-P8Nd-J88g3eSFDVuNe6zddj0ZB3yxjm_IuPNPyLhiSnxlWHImqXR6ajh3OzrzYm0bNb3f5C4IAScphyEdAfYGMcM-HvYOXxxxp5u5mryfiV3JH1CTqL1CzGyO8df7zUpRKXEXZ5SKmUvhfLU0XKCR_28FAZUgPCAi3GywkDDsH0by68j33BU5cnMT8KiEkHOX4wVUVDQc85_AuE7fN3ji_WkhnDCSLXU9dBCcXM3ziFFeX0RbvIRDG0vKdzwt4TOr4Jws7NP9w11GrUGDFKARZqvT7FTxwxO3MM-mmjb2xyGg'
return JWT.encode payload, hmac_secret, 'HS256'
unless decoded_token.first['claims'].include? 'is_machine'
status 401
return { reply: 'Unauthorized Access.' }.to_json
end
def get_claims (user_id)
puts "Getting claims for #{user_id}"
db = SQLite3::Database.new('./database/auth.db')
results = db.execute('
SELECT C.claim
FROM users U
INNER JOIN user_claims UC ON U.id = UC.user_id
INNER JOIN claims C ON UC.claim_id = U.id
WHERE u.id = ?
', user_id)
# Access the uploaded file through the params hash
file = params[:file]
claims_list = []
if results.empty?
puts 'No claims found.'
else
results.each do |column|
claim = column[0]
claims_list << claim
end
# Save the file to the 'uploads' folder
path = "#{DATA_LOCATION}#{FILE_STORAGE_LOCATION}/example.txt"
File.open(path, 'wb') do |f|
f.write(file[:tempfile].read)
end
return claims_list
"File uploaded successfully: #{file[:filename]}"
rescue JWT::DecodeError
status 401
return { reply: 'Unauthorized Access. Invalid token.' }.to_json
end
end
# Run the application

View File

@ -18,3 +18,4 @@ end
def generate_random_string(length)
SecureRandom.urlsafe_base64(length)
end

View File

@ -1,7 +1,12 @@
require 'sqlite3'
DATA_LOCATION = './data'
DATABASE_SUBPATH = '/database'
DATABASE_NAME = '/auth.db'
FILE_STORAGE_LOCATION = '/files'
def create_new_user(username, password, is_admin)
db = SQLite3::Database.new('./database/auth.db')
db = SQLite3::Database.new( DATA_LOCATION + DATABASE_SUBPATH + DATABASE_NAME )
db.execute('
INSERT INTO users (username, hashed_password, is_admin)
@ -10,7 +15,7 @@ def create_new_user(username, password, is_admin)
end
def check_if_user_exists(username)
db = SQLite3::Database.new('./database/auth.db')
db = SQLite3::Database.new( DATA_LOCATION + DATABASE_SUBPATH + DATABASE_NAME )
result = db.get_first_value('SELECT COUNT(*) FROM users WHERE username = ?', username.downcase)
@ -22,7 +27,7 @@ def check_if_user_exists(username)
end
def check_if_user_is_admin(user_id)
db = SQLite3::Database.new('./database/auth.db')
db = SQLite3::Database.new( DATA_LOCATION + DATABASE_SUBPATH + DATABASE_NAME )
result = db.get_first_value('SELECT is_admin FROM users WHERE id = ?', user_id)
@ -35,7 +40,7 @@ end
def get_user_id(username)
db = SQLite3::Database.new('./database/auth.db')
db = SQLite3::Database.new( DATA_LOCATION + DATABASE_SUBPATH + DATABASE_NAME )
user_id = db.get_first_value('
SELECT id
@ -48,7 +53,7 @@ def get_user_id(username)
end
def get_user_hashed_password(user_id)
db = SQLite3::Database.new('./database/auth.db')
db = SQLite3::Database.new( DATA_LOCATION + DATABASE_SUBPATH + DATABASE_NAME )
password_hash = db.get_first_value('
SELECT hashed_password
@ -61,7 +66,7 @@ def get_user_hashed_password(user_id)
end
def update_user_password(user_id, password)
db = SQLite3::Database.new('./database/auth.db')
db = SQLite3::Database.new( DATA_LOCATION + DATABASE_SUBPATH + DATABASE_NAME )
db.execute('
UPDATE users
@ -69,3 +74,29 @@ def update_user_password(user_id, password)
WHERE id = ?
', [hash_password, salt, user_id])
end
def get_claims (user_id)
puts "Getting claims for #{user_id}"
db = SQLite3::Database.new( DATA_LOCATION + DATABASE_SUBPATH + DATABASE_NAME )
results = db.execute('
SELECT C.claim
FROM users U
INNER JOIN user_claims UC ON U.id = UC.user_id
INNER JOIN claims C ON UC.claim_id = U.id
WHERE u.id = ?
', user_id)
claims_list = []
if results.empty?
puts 'No claims found.'
else
results.each do |column|
claim = column[0]
claims_list << claim
end
end
return claims_list
end

View File

@ -5,15 +5,25 @@ require 'sqlite3'
def initialize_database
puts 'Checking if database needs initializing.'
directory_path = './database'
database_path = DATA_LOCATION + DATABASE_SUBPATH
file_path = DATA_LOCATION + FILE_STORAGE_LOCATION
puts database_path
unless File.directory?(directory_path)
# If not, create the directory
Dir.mkdir(directory_path)
puts "Directory '#{directory_path}' created successfully."
unless File.directory?(DATA_LOCATION)
Dir.mkdir(DATA_LOCATION)
unless File.directory?(database_path)
Dir.mkdir(database_path)
puts "Directory '#{database_path}' created successfully."
end
db = SQLite3::Database.new('./database/auth.db')
unless File.directory?(file_path)
Dir.mkdir(file_path)
puts "Directory '#{file_path}' created successfully."
end
end
db = SQLite3::Database.new( DATA_LOCATION + DATABASE_SUBPATH + DATABASE_NAME )#'./database/auth.db')
puts 'Creating tables if necessary.'
db.execute('CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY, username TEXT, hashed_password TEXT, is_admin INTEGER)')

View File

@ -1,4 +1,5 @@
require 'net/http'
require 'net/http/post/multipart'
require 'uri'
require 'json'
@ -41,6 +42,7 @@ puts 'Reauthentication token stored.'
response_data = JSON.parse(response.body)
reauthentication_token = response_data['token']
#while true
url = URI.parse('http://localhost:4567/auth/reauthenticate')
request = Net::HTTP::Post.new(url.path)
@ -55,5 +57,40 @@ unless response.code == '200'
exit
end
#puts response.body
response_data = JSON.parse(response.body)
authentication_token = response_data['jwt']
#end
############# Do Files Test
#sleep(2)
# Read the file contents
file_content = File.read('./example.txt')
# Create a URI object for the API endpoint
uri = URI.parse('http://localhost:4567/upload')
# Create a Net::HTTP object
http = Net::HTTP.new(uri.host, uri.port)
request = Net::HTTP::Post::Multipart.new(
uri.path,
'file' => UploadIO.new(StringIO.new(file_content), 'application/octet-stream', 'example.txt')
)
request['Authorization'] = "Bearer #{authentication_token}"
# Send the request
puts "Sending file of size #{(File.size('./example.txt') / 2**20).round(2)} MB"
response = http.request(request)
#puts response.code
unless response.code == '200'
puts response.code
else
puts response.body
end