Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
120 changes: 120 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
name: Release Ruby Connector

on:
push:
branches:
- main

jobs:
create-release:
name: Create GitHub Release
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Extract SDK version from Ruby file
id: extract_version
run: |
# Extract SDK version from Ruby file
SDK_VERSION=$(ruby -e "
require './lib/queueit_knownuserv3/user_in_queue_service'
puts QueueIt::UserInQueueService::SDK_VERSION_NO
")

if [ -z \"$SDK_VERSION\" ]; then
echo \"Error: Could not extract SDK version.\"
exit 1
fi

# Generate a build suffix with date + commit SHA short
BUILD_DATE=$(date +%Y%m%d)
SHORT_SHA=$(echo $GITHUB_SHA | cut -c1-7)
BUILD_SUFFIX=\"$BUILD_DATE-$SHORT_SHA\"

echo "SDK_VERSION=$SDK_VERSION" >> $GITHUB_ENV
echo "BUILD_SUFFIX=$BUILD_SUFFIX" >> $GITHUB_ENV
echo "VERSION_TAG=$SDK_VERSION" >> $GITHUB_ENV

echo "Extracted SDK Version: $SDK_VERSION"
echo "Build Suffix: $BUILD_SUFFIX"
echo "Full Tag: $SDK_VERSION-$BUILD_SUFFIX"

# Find the PR associated with this commit (merge, squash or rebase)
- name: Get PR for this commit
id: pr
uses: actions/github-script@v7
with:
script: |
const {owner, repo} = context.repo;
const sha = context.sha;
// REST: list PRs associated with a commit
const res = await github.request('GET /repos/{owner}/{repo}/commits/{ref}/pulls', {
owner, repo, ref: sha,
headers: { accept: 'application/vnd.github+json' }
});

if (!res.data.length) {
core.notice('No PR associated with this commit. Falling back to default body.');
core.setOutput('number', '');
core.setOutput('title', '');
core.setOutput('body', '');
} else {
// If multiple, grab the first (usually the relevant one for the head commit)
const pr = res.data[0];
core.setOutput('number', String(pr.number));
core.setOutput('title', pr.title ?? '');
core.setOutput('body', pr.body ?? '');
}

# Prepare PR body for release notes
- name: Write PR body to file
run: |
cat <<'EOF' > pr_body.md
${{ steps.pr.outputs.body }}
EOF

- name: Create release asset archive
run: |
mkdir -p release-assets
tar -czf "release-assets/ruby-connector-${{ env.VERSION_TAG }}.tar.gz" \
lib/ \
test/ \
bin/ \
*.gemspec \
Gemfile \
Rakefile \
README.md \
license.txt

- name: Show debug release variables
run: |
echo "SDK_VERSION: ${{ env.SDK_VERSION }}"
echo "BUILD_SUFFIX: ${{ env.BUILD_SUFFIX }}"
echo "VERSION_TAG: ${{ env.VERSION_TAG }}"
echo "PR_NUMBER: ${{ steps.pr.outputs.number }}"
echo "PR_TITLE: ${{ steps.pr.outputs.title }}"
echo "RELEASE_NAME: ${{ env.RELEASE_NAME }}"
echo "Asset path: release-assets/ruby-connector-${{ env.VERSION_TAG }}.tar.gz"

- name: Create Git tag
run: |
git config user.name "$QUEUEIT_GITHUB_NAME"
git config user.email "$QUEUEIT_GITHUB_EMAIL"
git tag "${{ env.VERSION_TAG }}"
git push origin "${{ env.VERSION_TAG }}"

- name: Create GitHub Release
uses: softprops/action-gh-release@v2
with:
tag_name: ${{ env.VERSION_TAG }}
name: ${{ env.VERSION_TAG }}
body_path: pr_body.md
files: release-assets/ruby-connector-${{ env.VERSION_TAG }}.tar.gz

- name: Display release links
run: |
echo "Release creation completed. Check:"
echo "- Tags: https://github.com/${{ github.repository }}/tags"
echo "- Releases: https://github.com/${{ github.repository }}/releases"
echo "- Latest Release: https://github.com/${{ github.repository }}/releases/tag/${{ env.VERSION_TAG }}"
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
################################################################################
# This .gitignore file was automatically created by Microsoft(R) Visual Studio.
################################################################################

/.vs
33 changes: 19 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# KnownUser.V3.RubyOnRails
Before getting started please read the [documentation](https://github.com/queueit/Documentation/tree/main/serverside-connectors) to get acquainted with server-side connectors.

This connector supports Ruby v.1.9.3+ and Rails v.3.2+.
This connector supports Ruby v.3.4+ and Rails v.5.0.5+.

## Installation
Queue-it KnownUser V3 is distributed as a gem, which is how it should be used in your app.
Expand Down Expand Up @@ -40,18 +40,18 @@ class ResourceController < ApplicationController
#requestUriNoToken.host = "INSERT-REPLACEMENT-HOST-HERE"
#requestUrlWithoutToken = requestUriNoToken.to_s

queueitToken = request.query_parameters[QueueIt::KnownUser::QUEUEIT_TOKEN_KEY.to_sym]
queueitToken = QueueIt::Utils::getParameterByName(requestUrl, QueueIt::KnownUser::QUEUEIT_TOKEN_KEY)

# Initialize the SDK with the rails http context (must be done before calling validateRequestByIntegrationConfig)
QueueIt::HttpContextProvider::setHttpContext(QueueIt::RailsHttpContext.new(request))
httpContextProvider = QueueIt::HttpContextProvider.new(QueueIt::RailsHttpContext.new(request))

# Verify if the user has been through the queue
validationResult = QueueIt::KnownUser.validateRequestByIntegrationConfig(
requestUrlWithoutToken,
queueitToken,
configJson,
customerId,
secretKey)
secretKey,
httpContextProvider)

if(validationResult.doRedirect)
#Adding no cache headers to prevent browsers to cache requests
Expand All @@ -63,19 +63,21 @@ class ResourceController < ApplicationController
if(!validationResult.isAjaxResult)
# Send the user to the queue - either becuase hash was missing or becuase is was invalid
redirect_to validationResult.redirectUrl
return
else
head :ok
ajaxQueueRedirectHeaderName = validationResult.getAjaxQueueRedirectHeaderKey()
response.headers[ajaxQueueRedirectHeaderName] = validationResult.getAjaxRedirectUrl()
response.headers["Access-Control-Expose-Headers"] = ajaxQueueRedirectHeaderName
head :ok
return
end
else
# Request can continue, we remove queueittoken from url to avoid sharing of user specific token
if(requestUrl != requestUrlWithoutToken && validationResult.actionType == "Queue")
redirect_to requestUrlWithoutToken
return
end
end

rescue StandardError => stdErr
# There was an error validating the request
# Use your own logging framework to log the error
Expand Down Expand Up @@ -110,18 +112,18 @@ class ResourceController < ApplicationController
# eventConfig.layoutName = "NameOfYourCustomLayout" # Optional - Name of the queue layout. If unspecified then settings from Event will be used.

requestUrl = request.original_url
queueitToken = request.query_parameters[QueueIt::KnownUser::QUEUEIT_TOKEN_KEY.to_sym]
queueitToken = QueueIt::Utils::getParameterByName(requestUrl, QueueIt::KnownUser::QUEUEIT_TOKEN_KEY)

# Initialize the SDK with the rails http context (must be done before calling validateRequestByIntegrationConfig)
QueueIt::HttpContextProvider::setHttpContext(QueueIt::RailsHttpContext.new(request))
httpContextProvider = QueueIt::HttpContextProvider.new(QueueIt::RailsHttpContext.new(request))

# Verify if the user has been through the queue
validationResult = QueueIt::KnownUser.resolveQueueRequestByLocalConfig(
requestUrl,
queueitToken,
eventConfig,
customerId,
secretKey)
secretKey,
httpContextProvider)

if(validationResult.doRedirect)
#Adding no cache headers to prevent browsers to cache requests
Expand All @@ -132,11 +134,13 @@ class ResourceController < ApplicationController
if(!validationResult.isAjaxResult)
# Send the user to the queue - either becuase hash was missing or becuase is was invalid
redirect_to validationResult.redirectUrl
return
else
head :ok
ajaxQueueRedirectHeaderName = validationResult.getAjaxQueueRedirectHeaderKey()
response.headers[ajaxQueueRedirectHeaderName] = validationResult.getAjaxRedirectUrl()
response.headers["Access-Control-Expose-Headers"] = ajaxQueueRedirectHeaderName
head :ok
return
end
else
# Request can continue - we remove queueittoken form querystring parameter to avoid sharing of user specific token
Expand All @@ -145,9 +149,9 @@ class ResourceController < ApplicationController

if(requestUrl != requestUrlWithoutToken && validationResult.actionType == "Queue")
redirect_to requestUrlWithoutToken
return
end
end

rescue StandardError => stdErr
# There was an error validating the request
# Use your own logging framework to log the error
Expand All @@ -158,6 +162,7 @@ class ResourceController < ApplicationController
end
```


## Advanced Features
### Request body trigger

Expand All @@ -184,5 +189,5 @@ end
Then, on each request, before calling the any of the SDK methods, you should initialize the SDK with your custom RailsHttpContext implementation, instead of the RailsHttpContext:

```ruby
QueueIt::HttpContextProvider::setHttpContext(RailsHttpContextWithRequestBody.new(request))
httpContextProvider = QueueIt::HttpContextProvider.new(QueueIt::RailsHttpContextWithRequestBody.new(request))
```
Empty file modified bin/console
100755 → 100644
Empty file.
Empty file modified bin/setup
100755 → 100644
Empty file.
51 changes: 16 additions & 35 deletions lib/queueit_knownuserv3/httpcontext_provider.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
module QueueIt
class IHttpContext

def userAgent
raise 'userAgent not implemented'
end
Expand All @@ -24,70 +23,52 @@ def cookieManager
def requestBodyAsString
raise 'requestBodyAsString not implemented'
end

end

class RailsHttpContext < IHttpContext
@request

def initialize(request)
@request = request
end

def userAgent
return @request.user_agent
@request.user_agent
end

def headers
return @request.headers
@request.headers
end

def url
return @request.env["rack.url_scheme"] + "://" + @request.env["HTTP_HOST"] + @request.original_fullpath
@request.env["rack.url_scheme"] + "://" + @request.env["HTTP_HOST"] + @request.original_fullpath
end

def userHostAddress
return @request.remote_ip
@request.remote_ip
end

def cookieManager
cookieManager = CookieManager.new(@request.cookie_jar)
return cookieManager
CookieManager.new(@request.cookie_jar)
end

def requestBodyAsString
return ''
''
end

end

# Used to initialize SDK for each request
class SDKInitializer

def self.setHttpContext(httpContext)
if (httpContext.class < IHttpContext)
HttpContextProvider.setHttpContext(httpContext)
else
raise "httpContext must be a subclass of IHttpContext (e.g. MyHttpContext < IHttpContext)"
end
end
class HttpContextProvider

end
def initialize(httpContext, userInQueueService = nil)
@httpContext = httpContext
@userInQueueService = userInQueueService
end

class HttpContextProvider
@@httpContext

def self.httpContext
if (defined?(@@httpContext))
return @@httpContext
else
raise "Please initialize the SDK using SDKInitializer.setHttpContext(httpContext) method"
end
def httpContext
@httpContext
end

def self.setHttpContext(httpContext)
@@httpContext = httpContext
def userInQueueService
@userInQueueService
end

end
end
end
Loading