Skip to content
This repository has been archived by the owner on Apr 17, 2023. It is now read-only.

Commit

Permalink
Moving to grape namespaces, teams, repos and tags
Browse files Browse the repository at this point in the history
This way we advance on our "let's go for grape" move and we get rid off some
gems.

Signed-off-by: Miquel Sabaté Solà <msabate@suse.com>
  • Loading branch information
mssola committed Sep 21, 2017
1 parent 82566a2 commit 451e508
Show file tree
Hide file tree
Showing 28 changed files with 513 additions and 233 deletions.
1 change: 0 additions & 1 deletion Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ gem "pundit"
gem "sprockets", "~> 2.12.3"
gem "jwt"
gem "base32"
gem "active_model_serializers"
gem "devise"
gem "gravatar_image_tag"
gem "public_activity"
Expand Down
9 changes: 0 additions & 9 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,6 @@ GEM
erubis (~> 2.7.0)
rails-dom-testing (~> 1.0, >= 1.0.5)
rails-html-sanitizer (~> 1.0, >= 1.0.3)
active_model_serializers (0.10.6)
actionpack (>= 4.1, < 6)
activemodel (>= 4.1, < 6)
case_transform (>= 0.2)
jsonapi-renderer (>= 0.1.1.beta1, < 0.2)
active_record_union (1.1.0)
activerecord (>= 4.0)
activejob (4.2.8)
Expand Down Expand Up @@ -85,8 +80,6 @@ GEM
rack (>= 1.0.0)
rack-test (>= 0.5.4)
xpath (~> 2.0)
case_transform (0.2)
activesupport
cconfig (1.1.1)
safe_yaml (~> 1.0.0, >= 1.0.0)
choice (0.2.0)
Expand Down Expand Up @@ -194,7 +187,6 @@ GEM
json (1.8.6)
json-schema (2.5.1)
addressable (~> 2.3.7)
jsonapi-renderer (0.1.3)
jwt (1.5.6)
kaminari (0.16.3)
actionpack (>= 3.0.0)
Expand Down Expand Up @@ -463,7 +455,6 @@ PLATFORMS
ruby

DEPENDENCIES
active_model_serializers
active_record_union
annotate
awesome_print
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ const customActions = {
},
};

const resource = Vue.resource('namespaces{/id}.json', {}, customActions);
const resource = Vue.resource('api/v1/namespaces{/id}', {}, customActions);

