add file transfer feature and add more jwt functionality
This commit is contained in:
parent
894b2af373
commit
29c8bb368f
|
@ -12,5 +12,7 @@ gem 'sqlite3'
|
||||||
gem 'bcrypt'
|
gem 'bcrypt'
|
||||||
gem 'securerandom'
|
gem 'securerandom'
|
||||||
gem 'json'
|
gem 'json'
|
||||||
|
gem 'multipart-post'
|
||||||
|
|
||||||
|
|
||||||
# bundle install
|
# bundle install
|
95
auth/auth.rb
95
auth/auth.rb
|
@ -2,6 +2,7 @@
|
||||||
require_relative "initialize_database"
|
require_relative "initialize_database"
|
||||||
require_relative "database_queries"
|
require_relative "database_queries"
|
||||||
require_relative "cryptography"
|
require_relative "cryptography"
|
||||||
|
require_relative "tokens"
|
||||||
|
|
||||||
|
|
||||||
require 'sinatra'
|
require 'sinatra'
|
||||||
|
@ -9,6 +10,10 @@ require 'json'
|
||||||
require 'sqlite3'
|
require 'sqlite3'
|
||||||
require 'jwt'
|
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)
|
#puts generate_random_string(256)
|
||||||
|
|
||||||
|
|
||||||
|
@ -68,11 +73,9 @@ post '/auth/reauthenticate' do
|
||||||
|
|
||||||
reauth_token = Regexp.last_match(1)
|
reauth_token = Regexp.last_match(1)
|
||||||
|
|
||||||
hmac_secret = 'WChX-tQWbGbj_pGJQREoFAZGC9JWh58KSk8O7KPj-P8Nd-J88g3eSFDVuNe6zddj0ZB3yxjm_IuPNPyLhiSnxlWHImqXR6ajh3OzrzYm0bNb3f5C4IAScphyEdAfYGMcM-HvYOXxxxp5u5mryfiV3JH1CTqL1CzGyO8df7zUpRKXEXZ5SKmUvhfLU0XKCR_28FAZUgPCAi3GywkDDsH0by68j33BU5cnMT8KiEkHOX4wVUVDQc85_AuE7fN3ji_WkhnDCSLXU9dBCcXM3ziFFeX0RbvIRDG0vKdzwt4TOr4Jws7NP9w11GrUGDFKARZqvT7FTxwxO3MM-mmjb2xyGg'
|
|
||||||
|
|
||||||
begin
|
begin
|
||||||
# Verify the token using the secret key
|
# 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
|
# At this point, the token is valid
|
||||||
# You can access the claims inside the 'decoded_token' variable
|
# You can access the claims inside the 'decoded_token' variable
|
||||||
|
@ -82,71 +85,47 @@ post '/auth/reauthenticate' do
|
||||||
# Your reauthentication logic here...
|
# Your reauthentication logic here...
|
||||||
|
|
||||||
# Return a response (replace with your own logic)
|
# Return a response (replace with your own logic)
|
||||||
{ reply: get_jwt(uid) }.to_json
|
{ jwt: get_jwt(uid) }.to_json
|
||||||
rescue JWT::DecodeError
|
rescue JWT::DecodeError
|
||||||
status 401
|
status 401
|
||||||
return { reply: 'Unauthorized Access. Invalid token.' }.to_json
|
return { reply: 'Unauthorized Access. Invalid token.' }.to_json
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def get_reauth_jwt (user_id)
|
post '/upload' do
|
||||||
#claims = get_claims user_id
|
|
||||||
|
|
||||||
payload = {
|
authorization_header = request.env['HTTP_AUTHORIZATION']
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
hmac_secret = 'WChX-tQWbGbj_pGJQREoFAZGC9JWh58KSk8O7KPj-P8Nd-J88g3eSFDVuNe6zddj0ZB3yxjm_IuPNPyLhiSnxlWHImqXR6ajh3OzrzYm0bNb3f5C4IAScphyEdAfYGMcM-HvYOXxxxp5u5mryfiV3JH1CTqL1CzGyO8df7zUpRKXEXZ5SKmUvhfLU0XKCR_28FAZUgPCAi3GywkDDsH0by68j33BU5cnMT8KiEkHOX4wVUVDQc85_AuE7fN3ji_WkhnDCSLXU9dBCcXM3ziFFeX0RbvIRDG0vKdzwt4TOr4Jws7NP9w11GrUGDFKARZqvT7FTxwxO3MM-mmjb2xyGg'
|
unless authorization_header && authorization_header.match(/^Bearer (.+)/)
|
||||||
return JWT.encode payload, hmac_secret, 'HS256'
|
status 401
|
||||||
#data: {time: 'now', help: 'no'}.to_json
|
return { reply: 'Unauthorized Access. Token missing or invalid.' }.to_json
|
||||||
end
|
|
||||||
|
|
||||||
def get_jwt (user_id)
|
|
||||||
claims = get_claims user_id
|
|
||||||
|
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
hmac_secret = 'WChX-tQWbGbj_pGJQREoFAZGC9JWh58KSk8O7KPj-P8Nd-J88g3eSFDVuNe6zddj0ZB3yxjm_IuPNPyLhiSnxlWHImqXR6ajh3OzrzYm0bNb3f5C4IAScphyEdAfYGMcM-HvYOXxxxp5u5mryfiV3JH1CTqL1CzGyO8df7zUpRKXEXZ5SKmUvhfLU0XKCR_28FAZUgPCAi3GywkDDsH0by68j33BU5cnMT8KiEkHOX4wVUVDQc85_AuE7fN3ji_WkhnDCSLXU9dBCcXM3ziFFeX0RbvIRDG0vKdzwt4TOr4Jws7NP9w11GrUGDFKARZqvT7FTxwxO3MM-mmjb2xyGg'
|
|
||||||
return JWT.encode payload, hmac_secret, 'HS256'
|
|
||||||
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)
|
|
||||||
|
|
||||||
|
|
||||||
claims_list = []
|
|
||||||
|
|
||||||
if results.empty?
|
|
||||||
puts 'No claims found.'
|
|
||||||
else
|
|
||||||
results.each do |column|
|
|
||||||
claim = column[0]
|
|
||||||
claims_list << claim
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
return claims_list
|
token = Regexp.last_match(1)
|
||||||
|
|
||||||
|
begin
|
||||||
|
# Verify the token using the secret key
|
||||||
|
decoded_token = JWT.decode(token, TOKEN_SECRET, true, algorithm: 'HS256')
|
||||||
|
|
||||||
|
unless decoded_token.first['claims'].include? 'is_machine'
|
||||||
|
status 401
|
||||||
|
return { reply: 'Unauthorized Access.' }.to_json
|
||||||
|
end
|
||||||
|
|
||||||
|
# Access the uploaded file through the params hash
|
||||||
|
file = params[:file]
|
||||||
|
|
||||||
|
# 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
|
||||||
|
|
||||||
|
"File uploaded successfully: #{file[:filename]}"
|
||||||
|
rescue JWT::DecodeError
|
||||||
|
status 401
|
||||||
|
return { reply: 'Unauthorized Access. Invalid token.' }.to_json
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Run the application
|
# Run the application
|
||||||
|
|
|
@ -17,4 +17,5 @@ end
|
||||||
|
|
||||||
def generate_random_string(length)
|
def generate_random_string(length)
|
||||||
SecureRandom.urlsafe_base64(length)
|
SecureRandom.urlsafe_base64(length)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,12 @@
|
||||||
require 'sqlite3'
|
require 'sqlite3'
|
||||||
|
|
||||||
|
DATA_LOCATION = './data'
|
||||||
|
DATABASE_SUBPATH = '/database'
|
||||||
|
DATABASE_NAME = '/auth.db'
|
||||||
|
FILE_STORAGE_LOCATION = '/files'
|
||||||
|
|
||||||
def create_new_user(username, password, is_admin)
|
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('
|
db.execute('
|
||||||
INSERT INTO users (username, hashed_password, is_admin)
|
INSERT INTO users (username, hashed_password, is_admin)
|
||||||
|
@ -10,7 +15,7 @@ def create_new_user(username, password, is_admin)
|
||||||
end
|
end
|
||||||
|
|
||||||
def check_if_user_exists(username)
|
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)
|
result = db.get_first_value('SELECT COUNT(*) FROM users WHERE username = ?', username.downcase)
|
||||||
|
|
||||||
|
@ -22,7 +27,7 @@ def check_if_user_exists(username)
|
||||||
end
|
end
|
||||||
|
|
||||||
def check_if_user_is_admin(user_id)
|
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)
|
result = db.get_first_value('SELECT is_admin FROM users WHERE id = ?', user_id)
|
||||||
|
|
||||||
|
@ -35,7 +40,7 @@ end
|
||||||
|
|
||||||
|
|
||||||
def get_user_id(username)
|
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('
|
user_id = db.get_first_value('
|
||||||
SELECT id
|
SELECT id
|
||||||
|
@ -48,7 +53,7 @@ def get_user_id(username)
|
||||||
end
|
end
|
||||||
|
|
||||||
def get_user_hashed_password(user_id)
|
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('
|
password_hash = db.get_first_value('
|
||||||
SELECT hashed_password
|
SELECT hashed_password
|
||||||
|
@ -61,7 +66,7 @@ def get_user_hashed_password(user_id)
|
||||||
end
|
end
|
||||||
|
|
||||||
def update_user_password(user_id, password)
|
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('
|
db.execute('
|
||||||
UPDATE users
|
UPDATE users
|
||||||
|
@ -69,3 +74,29 @@ def update_user_password(user_id, password)
|
||||||
WHERE id = ?
|
WHERE id = ?
|
||||||
', [hash_password, salt, user_id])
|
', [hash_password, salt, user_id])
|
||||||
end
|
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
|
|
@ -5,15 +5,25 @@ require 'sqlite3'
|
||||||
def initialize_database
|
def initialize_database
|
||||||
puts 'Checking if database needs initializing.'
|
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)
|
unless File.directory?(DATA_LOCATION)
|
||||||
# If not, create the directory
|
Dir.mkdir(DATA_LOCATION)
|
||||||
Dir.mkdir(directory_path)
|
|
||||||
puts "Directory '#{directory_path}' created successfully."
|
unless File.directory?(database_path)
|
||||||
|
Dir.mkdir(database_path)
|
||||||
|
puts "Directory '#{database_path}' created successfully."
|
||||||
|
end
|
||||||
|
|
||||||
|
unless File.directory?(file_path)
|
||||||
|
Dir.mkdir(file_path)
|
||||||
|
puts "Directory '#{file_path}' created successfully."
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
db = SQLite3::Database.new('./database/auth.db')
|
db = SQLite3::Database.new( DATA_LOCATION + DATABASE_SUBPATH + DATABASE_NAME )#'./database/auth.db')
|
||||||
|
|
||||||
puts 'Creating tables if necessary.'
|
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)')
|
db.execute('CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY, username TEXT, hashed_password TEXT, is_admin INTEGER)')
|
||||||
|
|
57
auth/post.rb
57
auth/post.rb
|
@ -1,4 +1,5 @@
|
||||||
require 'net/http'
|
require 'net/http'
|
||||||
|
require 'net/http/post/multipart'
|
||||||
require 'uri'
|
require 'uri'
|
||||||
require 'json'
|
require 'json'
|
||||||
|
|
||||||
|
@ -41,19 +42,55 @@ puts 'Reauthentication token stored.'
|
||||||
response_data = JSON.parse(response.body)
|
response_data = JSON.parse(response.body)
|
||||||
reauthentication_token = response_data['token']
|
reauthentication_token = response_data['token']
|
||||||
|
|
||||||
url = URI.parse('http://localhost:4567/auth/reauthenticate')
|
#while true
|
||||||
request = Net::HTTP::Post.new(url.path)
|
url = URI.parse('http://localhost:4567/auth/reauthenticate')
|
||||||
|
request = Net::HTTP::Post.new(url.path)
|
||||||
|
|
||||||
request['Authorization'] = "Bearer #{reauthentication_token}"
|
request['Authorization'] = "Bearer #{reauthentication_token}"
|
||||||
|
|
||||||
|
response = http.request(request)
|
||||||
|
|
||||||
|
unless response.code == '200'
|
||||||
|
puts "Response Code: #{response.code}. Aborting."
|
||||||
|
puts "Response Body: #{response.body}"
|
||||||
|
puts "Aborting."
|
||||||
|
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)
|
response = http.request(request)
|
||||||
|
|
||||||
|
#puts response.code
|
||||||
|
|
||||||
unless response.code == '200'
|
unless response.code == '200'
|
||||||
puts "Response Code: #{response.code}. Aborting."
|
puts response.code
|
||||||
puts "Response Body: #{response.body}"
|
else
|
||||||
puts "Aborting."
|
puts response.body
|
||||||
exit
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
puts response.body
|
|
||||||
|
|
Loading…
Reference in New Issue