mumuki-bibliotheca 6.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 20ad4ce643d71a35210b3a5147bb148fa9db30fc
4
+ data.tar.gz: d6cf6ab9a0a1ef05070e6a62cc3be0cef7a656b8
5
+ SHA512:
6
+ metadata.gz: 945fdcd017255e86ea50565ffa29cef07393f628365048804cf259e299d1dc4107d8e9899512f2851ddeef56b5d42263b6932da9c78cf26dd5cef55e3ddb9ec0
7
+ data.tar.gz: 2b75fdbd6b1952a77009a19b894450366eccacf9ba70afbb347fa6912e963bda1c15a7331df00ef62288cdb7c8e2bd47c0a83e7cde26f1cea6e160e9cf03fcde
data/README.md ADDED
@@ -0,0 +1,141 @@
1
+ [![Build Status](https://travis-ci.org/mumuki/mumuki-bibliotheca-api.svg?branch=master)](https://travis-ci.org/mumuki/mumuki-bibliotheca-api)
2
+ [![Code Climate](https://codeclimate.com/github/mumuki/mumuki-bibliotheca-api/badges/gpa.svg)](https://codeclimate.com/github/mumuki/mumuki-bibliotheca-api)
3
+ [![Test Coverage](https://codeclimate.com/github/mumuki/mumuki-bibliotheca-api/badges/coverage.svg)](https://codeclimate.com/github/mumuki/mumuki-bibliotheca-api)
4
+ [![Issue Count](https://codeclimate.com/github/mumuki/mumuki-bibliotheca-api/badges/issue_count.svg)](https://codeclimate.com/github/mumuki/mumuki-bibliotheca-api)
5
+
6
+ # Mumuki Bibliotheca API
7
+ > Storage and formatting API for guides
8
+
9
+ ## About
10
+
11
+ Bibliotheca is a service for storing Mumuki content - Books, Topics and Guides. Its main persistent media is MongoDB, but it is also capable of importing and exporting guides from a Github repository. Features:
12
+
13
+ * REST API
14
+ * Importing and exporting to a Github repository
15
+ * Listing and upserting guides in JSON format
16
+ * Pemissions validation
17
+ * Optional changes notifications to Aheneum
18
+
19
+ ## Preparing environment
20
+
21
+ ### 1. Install essentials and base libraries
22
+
23
+ > First, we need to install some software: MongoDB and some common Ruby on Rails native dependencies
24
+
25
+ 1. Follow [MongoDB installation guide](https://docs.mongodb.com/v3.2/tutorial/install-mongodb-on-ubuntu/)
26
+ 2. Run:
27
+
28
+ ```bash
29
+ sudo apt-get install autoconf curl git build-essential libssl-dev autoconf bison libreadline6 libreadline6-dev zlib1g zlib1g-dev
30
+ ```
31
+
32
+ ### 2. Install rbenv
33
+
34
+ > [rbenv](https://github.com/rbenv/rbenv) is a ruby versions manager, similar to rvm, nvm, and so on.
35
+
36
+ ```bash
37
+ curl https://raw.githubusercontent.com/rbenv/rbenv-installer/master/bin/rbenv-installer | bash
38
+ echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bashrc # or .bash_profile
39
+ echo 'eval "$(rbenv init -)"' >> ~/.bashrc # or .bash_profile
40
+ ```
41
+
42
+ ### 3. Install ruby
43
+
44
+ > Now we have rbenv installed, we can install ruby and [bundler](http://bundler.io/)
45
+
46
+ ```bash
47
+ rbenv install 2.3.1
48
+ rbenv global 2.3.1
49
+ rbenv rehash
50
+ gem install bundler
51
+ gem install escualo
52
+ ```
53
+
54
+ ### 4. Clone this repository
55
+
56
+ > Because, err... we need to clone this repostory before developing it :stuck_out_tongue:
57
+
58
+ ```bash
59
+ git clone https://github.com/mumuki/mumuki-bibliotheca-api bibliotheca-api
60
+ cd bibliotheca-api
61
+ ```
62
+
63
+ ## Installing and Running
64
+
65
+ ### Quick start
66
+
67
+ If you want to start the server quickly in developer environment,
68
+ you can just do the following:
69
+
70
+ ```bash
71
+ ./devstart
72
+ ```
73
+
74
+ This will install your dependencies and boot the server.
75
+
76
+ ### Installing the server
77
+
78
+ If you just want to install dependencies, just do:
79
+
80
+ ```
81
+ bundle install
82
+ ```
83
+
84
+ ### Running the server
85
+
86
+ You can boot the server by using the standard rackup command:
87
+
88
+ ```
89
+ # using defaults from config/puma.rb and rackup default port 9292
90
+ bundle exec rackup
91
+
92
+ # changing port
93
+ bundle exec rackup -p 8080
94
+
95
+ # changing threads count
96
+ MUMUKI_BIBLIOTHECA_API_THREADS=30 bundle exec rackup
97
+ ```
98
+
99
+ Or you can also start it with `puma` command, which gives you more control:
100
+
101
+ ```
102
+ # using defaults from config/puma.rb
103
+ bundle exec puma
104
+
105
+ # changing ports and threads count, using puma-specific options:
106
+ bundle exec puma -t 2:30 -p 8080
107
+
108
+ # changing ports and threads count, using environment variables:
109
+ MUMUKI_BIBLIOTHECA_API_PORT=8080 MUMUKI_BIBLIOTHECA_API_THREADS=30 bundle exec puma
110
+ ```
111
+
112
+ ## Running tests
113
+
114
+ ```bash
115
+ bundle exec rspec
116
+ ```
117
+
118
+ ## Running tasks
119
+
120
+ ```bash
121
+ # import guides from a github organization
122
+ bundle exec rake guides:import[<a github organization>]
123
+
124
+ # import languages from http://thesaurus.mumuki.io
125
+ bundle exec rake languages:import
126
+ ```
127
+
128
+ ## Running Migrations
129
+
130
+ ```bash
131
+ # migration_name is the name of the migration file in ./migrations/, without extension and the "migrate_" prefix
132
+ bundle exec rake db:migrate[<migration_name>]
133
+ ```
134
+
135
+ ## See also
136
+
137
+ [Bibliotheca Web Client](https://github.com/mumuki/mumuki-bibliotheca)
138
+
139
+ ## Authentication Powered by Auth0
140
+
141
+ <a width="150" height="50" href="https://auth0.com/" target="_blank" alt="Single Sign On & Token Based Authentication - Auth0"><img width="150" height="50" alt="JWT Auth for open source projects" src="http://cdn.auth0.com/oss/badges/a0-badge-dark.png"/></a>
data/Rakefile ADDED
@@ -0,0 +1,29 @@
1
+ begin
2
+ require 'bundler/setup'
3
+ rescue LoadError
4
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
5
+ end
6
+
7
+ require 'rdoc/task'
8
+
9
+ RDoc::Task.new(:rdoc) do |rdoc|
10
+ rdoc.rdoc_dir = 'rdoc'
11
+ rdoc.title = 'Mumuki::Bibliotheca'
12
+ rdoc.options << '--line-numbers'
13
+ rdoc.rdoc_files.include('README.md')
14
+ rdoc.rdoc_files.include('lib/**/*.rb')
15
+ end
16
+
17
+ APP_RAKEFILE = File.expand_path("../spec/dummy/Rakefile", __FILE__)
18
+ load 'rails/tasks/engine.rake'
19
+ load 'rails/tasks/statistics.rake'
20
+
21
+ require 'bundler/gem_tasks'
22
+
23
+ require 'rspec/core'
24
+ require 'rspec/core/rake_task'
25
+
26
+ desc "Run all specs in spec directory (excluding plugin specs)"
27
+ RSpec::Core::RakeTask.new(:spec => 'app:db:test:prepare')
28
+
29
+ task default: :spec
data/config/routes.rb ADDED
@@ -0,0 +1,2 @@
1
+ Rails.application.routes.draw do
2
+ end
data/lib/events.rb ADDED
@@ -0,0 +1,15 @@
1
+ Mumukit::Nuntius::EventConsumer.handle do
2
+ # Emitted by:
3
+ # * new logins in laboratory
4
+ # * new logins in classroom
5
+ # * user creation and modification in laboratory
6
+ # * user creation and modification in classroom
7
+ event :UserChanged do |data|
8
+ User.import_from_resource_h! payload.deep_symbolize_keys[:user]
9
+ end
10
+
11
+ # Emitted by organization creation and modification in laboratory
12
+ event :OrganizationChanged do |payload|
13
+ Organization.import_from_resource_h! payload.deep_symbolize_keys[:organization]
14
+ end
15
+ end
@@ -0,0 +1,22 @@
1
+ module Mumuki
2
+ module Bibliotheca
3
+ end
4
+ end
5
+
6
+ require 'mumuki/domain'
7
+ require 'mumukit/login'
8
+ require 'mumukit/nuntius'
9
+ require 'mumukit/platform'
10
+
11
+ Mumukit::Nuntius.configure do |c|
12
+ c.app_name = 'bibliotheca'
13
+ end
14
+
15
+ Mumukit::Platform.configure do |config|
16
+ config.application = Mumukit::Platform.bibliotheca_api
17
+ config.web_framework = Mumukit::Platform::WebFramework::Sinatra
18
+ end
19
+
20
+ require_relative './bibliotheca/syncer'
21
+ require_relative './bibliotheca/sinatra'
22
+ require_relative './bibliotheca/engine'
@@ -0,0 +1,8 @@
1
+ module Mumuki
2
+ module Bibliotheca
3
+ class Engine < ::Rails::Engine
4
+ endpoint Sinatra::Application.new
5
+ config.generators.api_only = true
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,176 @@
1
+ require 'sinatra'
2
+ require 'mumukit/content_type'
3
+
4
+ require 'sinatra/cross_origin'
5
+ require 'logger'
6
+ require 'mumukit/auth'
7
+
8
+ require 'json'
9
+ require 'yaml'
10
+
11
+ configure do
12
+ enable :cross_origin
13
+ set :allow_methods, [:get, :put, :post, :options, :delete]
14
+ set :show_exceptions, false
15
+
16
+ set :app_name, 'bibliotheca'
17
+ set :static, true
18
+ set :public_folder, 'public'
19
+
20
+ use ::Rack::CommonLogger, Rails.logger
21
+ end
22
+
23
+ helpers do
24
+ def json_body
25
+ @json_body ||= JSON.parse(request.body.read) rescue nil
26
+ end
27
+
28
+ def slug
29
+ if route_slug_parts.present?
30
+ Mumukit::Auth::Slug.join(*route_slug_parts)
31
+ elsif subject
32
+ Mumukit::Auth::Slug.parse(subject.slug)
33
+ elsif json_body
34
+ Mumukit::Auth::Slug.parse(json_body['slug'])
35
+ else
36
+ raise Mumukit::Auth::InvalidSlugFormatError.new('Slug not available')
37
+ end
38
+ end
39
+
40
+ def route_slug_parts
41
+ []
42
+ end
43
+ end
44
+
45
+ before do
46
+ content_type 'application/json', 'charset' => 'utf-8'
47
+ end
48
+
49
+ after do
50
+ error_message = env['sinatra.error']
51
+ if response.body.is_a?(Array)&& response.body[0].is_a?(String)
52
+ if content_type != 'application/csv'
53
+ content_type 'text/html'
54
+ response.body[0] = <<HTML
55
+ <html>
56
+ <body>
57
+ #{response.body[0]}
58
+ </body>
59
+ </html>
60
+ HTML
61
+ end
62
+ response.body = response.body[0]
63
+ elsif error_message.blank?
64
+ response.body = response.body.to_json
65
+ else
66
+ response.body = {message: env['sinatra.error'].message}.to_json
67
+ end
68
+ end
69
+
70
+ error JSON::ParserError do
71
+ halt 400
72
+ end
73
+
74
+ error Mumukit::Auth::InvalidTokenError do
75
+ halt 401
76
+ end
77
+
78
+ error Mumukit::Auth::UnauthorizedAccessError do
79
+ halt 403
80
+ end
81
+
82
+ error ActiveRecord::RecordInvalid do
83
+ halt 400
84
+ end
85
+
86
+ error Mumukit::Auth::InvalidSlugFormatError do
87
+ halt 400
88
+ end
89
+
90
+ error ActiveRecord::RecordNotFound do
91
+ halt 404
92
+ end
93
+
94
+ options '*' do
95
+ response.headers['Allow'] = settings.allow_methods.map { |it| it.to_s.upcase }.join(',')
96
+ response.headers['Access-Control-Allow-Headers'] = 'X-Mumuki-Auth-Token, X-Requested-With, X-HTTP-Method-Override, Content-Type, Cache-Control, Accept, Authorization'
97
+ 200
98
+ end
99
+
100
+ helpers do
101
+ Mumukit::Login.configure_controller! self
102
+ end
103
+
104
+ before do
105
+ I18n.locale = 'en' #TODO: Remove hardcoded locale
106
+ end
107
+
108
+ helpers do
109
+ def authenticate!
110
+ halt 401 unless current_user?
111
+ end
112
+
113
+ def authorization_slug
114
+ slug
115
+ end
116
+
117
+ def subject
118
+ Guide.find_by_id(params[:id])
119
+ end
120
+
121
+ def route_slug_parts
122
+ [params[:organization], params[:repository]].compact
123
+ end
124
+
125
+ def history_syncer
126
+ Mumuki::Bibliotheca.history_syncer(current_user)
127
+ end
128
+
129
+ def api_syncer
130
+ Mumuki::Bibliotheca.api_syncer(json_body)
131
+ end
132
+
133
+ def upsert!(content_kind)
134
+ authorize! :writer
135
+ content = api_syncer.locate_and_import! content_kind, slug.to_s
136
+ history_syncer.export! content
137
+ content.to_resource_h
138
+ end
139
+
140
+ def fork!(collection_class)
141
+ authorize! :writer
142
+ destination = json_body['organization']
143
+ collection_class.find_by_slug!(slug.to_s).fork_to!(destination, history_syncer).as_json
144
+ end
145
+
146
+ def delete!(collection_class)
147
+ authorize! :editor
148
+ collection_class.find_by_slug!(slug.to_s).destroy!
149
+ {}
150
+ end
151
+ end
152
+
153
+ post '/markdown' do
154
+ {markdown: Mumukit::ContentType::Markdown.to_html(json_body['markdown'])}
155
+ end
156
+
157
+ post '/markdowns' do
158
+ json_body.with_indifferent_access.tap do |guide|
159
+ guide[:exercises].each do |exercise|
160
+ exercise[:description] = Mumukit::ContentType::Markdown.to_html(exercise[:description])
161
+ end
162
+ end
163
+ end
164
+
165
+ get '/permissions' do
166
+ authenticate!
167
+
168
+ {permissions: current_user.permissions}
169
+ end
170
+
171
+
172
+ require_relative './sinatra/organization'
173
+ require_relative './sinatra/languages'
174
+ require_relative './sinatra/guides'
175
+ require_relative './sinatra/books'
176
+ require_relative './sinatra/topics'
@@ -0,0 +1,29 @@
1
+ helpers do
2
+ def list_books(books)
3
+ { books: books.as_json(only: [:name, :slug, :chapters]) }
4
+ end
5
+ end
6
+
7
+ get '/books' do
8
+ list_books Book.all
9
+ end
10
+
11
+ get '/books/writable' do
12
+ list_books Book.allowed(current_user.permissions)
13
+ end
14
+
15
+ get '/books/:organization/:repository' do
16
+ Book.find_by_slug!(slug.to_s).to_resource_h
17
+ end
18
+
19
+ post '/books' do
20
+ upsert! :book
21
+ end
22
+
23
+ post '/book/:organization/:repository/fork' do
24
+ fork! Book
25
+ end
26
+
27
+ delete '/books/:organization/:repository' do
28
+ delete! Book
29
+ end
@@ -0,0 +1,45 @@
1
+ helpers do
2
+ def list_guides(guides)
3
+ { guides: guides.map { |it| it.as_json(only: [:name, :slug, :type]).merge(language: it.language.name) } }
4
+ end
5
+
6
+ def slice_guide_resource_h_for_api(guide)
7
+ guide.merge(language: guide.dig(:language, :name)).merge(exercises: guide[:exercises].map { |it| it.tap { |it| it[:language] = it.dig(:language, :name) if it[:language]}})
8
+ end
9
+ end
10
+
11
+ get '/guides' do
12
+ list_guides Guide.visible(current_user&.permissions)
13
+ end
14
+
15
+ get '/guides/writable' do
16
+ list_guides Guide.allowed(current_user&.permissions)
17
+ end
18
+
19
+ delete '/guides/:organization/:repository' do
20
+ delete! Guide
21
+ end
22
+
23
+ get '/guides/:organization/:repository/markdown' do
24
+ slice_guide_resource_h_for_api Guide.find_by_slug!(slug.to_s).to_markdownified_resource_h
25
+ end
26
+
27
+ get '/guides/:organization/:repository' do
28
+ slice_guide_resource_h_for_api Guide.find_by_slug!(slug.to_s).to_resource_h
29
+ end
30
+
31
+ post '/guides' do
32
+ upsert! :guide
33
+ end
34
+
35
+ post '/guides/import/:organization/:repository' do
36
+ history_syncer.locate_and_import! :guide, slug.to_s
37
+ end
38
+
39
+ post '/guides/:organization/:repository/assets' do
40
+ Mumuki::Bibliotheca.upload_asset! slug, json_body['filename'], json_body['content']
41
+ end
42
+
43
+ post '/guides/:organization/:repository/fork' do
44
+ fork! Guide
45
+ end
@@ -0,0 +1,10 @@
1
+ get '/languages' do
2
+ { languages: Language.all.map { |it| transform(it) } }
3
+ end
4
+
5
+ def transform(language)
6
+ language
7
+ .to_resource_h
8
+ .replace_key!(:highlight_mode, :ace_mode)
9
+ .replace_key!(:runner_url, :test_runner_url)
10
+ end
@@ -0,0 +1,3 @@
1
+ get '/organization' do
2
+ Organization.base.to_resource_h
3
+ end
@@ -0,0 +1,29 @@
1
+ helpers do
2
+ def list_topics(topics)
3
+ { topics: topics.as_json(only: [:name, :slug]) }
4
+ end
5
+ end
6
+
7
+ get '/topics' do
8
+ list_topics Topic.all
9
+ end
10
+
11
+ get '/topics/writable' do
12
+ list_topics Topic.allowed(current_user.permissions)
13
+ end
14
+
15
+ get '/topics/:organization/:repository' do
16
+ Topic.find_by_slug!(slug.to_s).to_resource_h
17
+ end
18
+
19
+ post '/topics' do
20
+ upsert! :topic
21
+ end
22
+
23
+ post '/book/:organization/:repository/fork' do
24
+ fork! Topic
25
+ end
26
+
27
+ delete '/topics/:organization/:repository' do
28
+ delete! Topic
29
+ end
@@ -0,0 +1,29 @@
1
+ module Mumuki
2
+ module Bibliotheca
3
+ class ApiSource < Mumukit::Sync::Store::Json
4
+ include Mumukit::Sync::Store::WithWrappedLanguage
5
+ include Mumukit::Sync::Store::WithFilteredId
6
+ end
7
+
8
+ class << self
9
+ class_attribute :api_inflators, :history_inflators, :history_store, :assets_uploader
10
+
11
+ self.api_inflators = [Mumukit::Sync::Inflator::SingleChoice.new, Mumukit::Sync::Inflator::MultipleChoice.new]
12
+ self.history_inflators = []
13
+ self.history_store = proc { |_user| Mumukit::Sync::Store::NullStore.new }
14
+ self.assets_uploader = proc { |_slug, _name, _content| raise 'Can not upload file' }
15
+
16
+ def upload_asset!(slug, name, content)
17
+ assets_uploader[slug, name, content]
18
+ end
19
+
20
+ def history_syncer(user)
21
+ Mumukit::Sync::Syncer.new(history_store[user], history_inflators)
22
+ end
23
+
24
+ def api_syncer(json)
25
+ Mumukit::Sync::Syncer.new(ApiSource.new(json), api_inflators)
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,5 @@
1
+ module Mumuki
2
+ module Bibliotheca
3
+ VERSION = '6.0.0'
4
+ end
5
+ end
@@ -0,0 +1,10 @@
1
+ namespace :content do
2
+ task :import do
3
+ bridge = Mumukit::Platform.bibliotheca_bridge
4
+ bridge.import_contents! do |resource_type, slug|
5
+ resource = bridge.send(resource_type, slug)
6
+
7
+ Bibliotheca::Collection.insert_hash! resource_type, resource
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,11 @@
1
+ logger = Mumukit::Nuntius::Logger
2
+ namespace :events do
3
+ task :listen do
4
+ logger.info 'Loading event handlers....'
5
+ require_relative '../events'
6
+ logger.info "Loaded handlers #{Mumukit::Nuntius::EventConsumer.handled_events}!"
7
+
8
+ logger.info 'Listening to events...'
9
+ Mumukit::Nuntius::EventConsumer.start!
10
+ end
11
+ end
@@ -0,0 +1,36 @@
1
+ namespace :guides do
2
+ def guides_for_organization(org)
3
+ Octokit.auto_paginate = true
4
+ Octokit.repos(org).map(&:full_name).select { |it| it =~ /guia/ }
5
+ end
6
+
7
+ task :export, [:author_email] do |_t, args|
8
+ author_email = args[:author_email]
9
+ Bibliotheca::Collection::Guides.all.each do |it|
10
+ it.export! author_email rescue (puts "ignoring #{it.slug}")
11
+ end
12
+ end
13
+
14
+ task :import_from_github, [:organization, :url] do |_t, args|
15
+ args.with_defaults(url: 'http://localhost:3004')
16
+
17
+ org = args[:organization]
18
+ url = args[:url]
19
+
20
+ puts "importing guides from organization #{org} into #{url}"
21
+
22
+ guides_for_organization(org).each do |slug|
23
+ puts "importing guide #{slug}...."
24
+ begin
25
+ RestClient.post "#{url}/guides/import/#{slug}", {}
26
+ rescue => e
27
+ puts "import failed! #{e.response}"
28
+ end
29
+ end
30
+ end
31
+ end
32
+
33
+
34
+
35
+
36
+
metadata ADDED
@@ -0,0 +1,187 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mumuki-bibliotheca
3
+ version: !ruby/object:Gem::Version
4
+ version: 6.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Franco Bulgarelli
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2018-11-24 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rails
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 5.1.6
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 5.1.6
27
+ - !ruby/object:Gem::Dependency
28
+ name: sinatra-contrib
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: sinatra-cross_origin
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: 0.3.1
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: 0.3.1
55
+ - !ruby/object:Gem::Dependency
56
+ name: mumuki-domain
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: 6.0.0
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: 6.0.0
69
+ - !ruby/object:Gem::Dependency
70
+ name: mumukit-login
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '6.1'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '6.1'
83
+ - !ruby/object:Gem::Dependency
84
+ name: mumukit-nuntius
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '6.1'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '6.1'
97
+ - !ruby/object:Gem::Dependency
98
+ name: mumukit-sync
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '0.2'
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '0.2'
111
+ - !ruby/object:Gem::Dependency
112
+ name: rack
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: '2.0'
118
+ type: :runtime
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: '2.0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: pg
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - "~>"
130
+ - !ruby/object:Gem::Version
131
+ version: 0.18.0
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - "~>"
137
+ - !ruby/object:Gem::Version
138
+ version: 0.18.0
139
+ description: API for editing content on mumuki
140
+ email:
141
+ - franco@mumuki.org
142
+ executables: []
143
+ extensions: []
144
+ extra_rdoc_files: []
145
+ files:
146
+ - README.md
147
+ - Rakefile
148
+ - config/routes.rb
149
+ - lib/events.rb
150
+ - lib/mumuki/bibliotheca.rb
151
+ - lib/mumuki/bibliotheca/engine.rb
152
+ - lib/mumuki/bibliotheca/sinatra.rb
153
+ - lib/mumuki/bibliotheca/sinatra/books.rb
154
+ - lib/mumuki/bibliotheca/sinatra/guides.rb
155
+ - lib/mumuki/bibliotheca/sinatra/languages.rb
156
+ - lib/mumuki/bibliotheca/sinatra/organization.rb
157
+ - lib/mumuki/bibliotheca/sinatra/topics.rb
158
+ - lib/mumuki/bibliotheca/syncer.rb
159
+ - lib/mumuki/bibliotheca/version.rb
160
+ - lib/tasks/content.rake
161
+ - lib/tasks/events.rake
162
+ - lib/tasks/guides.rake
163
+ homepage: https://mumuki.org
164
+ licenses:
165
+ - GPL-3.0
166
+ metadata: {}
167
+ post_install_message:
168
+ rdoc_options: []
169
+ require_paths:
170
+ - lib
171
+ required_ruby_version: !ruby/object:Gem::Requirement
172
+ requirements:
173
+ - - ">="
174
+ - !ruby/object:Gem::Version
175
+ version: '0'
176
+ required_rubygems_version: !ruby/object:Gem::Requirement
177
+ requirements:
178
+ - - ">="
179
+ - !ruby/object:Gem::Version
180
+ version: '0'
181
+ requirements: []
182
+ rubyforge_project:
183
+ rubygems_version: 2.5.1
184
+ signing_key:
185
+ specification_version: 4
186
+ summary: API for editing content on mumuki
187
+ test_files: []