diff --git a/lib/travis/api/v3/model.rb b/lib/travis/api/v3/model.rb index 90b26d1d..45d70920 100644 --- a/lib/travis/api/v3/model.rb +++ b/lib/travis/api/v3/model.rb @@ -2,5 +2,9 @@ module Travis::API::V3 class Model < ActiveRecord::Base include Extensions::BelongsTo self.abstract_class = true + + def self.===(other) + super or other.class.parent == Models + end end end diff --git a/lib/travis/api/v3/models/account.rb b/lib/travis/api/v3/models/account.rb new file mode 100644 index 00000000..a78a4b13 --- /dev/null +++ b/lib/travis/api/v3/models/account.rb @@ -0,0 +1,29 @@ +module Travis::API::V3 + class Models::Account + attr_accessor :owner + + def initialize(owner) + @owner = owner + end + + def id + owner.github_id + end + + def subscription + owner.subscription if owner.respond_to? :subscription + end + + def educational? + return false unless owner.respond_to? :educational + !!owner.educational + end + + def subscribed? + subscription.present? and subscription.active? + end + + alias_method :educational, :educational? + alias_method :subscribed, :subscribed? + end +end \ No newline at end of file diff --git a/lib/travis/api/v3/queries/accounts.rb b/lib/travis/api/v3/queries/accounts.rb new file mode 100644 index 00000000..d0d00d1f --- /dev/null +++ b/lib/travis/api/v3/queries/accounts.rb @@ -0,0 +1,22 @@ +module Travis::API::V3 + class Queries::Accounts < Query + def for_member(user) + organizations = Queries[:organizations].new(params, main_type).for_member(user) + accounts(user, organizations) + end + + private + + def accounts(*list) + list.flatten.map { |entry| account(entry) } + end + + def account(entry) + case entry + when Models::User, Models::Organization then Models::Account.new(entry) + when Models::Account, nil then entry + else raise ArgumentError, 'cannot convert %p into an account'.freeze % [entry] + end + end + end +end diff --git a/lib/travis/api/v3/renderer/account.rb b/lib/travis/api/v3/renderer/account.rb new file mode 100644 index 00000000..19cd16d1 --- /dev/null +++ b/lib/travis/api/v3/renderer/account.rb @@ -0,0 +1,8 @@ +require 'travis/api/v3/renderer/model_renderer' + +module Travis::API::V3 + class Renderer::Account < Renderer::ModelRenderer + representation(:minimal, :id) + representation(:standard, :id, :subscribed, :educational, :owner) + end +end diff --git a/lib/travis/api/v3/renderer/accounts.rb b/lib/travis/api/v3/renderer/accounts.rb new file mode 100644 index 00000000..734a5f2e --- /dev/null +++ b/lib/travis/api/v3/renderer/accounts.rb @@ -0,0 +1,8 @@ +require 'travis/api/v3/renderer/collection_renderer' + +module Travis::API::V3 + class Renderer::Accounts < Renderer::CollectionRenderer + type :accounts + collection_key :accounts + end +end diff --git a/lib/travis/api/v3/routes.rb b/lib/travis/api/v3/routes.rb index 1384cf4c..18ea5ddc 100644 --- a/lib/travis/api/v3/routes.rb +++ b/lib/travis/api/v3/routes.rb @@ -3,6 +3,11 @@ module Travis::API::V3 require 'travis/api/v3/routes/dsl' extend DSL + resource :accounts do + route '/accounts' + get :for_current_user + end + resource :owner do route '/owner/({owner.login}|{user.login}|{organization.login})' get :find diff --git a/lib/travis/api/v3/services.rb b/lib/travis/api/v3/services.rb index 0da1369e..9df67da4 100644 --- a/lib/travis/api/v3/services.rb +++ b/lib/travis/api/v3/services.rb @@ -2,6 +2,7 @@ module Travis::API::V3 module Services extend ConstantResolver + Accounts = Module.new { extend Services } Branch = Module.new { extend Services } Build = Module.new { extend Services } Organization = Module.new { extend Services } diff --git a/lib/travis/api/v3/services/accounts/for_current_user.rb b/lib/travis/api/v3/services/accounts/for_current_user.rb new file mode 100644 index 00000000..7bbb6680 --- /dev/null +++ b/lib/travis/api/v3/services/accounts/for_current_user.rb @@ -0,0 +1,8 @@ +module Travis::API::V3 + class Services::Accounts::ForCurrentUser < Service + def run! + raise LoginRequired unless access_control.logged_in? + query.for_member(access_control.user) + end + end +end diff --git a/spec/v3/services/accounts/for_current_user_spec.rb b/spec/v3/services/accounts/for_current_user_spec.rb new file mode 100644 index 00000000..01d45c9a --- /dev/null +++ b/spec/v3/services/accounts/for_current_user_spec.rb @@ -0,0 +1,45 @@ +require 'spec_helper' + +describe Travis::API::V3::Services::Accounts::ForCurrentUser do + let(:repo) { Repository.by_slug('svenfuchs/minimal').first } + + let(:token) { Travis::Api::App::AccessToken.create(user: repo.owner, app_id: 1) } + let(:headers) {{ 'HTTP_AUTHORIZATION' => "token #{token}" }} + before { Permission.create(repository: repo, user: repo.owner, pull: true) } + before { repo.update_attribute(:private, true) } + after { repo.update_attribute(:private, false) } + + let(:org) { Organization.new(login: 'example-org', github_id: 42) } + before { org.save! } + before { org.memberships.create(user: repo.owner) } + after { org.delete } + + describe "authenticated as user with access" do + before { get("/v3/accounts", {}, headers) } + example { expect(last_response).to be_ok } + example { expect(JSON.load(body)).to be == { + "@type" => "accounts", + "@href" => "/v3/accounts", + "accounts" => [{ + "@type" => "account", + "id" => repo.owner.github_id, + "subscribed" => false, + "educational" => false, + "owner" => { + "@type" => "user", + "@href" => "/v3/user/#{repo.owner_id}", + "id" => repo.owner_id, + "login" => "svenfuchs" }}, + {"@type" => "account", + "id" => 42, + "subscribed" => false, + "educational" => false, + "owner" => { + "@type" => "organization", + "@href" => "/v3/org/#{org.id}", + "id" => org.id, + "login" => "example-org"} + }] + }} + end +end \ No newline at end of file