Security News
Research
Data Theft Repackaged: A Case Study in Malicious Wrapper Packages on npm
The Socket Research Team breaks down a malicious wrapper package that uses obfuscation to harvest credentials and exfiltrate sensitive data.
strongmind-agilix-buzz-client
Advanced tools
Fully Implements the Agilix Buzz API in Ruby
Add this line to your application's Gemfile:
gem 'agilix'
And then execute:
$ bundle
Or install it yourself as:
$ gem install agilix
Be sure to define your Agilix Buzz credentials by setting up environment variables in your application appropriately. Refer to the .env.sample file for details.
AGILIX_BUZZ_USERNAME = 'my-username'
AGILIX_BUZZ_PASSWORD = 'my-password'
Optionally, if your Buzz instance runs on your own url, you can define it as well:
AGILIX_BUZZ_URL = 'https://api.mycustomdomain.com'
There are many primary APIs that are wrapped. Below you will see basic examples of how to use them. For more information about what optional query parameters are available, please consult the Agilix Buzz API Docs
You need to authenticate to use the api. Set the credentials in Environment variables as seen above. If you've done that, you can set and refernce the api object by:
api = Agilix::Buzz::Api.new
Otherwise, you can pass :username
, :password
, and :domain
into the initializer
api = Agilix::Buzz::Api.new username: 'my-username', password: 'my-password', domain: 'my-domain'
The authentication API gives you back a token that can be used within a 15 minute window. This library will manage the need to fetch a new token or extend_session
by setting the token & token expiration in the initialized api object.
All APIs have defined required arguments and optional arguments, and an argument cleaner will prevent the calls from being made if conditions are not met. Additionally it will strip out any unsupported api params that are not defined in the required or optional fields.
Below are instructions for basic invocation of the api methods. For additional information about each API method, please consult the Agilix documentation, linked in each method's name.
api.create_domains [{name: "BuzzTest1", userspace: 'buzz-test-fc-1', parentid: '57025'}]
api.delete_domain domainid: '57027'
This is aliased to get_domain
api.get_domain domainid: '57025'
api.get_domain_content domainid: '57025'
api.get_domain_enrollment_metrics domainid: '57025'
api.get_domain_parent_list domainid: '57025'
api.get_domain_settings domainid: '57025', path: "AgilixBuzzSettings.xml"
api.get_domain_stats domainid: '57025', options: "users|courses"
api.list_domains domainid: '57025'
api.restore_domain domainid: '57027'
api.update_domains [{ domainid: "57027", name: "BuzzTestUpdated1", userspace: 'buzz-test-fc-1', parentid: '57025'}]
get_runnable_report_list
and run_report
are probably the only ones you would use.
api.get_report_info reportid: 127
api.get_report_list domainid: 1
api.get_runnable_report_list domainid: 57025
api.run_report reportid: 127, entityid: 57025, format: 'json'
This is aliased to create_users
api.create_users( [{
domainid: '57025',
username: "BuzzUserTest1",
email: 'buzzusertest1@agilix.com',
password: 'testpassword1234',
firstname: 'Buzz',
lastname: "Man",
passwordquestion: "Who's your best friend?",
passwordanswer: "Me"
}] )
api.delete_users [userid: '57181']
api.get_active_user_count domainid: '57025'
api.get_active_user_count domainid: '5', includedescendantdomains: true, bymonth:true, startdate: '2018-01-01', enddate: '2019-03-01'
api.get_domain_activity domainid: '57025'
Returns base 64 encoded picture
api.get_profile_picture entityid: 57026
The api will return 404 not found if they don't have one, unless you supply it with a default profile pic, then it will return that
api.get_profile_picture entityid: 57025, default: "https://www.gravatar.com/avatar/00000000000000000000000000000000?d=mm"
This is aliased to get_user
api.get_user userid: 57026
api.get_user_activity userid: 57026
api.get_user_activity_stream userid: 57026
api.list_users domainid: 57025
api.restore_user userid: 57026
api.update_users [{ userid: '57026', username: "BuzzUserTestUpdated1", email: 'buzzusertest1@agilix.com',firstname: 'Buzz', lastname: "ManUpdated"}]
This is handled automatically by instantiation of a base Agilix::Buzz::Api instance. It wouldn't need to be called manually unless using for other users or making calls on their behalf
api.login username: 'my-username', password: 'my-password', domain: 'my-domain'
Clears your login session
api.logout
This is handled automatically by instantiation of a base Agilix::Buzz::Api instance and on subsequent calls to the api through the check_authentication method
api.extend_session
api.force_password_change userid: 57181
api.get_password_login_attempt_history userid: 57181
api.get_password_login_attempt_history userid: 57181, earliestrecordtoreturn: '2018-01-01'
For current domain
api.get_password_policy
for a specific domain
api.get_password_policy domainid: 57031
api.get_password_question username: "auto-tests/BuzzUserUp1"
ISSUE: This works with a GET call
api.update_password_question_answer userid: 57181, passwordquestion: "Where is your favorite vacation place?", passwordanswer: "Hawaii"
api.proxy userid: 57181
In addition to these, we've created a proxy api method that will setup an api client for the proxied connection:
proxy_api = api.proxy_api userid: 57181
This will allow you to make requests as the proxied user, like you would the main api user. It's required to demonstrate how unproxy works below
First setup a proxy_api
proxy_api = api.proxy_api userid: 57181
Then you can unproxy out of it to logout as the proxied user
proxy_api.unproxy userid: 57181
api.reset_lockout userid: 57181
api.reset_password username:'auto-tests/BuzzUserUp1'
api.update_password userid: 57181, password: "IChanged123"
ISSUE: This should be a POST method as it's storing data
api.put_key entityid: 57031, name: 'secret_key_1', value: "Super Secret"
api.get_key entityid: 57031, name: 'secret_key_1'
This requires a key to exist with the given keyname, see put_key
. not sure what its used for yet
api.compute_hmac domainid: 57025, keyname: "secret_key_1", message:"my-secret-1"
api.copy_courses [{courseid: 60982, domainid: 57025}]
api.create_courses title: "Starter Course", domainid: 57025
ISSUE: documentation on request format is inconsistent, not sure if it is bulk
api.create_demo_course courseid: 60982, domainid: 57025, title: "Demo Course",
ISSUE: get request should be delete, put, patch
api.deactivate_course
ISSUE: Why so different than deactivate course
api.delete_courses [{courseid: 60994}]
api.get_course2 courseid: 60994
api.get_course_history courseid: 60994
api.list_courses domainid: 5
api.merge_courses courseid: 60994
api.restore_course courseid: 60994
api.update_courses [{courseid: 60994, title: "Updated Course"}]
ISSUE: API format is very inconsistent on this one, requires both query string modification & body modification
api.create_enrollments [{userid: 57026, entityid: 57025}]
ISSUE: Inconsistent from other delete apis. many are singular, not plural
api.delete_enrollments [ { enrollmentid: 60997 }]
This is aliased to get_enrollment
api.get_enrollment enrollmentid: 60997
api.get_enrollment_activity enrollmentid: 60997
api.get_enrollment_gradebook enrollmentid: 60997
api.get_enrollment_group_list enrollmentid: 60997
This is available in two types: Student Report
api.get_enrollment_metrics_report entityid: 50725, report: "Student"
Enrollment Report
api.get_enrollment_metrics_report entityid: 50725, report: "Enrollment"
api.list_enrollments domainid: 50725
api.list_enrollments_by_teacher teacheruserid: 50726
# If you don't pass in a teacher user id, it will default to the logged in API user
api.list_enrollments_by_teacher
api.list_entity_enrollments entityid: 60982
api.list_user_enrollments userid: 57181
api.put_self_assessment enrollmentid: 60997, understanding: 200, effort: 220, interest: 100
api.restore_enrollment enrollmentid: 60997
api.update_enrollments [{enrollmentid: 60997, status: 7}]
api.echo test: 'param'
api.get_command_list
ISSUE: nothing saying this is an authenticated call, when others are non-authenticated
api.get_entity_type entityid: 57025
ISSUE: docs in getting started reference a level
param, actual docs suggest using rating
api.get_status rating: 4, html: true, sms: true
# you can also call this one non-authenticated
api.get_basic_status
ISSUE: Docs have cmd spelled wrong, this API doesn't seem to work at all AccessDenied. It did say experimental
api.get_upload_limits
api.get_upload_limits domainid: 57025
This is one of the more confusing APIs, it allows you to send emails to people in the same enrollment grouping as the person wanting to send the email (enrollmentid
).
api.send_mail subject: "Test email", body: "Did you get this?", enrollmentid: 60997, enrollment_ids: ["all"]
api.copy_resources [ {sourceentityid: 57025, destinationentityid: 57031, sourcepath: "banner.css" }]
api.delete_resources [{entityid: 57031, path: 'banner.css'}]
api.get_entity_resource_id entityid: 57025
api.get_resource entityid: 57031, path: "banner.css"
ISSUE: This is a get request with a POST verb. The documentation only suggests getting a single resoure, so I'm not sure why it would be a bulk post syntax. it does seem to respond to multiple resources though,so we'll adapt
api.get_resource_info [{entityid: 57031, path: "banner.css"}]
api.get_resource_list entityid: 57025
api.list_restorable_resources entityid: 57025
file_name = "my-file.pdf"
file = File.open file_name
api.put_resource file, {entityid: 57025, path: file_name}
api.put_resource_folders [{entityid: 57031, path: 'test/folder-1'}]
api.restore_resources [{entityid: 57031, path: 'banner.css'}]
ISSUE: Why is this create singular, not multiple?
api.create_role domainid: 57025, name: "Test Role", privileges: api.right_flags[:create_domain]
api.delete_role roleid: 61316
ISSUE: Why is this create singular, not multiple?
api.delete_subscriptions subscriberid: 57181, entityid: 57025
ISSUE: Why is this create singular, not multiple?
api.create_role domainid: 57025, name: "Test Role", privileges: api.right_flags[:create_domain]
api.get_effective_rights entityid: 57025
api.get_effective_subscription_list
api.get_entity_rights entityid: 57025
api.get_entity_subscription_list entityid: 57025
api.get_personas userid: 57026
api.get_rights actorid: 57026, entityid: 57025
api.get_rights_list domainid: 57025
api.get_role roleid: 61316
# Get for a domain
api.get_subscription_list subscriberid: 57025
# Get for a user
api.get_subscription_list subscriberid: 57026
api.list_roles domainid: 57025
api.restore_role roleid: 61316
api.update_rights [ {actorid: 57026, entityid: 57025, roleid: 61316}]
api.update_role roleid: 61316, name: "Test Role Updates", privileges: api.right_flags[:update_domain]
ISSUE: Why is this root node singular?
api.update_subscriptions subscriberid: 57181, entityid: 60982, startdate: "2019-03-15", enddate: "2019-03-15"
Implemented APIs from Agilix Buzz API Docs
(Last updated on March 7, 2019)
After checking out the repo, run bin/setup
to install dependencies. Then, run rake test
to run the tests. You can also run bin/console
for an interactive prompt that will allow you to experiment.
To install this gem onto your local machine, run bundle exec rake install
. To release a new version, update the version number in version.rb
, and then run bundle exec rake release
, which will create a git tag for the version, push git commits and tags, and push the .gem
file to rubygems.org.
Run this command at the application's root directory to view test code coverage:
open coverage/index.html
Bug reports and pull requests are welcome on GitHub at https://github.com/beneggett/agilix. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the Contributor Covenant code of conduct.
The gem is available as open source under the terms of the MIT License.
Everyone interacting in the Agilix::Buzz projectβs codebases, issue trackers, chat rooms and mailing lists is expected to follow the code of conduct.
FAQs
Unknown package
We found that strongmind-agilix-buzz-client demonstrated a not healthy version release cadence and project activity because the last version was released a year ago.Β It has 2 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Research
The Socket Research Team breaks down a malicious wrapper package that uses obfuscation to harvest credentials and exfiltrate sensitive data.
Research
Security News
Attackers used a malicious npm package typosquatting a popular ESLint plugin to steal sensitive data, execute commands, and exploit developer systems.
Security News
The Ultralytics' PyPI Package was compromised four times in one weekend through GitHub Actions cache poisoning and failure to rotate previously compromised API tokens.