diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..85ffe74 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +bin/ + +*.db diff --git a/auth/Gemfile b/auth/Gemfile new file mode 100644 index 0000000..ede6601 --- /dev/null +++ b/auth/Gemfile @@ -0,0 +1,14 @@ +# Gemfile + +source "https://rubygems.org" + +ruby '3.2.2' +#ruby '2.6.10' + +gem 'sinatra' +gem 'webrick' +gem 'jwt' +gem 'sqlite3' +gem 'bcrypt' + +# bundle install \ No newline at end of file diff --git a/auth/Gemfile.lock b/auth/Gemfile.lock new file mode 100644 index 0000000..034e13d --- /dev/null +++ b/auth/Gemfile.lock @@ -0,0 +1,33 @@ +GEM + remote: https://rubygems.org/ + specs: + jwt (2.7.1) + mustermann (3.0.0) + ruby2_keywords (~> 0.0.1) + rack (2.2.8) + rack-protection (3.1.0) + rack (~> 2.2, >= 2.2.4) + ruby2_keywords (0.0.5) + sinatra (3.1.0) + mustermann (~> 3.0) + rack (~> 2.2, >= 2.2.4) + rack-protection (= 3.1.0) + tilt (~> 2.0) + sqlite3 (1.6.9-x64-mingw-ucrt) + tilt (2.3.0) + webrick (1.8.1) + +PLATFORMS + x64-mingw-ucrt + +DEPENDENCIES + jwt + sinatra + sqlite3 + webrick + +RUBY VERSION + ruby 3.2.2p53 + +BUNDLED WITH + 2.4.22 diff --git a/auth/README.md b/auth/README.md new file mode 100644 index 0000000..69c483c --- /dev/null +++ b/auth/README.md @@ -0,0 +1,7 @@ +Install dependancies + +gem install sinatra webrick +ruby ./auth -p 4567 + +To use the Gemfile: +bundle installd \ No newline at end of file diff --git a/auth/auth.rb b/auth/auth.rb new file mode 100644 index 0000000..fbd4d0f --- /dev/null +++ b/auth/auth.rb @@ -0,0 +1,67 @@ +# Install Sinatra: gem install sinatra +require_relative "initialize_database" +require_relative "database_queries" +require_relative "cryptography" + + +require 'sinatra' +require 'json' +require 'sqlite3' +require 'jwt' + +payload = { data: 'test', test: 'hello' } +hmac_secret = 'my$ecretK3y' +token = JWT.encode payload, hmac_secret, 'HS256' +#puts token + +decoded_token = JWT.decode token, hmac_secret, true, { algorithm: 'HS256' } +#puts decoded_token + +initialize_database + +post '/auth/login' do + content_type :json + + username = params[:username] + password = params[:password] + + user_id = get_user_id username + + unless check_password_for_user(user_id, password) + status 401 + + return { jwt: "Unuthorized Access" }.to_json + end + + { jwt: "Logged in" }.to_json +end + +def get_jwt (username, expiry_time) + get_claims username +end + +def get_claims (username) + puts "Getting claims for #{username}" + 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.username = ? + ', username) + + + if results.empty? + puts 'No claims found.' + else + results.each do |column| + puts "#{column[0]}" + end + end + + return results +end + +# Run the application +# ruby your_file_name.rb diff --git a/auth/cryptography.rb b/auth/cryptography.rb new file mode 100644 index 0000000..e3f87db --- /dev/null +++ b/auth/cryptography.rb @@ -0,0 +1,15 @@ +require 'bcrypt' + +def create_password_for_user(password) + return BCrypt::Password.create(password) +end + +def check_password_for_user(user_id, entered_password) + hashed_password = get_user_hashed_password(user_id) + + if BCrypt::Password.new(hashed_password) == entered_password + return true + else + return false + end +end \ No newline at end of file diff --git a/auth/database_queries.rb b/auth/database_queries.rb new file mode 100644 index 0000000..19ea04e --- /dev/null +++ b/auth/database_queries.rb @@ -0,0 +1,49 @@ +require 'sqlite3' + + +def create_new_user(username, password) + db = SQLite3::Database.new('./database/auth.db') + + db.execute(' + INSERT INTO users (username, hashed_password) + VALUES (?, ?) + ', [username, create_password_for_user(password)]) +end + + + +def get_user_id(username) + db = SQLite3::Database.new('./database/auth.db') + + user_id = db.get_first_value(' + SELECT id + FROM users U + WHERE U.username = ? + + ', [username]) + + return user_id +end + +def get_user_hashed_password(user_id) + db = SQLite3::Database.new('./database/auth.db') + + password_hash = db.get_first_value(' + SELECT hashed_password + FROM users U + WHERE U.id = ? + + ', [user_id]) + + return password_hash +end + +def update_user_password(user_id, password) + db = SQLite3::Database.new('./database/auth.db') + + db.execute(' + UPDATE users + SET hashed_password = ?, salt = ? + WHERE id = ? + ', [hash_password, salt, user_id]) +end \ No newline at end of file diff --git a/auth/docker_compose.yml b/auth/docker_compose.yml new file mode 100644 index 0000000..2f75842 --- /dev/null +++ b/auth/docker_compose.yml @@ -0,0 +1,12 @@ +version: "3" + +services: + app: + build: + context: . + dockerfile: Dockerfile + ports: + - "4567:4567" + volumes: + - ./auth:/app # Adjust the path accordingly + command: ["./auth.rb"] diff --git a/auth/dockerfile b/auth/dockerfile new file mode 100644 index 0000000..d93b2ba --- /dev/null +++ b/auth/dockerfile @@ -0,0 +1,22 @@ +# Stage 1: Build stage with git +FROM ubuntu:jammy AS GITCOPY + +WORKDIR /roysathome + +RUN apt-get update && apt-get install -y git + +RUN git clone https://git.roysathome.net/joseph/roysathome.net.git . + +# Stage 2: Final image with Ruby +FROM ruby:3.2.2 + +# Copy files from the first stage +COPY --from=GITCOPY /roysathome/auth /app + +WORKDIR /app + +# Gemfile and Gemfile.lock are already in /usr/src/app/roysathome/auth due to the previous COPY command + +RUN bundle install + +CMD ["./auth.rb"] diff --git a/auth/initialize_database.rb b/auth/initialize_database.rb new file mode 100644 index 0000000..63c9c89 --- /dev/null +++ b/auth/initialize_database.rb @@ -0,0 +1,49 @@ +require_relative "cryptography" + +require 'sqlite3' + +def initialize_database + puts 'Checking if database needs initializing.' + + directory_path = './database' + + unless File.directory?(directory_path) + # If not, create the directory + Dir.mkdir(directory_path) + puts "Directory '#{directory_path}' created successfully." + end + + db = SQLite3::Database.new('./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, salt TEXT)') + db.execute('CREATE TABLE IF NOT EXISTS claims (id INTEGER PRIMARY KEY, claim TEXT)') + db.execute('CREATE TABLE IF NOT EXISTS user_claims (id INTEGER PRIMARY KEY, user_id INTEGER, claim_id INTEGER)') + + result = db.get_first_value('SELECT COUNT(*) FROM users') + + if result == 0 + puts 'Default admin user added.' + + create_new_user('admin', 'pass123') + else + puts 'Table already contains data. Skipping default user creation.' + end + + result = db.get_first_value('SELECT COUNT(*) FROM claims') + + if result == 0 + db.execute('INSERT INTO claims (claim) VALUES (?)', ['add_user']) + db.execute('INSERT INTO claims (claim) VALUES (?)', ['remove_user']) + db.execute('INSERT INTO claims (claim) VALUES (?)', ['add_claim_to_user']) + db.execute('INSERT INTO claims (claim) VALUES (?)', ['remove_claim_from_user']) + end + + admin_user_id = db.get_first_value('SELECT id FROM users WHERE username = ?', ['admin']) + claim_ids = db.execute('SELECT id FROM claims') + + claim_ids.each do |claim_id| + db.execute('INSERT INTO user_claims (user_id, claim_id) VALUES (?, ?)', [admin_user_id, claim_id]) + end +end + diff --git a/auth/post.rb b/auth/post.rb new file mode 100644 index 0000000..9391862 --- /dev/null +++ b/auth/post.rb @@ -0,0 +1,27 @@ +require 'net/http' +require 'uri' + +# The URL you want to send the POST request to +url = URI.parse('http://localhost:4567/auth/login') + +# Create a new Net::HTTP object with the target server +http = Net::HTTP.new(url.host, url.port) + +# If your server uses HTTPS, you might need to enable SSL +# http.use_ssl = true + +# Create a new Net::HTTP::Post request with the desired path +request = Net::HTTP::Post.new(url.path) + +# Set the request body with the data you want to send +request.body = 'username=admin&password=pass1re23' + +# Set the 'Content-Type' header if needed +request['Content-Type'] = 'application/x-www-form-urlencoded' + +# Send the request and get the response +response = http.request(request) + +# Output the response +puts "Response Code: #{response.code}" +puts "Response Body: #{response.body}"