commit
5f9c46b42c
@ -7,15 +7,13 @@ module Locomotive
|
||||
|
||||
skip_before_filter :verify_authenticity_token
|
||||
|
||||
skip_load_and_authorize_resource
|
||||
|
||||
before_filter :require_account
|
||||
|
||||
before_filter :require_site
|
||||
|
||||
before_filter :set_locale
|
||||
|
||||
# before_filter :validate_site_membership
|
||||
before_filter :set_current_thread_variables
|
||||
|
||||
self.responder = Locomotive::ActionController::Responder # custom responder
|
||||
|
||||
@ -23,6 +21,11 @@ module Locomotive
|
||||
|
||||
protected
|
||||
|
||||
def set_current_thread_variables
|
||||
Thread.current[:account] = current_locomotive_account
|
||||
Thread.current[:site] = current_site
|
||||
end
|
||||
|
||||
def current_ability
|
||||
@current_ability ||= Ability.new(current_locomotive_account, current_site)
|
||||
end
|
||||
@ -40,4 +43,4 @@ module Locomotive
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -2,11 +2,18 @@ module Locomotive
|
||||
module Api
|
||||
class ContentAssetsController < BaseController
|
||||
|
||||
load_and_authorize_resource :class => Locomotive::ContentAsset
|
||||
|
||||
def index
|
||||
@content_assets = current_site.content_assets
|
||||
respond_with(@content_assets)
|
||||
end
|
||||
|
||||
def show
|
||||
@content_asset = current_site.content_assets.find(params[:id])
|
||||
respond_with(@content_asset)
|
||||
end
|
||||
|
||||
def create
|
||||
@content_asset = current_site.content_assets.create(params[:content_asset])
|
||||
respond_with @content_asset, :location => main_app.locomotive_api_content_assets_url
|
||||
@ -18,6 +25,12 @@ module Locomotive
|
||||
respond_with @content_asset, :location => main_app.locomotive_api_content_assets_url
|
||||
end
|
||||
|
||||
def destroy
|
||||
@content_asset = current_site.content_assets.find(params[:id])
|
||||
@content_asset.destroy
|
||||
respond_with @content_asset
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -2,11 +2,18 @@ module Locomotive
|
||||
module Api
|
||||
class ContentTypesController < BaseController
|
||||
|
||||
load_and_authorize_resource :class => Locomotive::ContentType
|
||||
|
||||
def index
|
||||
@content_types = current_site.content_types
|
||||
respond_with(@content_types)
|
||||
end
|
||||
|
||||
def show
|
||||
@content_type = current_site.content_types.find(params[:id])
|
||||
respond_with @content_type
|
||||
end
|
||||
|
||||
def create
|
||||
@content_type = current_site.content_types.create(params[:content_type])
|
||||
respond_with @content_type, :location => main_app.locomotive_api_content_types_url
|
||||
@ -18,6 +25,12 @@ module Locomotive
|
||||
respond_with @content_type, :location => main_app.locomotive_api_content_types_url
|
||||
end
|
||||
|
||||
def destroy
|
||||
@content_type = current_site.content_types.find(params[:id])
|
||||
@content_type.destroy
|
||||
respond_with @content_type
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -3,7 +3,9 @@ module Locomotive
|
||||
class CurrentSiteController < BaseController
|
||||
|
||||
def show
|
||||
respond_with(current_site)
|
||||
@site = current_site
|
||||
authorize! :show, @site
|
||||
respond_with(@site)
|
||||
end
|
||||
|
||||
end
|
||||
|
49
app/controllers/locomotive/api/memberships_controller.rb
Normal file
49
app/controllers/locomotive/api/memberships_controller.rb
Normal file
@ -0,0 +1,49 @@
|
||||
module Locomotive
|
||||
module Api
|
||||
class MembershipsController < BaseController
|
||||
|
||||
# It's an embedded document, so we'll just load manually
|
||||
before_filter :load_membership, :only => [ :show, :update, :destroy ]
|
||||
before_filter :load_memberships, :only => [ :index ]
|
||||
|
||||
authorize_resource :class => Locomotive::Membership
|
||||
|
||||
def index
|
||||
respond_with(@memberships)
|
||||
end
|
||||
|
||||
def show
|
||||
respond_with(@membership)
|
||||
end
|
||||
|
||||
def create
|
||||
build_params = params[:membership].merge({ :role => 'author' }) # force author by default
|
||||
@membership = current_site.memberships.create(build_params)
|
||||
respond_with(@membership)
|
||||
end
|
||||
|
||||
def update
|
||||
@membership.update_attributes(params[:membership])
|
||||
respond_with(@membership)
|
||||
end
|
||||
|
||||
def destroy
|
||||
@membership.destroy
|
||||
respond_with(@membership)
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def load_membership
|
||||
@membership ||= load_memberships.find(params[:id])
|
||||
end
|
||||
|
||||
def load_memberships
|
||||
@memberships ||= current_site.memberships
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
@ -2,11 +2,18 @@ module Locomotive
|
||||
module Api
|
||||
class PagesController < BaseController
|
||||
|
||||
load_and_authorize_resource :class => Locomotive::Page
|
||||
|
||||
def index
|
||||
@pages = current_site.pages.order_by([[:depth, :asc], [:position, :asc]])
|
||||
respond_with(@pages)
|
||||
end
|
||||
|
||||
def show
|
||||
@page = current_site.pages.find(params[:id])
|
||||
respond_with(@page)
|
||||
end
|
||||
|
||||
def create
|
||||
@page = current_site.pages.create(params[:page])
|
||||
respond_with @page, :location => main_app.locomotive_api_pages_url
|
||||
@ -18,6 +25,12 @@ module Locomotive
|
||||
respond_with @page, :location => main_app.locomotive_api_pages_url
|
||||
end
|
||||
|
||||
def destroy
|
||||
@page = current_site.pages.find(params[:id])
|
||||
@page.destroy
|
||||
respond_with @page
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
44
app/controllers/locomotive/api/sites_controller.rb
Normal file
44
app/controllers/locomotive/api/sites_controller.rb
Normal file
@ -0,0 +1,44 @@
|
||||
module Locomotive
|
||||
module Api
|
||||
class SitesController < BaseController
|
||||
|
||||
load_and_authorize_resource :class => Locomotive::Site
|
||||
|
||||
# FIXME: the auto-loaded site won't pass authorization for show, update, or destroy
|
||||
skip_load_and_authorize_resource :only => [ :show, :update, :destroy ]
|
||||
|
||||
def index
|
||||
@sites = Locomotive::Site.all
|
||||
respond_with(@sites)
|
||||
end
|
||||
|
||||
def show
|
||||
@site = Locomotive::Site.find(params[:id])
|
||||
authorize! :show, @site
|
||||
respond_with(@site)
|
||||
end
|
||||
|
||||
def create
|
||||
@site = Locomotive::Site.create(params[:site])
|
||||
respond_with(@site)
|
||||
end
|
||||
|
||||
def update
|
||||
@site = Locomotive::Site.find(params[:id])
|
||||
authorize! :update, @site
|
||||
@site.update_attributes(params[:site])
|
||||
respond_with @site
|
||||
end
|
||||
|
||||
def destroy
|
||||
@site = Locomotive::Site.find(params[:id])
|
||||
authorize! :destroy, @site
|
||||
@site.destroy
|
||||
respond_with @site
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
@ -2,11 +2,18 @@ module Locomotive
|
||||
module Api
|
||||
class SnippetsController < BaseController
|
||||
|
||||
load_and_authorize_resource :class => Locomotive::Snippet
|
||||
|
||||
def index
|
||||
@snippets = current_site.snippets.all
|
||||
respond_with(@snippets)
|
||||
end
|
||||
|
||||
def show
|
||||
@snippet = current_site.snippets.find(params[:id])
|
||||
respond_with @snippet
|
||||
end
|
||||
|
||||
def create
|
||||
@snippet = current_site.snippets.create(params[:snippet])
|
||||
respond_with @snippet, :location => main_app.locomotive_api_snippets_url
|
||||
@ -18,6 +25,12 @@ module Locomotive
|
||||
respond_with @snippet, :location => main_app.locomotive_api_snippets_url
|
||||
end
|
||||
|
||||
def destroy
|
||||
@snippet = current_site.snippets.find(params[:id])
|
||||
@snippet.destroy
|
||||
respond_with @snippet
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -2,11 +2,18 @@ module Locomotive
|
||||
module Api
|
||||
class ThemeAssetsController < BaseController
|
||||
|
||||
load_and_authorize_resource :class => Locomotive::ThemeAsset
|
||||
|
||||
def index
|
||||
@theme_assets = current_site.theme_assets.all
|
||||
respond_with(@theme_assets)
|
||||
end
|
||||
|
||||
def show
|
||||
@theme_asset = current_site.theme_assets.find(params[:id])
|
||||
respond_with @theme_asset
|
||||
end
|
||||
|
||||
def create
|
||||
@theme_asset = current_site.theme_assets.create(params[:theme_asset])
|
||||
respond_with @theme_asset, :location => main_app.locomotive_api_theme_assets_url
|
||||
@ -18,6 +25,12 @@ module Locomotive
|
||||
respond_with @theme_asset, :location => main_app.locomotive_api_theme_assets_url
|
||||
end
|
||||
|
||||
def destroy
|
||||
@theme_asset = current_site.theme_assets.find(params[:id])
|
||||
@theme_asset.destroy
|
||||
respond_with @theme_asset
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -37,6 +37,8 @@ module Locomotive
|
||||
can :touch, Site do |site|
|
||||
site == @site
|
||||
end
|
||||
|
||||
can :read, ContentType
|
||||
end
|
||||
|
||||
def setup_designer_permissions!
|
||||
|
@ -68,6 +68,10 @@ Rails.application.routes.draw do
|
||||
|
||||
resources :content_entries, :path => 'content_types/:slug/entries'
|
||||
|
||||
resources :sites
|
||||
|
||||
resources :memberships
|
||||
|
||||
resource :current_site, :controller => 'current_site'
|
||||
|
||||
end
|
||||
|
147
features/api/authorization/content_assets.feature
Normal file
147
features/api/authorization/content_assets.feature
Normal file
@ -0,0 +1,147 @@
|
||||
Feature: Content Assets
|
||||
In order to ensure content assets are not tampered with
|
||||
As an admin, designer or author
|
||||
I will be restricted based on my role
|
||||
|
||||
Background:
|
||||
Given I have the site: "test site" set up
|
||||
And I have the following content assets:
|
||||
| id | file |
|
||||
| 4f832c2cb0d86d3f42fffffe | 5k.png |
|
||||
| 4f832c2cb0d86d3f42ffffff | 5k_2.png |
|
||||
And I have a designer and an author
|
||||
|
||||
Scenario: As an unauthenticated user
|
||||
Given I am not authenticated
|
||||
When I do an API GET to content_assets.json
|
||||
Then the JSON response at "error" should be "You need to sign in or sign up before continuing."
|
||||
|
||||
# listing content assets
|
||||
|
||||
Scenario: Accessing content assets as an Admin
|
||||
Given I have an "admin" API token
|
||||
When I do an API GET request to content_assets.json
|
||||
Then the JSON response should be an array
|
||||
And the JSON response should have 2 entries
|
||||
|
||||
Scenario: Accessing content assets as a Designer
|
||||
Given I have a "designer" API token
|
||||
When I do an API GET request to content_assets.json
|
||||
Then the JSON response should be an array
|
||||
And the JSON response should have 2 entries
|
||||
|
||||
Scenario: Accessing content assets as an Author
|
||||
Given I have an "author" API token
|
||||
When I do an API GET request to content_assets.json
|
||||
Then the JSON response should be an array
|
||||
And the JSON response should have 2 entries
|
||||
|
||||
# showing content asset
|
||||
|
||||
Scenario: Accessing content asset as an Admin
|
||||
Given I have an "admin" API token
|
||||
When I do an API GET request to content_assets/4f832c2cb0d86d3f42fffffe.json
|
||||
Then the JSON response at "filename" should be "5k.png"
|
||||
|
||||
Scenario: Accessing content asset as a Designer
|
||||
Given I have a "designer" API token
|
||||
When I do an API GET request to content_assets/4f832c2cb0d86d3f42fffffe.json
|
||||
Then the JSON response at "filename" should be "5k.png"
|
||||
|
||||
Scenario: Accessing content asset as an Author
|
||||
Given I have an "author" API token
|
||||
When I do an API GET request to content_assets/4f832c2cb0d86d3f42fffffe.json
|
||||
Then the JSON response at "filename" should be "5k.png"
|
||||
|
||||
# create content asset
|
||||
|
||||
Scenario: Creating new content asset as an Admin
|
||||
Given I have an "admin" API token
|
||||
When I do an API GET request to content_assets.json
|
||||
Then the JSON response should be an array
|
||||
And the JSON response should have 2 entries
|
||||
When I do a multipart API POST to content_assets.json with base key "content_asset" and:
|
||||
| source | assets/application.js |
|
||||
When I do an API GET request to content_assets.json
|
||||
Then the JSON response should be an array
|
||||
And the JSON response should have 3 entries
|
||||
And the JSON at "2/filename" should be "application.js"
|
||||
|
||||
Scenario: Creating new content asset as a Designer
|
||||
Given I have a "designer" API token
|
||||
When I do an API GET request to content_assets.json
|
||||
Then the JSON response should be an array
|
||||
And the JSON response should have 2 entries
|
||||
When I do a multipart API POST to content_assets.json with base key "content_asset" and:
|
||||
| source | assets/application.js |
|
||||
When I do an API GET request to content_assets.json
|
||||
Then the JSON response should be an array
|
||||
And the JSON response should have 3 entries
|
||||
And the JSON at "2/filename" should be "application.js"
|
||||
|
||||
Scenario: Creating new content asset as an Author
|
||||
Given I have an "author" API token
|
||||
When I do an API GET request to content_assets.json
|
||||
Then the JSON response should be an array
|
||||
And the JSON response should have 2 entries
|
||||
When I do a multipart API POST to content_assets.json with base key "content_asset" and:
|
||||
| source | assets/application.js |
|
||||
When I do an API GET request to content_assets.json
|
||||
Then the JSON response should be an array
|
||||
And the JSON response should have 3 entries
|
||||
And the JSON at "2/filename" should be "application.js"
|
||||
|
||||
# update content asset
|
||||
|
||||
Scenario: Updating content asset as an Admin
|
||||
Given I have an "admin" API token
|
||||
When I do a multipart API PUT to content_assets/4f832c2cb0d86d3f42fffffe.json with base key "content_asset" and:
|
||||
| source | assets/main.css |
|
||||
When I do an API GET request to content_assets/4f832c2cb0d86d3f42fffffe.json
|
||||
Then the JSON response at "filename" should be "main.css"
|
||||
|
||||
Scenario: Updating content asset as a Designer
|
||||
Given I have a "designer" API token
|
||||
When I do a multipart API PUT to content_assets/4f832c2cb0d86d3f42fffffe.json with base key "content_asset" and:
|
||||
| source | assets/main.css |
|
||||
When I do an API GET request to content_assets/4f832c2cb0d86d3f42fffffe.json
|
||||
Then the JSON response at "filename" should be "main.css"
|
||||
|
||||
Scenario: Updating content asset as an Author
|
||||
Given I have a "author" API token
|
||||
When I do a multipart API PUT to content_assets/4f832c2cb0d86d3f42fffffe.json with base key "content_asset" and:
|
||||
| source | assets/main.css |
|
||||
When I do an API GET request to content_assets/4f832c2cb0d86d3f42fffffe.json
|
||||
Then the JSON response at "filename" should be "main.css"
|
||||
|
||||
# destroy content asset
|
||||
|
||||
Scenario: Destroying content asset as an Admin
|
||||
Given I have an "admin" API token
|
||||
When I do an API GET request to content_assets.json
|
||||
Then the JSON response should be an array
|
||||
And the JSON response should have 2 entries
|
||||
When I do an API DELETE to content_assets/4f832c2cb0d86d3f42fffffe.json
|
||||
When I do an API GET request to content_assets.json
|
||||
Then the JSON response should be an array
|
||||
And the JSON response should have 1 entry
|
||||
|
||||
Scenario: Destroying content asset as a Designer
|
||||
Given I have a "designer" API token
|
||||
When I do an API GET request to content_assets.json
|
||||
Then the JSON response should be an array
|
||||
And the JSON response should have 2 entries
|
||||
When I do an API DELETE to content_assets/4f832c2cb0d86d3f42fffffe.json
|
||||
When I do an API GET request to content_assets.json
|
||||
Then the JSON response should be an array
|
||||
And the JSON response should have 1 entry
|
||||
|
||||
Scenario: Deleting content asset as an Author
|
||||
Given I have a "author" API token
|
||||
When I do an API GET request to content_assets.json
|
||||
Then the JSON response should be an array
|
||||
And the JSON response should have 2 entries
|
||||
When I do an API DELETE to content_assets/4f832c2cb0d86d3f42fffffe.json
|
||||
When I do an API GET request to content_assets.json
|
||||
Then the JSON response should be an array
|
||||
And the JSON response should have 1 entry
|
202
features/api/authorization/content_entries.feature
Normal file
202
features/api/authorization/content_entries.feature
Normal file
@ -0,0 +1,202 @@
|
||||
Feature: Content Entries
|
||||
In order to ensure content entries are not tampered with
|
||||
As an admin, designer or author
|
||||
I will be restricted based on my role
|
||||
|
||||
Background:
|
||||
Given I have the site: "test site" set up
|
||||
And I have a custom model named "Projects" with
|
||||
| label | type | required |
|
||||
| Name | string | true |
|
||||
| Description | text | false |
|
||||
And I have entries for "Projects" with
|
||||
| id | name | description |
|
||||
| 4f832c2cb0d86d3f42fffffe | Project 1 | The first project |
|
||||
| 4f832c2cb0d86d3f42ffffff | Project 2 | The second project |
|
||||
And I have a designer and an author
|
||||
|
||||
Scenario: As an unauthenticated user
|
||||
Given I am not authenticated
|
||||
When I do an API GET to content_types/projects/entries.json
|
||||
Then the JSON response at "error" should be "You need to sign in or sign up before continuing."
|
||||
|
||||
# listing content entries
|
||||
|
||||
Scenario: Accessing content entries as an Admin
|
||||
Given I have an "admin" API token
|
||||
When I do an API GET request to content_types/projects/entries.json
|
||||
Then the JSON response should be an array
|
||||
And the JSON response should have 2 entries
|
||||
|
||||
Scenario: Accessing content entries as a Designer
|
||||
Given I have a "designer" API token
|
||||
When I do an API GET request to content_types/projects/entries.json
|
||||
Then the JSON response should be an array
|
||||
And the JSON response should have 2 entries
|
||||
|
||||
Scenario: Accessing content entries as an Author
|
||||
Given I have an "author" API token
|
||||
When I do an API GET request to content_types/projects/entries.json
|
||||
Then the JSON response should be an array
|
||||
And the JSON response should have 2 entries
|
||||
|
||||
# showing content entry
|
||||
|
||||
Scenario: Accessing content entry as an Admin
|
||||
Given I have an "admin" API token
|
||||
When I do an API GET request to content_types/projects/entries/4f832c2cb0d86d3f42fffffe.json
|
||||
Then the JSON response at "id" should be "4f832c2cb0d86d3f42fffffe"
|
||||
And the JSON response at "name" should be "Project 1"
|
||||
|
||||
Scenario: Accessing content entry as a Designer
|
||||
Given I have a "designer" API token
|
||||
When I do an API GET request to content_types/projects/entries/4f832c2cb0d86d3f42fffffe.json
|
||||
Then the JSON response at "id" should be "4f832c2cb0d86d3f42fffffe"
|
||||
And the JSON response at "name" should be "Project 1"
|
||||
|
||||
Scenario: Accessing content entry as an Author
|
||||
Given I have an "author" API token
|
||||
When I do an API GET request to content_types/projects/entries/4f832c2cb0d86d3f42fffffe.json
|
||||
Then the JSON response at "id" should be "4f832c2cb0d86d3f42fffffe"
|
||||
And the JSON response at "name" should be "Project 1"
|
||||
|
||||
# create content entry
|
||||
|
||||
Scenario: Creating new content entry as an Admin
|
||||
Given I have an "admin" API token
|
||||
When I do an API GET request to content_types/projects/entries.json
|
||||
Then the JSON response should be an array
|
||||
And the JSON response should have 2 entries
|
||||
When I do an API POST to content_types/projects/entries.json with:
|
||||
"""
|
||||
{
|
||||
"content_entry": {
|
||||
"name": "Project 3",
|
||||
"description": "The third..."
|
||||
}
|
||||
}
|
||||
"""
|
||||
When I do an API GET request to content_types/projects/entries.json
|
||||
Then the JSON response should be an array
|
||||
And the JSON response should have 3 entries
|
||||
And the JSON should have the following:
|
||||
| 2/name | "Project 3" |
|
||||
| 2/description | "The third..." |
|
||||
|
||||
Scenario: Creating new content entry as a Designer
|
||||
Given I have a "designer" API token
|
||||
When I do an API GET request to content_types/projects/entries.json
|
||||
Then the JSON response should be an array
|
||||
And the JSON response should have 2 entries
|
||||
When I do an API POST to content_types/projects/entries.json with:
|
||||
"""
|
||||
{
|
||||
"content_entry": {
|
||||
"name": "Project 3",
|
||||
"description": "The third..."
|
||||
}
|
||||
}
|
||||
"""
|
||||
When I do an API GET request to content_types/projects/entries.json
|
||||
Then the JSON response should be an array
|
||||
And the JSON response should have 3 entries
|
||||
And the JSON should have the following:
|
||||
| 2/name | "Project 3" |
|
||||
| 2/description | "The third..." |
|
||||
|
||||
Scenario: Creating new content entry as an Author
|
||||
Given I have an "author" API token
|
||||
When I do an API GET request to content_types/projects/entries.json
|
||||
Then the JSON response should be an array
|
||||
And the JSON response should have 2 entries
|
||||
When I do an API POST to content_types/projects/entries.json with:
|
||||
"""
|
||||
{
|
||||
"content_entry": {
|
||||
"name": "Project 3",
|
||||
"description": "The third..."
|
||||
}
|
||||
}
|
||||
"""
|
||||
When I do an API GET request to content_types/projects/entries.json
|
||||
Then the JSON response should be an array
|
||||
And the JSON response should have 3 entries
|
||||
And the JSON should have the following:
|
||||
| 2/name | "Project 3" |
|
||||
| 2/description | "The third..." |
|
||||
|
||||
# update content entry
|
||||
|
||||
Scenario: Updating content entry as an Admin
|
||||
Given I have an "admin" API token
|
||||
When I do an API PUT to content_types/projects/entries/4f832c2cb0d86d3f42fffffe.json with:
|
||||
"""
|
||||
{
|
||||
"content_entry": {
|
||||
"description": "The awesomest project ever!"
|
||||
}
|
||||
}
|
||||
"""
|
||||
When I do an API GET request to content_types/projects/entries/4f832c2cb0d86d3f42fffffe.json
|
||||
Then the JSON response at "name" should be "Project 1"
|
||||
And the JSON response at "description" should be "The awesomest project ever!"
|
||||
|
||||
Scenario: Updating content entry as a Designer
|
||||
Given I have a "designer" API token
|
||||
When I do an API PUT to content_types/projects/entries/4f832c2cb0d86d3f42fffffe.json with:
|
||||
"""
|
||||
{
|
||||
"content_entry": {
|
||||
"description": "The awesomest project ever!"
|
||||
}
|
||||
}
|
||||
"""
|
||||
When I do an API GET request to content_types/projects/entries/4f832c2cb0d86d3f42fffffe.json
|
||||
Then the JSON response at "name" should be "Project 1"
|
||||
And the JSON response at "description" should be "The awesomest project ever!"
|
||||
|
||||
Scenario: Updating content entry as an Author
|
||||
Given I have a "author" API token
|
||||
When I do an API PUT to content_types/projects/entries/4f832c2cb0d86d3f42fffffe.json with:
|
||||
"""
|
||||
{
|
||||
"content_entry": {
|
||||
"description": "The awesomest project ever!"
|
||||
}
|
||||
}
|
||||
"""
|
||||
When I do an API GET request to content_types/projects/entries/4f832c2cb0d86d3f42fffffe.json
|
||||
Then the JSON response at "name" should be "Project 1"
|
||||
And the JSON response at "description" should be "The awesomest project ever!"
|
||||
|
||||
# destroy content entry
|
||||
|
||||
Scenario: Destroying content entry as an Admin
|
||||
Given I have an "admin" API token
|
||||
When I do an API GET request to content_types/projects/entries.json
|
||||
Then the JSON response should be an array
|
||||
And the JSON response should have 2 entries
|
||||
When I do an API DELETE to content_types/projects/entries/4f832c2cb0d86d3f42fffffe.json
|
||||
When I do an API GET request to content_types/projects/entries.json
|
||||
Then the JSON response should be an array
|
||||
And the JSON response should have 1 entry
|
||||
|
||||
Scenario: Destroying content entry as a Designer
|
||||
Given I have a "designer" API token
|
||||
When I do an API GET request to content_types/projects/entries.json
|
||||
Then the JSON response should be an array
|
||||
And the JSON response should have 2 entries
|
||||
When I do an API DELETE to content_types/projects/entries/4f832c2cb0d86d3f42fffffe.json
|
||||
When I do an API GET request to content_types/projects/entries.json
|
||||
Then the JSON response should be an array
|
||||
And the JSON response should have 1 entry
|
||||
|
||||
Scenario: Deleting content entry as an Author
|
||||
Given I have a "author" API token
|
||||
When I do an API GET request to content_types/projects/entries.json
|
||||
Then the JSON response should be an array
|
||||
And the JSON response should have 2 entries
|
||||
When I do an API DELETE to content_types/projects/entries/4f832c2cb0d86d3f42fffffe.json
|
||||
When I do an API GET request to content_types/projects/entries.json
|
||||
Then the JSON response should be an array
|
||||
And the JSON response should have 1 entry
|
237
features/api/authorization/content_types.feature
Normal file
237
features/api/authorization/content_types.feature
Normal file
@ -0,0 +1,237 @@
|
||||
Feature: Content Types
|
||||
In order to ensure content types are not tampered with
|
||||
As an admin, designer or author
|
||||
I will be restricted based on my role
|
||||
|
||||
Background:
|
||||
Given I have the site: "test site" set up
|
||||
And I have a custom model named "Projects" with id "4f832c2cb0d86d3f42fffffe" and
|
||||
| label | type | required |
|
||||
| Name | string | true |
|
||||
| Description | text | false |
|
||||
And I have a designer and an author
|
||||
|
||||
Scenario: As an unauthenticated user
|
||||
Given I am not authenticated
|
||||
When I do an API GET to content_types.json
|
||||
Then the JSON response at "error" should be "You need to sign in or sign up before continuing."
|
||||
|
||||
# listing content types
|
||||
|
||||
Scenario: Accessing content types as an Admin
|
||||
Given I have an "admin" API token
|
||||
When I do an API GET request to content_types.json
|
||||
Then the JSON response should be an array
|
||||
And the JSON response should have 1 entry
|
||||
|
||||
Scenario: Accessing content types as a Designer
|
||||
Given I have a "designer" API token
|
||||
When I do an API GET request to content_types.json
|
||||
Then the JSON response should be an array
|
||||
And the JSON response should have 1 entry
|
||||
|
||||
Scenario: Accessing content types as an Author
|
||||
Given I have an "author" API token
|
||||
When I do an API GET request to content_types.json
|
||||
Then the JSON response should be an array
|
||||
And the JSON response should have 1 entry
|
||||
|
||||
# showing content type
|
||||
|
||||
Scenario: Accessing content type as an Admin
|
||||
Given I have an "admin" API token
|
||||
When I do an API GET request to content_types/4f832c2cb0d86d3f42fffffe.json
|
||||
Then the JSON response at "id" should be "4f832c2cb0d86d3f42fffffe"
|
||||
And the JSON response at "name" should be "Projects"
|
||||
|
||||
Scenario: Accessing content type as a Designer
|
||||
Given I have a "designer" API token
|
||||
When I do an API GET request to content_types/4f832c2cb0d86d3f42fffffe.json
|
||||
Then the JSON response at "id" should be "4f832c2cb0d86d3f42fffffe"
|
||||
And the JSON response at "name" should be "Projects"
|
||||
|
||||
Scenario: Accessing content type as an Author
|
||||
Given I have an "author" API token
|
||||
When I do an API GET request to content_types/4f832c2cb0d86d3f42fffffe.json
|
||||
Then the JSON response at "id" should be "4f832c2cb0d86d3f42fffffe"
|
||||
And the JSON response at "name" should be "Projects"
|
||||
|
||||
# create content type
|
||||
|
||||
Scenario: Creating new content type as an Admin
|
||||
Given I have an "admin" API token
|
||||
When I do an API GET request to content_types.json
|
||||
Then the JSON response should be an array
|
||||
And the JSON response should have 1 entry
|
||||
When I do an API POST to content_types.json with:
|
||||
"""
|
||||
{
|
||||
"content_type": {
|
||||
"name": "Employees",
|
||||
"slug": "employees",
|
||||
"entries_custom_fields": [
|
||||
{
|
||||
"label": "Name",
|
||||
"name": "name",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"label": "Position",
|
||||
"name": "position",
|
||||
"type": "string"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
"""
|
||||
When I do an API GET request to content_types.json
|
||||
Then the JSON response should be an array
|
||||
And the JSON response should have 2 entries
|
||||
And the JSON should have the following:
|
||||
| 1/name | "Employees" |
|
||||
| 1/slug | "employees" |
|
||||
| 1/entries_custom_fields/0/label | "Name" |
|
||||
| 1/entries_custom_fields/0/name | "name" |
|
||||
| 1/entries_custom_fields/0/type | "string" |
|
||||
| 1/entries_custom_fields/1/label | "Position" |
|
||||
| 1/entries_custom_fields/1/name | "position" |
|
||||
| 1/entries_custom_fields/1/type | "string" |
|
||||
|
||||
Scenario: Creating new content type as a Designer
|
||||
Given I have a "designer" API token
|
||||
When I do an API GET request to content_types.json
|
||||
Then the JSON response should be an array
|
||||
And the JSON response should have 1 entry
|
||||
When I do an API POST to content_types.json with:
|
||||
"""
|
||||
{
|
||||
"content_type": {
|
||||
"name": "Employees",
|
||||
"slug": "employees",
|
||||
"entries_custom_fields": [
|
||||
{
|
||||
"label": "Name",
|
||||
"name": "name",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"label": "Position",
|
||||
"name": "position",
|
||||
"type": "string"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
"""
|
||||
When I do an API GET request to content_types.json
|
||||
Then the JSON response should be an array
|
||||
And the JSON response should have 2 entries
|
||||
And the JSON should have the following:
|
||||
| 1/name | "Employees" |
|
||||
| 1/slug | "employees" |
|
||||
| 1/entries_custom_fields/0/label | "Name" |
|
||||
| 1/entries_custom_fields/0/name | "name" |
|
||||
| 1/entries_custom_fields/0/type | "string" |
|
||||
| 1/entries_custom_fields/1/label | "Position" |
|
||||
| 1/entries_custom_fields/1/name | "position" |
|
||||
| 1/entries_custom_fields/1/type | "string" |
|
||||
|
||||
Scenario: Creating new content type as an Author
|
||||
Given I have an "author" API token
|
||||
When I do an API GET request to content_types.json
|
||||
Then the JSON response should be an array
|
||||
And the JSON response should have 1 entry
|
||||
When I do an API POST to content_types.json with:
|
||||
"""
|
||||
{
|
||||
"content_type": {
|
||||
"name": "Employees",
|
||||
"slug": "employees",
|
||||
"entries_custom_fields": [
|
||||
{
|
||||
"label": "Name",
|
||||
"name": "name",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"label": "Position",
|
||||
"name": "position",
|
||||
"type": "string"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
"""
|
||||
Then an access denied error should occur
|
||||
|
||||
# update content type
|
||||
|
||||
Scenario: Updating content type as an Admin
|
||||
Given I have an "admin" API token
|
||||
When I do an API PUT to content_types/4f832c2cb0d86d3f42fffffe.json with:
|
||||
"""
|
||||
{
|
||||
"content_type": {
|
||||
"name": "Brand new updated name"
|
||||
}
|
||||
}
|
||||
"""
|
||||
When I do an API GET request to content_types/4f832c2cb0d86d3f42fffffe.json
|
||||
Then the JSON response at "id" should be "4f832c2cb0d86d3f42fffffe"
|
||||
And the JSON response at "name" should be "Brand new updated name"
|
||||
|
||||
Scenario: Updating content type as a Designer
|
||||
Given I have a "designer" API token
|
||||
When I do an API PUT to content_types/4f832c2cb0d86d3f42fffffe.json with:
|
||||
"""
|
||||
{
|
||||
"content_type": {
|
||||
"name": "Brand new updated name"
|
||||
}
|
||||
}
|
||||
"""
|
||||
When I do an API GET request to content_types/4f832c2cb0d86d3f42fffffe.json
|
||||
Then the JSON response at "id" should be "4f832c2cb0d86d3f42fffffe"
|
||||
And the JSON response at "name" should be "Brand new updated name"
|
||||
|
||||
Scenario: Updating content type as an Author
|
||||
Given I have a "author" API token
|
||||
When I do an API PUT to content_types/4f832c2cb0d86d3f42fffffe.json with:
|
||||
"""
|
||||
{
|
||||
"content_type": {
|
||||
"name": "Brand new updated name"
|
||||
}
|
||||
}
|
||||
"""
|
||||
Then an access denied error should occur
|
||||
|
||||
# destroy content type
|
||||
|
||||
Scenario: Destroying content type as an Admin
|
||||
Given I have an "admin" API token
|
||||
When I do an API GET request to content_types.json
|
||||
Then the JSON response should be an array
|
||||
And the JSON response should have 1 entry
|
||||
When I do an API DELETE to content_types/4f832c2cb0d86d3f42fffffe.json
|
||||
When I do an API GET request to content_types.json
|
||||
Then the JSON response should be an array
|
||||
And the JSON response should have 0 entries
|
||||
|
||||
Scenario: Destroying content type as a Designer
|
||||
Given I have a "designer" API token
|
||||
When I do an API GET request to content_types.json
|
||||
Then the JSON response should be an array
|
||||
And the JSON response should have 1 entry
|
||||
When I do an API DELETE to content_types/4f832c2cb0d86d3f42fffffe.json
|
||||
When I do an API GET request to content_types.json
|
||||
Then the JSON response should be an array
|
||||
And the JSON response should have 0 entries
|
||||
|
||||
Scenario: Deleting content type as an Author
|
||||
Given I have a "author" API token
|
||||
When I do an API GET request to content_types.json
|
||||
Then the JSON response should be an array
|
||||
And the JSON response should have 1 entries
|
||||
When I do an API DELETE to content_types/4f832c2cb0d86d3f42fffffe.json
|
||||
Then an access denied error should occur
|
30
features/api/authorization/current_site.feature
Normal file
30
features/api/authorization/current_site.feature
Normal file
@ -0,0 +1,30 @@
|
||||
Feature: Current Site
|
||||
In order to ensure the current site can be viewed by all authenticated users
|
||||
As an admin, designer or author
|
||||
I should be able to show the current site
|
||||
|
||||
Background:
|
||||
Given I have the site: "test site" set up
|
||||
And I have a designer and an author
|
||||
|
||||
Scenario: As an unauthenticated user
|
||||
Given I am not authenticated
|
||||
When I do an API GET to current_site.json
|
||||
Then the JSON response at "error" should be "You need to sign in or sign up before continuing."
|
||||
|
||||
# showing current site
|
||||
|
||||
Scenario: Accessing current site as an Admin
|
||||
Given I have an "admin" API token
|
||||
When I do an API GET to current_site.json
|
||||
Then the JSON response at "name" should be "Locomotive test website"
|
||||
|
||||
Scenario: Accessing current site as a Designer
|
||||
Given I have a "designer" API token
|
||||
When I do an API GET to current_site.json
|
||||
Then the JSON response at "name" should be "Locomotive test website"
|
||||
|
||||
Scenario: Accessing current site as an Author
|
||||
Given I have an "author" API token
|
||||
When I do an API GET to current_site.json
|
||||
Then the JSON response at "name" should be "Locomotive test website"
|
225
features/api/authorization/memberships.feature
Normal file
225
features/api/authorization/memberships.feature
Normal file
@ -0,0 +1,225 @@
|
||||
Feature: Memberships
|
||||
In order to ensure memberships are not tampered with
|
||||
As an admin, designer or author
|
||||
I will be restricted based on my role
|
||||
|
||||
Background:
|
||||
Given I have the site: "test site" set up with id: "4f832c2cb0d86d3f42fffffb"
|
||||
And I have accounts:
|
||||
| email | id |
|
||||
| new-user@a.com | 4f832c2cb0d86d3f42fffffc |
|
||||
And I have memberships:
|
||||
| email | role | id |
|
||||
| admin@a.com | admin | 4f832c2cb0d86d3f42fffffd |
|
||||
| designer@a.com | designer | 4f832c2cb0d86d3f42fffffe |
|
||||
| author@a.com | author | 4f832c2cb0d86d3f42ffffff |
|
||||
|
||||
Scenario: As an unauthenticated user
|
||||
Given I am not authenticated
|
||||
When I do an API GET to memberships.json
|
||||
Then the JSON response at "error" should be "You need to sign in or sign up before continuing."
|
||||
|
||||
# listing memberships
|
||||
|
||||
Scenario: Accessing memberships as an Admin
|
||||
Given I have an "admin" API token
|
||||
When I do an API GET request to memberships.json
|
||||
Then the JSON response should be an array
|
||||
And the JSON response should have 4 entries
|
||||
|
||||
Scenario: Accessing memberships as a Designer
|
||||
Given I have a "designer" API token
|
||||
When I do an API GET request to memberships.json
|
||||
Then the JSON response should be an array
|
||||
And the JSON response should have 4 entries
|
||||
|
||||
Scenario: Accessing memberships as an Author
|
||||
Given I have an "author" API token
|
||||
When I do an API GET request to memberships.json
|
||||
Then an access denied error should occur
|
||||
|
||||
# showing membership
|
||||
|
||||
Scenario: Accessing membership as an Admin
|
||||
Given I have an "admin" API token
|
||||
When I do an API GET request to memberships/4f832c2cb0d86d3f42fffffd.json
|
||||
Then the JSON response at "email" should be "admin@a.com"
|
||||
When I do an API GET request to memberships/4f832c2cb0d86d3f42fffffe.json
|
||||
Then the JSON response at "email" should be "designer@a.com"
|
||||
When I do an API GET request to memberships/4f832c2cb0d86d3f42ffffff.json
|
||||
Then the JSON response at "email" should be "author@a.com"
|
||||
|
||||
Scenario: Accessing membership as a Designer
|
||||
Given I have a "designer" API token
|
||||
When I do an API GET request to memberships/4f832c2cb0d86d3f42fffffd.json
|
||||
Then the JSON response at "email" should be "admin@a.com"
|
||||
When I do an API GET request to memberships/4f832c2cb0d86d3f42fffffe.json
|
||||
Then the JSON response at "email" should be "designer@a.com"
|
||||
When I do an API GET request to memberships/4f832c2cb0d86d3f42ffffff.json
|
||||
Then the JSON response at "email" should be "author@a.com"
|
||||
|
||||
Scenario: Accessing membership as an Author
|
||||
Given I have an "author" API token
|
||||
When I do an API GET request to memberships/4f832c2cb0d86d3f42fffffe.json
|
||||
Then an access denied error should occur
|
||||
|
||||
# create membership
|
||||
|
||||
Scenario: Creating new membership as an Admin
|
||||
Given I have an "admin" API token
|
||||
When I do an API POST to memberships.json with:
|
||||
"""
|
||||
{
|
||||
"membership": {
|
||||
"site_id": "4f832c2cb0d86d3f42fffffb",
|
||||
"account_id": "4f832c2cb0d86d3f42fffffc"
|
||||
}
|
||||
}
|
||||
"""
|
||||
When I do an API GET request to memberships.json
|
||||
Then the JSON response should be an array
|
||||
And the JSON response should have 5 entries
|
||||
|
||||
Scenario: Creating new membership as a Designer
|
||||
Given I have a "designer" API token
|
||||
When I do an API POST to memberships.json with:
|
||||
"""
|
||||
{
|
||||
"membership": {
|
||||
"site_id": "4f832c2cb0d86d3f42fffffb",
|
||||
"account_id": "4f832c2cb0d86d3f42fffffc"
|
||||
}
|
||||
}
|
||||
"""
|
||||
When I do an API GET request to memberships.json
|
||||
Then the JSON response should be an array
|
||||
And the JSON response should have 5 entries
|
||||
|
||||
Scenario: Creating new membership as an Author
|
||||
Given I have an "author" API token
|
||||
When I do an API POST to memberships.json with:
|
||||
"""
|
||||
{
|
||||
"membership": {
|
||||
"site_id": "4f832c2cb0d86d3f42fffffb",
|
||||
"account_id": "4f832c2cb0d86d3f42fffffc"
|
||||
}
|
||||
}
|
||||
"""
|
||||
Then an access denied error should occur
|
||||
|
||||
Scenario: Created membership should always be Author
|
||||
Given I have an "admin" API token
|
||||
When I do an API POST to memberships.json with:
|
||||
"""
|
||||
{
|
||||
"membership": {
|
||||
"site_id": "4f832c2cb0d86d3f42fffffb",
|
||||
"account_id": "4f832c2cb0d86d3f42fffffc",
|
||||
"role": "admin"
|
||||
}
|
||||
}
|
||||
"""
|
||||
When I do an API GET request to memberships.json
|
||||
Then the JSON response should be an array
|
||||
And the JSON response should have 5 entries
|
||||
And the JSON at "4/role" should be "author"
|
||||
|
||||
# update membership
|
||||
|
||||
Scenario: Updating membership as an Admin
|
||||
Given I have an "admin" API token
|
||||
When I do an API PUT to memberships/4f832c2cb0d86d3f42ffffff.json with:
|
||||
"""
|
||||
{
|
||||
"membership": {
|
||||
"role": "admin"
|
||||
}
|
||||
}
|
||||
"""
|
||||
When I do an API GET request to memberships/4f832c2cb0d86d3f42ffffff.json
|
||||
Then the JSON response at "role" should be "admin"
|
||||
|
||||
Scenario: Updating membership as a Designer
|
||||
Given I have a "designer" API token
|
||||
When I do an API PUT to memberships/4f832c2cb0d86d3f42ffffff.json with:
|
||||
"""
|
||||
{
|
||||
"membership": {
|
||||
"role": "admin"
|
||||
}
|
||||
}
|
||||
"""
|
||||
When I do an API GET request to memberships/4f832c2cb0d86d3f42ffffff.json
|
||||
Then the JSON response at "role" should be "author"
|
||||
When I do an API PUT to memberships/4f832c2cb0d86d3f42ffffff.json with:
|
||||
"""
|
||||
{
|
||||
"membership": {
|
||||
"role": "designer"
|
||||
}
|
||||
}
|
||||
"""
|
||||
When I do an API GET request to memberships/4f832c2cb0d86d3f42ffffff.json
|
||||
Then the JSON response at "role" should be "designer"
|
||||
|
||||
Scenario: Updating membership as an Author
|
||||
Given I have a "author" API token
|
||||
When I do an API PUT to memberships/4f832c2cb0d86d3f42ffffff.json with:
|
||||
"""
|
||||
{
|
||||
"membership": {
|
||||
"role": "admin"
|
||||
}
|
||||
}
|
||||
"""
|
||||
Then an access denied error should occur
|
||||
When I do an API PUT to memberships/4f832c2cb0d86d3f42ffffff.json with:
|
||||
"""
|
||||
{
|
||||
"membership": {
|
||||
"role": "designer"
|
||||
}
|
||||
}
|
||||
"""
|
||||
Then an access denied error should occur
|
||||
When I do an API PUT to memberships/4f832c2cb0d86d3f42ffffff.json with:
|
||||
"""
|
||||
{
|
||||
"membership": {
|
||||
"role": "author"
|
||||
}
|
||||
}
|
||||
"""
|
||||
Then an access denied error should occur
|
||||
|
||||
# destroy membership
|
||||
|
||||
Scenario: Destroying membership as an Admin
|
||||
Given I have an "admin" API token
|
||||
When I do an API GET request to memberships.json
|
||||
Then the JSON response should be an array
|
||||
And the JSON response should have 4 entries
|
||||
When I do an API DELETE to memberships/4f832c2cb0d86d3f42ffffff.json
|
||||
When I do an API GET request to memberships.json
|
||||
Then the JSON response should be an array
|
||||
And the JSON response should have 3 entries
|
||||
|
||||
Scenario: Destroying membership as a Designer
|
||||
Given I have a "designer" API token
|
||||
When I do an API GET request to memberships.json
|
||||
Then the JSON response should be an array
|
||||
And the JSON response should have 4 entries
|
||||
When I do an API DELETE to memberships/4f832c2cb0d86d3f42ffffff.json
|
||||
When I do an API GET request to memberships.json
|
||||
Then the JSON response should be an array
|
||||
And the JSON response should have 3 entries
|
||||
When I do an API DELETE to memberships/4f832c2cb0d86d3f42fffffe.json
|
||||
Then an access denied error should occur
|
||||
When I do an API DELETE to memberships/4f832c2cb0d86d3f42fffffd.json
|
||||
Then an access denied error should occur
|
||||
|
||||
Scenario: Deleting membership as an Author
|
||||
Given I have a "author" API token
|
||||
When I do an API DELETE to memberships/4f832c2cb0d86d3f42fffffe.json
|
||||
Then an access denied error should occur
|
187
features/api/authorization/pages.feature
Normal file
187
features/api/authorization/pages.feature
Normal file
@ -0,0 +1,187 @@
|
||||
Feature: Pages
|
||||
In order to ensure pages are not tampered with
|
||||
As an admin, designer or author
|
||||
I will be restricted based on my role
|
||||
|
||||
Background:
|
||||
Given I have the site: "test site" set up
|
||||
And I have a custom model named "Projects" with
|
||||
| label | type | required |
|
||||
| Name | string | true |
|
||||
| Description | text | false |
|
||||
And I have a designer and an author
|
||||
And a page named "hello-world" with id "4f832c2cb0d86d3f42fffffe"
|
||||
And a page named "goodbye-world" with id "4f832c2cb0d86d3f42ffffff"
|
||||
|
||||
Scenario: As an unauthenticated user
|
||||
Given I am not authenticated
|
||||
When I do an API GET to pages.json
|
||||
Then the JSON response at "error" should be "You need to sign in or sign up before continuing."
|
||||
|
||||
# listing pages
|
||||
|
||||
Scenario: Accessing pages as an Admin
|
||||
Given I have an "admin" API token
|
||||
When I do an API GET request to pages.json
|
||||
Then the JSON response should be an array
|
||||
And the JSON response should have 4 entries
|
||||
|
||||
Scenario: Accessing pages as a Designer
|
||||
Given I have a "designer" API token
|
||||
When I do an API GET request to pages.json
|
||||
Then the JSON response should be an array
|
||||
And the JSON response should have 4 entries
|
||||
|
||||
Scenario: Accessing pages as an Author
|
||||
Given I have an "author" API token
|
||||
When I do an API GET request to pages.json
|
||||
Then the JSON response should be an array
|
||||
And the JSON response should have 4 entries
|
||||
|
||||
# showing page
|
||||
|
||||
Scenario: Accessing page as an Admin
|
||||
Given I have an "admin" API token
|
||||
When I do an API GET request to pages/4f832c2cb0d86d3f42fffffe.json
|
||||
Then the JSON response at "id" should be "4f832c2cb0d86d3f42fffffe"
|
||||
And the JSON response at "slug" should be "hello-world"
|
||||
|
||||
Scenario: Accessing page as a Designer
|
||||
Given I have a "designer" API token
|
||||
When I do an API GET request to pages/4f832c2cb0d86d3f42fffffe.json
|
||||
Then the JSON response at "id" should be "4f832c2cb0d86d3f42fffffe"
|
||||
And the JSON response at "slug" should be "hello-world"
|
||||
|
||||
Scenario: Accessing page as an Author
|
||||
Given I have an "author" API token
|
||||
When I do an API GET request to pages/4f832c2cb0d86d3f42fffffe.json
|
||||
Then the JSON response at "id" should be "4f832c2cb0d86d3f42fffffe"
|
||||
And the JSON response at "slug" should be "hello-world"
|
||||
|
||||
# create page
|
||||
|
||||
Scenario: Creating new page as an Admin
|
||||
Given I have an "admin" API token
|
||||
When I do an API GET request to pages.json
|
||||
Then the JSON response should be an array
|
||||
And the JSON response should have 4 entries
|
||||
When I do an API POST to pages.json with:
|
||||
"""
|
||||
{
|
||||
"page": {
|
||||
"title": "New Page",
|
||||
"slug": "new-page",
|
||||
"parent_id": "4f832c2cb0d86d3f42fffffe"
|
||||
}
|
||||
}
|
||||
"""
|
||||
When I do an API GET request to pages.json
|
||||
Then the JSON response should be an array
|
||||
And the JSON response should have 5 entries
|
||||
|
||||
Scenario: Creating new page as a Designer
|
||||
Given I have a "designer" API token
|
||||
When I do an API GET request to pages.json
|
||||
Then the JSON response should be an array
|
||||
And the JSON response should have 4 entries
|
||||
When I do an API POST to pages.json with:
|
||||
"""
|
||||
{
|
||||
"page": {
|
||||
"title": "New Page",
|
||||
"slug": "new-page",
|
||||
"parent_id": "4f832c2cb0d86d3f42fffffe"
|
||||
}
|
||||
}
|
||||
"""
|
||||
When I do an API GET request to pages.json
|
||||
Then the JSON response should be an array
|
||||
And the JSON response should have 5 entries
|
||||
|
||||
Scenario: Creating new page as an Author
|
||||
Given I have an "author" API token
|
||||
When I do an API POST to pages.json with:
|
||||
"""
|
||||
{
|
||||
"page": {
|
||||
"title": "New Page",
|
||||
"slug": "new-page",
|
||||
"parent_id": "4f832c2cb0d86d3f42fffffe"
|
||||
}
|
||||
}
|
||||
"""
|
||||
Then an access denied error should occur
|
||||
|
||||
# update page
|
||||
|
||||
Scenario: Updating page as an Admin
|
||||
Given I have an "admin" API token
|
||||
When I do an API PUT to pages/4f832c2cb0d86d3f42fffffe.json with:
|
||||
"""
|
||||
{
|
||||
"page": {
|
||||
"title": "Brand new updated title"
|
||||
}
|
||||
}
|
||||
"""
|
||||
When I do an API GET request to pages/4f832c2cb0d86d3f42fffffe.json
|
||||
Then the JSON response at "id" should be "4f832c2cb0d86d3f42fffffe"
|
||||
And the JSON response at "title" should be "Brand new updated title"
|
||||
|
||||
Scenario: Updating page as a Designer
|
||||
Given I have a "designer" API token
|
||||
When I do an API PUT to pages/4f832c2cb0d86d3f42fffffe.json with:
|
||||
"""
|
||||
{
|
||||
"page": {
|
||||
"title": "Brand new updated title"
|
||||
}
|
||||
}
|
||||
"""
|
||||
When I do an API GET request to pages/4f832c2cb0d86d3f42fffffe.json
|
||||
Then the JSON response at "id" should be "4f832c2cb0d86d3f42fffffe"
|
||||
And the JSON response at "title" should be "Brand new updated title"
|
||||
|
||||
Scenario: Updating page as an Author
|
||||
Given I have a "author" API token
|
||||
When I do an API PUT to pages/4f832c2cb0d86d3f42fffffe.json with:
|
||||
"""
|
||||
{
|
||||
"page": {
|
||||
"title": "Brand new updated title"
|
||||
}
|
||||
}
|
||||
"""
|
||||
When I do an API GET request to pages/4f832c2cb0d86d3f42fffffe.json
|
||||
Then the JSON response at "id" should be "4f832c2cb0d86d3f42fffffe"
|
||||
And the JSON response at "title" should be "Brand new updated title"
|
||||
|
||||
# destroy page
|
||||
|
||||
Scenario: Destroying page as an Admin
|
||||
Given I have an "admin" API token
|
||||
When I do an API GET request to pages.json
|
||||
Then the JSON response should be an array
|
||||
And the JSON response should have 4 entries
|
||||
When I do an API DELETE to pages/4f832c2cb0d86d3f42fffffe.json
|
||||
When I do an API GET request to pages.json
|
||||
Then the JSON response should be an array
|
||||
And the JSON response should have 3 entries
|
||||
|
||||
Scenario: Destroying page as a Designer
|
||||
Given I have a "designer" API token
|
||||
When I do an API GET request to pages.json
|
||||
Then the JSON response should be an array
|
||||
And the JSON response should have 4 entries
|
||||
When I do an API DELETE to pages/4f832c2cb0d86d3f42fffffe.json
|
||||
When I do an API GET request to pages.json
|
||||
Then the JSON response should be an array
|
||||
And the JSON response should have 3 entries
|
||||
|
||||
Scenario: Deleting page as an Author
|
||||
Given I have a "author" API token
|
||||
When I do an API GET request to pages.json
|
||||
Then the JSON response should be an array
|
||||
And the JSON response should have 4 entries
|
||||
When I do an API DELETE to pages/4f832c2cb0d86d3f42fffffe.json
|
||||
Then an access denied error should occur
|
206
features/api/authorization/sites.feature
Normal file
206
features/api/authorization/sites.feature
Normal file
@ -0,0 +1,206 @@
|
||||
Feature: Sites
|
||||
In order to ensure sites are not tampered with
|
||||
As an admin, designer or author
|
||||
I will be restricted based on my role
|
||||
|
||||
Background:
|
||||
Given I have the site: "test site" set up with id: "4f832c2cb0d86d3f42fffffe"
|
||||
And I have the site: "another site" set up with id: "4f832c2cb0d86d3f42ffffff"
|
||||
And I have a designer and an author
|
||||
|
||||
Scenario: As an unauthenticated user
|
||||
Given I am not authenticated
|
||||
When I do an API GET to sites.json
|
||||
Then the JSON response at "error" should be "You need to sign in or sign up before continuing."
|
||||
|
||||
# listing sites
|
||||
|
||||
Scenario: Accessing sites as an Admin
|
||||
Given I have an "admin" API token
|
||||
When I do an API GET request to sites.json
|
||||
Then the JSON response should be an array
|
||||
And the JSON response should have 2 entries
|
||||
|
||||
Scenario: Accessing sites as a Designer
|
||||
Given I have a "designer" API token
|
||||
When I do an API GET request to sites.json
|
||||
Then an access denied error should occur
|
||||
|
||||
Scenario: Accessing sites as an Author
|
||||
Given I have an "author" API token
|
||||
When I do an API GET request to sites.json
|
||||
Then an access denied error should occur
|
||||
|
||||
# showing site
|
||||
|
||||
Scenario: Accessing site as an Admin
|
||||
Given I have an "admin" API token
|
||||
When I do an API GET request to sites/4f832c2cb0d86d3f42fffffe.json
|
||||
Then the JSON response at "name" should be "Locomotive test website"
|
||||
|
||||
Scenario: Accessing my site as a Designer
|
||||
Given I have a "designer" API token
|
||||
When I do an API GET request to sites/4f832c2cb0d86d3f42fffffe.json
|
||||
Then the JSON response at "name" should be "Locomotive test website"
|
||||
|
||||
Scenario: Accessing other site as a Designer
|
||||
Given I have a "designer" API token
|
||||
When I do an API GET request to sites/4f832c2cb0d86d3f42ffffff.json
|
||||
Then an access denied error should occur
|
||||
|
||||
Scenario: Accessing my site as an Author
|
||||
Given I have an "author" API token
|
||||
When I do an API GET request to sites/4f832c2cb0d86d3f42fffffe.json
|
||||
Then the JSON response at "name" should be "Locomotive test website"
|
||||
|
||||
Scenario: Accessing other site as an Author
|
||||
Given I have an "author" API token
|
||||
When I do an API GET request to sites/4f832c2cb0d86d3f42ffffff.json
|
||||
Then an access denied error should occur
|
||||
|
||||
# create site
|
||||
|
||||
Scenario: Creating new site as an Admin
|
||||
Given I have an "admin" API token
|
||||
When I do an API GET request to sites.json
|
||||
Then the JSON response should be an array
|
||||
And the JSON response should have 2 entries
|
||||
When I do an API POST to sites.json with:
|
||||
"""
|
||||
{
|
||||
"site": {
|
||||
"name": "New site",
|
||||
"subdomain": "new-site"
|
||||
}
|
||||
}
|
||||
"""
|
||||
When I do an API GET request to sites.json
|
||||
Then the JSON response should be an array
|
||||
And the JSON response should have 3 entries
|
||||
|
||||
Scenario: Creating new site as a Designer
|
||||
Given I have a "designer" API token
|
||||
When I do an API POST to sites.json with:
|
||||
"""
|
||||
{
|
||||
"site": {
|
||||
"name": "New site",
|
||||
"subdomain": "new-site"
|
||||
}
|
||||
}
|
||||
"""
|
||||
Then an access denied error should occur
|
||||
|
||||
Scenario: Creating new site as an Author
|
||||
Given I have an "author" API token
|
||||
When I do an API POST to sites.json with:
|
||||
"""
|
||||
{
|
||||
"site": {
|
||||
"name": "New site",
|
||||
"subdomain": "new-site"
|
||||
}
|
||||
}
|
||||
"""
|
||||
Then an access denied error should occur
|
||||
|
||||
# update site
|
||||
|
||||
Scenario: Updating site as an Admin
|
||||
Given I have an "admin" API token
|
||||
When I do an API PUT to sites/4f832c2cb0d86d3f42fffffe.json with:
|
||||
"""
|
||||
{
|
||||
"site": {
|
||||
"name": "Brand new updated name"
|
||||
}
|
||||
}
|
||||
"""
|
||||
When I do an API GET request to sites/4f832c2cb0d86d3f42fffffe.json
|
||||
Then the JSON response at "id" should be "4f832c2cb0d86d3f42fffffe"
|
||||
And the JSON response at "name" should be "Brand new updated name"
|
||||
|
||||
Scenario: Updating my site as a Designer
|
||||
Given I have a "designer" API token
|
||||
When I do an API PUT to sites/4f832c2cb0d86d3f42fffffe.json with:
|
||||
"""
|
||||
{
|
||||
"site": {
|
||||
"name": "Brand new updated name"
|
||||
}
|
||||
}
|
||||
"""
|
||||
When I do an API GET request to sites/4f832c2cb0d86d3f42fffffe.json
|
||||
Then the JSON response at "id" should be "4f832c2cb0d86d3f42fffffe"
|
||||
And the JSON response at "name" should be "Brand new updated name"
|
||||
|
||||
Scenario: Updating other site as a Designer
|
||||
Given I have a "designer" API token
|
||||
When I do an API PUT to sites/4f832c2cb0d86d3f42ffffff.json with:
|
||||
"""
|
||||
{
|
||||
"site": {
|
||||
"name": "Brand new updated name"
|
||||
}
|
||||
}
|
||||
"""
|
||||
Then an access denied error should occur
|
||||
|
||||
Scenario: Updating my site as an Author
|
||||
Given I have a "author" API token
|
||||
When I do an API PUT to sites/4f832c2cb0d86d3f42fffffe.json with:
|
||||
"""
|
||||
{
|
||||
"site": {
|
||||
"name": "Brand new updated name"
|
||||
}
|
||||
}
|
||||
"""
|
||||
When I do an API GET request to sites/4f832c2cb0d86d3f42fffffe.json
|
||||
Then the JSON response at "id" should be "4f832c2cb0d86d3f42fffffe"
|
||||
And the JSON response at "name" should be "Brand new updated name"
|
||||
|
||||
Scenario: Updating other site as an Author
|
||||
Given I have a "author" API token
|
||||
When I do an API PUT to sites/4f832c2cb0d86d3f42ffffff.json with:
|
||||
"""
|
||||
{
|
||||
"site": {
|
||||
"name": "Brand new updated name"
|
||||
}
|
||||
}
|
||||
"""
|
||||
Then an access denied error should occur
|
||||
|
||||
# destroy site
|
||||
|
||||
Scenario: Destroying site as an Admin
|
||||
Given I have an "admin" API token
|
||||
When I do an API GET request to sites.json
|
||||
Then the JSON response should be an array
|
||||
And the JSON response should have 2 entries
|
||||
When I do an API DELETE to sites/4f832c2cb0d86d3f42fffffe.json
|
||||
When I do an API GET request to sites.json
|
||||
Then the JSON response should be an array
|
||||
And the JSON response should have 1 entries
|
||||
|
||||
Scenario: Destroying my site as a Designer
|
||||
Given I have a "designer" API token
|
||||
When I do an API DELETE to sites/4f832c2cb0d86d3f42fffffe.json
|
||||
When I do an API GET request to sites/4f832c2cb0d86d3f42fffffe.json
|
||||
Then it should not exist
|
||||
|
||||
Scenario: Deleting other site as a Designer
|
||||
Given I have a "designer" API token
|
||||
When I do an API DELETE to sites/4f832c2cb0d86d3f42ffffff.json
|
||||
Then an access denied error should occur
|
||||
|
||||
Scenario: Deleting my site as an Author
|
||||
Given I have a "author" API token
|
||||
When I do an API DELETE to sites/4f832c2cb0d86d3f42fffffe.json
|
||||
Then an access denied error should occur
|
||||
|
||||
Scenario: Deleting other site as an Author
|
||||
Given I have a "author" API token
|
||||
When I do an API DELETE to sites/4f832c2cb0d86d3f42ffffff.json
|
||||
Then an access denied error should occur
|
179
features/api/authorization/snippets.feature
Normal file
179
features/api/authorization/snippets.feature
Normal file
@ -0,0 +1,179 @@
|
||||
Feature: Snippets
|
||||
In order to ensure snippets are not tampered with
|
||||
As an admin, designer or author
|
||||
I will be restricted based on my role
|
||||
|
||||
Background:
|
||||
Given I have the site: "test site" set up
|
||||
And a snippet named "My Snippet" with id "4f832c2cb0d86d3f42fffffe" and template:
|
||||
"""
|
||||
My Snippet
|
||||
"""
|
||||
And I have a designer and an author
|
||||
|
||||
Scenario: As an unauthenticated user
|
||||
Given I am not authenticated
|
||||
When I do an API GET to snippets.json
|
||||
Then the JSON response at "error" should be "You need to sign in or sign up before continuing."
|
||||
|
||||
# listing content types
|
||||
|
||||
Scenario: Accessing snippets as an Admin
|
||||
Given I have an "admin" API token
|
||||
When I do an API GET request to snippets.json
|
||||
Then the JSON response should be an array
|
||||
And the JSON response should have 1 entry
|
||||
|
||||
Scenario: Accessing snippets as a Designer
|
||||
Given I have a "designer" API token
|
||||
When I do an API GET request to snippets.json
|
||||
Then the JSON response should be an array
|
||||
And the JSON response should have 1 entry
|
||||
|
||||
Scenario: Accessing snippets as an Author
|
||||
Given I have an "author" API token
|
||||
When I do an API GET request to snippets.json
|
||||
Then an access denied error should occur
|
||||
|
||||
# showing snippet
|
||||
|
||||
Scenario: Accessing snippet as an Admin
|
||||
Given I have an "admin" API token
|
||||
When I do an API GET request to snippets/4f832c2cb0d86d3f42fffffe.json
|
||||
Then the JSON response at "id" should be "4f832c2cb0d86d3f42fffffe"
|
||||
And the JSON response at "name" should be "My Snippet"
|
||||
|
||||
Scenario: Accessing snippet as a Designer
|
||||
Given I have a "designer" API token
|
||||
When I do an API GET request to snippets/4f832c2cb0d86d3f42fffffe.json
|
||||
Then the JSON response at "id" should be "4f832c2cb0d86d3f42fffffe"
|
||||
And the JSON response at "name" should be "My Snippet"
|
||||
|
||||
Scenario: Accessing snippet as an Author
|
||||
Given I have an "author" API token
|
||||
When I do an API GET request to snippets/4f832c2cb0d86d3f42fffffe.json
|
||||
Then an access denied error should occur
|
||||
|
||||
# create snippet
|
||||
|
||||
Scenario: Creating new snippet as an Admin
|
||||
Given I have an "admin" API token
|
||||
When I do an API GET request to snippets.json
|
||||
Then the JSON response should be an array
|
||||
And the JSON response should have 1 entry
|
||||
When I do an API POST to snippets.json with:
|
||||
"""
|
||||
{
|
||||
"snippet": {
|
||||
"name": "Another snippet",
|
||||
"template": "<h1>Another Snippet!</h1>"
|
||||
}
|
||||
}
|
||||
"""
|
||||
When I do an API GET request to snippets.json
|
||||
Then the JSON response should be an array
|
||||
And the JSON response should have 2 entries
|
||||
And the JSON should have the following:
|
||||
| 1/name | "Another Snippet" |
|
||||
| 1/template | "<h1>Another Snippet!</h1>" |
|
||||
|
||||
Scenario: Creating new snippet as a Designer
|
||||
Given I have a "designer" API token
|
||||
When I do an API GET request to snippets.json
|
||||
Then the JSON response should be an array
|
||||
And the JSON response should have 1 entry
|
||||
When I do an API POST to snippets.json with:
|
||||
"""
|
||||
{
|
||||
"snippet": {
|
||||
"name": "Another snippet",
|
||||
"template": "<h1>Another Snippet!</h1>"
|
||||
}
|
||||
}
|
||||
"""
|
||||
When I do an API GET request to snippets.json
|
||||
Then the JSON response should be an array
|
||||
And the JSON response should have 2 entries
|
||||
And the JSON should have the following:
|
||||
| 1/name | "Another Snippet" |
|
||||
| 1/template | "<h1>Another Snippet!</h1>" |
|
||||
|
||||
Scenario: Creating new snippet as an Author
|
||||
Given I have an "author" API token
|
||||
When I do an API POST to snippets.json with:
|
||||
"""
|
||||
{
|
||||
"snippet": {
|
||||
"name": "Another snippet",
|
||||
"template": "<h1>Another Snippet!</h1>"
|
||||
}
|
||||
}
|
||||
"""
|
||||
Then an access denied error should occur
|
||||
|
||||
# update snippet
|
||||
|
||||
Scenario: Updating snippet as an Admin
|
||||
Given I have an "admin" API token
|
||||
When I do an API PUT to snippets/4f832c2cb0d86d3f42fffffe.json with:
|
||||
"""
|
||||
{
|
||||
"snippet": {
|
||||
"name": "Brand new updated name"
|
||||
}
|
||||
}
|
||||
"""
|
||||
When I do an API GET request to snippets/4f832c2cb0d86d3f42fffffe.json
|
||||
Then the JSON response at "name" should be "Brand new updated name"
|
||||
|
||||
Scenario: Updating snippet as a Designer
|
||||
Given I have a "designer" API token
|
||||
When I do an API PUT to snippets/4f832c2cb0d86d3f42fffffe.json with:
|
||||
"""
|
||||
{
|
||||
"snippet": {
|
||||
"name": "Brand new updated name"
|
||||
}
|
||||
}
|
||||
"""
|
||||
When I do an API GET request to snippets/4f832c2cb0d86d3f42fffffe.json
|
||||
Then the JSON response at "name" should be "Brand new updated name"
|
||||
|
||||
Scenario: Updating snippet as an Author
|
||||
Given I have a "author" API token
|
||||
When I do an API PUT to snippets/4f832c2cb0d86d3f42fffffe.json with:
|
||||
"""
|
||||
{
|
||||
"snippet": {
|
||||
"name": "Brand new updated name"
|
||||
}
|
||||
}
|
||||
"""
|
||||
Then an access denied error should occur
|
||||
|
||||
# destroy snippet
|
||||
|
||||
Scenario: Destroying snippet as an Admin
|
||||
Given I have an "admin" API token
|
||||
When I do an API GET request to snippets.json
|
||||
Then the JSON response should be an array
|
||||
And the JSON response should have 1 entry
|
||||
When I do an API DELETE to snippets/4f832c2cb0d86d3f42fffffe.json
|
||||
When I do an API GET request to snippets.json
|
||||
Then the JSON response should be an array
|
||||
And the JSON response should have 0 entries
|
||||
|
||||
Scenario: Destroying snippet as a Designer
|
||||
Given I have a "designer" API token
|
||||
When I do an API GET request to snippets.json
|
||||
Then the JSON response should be an array
|
||||
And the JSON response should have 1 entry
|
||||
When I do an API DELETE to snippets/4f832c2cb0d86d3f42fffffe.json
|
||||
When I do an API GET request to snippets.json
|
||||
Then the JSON response should be an array
|
||||
And the JSON response should have 0 entries
|
||||
|
||||
Scenario: Deleting snippet as an Author
|
||||
Given I have a "author" API token
|
||||
When I do an API DELETE to snippets/4f832c2cb0d86d3f42fffffe.json
|
||||
Then an access denied error should occur
|
185
features/api/authorization/theme_assets.feature
Normal file
185
features/api/authorization/theme_assets.feature
Normal file
@ -0,0 +1,185 @@
|
||||
Feature: Theme Assets
|
||||
In order to ensure theme assets are not tampered with
|
||||
As an admin, designer or author
|
||||
I will be restricted based on my role
|
||||
|
||||
Background:
|
||||
Given I have the site: "test site" set up
|
||||
And a javascript asset named "my_javascript.js" with id "4f832c2cb0d86d3f42fffffe"
|
||||
And a stylesheet asset named "my_stylesheet.css" with id "4f832c2cb0d86d3f42ffffff"
|
||||
|
||||
Scenario: As an unauthenticated user
|
||||
Given I am not authenticated
|
||||
When I do an API GET to theme_assets.json
|
||||
Then the JSON response at "error" should be "You need to sign in or sign up before continuing."
|
||||
|
||||
# listing theme assets
|
||||
|
||||
Scenario: Accessing theme assets as an Admin
|
||||
Given I have an "admin" API token
|
||||
When I do an API GET request to theme_assets.json
|
||||
Then the JSON response should be an array
|
||||
And the JSON response should have 2 entries
|
||||
|
||||
Scenario: Accessing theme assets as a Designer
|
||||
Given I have a "designer" API token
|
||||
When I do an API GET request to theme_assets.json
|
||||
Then the JSON response should be an array
|
||||
And the JSON response should have 2 entries
|
||||
|
||||
Scenario: Accessing theme assets as an Author
|
||||
Given I have an "author" API token
|
||||
When I do an API GET request to theme_assets.json
|
||||
Then the JSON response should be an array
|
||||
And the JSON response should have 2 entries
|
||||
|
||||
# showing theme asset
|
||||
|
||||
Scenario: Accessing theme asset as an Admin
|
||||
Given I have an "admin" API token
|
||||
When I do an API GET request to theme_assets/4f832c2cb0d86d3f42fffffe.json
|
||||
Then the JSON response at "local_path" should be "my_javascript.js"
|
||||
|
||||
Scenario: Accessing theme asset as a Designer
|
||||
Given I have a "designer" API token
|
||||
When I do an API GET request to theme_assets/4f832c2cb0d86d3f42fffffe.json
|
||||
Then the JSON response at "local_path" should be "my_javascript.js"
|
||||
|
||||
Scenario: Accessing theme asset as an Author
|
||||
Given I have an "author" API token
|
||||
When I do an API GET request to theme_assets/4f832c2cb0d86d3f42fffffe.json
|
||||
Then the JSON response at "local_path" should be "my_javascript.js"
|
||||
|
||||
# create theme asset
|
||||
|
||||
Scenario: Creating new theme asset as an Admin
|
||||
Given I have an "admin" API token
|
||||
When I do an API GET request to theme_assets.json
|
||||
Then the JSON response should be an array
|
||||
And the JSON response should have 2 entries
|
||||
When I do an API POST to theme_assets.json with:
|
||||
"""
|
||||
{
|
||||
"theme_asset": {
|
||||
"plain_text_name": "new-javascript.js",
|
||||
"plain_text": "function doNothing() {}",
|
||||
"plain_text_type": "javascript",
|
||||
"performing_plain_text": "true"
|
||||
}
|
||||
}
|
||||
"""
|
||||
When I do an API GET request to theme_assets.json
|
||||
Then the JSON response should be an array
|
||||
And the JSON response should have 3 entries
|
||||
And the JSON should have the following:
|
||||
| 2/local_path | "new-javascript.js" |
|
||||
| 2/content_type | "javascript" |
|
||||
|
||||
Scenario: Creating new theme asset as a Designer
|
||||
Given I have a "designer" API token
|
||||
When I do an API GET request to theme_assets.json
|
||||
Then the JSON response should be an array
|
||||
And the JSON response should have 2 entries
|
||||
When I do an API POST to theme_assets.json with:
|
||||
"""
|
||||
{
|
||||
"theme_asset": {
|
||||
"plain_text_name": "new-javascript.js",
|
||||
"plain_text": "function doNothing() {}",
|
||||
"plain_text_type": "javascript",
|
||||
"performing_plain_text": "true"
|
||||
}
|
||||
}
|
||||
"""
|
||||
When I do an API GET request to theme_assets.json
|
||||
Then the JSON response should be an array
|
||||
And the JSON response should have 3 entries
|
||||
And the JSON should have the following:
|
||||
| 2/local_path | "new-javascript.js" |
|
||||
| 2/content_type | "javascript" |
|
||||
|
||||
Scenario: Creating new theme asset as an Author
|
||||
Given I have an "author" API token
|
||||
When I do an API POST to theme_assets.json with:
|
||||
"""
|
||||
{
|
||||
"theme_asset": {
|
||||
"plain_text_name": "new-javascript.js",
|
||||
"plain_text": "function doNothing() {}",
|
||||
"plain_text_type": "javascript",
|
||||
"performing_plain_text": "true"
|
||||
}
|
||||
}
|
||||
"""
|
||||
Then an access denied error should occur
|
||||
|
||||
# update theme asset
|
||||
|
||||
Scenario: Updating theme asset as an Admin
|
||||
Given I have an "admin" API token
|
||||
When I do an API PUT to theme_assets/4f832c2cb0d86d3f42fffffe.json with:
|
||||
"""
|
||||
{
|
||||
"theme_asset": {
|
||||
"plain_text_name": "newer-javascript.js"
|
||||
}
|
||||
}
|
||||
"""
|
||||
When I do an API GET request to theme_assets/4f832c2cb0d86d3f42fffffe.json
|
||||
Then the JSON response should have the following:
|
||||
| local_path | "newer-javascript.js" |
|
||||
|
||||
Scenario: Updating theme asset as a Designer
|
||||
Given I have a "designer" API token
|
||||
When I do an API PUT to theme_assets/4f832c2cb0d86d3f42fffffe.json with:
|
||||
"""
|
||||
{
|
||||
"theme_asset": {
|
||||
"plain_text_name": "newer-javascript.js"
|
||||
}
|
||||
}
|
||||
"""
|
||||
When I do an API GET request to theme_assets/4f832c2cb0d86d3f42fffffe.json
|
||||
Then the JSON response should have the following:
|
||||
| local_path | "newer-javascript.js" |
|
||||
|
||||
Scenario: Updating theme asset as an Author
|
||||
Given I have a "author" API token
|
||||
When I do an API PUT to theme_assets/4f832c2cb0d86d3f42fffffe.json with:
|
||||
"""
|
||||
{
|
||||
"theme_asset": {
|
||||
"plain_text_name": "newer-javascript.js"
|
||||
}
|
||||
}
|
||||
"""
|
||||
When I do an API GET request to theme_assets/4f832c2cb0d86d3f42fffffe.json
|
||||
Then the JSON response should have the following:
|
||||
| local_path | "newer-javascript.js" |
|
||||
|
||||
# destroy theme asset
|
||||
|
||||
Scenario: Destroying theme asset as an Admin
|
||||
Given I have an "admin" API token
|
||||
When I do an API GET request to theme_assets.json
|
||||
Then the JSON response should be an array
|
||||
And the JSON response should have 2 entries
|
||||
When I do an API DELETE to theme_assets/4f832c2cb0d86d3f42fffffe.json
|
||||
When I do an API GET request to theme_assets.json
|
||||
Then the JSON response should be an array
|
||||
And the JSON response should have 1 entries
|
||||
|
||||
Scenario: Destroying theme asset as a Designer
|
||||
Given I have a "designer" API token
|
||||
When I do an API GET request to theme_assets.json
|
||||
Then the JSON response should be an array
|
||||
And the JSON response should have 2 entries
|
||||
When I do an API DELETE to theme_assets/4f832c2cb0d86d3f42fffffe.json
|
||||
When I do an API GET request to theme_assets.json
|
||||
Then the JSON response should be an array
|
||||
And the JSON response should have 1 entries
|
||||
|
||||
Scenario: Deleting theme asset as an Author
|
||||
Given I have a "author" API token
|
||||
When I do an API DELETE to theme_assets/4f832c2cb0d86d3f42fffffe.json
|
||||
Then an access denied error should occur
|
@ -1,3 +1,26 @@
|
||||
|
||||
def api_base_url
|
||||
"http://#{Locomotive::Site.first.domains.first}/locomotive/api/"
|
||||
end
|
||||
|
||||
def do_api_request(type, url, param_string_or_hash = nil)
|
||||
begin
|
||||
if param_string_or_hash
|
||||
if param_string_or_hash.is_a? Hash
|
||||
params = param_string_or_hash
|
||||
else
|
||||
params = JSON.parse(param_string_or_hash)
|
||||
end
|
||||
else
|
||||
params = {}
|
||||
end
|
||||
@json_response = do_request(type, api_base_url, url,
|
||||
params.merge({ 'CONTENT_TYPE' => 'application/json' }))
|
||||
rescue CanCan::AccessDenied, Mongoid::Errors::DocumentNotFound
|
||||
@error = $!
|
||||
end
|
||||
end
|
||||
|
||||
def last_json
|
||||
@json_response.try(:body) || page.source
|
||||
end
|
||||
@ -11,13 +34,16 @@ Given /^I have an? "([^"]*)" API token$/ do |role|
|
||||
'password' => 'easyone'
|
||||
}
|
||||
|
||||
response = post("http://#{@site.domains.first}/locomotive/api/tokens.json", login_params.to_json, { 'CONTENT_TYPE' => 'application/json' })
|
||||
response = do_request('POST', api_base_url, 'tokens.json',
|
||||
login_params.merge({ 'CONTENT_TYPE' => 'application/json' }))
|
||||
|
||||
if response.status == 200
|
||||
@auth_token = JSON.parse(response.body)['token']
|
||||
else
|
||||
raise JSON.parse(response.body)['message']
|
||||
end
|
||||
|
||||
add_default_params(:auth_token => @auth_token)
|
||||
end
|
||||
|
||||
Given /^I do not have an API token$/ do
|
||||
@ -35,4 +61,36 @@ end
|
||||
|
||||
When /^I post to "([^"]*)" with:$/ do |path, json_string|
|
||||
@json_response = post("http://#{@site.domains.first}#{path}", json_string, { 'CONTENT_TYPE' => 'application/json' })
|
||||
end
|
||||
end
|
||||
|
||||
When /^I do an API (\w+) (?:request )?to ([\w.\/]+)$/ do |request_type, url|
|
||||
do_api_request(request_type, url)
|
||||
end
|
||||
|
||||
When /^I do an API (\w+) (?:request )?to ([\w.\/]+) with:$/ do |request_type, url, param_string|
|
||||
do_api_request(request_type, url, param_string)
|
||||
end
|
||||
|
||||
Then /^an access denied error should occur$/ do
|
||||
@error.should_not be_nil
|
||||
@error.is_a?(CanCan::AccessDenied).should be_true
|
||||
end
|
||||
|
||||
Then /^it should not exist$/ do
|
||||
@error.should_not be_nil
|
||||
@error.is_a?(Mongoid::Errors::DocumentNotFound).should be_true
|
||||
end
|
||||
|
||||
When /^I do a multipart API (\w+) (?:request )?to ([\w.\/]+) with base key "([^"]*)" and:$/ \
|
||||
do |request_type, url, base_key, table|
|
||||
params = {}
|
||||
params = table.rows_hash
|
||||
params.each do |key, filename|
|
||||
params[key] = Rack::Test::UploadedFile.new(Rails.root.join('..', 'fixtures', filename))
|
||||
end
|
||||
do_api_request(request_type, url, { base_key => params })
|
||||
end
|
||||
|
||||
Then /^I print the json response$/ do
|
||||
puts %{JSON: "#{last_json}"}
|
||||
end
|
||||
|
12
features/step_definitions/content_assets_steps.rb
Normal file
12
features/step_definitions/content_assets_steps.rb
Normal file
@ -0,0 +1,12 @@
|
||||
|
||||
Given /^I have the following content assets:$/ do |table|
|
||||
site = Locomotive::Site.first
|
||||
table.hashes.each do |asset_hash|
|
||||
asset_hash['site'] = site
|
||||
asset_hash['source'] = FixturedAsset.open(asset_hash['file'])
|
||||
asset_hash.delete('file')
|
||||
|
||||
asset = FactoryGirl.build(:asset, asset_hash)
|
||||
asset.save.should be_true
|
||||
end
|
||||
end
|
@ -1,6 +1,9 @@
|
||||
Given %r{^I have a custom model named "([^"]*)" with$} do |name, fields|
|
||||
def build_content_type(name)
|
||||
site = Locomotive::Site.first
|
||||
content_type = FactoryGirl.build(:content_type, :site => site, :name => name, :order_by => '_position')
|
||||
FactoryGirl.build(:content_type, :site => site, :name => name, :order_by => '_position')
|
||||
end
|
||||
|
||||
def set_custom_fields_from_table(content_type, fields)
|
||||
fields.hashes.each do |field|
|
||||
# found a belongs_to association
|
||||
if field['type'] == 'belongs_to'
|
||||
@ -12,6 +15,19 @@ Given %r{^I have a custom model named "([^"]*)" with$} do |name, fields|
|
||||
|
||||
content_type.entries_custom_fields.build field
|
||||
end
|
||||
end
|
||||
|
||||
Given %r{^I have a custom model named "([^"]*)" with id "([^"]*)" and$} do |name, id, fields|
|
||||
content_type = build_content_type(name)
|
||||
content_type.id = BSON::ObjectId(id)
|
||||
set_custom_fields_from_table(content_type, fields)
|
||||
content_type.valid?
|
||||
content_type.save.should be_true
|
||||
end
|
||||
|
||||
Given %r{^I have a custom model named "([^"]*)" with$} do |name, fields|
|
||||
content_type = build_content_type(name)
|
||||
set_custom_fields_from_table(content_type, fields)
|
||||
content_type.valid?
|
||||
content_type.save.should be_true
|
||||
end
|
||||
|
19
features/step_definitions/membership_steps.rb
Normal file
19
features/step_definitions/membership_steps.rb
Normal file
@ -0,0 +1,19 @@
|
||||
|
||||
Given /^I have accounts:$/ do |accounts_table|
|
||||
accounts_table.hashes.each do |account_hash|
|
||||
FactoryGirl.create(:account, account_hash)
|
||||
end
|
||||
end
|
||||
|
||||
Given /^I have memberships:$/ do |members_table|
|
||||
members_table.hashes.each do |member_hash|
|
||||
email = member_hash[:email]
|
||||
account = Locomotive::Account.where(:email => email).first \
|
||||
|| FactoryGirl.create(:account, :email => email)
|
||||
|
||||
member_hash.delete(:email)
|
||||
member_hash.merge!({ :account => account, :site => @site })
|
||||
|
||||
FactoryGirl.create(:membership, member_hash)
|
||||
end
|
||||
end
|
@ -2,9 +2,16 @@
|
||||
|
||||
# helps create a simple content page (parent: "index") with a slug, contents, and template
|
||||
def create_content_page(page_slug, page_contents, template = nil)
|
||||
@home = @site.pages.where(:slug => "index").first || FactoryGirl.create(:page)
|
||||
page = @site.pages.create(:slug => page_slug, :body => page_contents, :parent => @home, :title => "some title", :published => true, :raw_template => template)
|
||||
page = new_content_page(page_slug, page_contents, template)
|
||||
page.should be_valid
|
||||
page.save!
|
||||
page
|
||||
end
|
||||
|
||||
# build page without saving
|
||||
def new_content_page(page_slug, page_contents, template = nil)
|
||||
@home = @site.pages.where(:slug => "index").first || FactoryGirl.create(:page)
|
||||
page = @site.pages.new(:slug => page_slug, :body => page_contents, :parent => @home, :title => "some title", :published => true, :raw_template => template)
|
||||
page
|
||||
end
|
||||
|
||||
@ -17,6 +24,12 @@ Given /^a page named "([^"]*)" with the template:$/ do |page_slug, template|
|
||||
@page = create_content_page(page_slug, '', template)
|
||||
end
|
||||
|
||||
Given /^a page named "([^"]*)" with id "([^"]*)"$/ do |page_slug, id|
|
||||
@page = new_content_page(page_slug, '')
|
||||
@page.id = BSON::ObjectId(id)
|
||||
@page.save!
|
||||
end
|
||||
|
||||
# change the title
|
||||
When /^I change the page title to "([^"]*)"$/ do |page_title|
|
||||
page.evaluate_script "window.prompt = function() { return '#{page_title}'; }"
|
||||
|
@ -1,9 +1,13 @@
|
||||
### Snippets
|
||||
|
||||
# helps create a simple snippet with a slug and template
|
||||
def new_snippet(name, template = nil)
|
||||
@site.snippets.new(:name => name, :template => template)
|
||||
end
|
||||
|
||||
def create_snippet(name, template = nil)
|
||||
snippet = @site.snippets.create(:name => name, :template => template)
|
||||
snippet.should be_valid
|
||||
snippet = new_snippet(name, template)
|
||||
snippet.save!
|
||||
snippet
|
||||
end
|
||||
|
||||
@ -13,6 +17,12 @@ Given /^a snippet named "([^"]*)" with the template:$/ do |name, template|
|
||||
@snippet = create_snippet(name, template)
|
||||
end
|
||||
|
||||
Given /^a snippet named "([^"]*)" with id "([^"]*)" and template:$/ do |name, id, template|
|
||||
@snippet = new_snippet(name, template)
|
||||
@snippet.id = BSON::ObjectId(id)
|
||||
@snippet.save!
|
||||
end
|
||||
|
||||
When /^I change the snippet template to "([^"]*)"$/ do |code|
|
||||
page.evaluate_script "window.application_view.view.editor.setValue('#{code}')"
|
||||
end
|
||||
|
@ -1,15 +1,18 @@
|
||||
### Theme assets
|
||||
|
||||
# helps create a theme asset
|
||||
def create_plain_text_asset(name, type)
|
||||
asset = FactoryGirl.build(:theme_asset, {
|
||||
def new_plain_text_asset(name, type)
|
||||
FactoryGirl.build(:theme_asset, {
|
||||
:site => @site,
|
||||
:plain_text_name => name,
|
||||
:plain_text => 'Lorem ipsum',
|
||||
:plain_text_type => type,
|
||||
:performing_plain_text => true
|
||||
})
|
||||
end
|
||||
|
||||
def create_plain_text_asset(name, type)
|
||||
asset = new_plain_text_asset(name, type)
|
||||
asset.save!
|
||||
end
|
||||
|
||||
@ -19,10 +22,22 @@ Given /^a javascript asset named "([^"]*)"$/ do |name|
|
||||
@asset = create_plain_text_asset(name, 'javascript')
|
||||
end
|
||||
|
||||
Given /^a javascript asset named "([^"]*)" with id "([^"]*)"$/ do |name, id|
|
||||
@asset = new_plain_text_asset(name, 'javascript')
|
||||
@asset.id = BSON::ObjectId(id)
|
||||
@asset.save!
|
||||
end
|
||||
|
||||
Given /^a stylesheet asset named "([^"]*)"$/ do |name|
|
||||
@asset = create_plain_text_asset(name, 'stylesheet')
|
||||
end
|
||||
|
||||
Given /^a stylesheet asset named "([^"]*)" with id "([^"]*)"$/ do |name, id|
|
||||
@asset = new_plain_text_asset(name, 'stylesheet')
|
||||
@asset.id = BSON::ObjectId(id)
|
||||
@asset.save!
|
||||
end
|
||||
|
||||
Given /^I have an image theme asset named "([^"]*)"$/ do |name|
|
||||
@asset = FactoryGirl.create(:theme_asset, :site => @site, :source => File.open(Rails.root.join('..', 'fixtures', 'assets', '5k.png')))
|
||||
@asset.source_filename = name
|
||||
|
22
features/support/http.rb
Normal file
22
features/support/http.rb
Normal file
@ -0,0 +1,22 @@
|
||||
module HTTPHelpers
|
||||
|
||||
attr_accessor :default_params
|
||||
|
||||
def add_default_params(params)
|
||||
default_params.merge!(params)
|
||||
end
|
||||
|
||||
def do_request(type, base_url, url, params)
|
||||
request_method = type.downcase.to_sym
|
||||
send(request_method, "#{base_url}/#{url}", default_params.merge(params))
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def default_params
|
||||
@default_params ||= {}
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
World(HTTPHelpers)
|
BIN
spec/fixtures/assets/5k_2.png
vendored
Normal file
BIN
spec/fixtures/assets/5k_2.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.3 KiB |
Loading…
Reference in New Issue
Block a user