function all(params = {}) {
return resource.get({}, params);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import VueResource from 'vue-resource';

Vue.use(VueResource);

const resource = Vue.resource('repositories{/id}.json');
const resource = Vue.resource('api/v1/repositories{/id}');

function get(id) {
return resource.get({ id });
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import VueResource from 'vue-resource';

Vue.use(VueResource);

const resource = Vue.resource('tags{/id}.json');
const resource = Vue.resource('api/v1/tags{/id}');

function remove(id) {
return resource.delete({ id });
Expand Down
23 changes: 5 additions & 18 deletions app/controllers/application_controller.rb
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
require "portus/auth_from_token"

class ApplicationController < ActionController::Base
include Portus::Checks
include AuthFromToken
include ::Portus::Checks
before_action :check_requirements

include ::Portus::AuthFromToken
before_action :authenticate_user_from_authentication_token!

before_action :authenticate_user!
before_action :force_update_profile!
before_action :force_registry_config!
Expand All @@ -16,8 +19,6 @@ class ApplicationController < ActionController::Base

respond_to :html, :json

serialization_scope :view_context

# Two things can happen when signing in.
# 1. The current user has no email: this happens on LDAP registration. In
# this case, the user will be asked to submit an email.
Expand All @@ -34,20 +35,6 @@ def after_sign_out_path_for(_resource)

protected

# Serializes resource/collection as json using AMS
#
# This method is only necessary if you want to use the serializer
# out of the `render json: resource` situation.
def serialize_as_json(resource)
context = ActiveModelSerializers::SerializationContext.new(request)

ActiveModelSerializers::SerializableResource.new(
resource,
scope: view_context,
serialization_context: context
).as_json
end

# Authenticate the user:token as provided in the "PORTUS-AUTH" header.
def authenticate_user_from_authentication_token!
auth = request.headers["PORTUS-AUTH"].presence
Expand Down
20 changes: 0 additions & 20 deletions app/controllers/concerns/auth_from_token.rb

This file was deleted.

1 change: 1 addition & 0 deletions app/controllers/namespaces_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ class NamespacesController < ApplicationController

# GET /namespaces
# GET /namespaces.json
# TODO: remove this!
def index
if request.head?
check_namespace_by_name if params[:name]
Expand Down
1 change: 1 addition & 0 deletions app/controllers/teams_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ def index

# GET /teams/1
# GET /teams/1.json
# TODO: remove the JSON part in favor of the API
def show
raise ActiveRecord::RecordNotFound if @team.hidden?

Expand Down
15 changes: 0 additions & 15 deletions app/models/repository.rb
Original file line number Diff line number Diff line change
Expand Up @@ -68,21 +68,6 @@ def groupped_tags
end
end

# TODO: change this with a proper serializer or grape or something like that
def as_json(options = {})
options[:only] = [:id, :name]

super(options).tap do |json|
json["full_name"] = full_name
json["registry_hostname"] = registry.hostname
json["stars"] = stars.count
json["updated_at"] = updated_at
json["namespace"] = namespace.as_json(only: [:id, :name])
json["team"] = namespace.team.as_json(only: [:id, :name])
json["tags"] = groupped_tags
end
end

# Updates the activities related to this repository and adds a new activity
# regarding the removal of this.
def delete_and_update!(actor)
Expand Down
10 changes: 0 additions & 10 deletions app/models/tag.rb
Original file line number Diff line number Diff line change
Expand Up @@ -81,16 +81,6 @@ def delete_and_update!(actor)
create_delete_activities!(actor)
end

# TODO: serializer
def as_json(options = {})
options[:only] = [:id, :name, :image_id, :digest, :updated_at]
options[:include] = { author: { only: [:id, :username] } }

super(options).tap do |json|
json["vulnerabilities"] = vulnerabilities
end
end

def vulnerabilities
sec = ::Portus::Security.new(repository.full_name, name)
sec.vulnerabilities
Expand Down
3 changes: 0 additions & 3 deletions app/serializers/application_serializer.rb

This file was deleted.

45 changes: 0 additions & 45 deletions app/serializers/namespace_serializer.rb

This file was deleted.

2 changes: 1 addition & 1 deletion app/views/namespaces/components/_table_row.html.slim
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ tr :class="scopeClass"
a :href="namespace.links.self.href"
| {{ namespace.attributes.clean_name }}
td
| {{ namespace.relationships.repositories.meta.count }}
| {{ namespace.repositories }}
td v-if="namespace.relationships.webhooks.links.related"
a :href="namespace.relationships.webhooks.links.related.href"
| {{ namespace.relationships.webhooks.meta.count }}
Expand Down
2 changes: 0 additions & 2 deletions config/initializers/active_model_serializers.rb

This file was deleted.

1 change: 0 additions & 1 deletion examples/development/vagrant/portus_required_packages.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
- ruby2.1-rubygem-slim
- ruby2.1-rubygem-twitter-bootstrap-rails
- ruby2.1-rubygem-jwt
- ruby2.1-rubygem-active_model_serializers
- ruby2.1-rubygem-devise
- ruby2.1-rubygem-rake
- ruby2.1-rubygem-json
Expand Down
115 changes: 115 additions & 0 deletions lib/api/entities.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
module API
module Entities
# General entities

class ApiErrors < Grape::Entity
expose :errors, documentation: {
type: "API::Entities::Messages", is_array: true
}
end

class Messages < Grape::Entity
expose :message
end

# Users and application tokens

class Users < Grape::Entity
expose :id, documentation: { type: Integer, desc: "User ID" }
expose :username, documentation: { type: String, desc: "User name" }
expose :email, documentation: { type: String, desc: "E-mail" }
expose :current_sign_in_at, documentation: { type: DateTime }
expose :last_sign_in_at, documentation: { type: DateTime }
expose :created_at, :updated_at, documentation: { type: DateTime }
expose :admin, :enabled, documentation: { type: "boolean" }
expose :locked_at, documentation: { type: DateTime }
expose :namespace_id, documentation: { type: Integer }
expose :display_name, documentation: { type: String, desc: "Display name" }
end

class ApplicationTokens < Grape::Entity
expose :id, unless: { type: :create }, documentation: { type: Integer }
expose :application, unless: { type: :create }
expose :plain_token, if: { type: :create }
end

# Repositories and tags

class Tags < Grape::Entity
expose :id, documentation: { type: Integer, desc: "Tag ID" }
expose :name, documentation: { type: String, desc: "Tag name" }
expose :author, documentation: {
type: Integer,
desc: "The ID of the user that pushed this tag"
} { |t| { id: t.author.id, name: t.author.username } }
expose :digest, documentation: { type: String, desc: "The digest of the tag" }
expose :image_id, documentation: { type: String, desc: "The internal image ID" }
expose :created_at, :updated_at, documentation: { type: DateTime }
expose :vulnerabilities, documentation: {
is_array: true,
desc: "An array of vulnerabilities for this tag, or null if the feature is not enabled"
} do |tag|
sec = ::Portus::Security.new(tag.repository.full_name, tag.name)
sec.vulnerabilities
end
end

class Repositories < Grape::Entity
expose :id, documentation: { type: Integer, desc: "Repository ID" }
expose :name, documentation: { type: String, desc: "Repository name" }
# rubocop:disable Style/SymbolProc
expose :full_name, documentation: { type: String, desc: "Repository full name" } do |r|
r.full_name
end
# rubocop:enable Style/SymbolProc
expose :created_at, :updated_at, documentation: { type: DateTime }
expose :namespace, documentation: {
desc: "The ID of the namespace containing this repository"
} { |r| { id: r.namespace.id, name: r.namespace.name } }
expose :stars, documentation: {
type: Integer,
desc: "The number of stars for this repository"
} { |repository| repository.stars.count }
end

# Teams & namespaces

class Teams < Grape::Entity
expose :id, documentation: { type: Integer, desc: "Repository ID" }
expose :name, documentation: { type: String, desc: "Repository name" }
expose :created_at, :updated_at, documentation: { type: DateTime }
expose :hidden, :updated_at, documentation: {
type: "Boolean",
desc: "Whether the team is visible to the final user or not"
}
end

class Namespaces < Grape::Entity
expose :id, documentation: { type: Integer, desc: "Namespace ID" }
expose :name, documentation: { type: String, desc: "Namespace name" }
expose :created_at, :updated_at, documentation: { type: DateTime }
expose :team_id, documentation: {
type: Integer,
desc: "The ID of the team containing this namespace"
}
expose :repositories, documentation: {
type: Integer,
desc: "The number of repositories that belong to this namespace"
} { |n| n.repositories.count }
expose :registry_id, documentation: {
type: Integer,
desc: "The ID of the registry containing this namespace"
}
expose :visibility, documentation: {
type: String,
desc: "The visibility of namespaces by other people"
} do |namespace|
namespace.visibility.to_s.gsub("visibility_", "")
end
expose :global, documentation: {
type: "Boolean",
desc: "Whether this is the global namespace or not"
}
end
end
end
Loading

0 comments on commit 451e508

Please sign in to comment.