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 +7 -0
- data/README.md +141 -0
- data/Rakefile +29 -0
- data/config/routes.rb +2 -0
- data/lib/events.rb +15 -0
- data/lib/mumuki/bibliotheca.rb +22 -0
- data/lib/mumuki/bibliotheca/engine.rb +8 -0
- data/lib/mumuki/bibliotheca/sinatra.rb +176 -0
- data/lib/mumuki/bibliotheca/sinatra/books.rb +29 -0
- data/lib/mumuki/bibliotheca/sinatra/guides.rb +45 -0
- data/lib/mumuki/bibliotheca/sinatra/languages.rb +10 -0
- data/lib/mumuki/bibliotheca/sinatra/organization.rb +3 -0
- data/lib/mumuki/bibliotheca/sinatra/topics.rb +29 -0
- data/lib/mumuki/bibliotheca/syncer.rb +29 -0
- data/lib/mumuki/bibliotheca/version.rb +5 -0
- data/lib/tasks/content.rake +10 -0
- data/lib/tasks/events.rake +11 -0
- data/lib/tasks/guides.rake +36 -0
- metadata +187 -0
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
|
+
[](https://travis-ci.org/mumuki/mumuki-bibliotheca-api)
|
|
2
|
+
[](https://codeclimate.com/github/mumuki/mumuki-bibliotheca-api)
|
|
3
|
+
[](https://codeclimate.com/github/mumuki/mumuki-bibliotheca-api)
|
|
4
|
+
[](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
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,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,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,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: []
|