pagiii 0.0.7

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
+ SHA256:
3
+ metadata.gz: d70f2977bee3d72cf6643ed1a34093612c20c754b85b089b256797d91124eaba
4
+ data.tar.gz: 98a77db5ba8d05143d015b9e07e52d73d1f3e671f77ee6508cc531dc08a142ee
5
+ SHA512:
6
+ metadata.gz: ccd0773591d3d0bd8eabf5cd8dbcadd169255ae0e7b529ef17c19c25673e00f85723445c602eb6279fda5f4f3db6d0d8d0a0657a43c2cbbe40ac0a40a637965a
7
+ data.tar.gz: b543b85fa75d1a7ead7043d763cb1ad82f6946eee4ab83a95ec95c51e290b443ddd430b2b3dde52b0577f7dfaf4815f97bedd44a0c18bb7d64572b510fd2f91c
data/bin/pagiii ADDED
@@ -0,0 +1,275 @@
1
+ #!/usr/bin/env ruby
2
+ require 'pagiii'
3
+
4
+
5
+ require 'faraday'
6
+ require 'base64'
7
+ require 'filewatcher'
8
+ require 'commander/import'
9
+ require 'cgi'
10
+ require 'socket'
11
+
12
+ def root_api
13
+ return ENV['PAGIII_HOST'] if ENV['PAGIII_HOST']
14
+ "https://pagiii.duruxignition.com"
15
+ end
16
+
17
+ client_id = 'IuIwOC38m7acKuJRo-nkG22ZzeVpWLDPMPnoaoRzQp8'
18
+ secret_id = 'WlENailhg7KEbZqXXwX4Y470HYGL8-U2af_bOZGVWeQ'
19
+ redirect_uri = 'http://localhost:7654'
20
+ scope = 'read_theme write_theme delete_theme'
21
+
22
+ program :version, '0.0.7'
23
+ program :description, 'Pagiii CLI'
24
+
25
+
26
+
27
+ def get_current_site(token)
28
+ conn = Faraday.new(
29
+ url: "#{root_api}/api/v1/admin/sites/current",
30
+ params: {param: '1'},
31
+ headers: {
32
+ 'Content-Type' => 'application/json',
33
+ 'Authorization' => "Bearer #{token}"
34
+ }
35
+ )
36
+ response = conn.get
37
+ puts response.body
38
+ hash = JSON.parse(response.body)
39
+ end
40
+
41
+
42
+
43
+
44
+
45
+ def check_authorized(response)
46
+ if response.status == 401
47
+ say "Unauthorized. Please run theme:request to get access-token"
48
+ exit(false)
49
+ end
50
+ end
51
+
52
+ def update_config(site_name, token)
53
+ dir = "#{Dir.home}/.pagiii"
54
+ FileUtils.mkdir_p(dir) unless Dir.exists?(dir)
55
+ file = File.join(dir, 'config.json')
56
+ hash = {}
57
+ if File.exists?(file)
58
+ hash = JSON.parse(IO.read(file))
59
+ end
60
+ hash[site_name] = token
61
+ File.open(file, 'w+') do |f|
62
+ f.write(hash.to_json)
63
+ end
64
+ end
65
+
66
+ def read_config(site_name)
67
+ dir = "#{Dir.home}/.pagiii"
68
+ return nil unless Dir.exists?(dir)
69
+ file = File.join(dir, 'config.json')
70
+ return nil unless File.exists?(file)
71
+ hash = JSON.parse(IO.read(file))
72
+ hash[site_name]
73
+ end
74
+
75
+ command :help do |c|
76
+ c.action do |args, options|
77
+ say "Help.... pagiii"
78
+ end
79
+ end
80
+
81
+
82
+ # bundle exec ruby pagiii.rb theme:sync --site=dokumentasi --theme=doc
83
+ command 'theme:sync' do |c|
84
+ c.option '--theme STRING', String, 'Theme name'
85
+ c.option '--site STRING', String, 'Site name'
86
+ c.action do |args, options|
87
+ if options.theme.nil?
88
+ say "please specify theme name using --theme option"
89
+ exit(false)
90
+ elsif options.site.nil?
91
+ say "please specify site name using --site option"
92
+ exit(false)
93
+ end
94
+ token = read_config(options.site)
95
+ theme = Pagiii::ThemeSync.new(token: token, root_api: root_api)
96
+ theme.sync_all(options.theme)
97
+ end
98
+ end
99
+
100
+ command 'theme:watch' do |c|
101
+ c.option '--site STRING', String, 'Site name'
102
+ c.option '--theme STRING', String, 'Theme name'
103
+ c.action do |args, options|
104
+ if options.theme.nil?
105
+ say "please specify theme name using --theme option"
106
+ exit(false)
107
+ elsif options.site.nil?
108
+ say "please specify site name using --site option"
109
+ exit(false)
110
+ end
111
+ token = read_config(options.site)
112
+ theme_sync = Pagiii::ThemeSync.new(token: token, root_api: root_api)
113
+ theme_sync.watch(options.theme)
114
+ end
115
+ end
116
+
117
+ command 'theme:create' do |c|
118
+ c.syntax = "theme:create [options]"
119
+ c.description = "Create theme"
120
+ c.option '--site STRING', String, 'Site name'
121
+ c.option '--theme STRING', String, 'Theme name'
122
+
123
+ c.action do |args, options|
124
+ token = read_config(options.site)
125
+ if options.theme.nil?
126
+ say "please specify theme name using --theme option"
127
+ else
128
+ say "Create theme #{options.theme}"
129
+ theme_sync = Pagiii::ThemeSync.new(token: token, root_api: root_api)
130
+ response = theme_sync.create_theme(options.theme)
131
+
132
+ if response.status == 200
133
+ say "theme created"
134
+ else
135
+ say response.body
136
+ end
137
+ end
138
+ end
139
+ end
140
+
141
+ command 'theme:pull' do |c|
142
+ c.syntax = "theme:pull [options]"
143
+ c.description = "Pull theme"
144
+ c.option '--site STRING', String, 'Site name'
145
+ c.option '--theme STRING', String, 'Theme name'
146
+ c.action do |args, options|
147
+ if options.theme.nil?
148
+ say "please specify theme name using --theme option"
149
+ elsif options.site.nil?
150
+ say "please provide site name"
151
+ else
152
+ token = read_config(options.site)
153
+ say "Pull theme #{options.theme}"
154
+ theme_sync = Pagiii::ThemeSync.new(token: token, root_api: root_api)
155
+ theme_sync.pull_theme(options.theme)
156
+ end
157
+ end
158
+ end
159
+
160
+ command 'theme:list' do |c|
161
+ c.syntax = "theme:list [options]"
162
+ c.description = "List theme"
163
+ c.option '--site STRING', String, 'Site name'
164
+ c.action do |args, options|
165
+ if options.site.nil?
166
+ say "please provide name using --site"
167
+ else
168
+ token = read_config(options.site)
169
+ theme_sync = Pagiii::ThemeSync.new(token: token, root_api: root_api)
170
+ theme_sync.list_themes
171
+ end
172
+ end
173
+ end
174
+
175
+ command 'theme:delete' do |c|
176
+ c.syntax = "theme:delete [options]"
177
+ c.description = "Delete theme"
178
+ c.option '--theme STRING', String, 'Theme name'
179
+ c.option '--site STRING', String, 'Site'
180
+ c.action do |args, options|
181
+ if options.theme.nil?
182
+ say "please specify theme name using --theme option"
183
+ elsif options.site.nil?
184
+ say "please provide site name using --site"
185
+ else
186
+ say "Delete theme #{options.theme}"
187
+ token = read_config(options.site)
188
+
189
+ theme_sync = Pagiii::ThemeSync.new(token: token, root_api: root_api)
190
+ theme_sync.delete_theme(options.theme)
191
+ end
192
+ end
193
+ end
194
+
195
+ command 'theme:set_current' do |c|
196
+ c.syntax = "theme:set_current [options]"
197
+ c.description = "Delete theme"
198
+ c.option '--theme STRING', String, 'Theme name'
199
+ c.option '--site STRING', String, 'site name'
200
+
201
+ c.action do |args, options|
202
+ if options.theme.nil?
203
+ say "please specify theme name using --theme option"
204
+ elsif options.site.nil?
205
+ say "please provide name using --site"
206
+ else
207
+ say "Set current theme of #{options.site} to #{options.theme}"
208
+ token = read_config(options.site)
209
+ theme_sync = Pagiii::ThemeSync.new(token: token, root_api: root_api)
210
+ theme_sync.set_current_theme(options.theme)
211
+ end
212
+ end
213
+ end
214
+
215
+ command 'theme:request' do |c|
216
+ c.syntax = "theme:request [options]"
217
+ c.description = "Create theme"
218
+ c.option '--site STRING', String, 'Site name'
219
+ c.action do |args, options|
220
+ if options.site.nil?
221
+ say "please specify site name using --site option"
222
+ else
223
+ say "Site Request access #{options.site}"
224
+ url = "#{root_api}/#{options.site}/oauth/authorize?client_id=#{client_id}&redirect_uri=#{CGI.escape(redirect_uri)}&response_type=code&scope=#{scope}"
225
+ say url
226
+ `open "#{url}"`
227
+ server = TCPServer.new 7654
228
+ say "please check browser"
229
+ while session = server.accept
230
+ request = session.gets
231
+ puts request
232
+
233
+ # session.print "HTTP/1.1 200\r\n" # 1
234
+ # session.print "Content-Type: text/html\r\n" # 2
235
+ # session.print "\r\n" # 3
236
+ # session.print "Tutup " #4
237
+ # session.close
238
+
239
+ output = "<html><head></head><body>#</body></html>"
240
+ headers = ["HTTP/1.1 302 Found",
241
+ "Location: #{root_api}\r\n\r\n",
242
+ "content-length: #\r\n\r\n"].join("\r\n")
243
+ session.puts headers
244
+ session.puts output
245
+ session.close
246
+
247
+ if request =~ /code=([a-zA-Z0-9\-_]+)/
248
+ authorization_code = $1
249
+ say "authozation code: #{authorization_code}"
250
+
251
+ conn = Faraday.new(
252
+ url: "#{root_api}/#{options.site}/oauth/token",
253
+ params: {param: '1'},
254
+ headers: {
255
+ 'Content-Type' => 'application/x-www-form-urlencoded'
256
+ }
257
+ )
258
+ response = conn.post do |req|
259
+ req.body = "grant_type=authorization_code&code=#{authorization_code}&redirect_uri=#{CGI.escape(redirect_uri)}&client_id=#{client_id}&client_secret=#{secret_id}"
260
+ end
261
+
262
+ if response.status == 200
263
+ access_token = JSON.parse(response.body)['access_token']
264
+ say "access token: #{access_token}"
265
+ update_config(options.site, access_token)
266
+ break
267
+ else
268
+ say "unable to get access token"
269
+ end
270
+ end
271
+
272
+ end
273
+ end
274
+ end
275
+ end
@@ -0,0 +1,8 @@
1
+ module Pagiii
2
+ module Info
3
+ def info
4
+ puts "Access Token: #{@token}"
5
+ puts "Root API: #{@root_api}"
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,285 @@
1
+ require 'pagiii/info'
2
+
3
+ class Pagiii::ThemeSync
4
+ include Pagiii::Info
5
+
6
+ ALLOWED_DIRS = ['templates', 'sections', 'layout', 'assets', 'snippets']
7
+
8
+ def initialize(token:, root_api:)
9
+ @token = token
10
+ @root_api = root_api
11
+ end
12
+
13
+ def list_themes
14
+ conn = Faraday.new(
15
+ url: "#{root_api}/api/v1/admin/themes",
16
+ headers: {
17
+ 'Content-Type' => 'application/json',
18
+ 'Authorization' => "Bearer #{@token}"
19
+ }
20
+ )
21
+ response = conn.get
22
+ check_authorized(response)
23
+ if response.status == 200
24
+ hash = JSON.parse(response.body)
25
+ say "List themes at #{hash['site']['name']}"
26
+ say "--------------------------------------"
27
+ hash['themes'].each do |theme|
28
+ say " - #{theme['name']}"
29
+ end
30
+ else
31
+ say "error"
32
+ end
33
+ end
34
+
35
+
36
+ def sync_file(theme_name, file)
37
+ puts "sync #{file}"
38
+ conn = Faraday.new(
39
+ url: @root_api,
40
+ params: {param: '1'},
41
+ headers: {
42
+ 'Content-Type' => 'application/json',
43
+ 'Authorization' => "Bearer #{@token}"
44
+ }
45
+ )
46
+
47
+ data = ""
48
+
49
+ ext = File.extname(file)
50
+ if [".png", ".jpg", ".jpeg", ".gif"].include?(ext)
51
+ data = Base64.encode64(IO.read(file))
52
+ else
53
+ data = IO.read(file)
54
+ end
55
+ response = get_theme_by_name(name: theme_name)
56
+
57
+ check_authorized(response)
58
+ theme_id = JSON.parse(response.body)['theme']['id']
59
+
60
+ response = conn.post("/api/v1/admin/themes/#{theme_id}/assets") do |req|
61
+ req.params['limit'] = 100
62
+ req.body = {
63
+ key: get_asset_key(file),
64
+ data: data
65
+ }.to_json
66
+ end
67
+ end
68
+
69
+
70
+
71
+ def sync_delete(theme_name, file)
72
+ puts "deleteing #{file}"
73
+ response = get_theme_by_name(name: theme_name)
74
+ check_authorized(response)
75
+ theme_id = JSON.parse(response.body)['theme']['id']
76
+
77
+ conn = Faraday.new(
78
+ url: @root_api,
79
+ params: {param: '1'},
80
+ headers: {
81
+ 'Content-Type' => 'application/json',
82
+ 'Authorization' => "Bearer #{@token}"
83
+ }
84
+ )
85
+ response = conn.delete("/api/v1/admin/themes/#{theme_id}/assets?key=#{get_asset_key(file)}")
86
+ end
87
+
88
+ def delete_remote(theme, asset_key)
89
+ puts "deleting #{asset_key}"
90
+ response = get_theme_by_name(name: theme)
91
+ check_authorized(response)
92
+ theme_id = JSON.parse(response.body)['theme']['id']
93
+
94
+ conn = Faraday.new(
95
+ url: @root_api,
96
+ params: {param: '1'},
97
+ headers: {
98
+ 'Content-Type' => 'application/json',
99
+ 'Authorization' => "Bearer #{@token}"
100
+ }
101
+ )
102
+ response = conn.delete("/api/v1/admin/themes/#{theme_id}/assets?key=#{asset_key}")
103
+ end
104
+
105
+ def compare_and_delete(theme)
106
+ conn = Faraday.new(
107
+ url: @root_api,
108
+ params: {param: '1'},
109
+ headers: {
110
+ 'Content-Type' => 'application/json',
111
+ 'Authorization' => "Bearer #{@token}"
112
+ }
113
+ )
114
+ response = get_theme_by_name(name: theme)
115
+ check_authorized(response)
116
+ theme_id = JSON.parse(response.body)['theme']['id']
117
+ response = conn.get("/api/v1/admin/themes/#{theme_id}/assets")
118
+ remote_assets = JSON.parse(response.body)['assets'].map{|x| x['asset_key']}
119
+
120
+ local_assets = []
121
+
122
+ Dir.entries('.').each do |dir|
123
+ if ALLOWED_DIRS.include?(dir) && File.directory?(dir)
124
+ Dir.entries(dir).reject{|x| [".", ".."].include?(x)}.each do |file|
125
+ file_path = "#{dir}/#{file}"
126
+ local_assets << file_path
127
+ end
128
+ end
129
+ end
130
+
131
+ assets_to_be_deleted = remote_assets - local_assets
132
+ assets_to_be_deleted.each do |asset_key|
133
+ delete_remote(theme, asset_key)
134
+ end
135
+ end
136
+
137
+
138
+
139
+ def get_asset_key(file)
140
+ folder, file = File.split(file)
141
+ dir = File.split(folder).last
142
+ "#{dir}/#{file}"
143
+ end
144
+
145
+ def sync_all(theme)
146
+ compare_and_delete(theme)
147
+ Dir.entries('.').each do |dir|
148
+ if ALLOWED_DIRS.include?(dir) && File.directory?(dir)
149
+ puts "--#{dir}"
150
+ Dir.entries(dir).reject{|x| [".", ".."].include?(x)}.each do |file|
151
+ puts "----#{file}"
152
+ file_path = "./#{dir}/#{file}"
153
+ sync_file(theme, file_path)
154
+ end
155
+ end
156
+ end
157
+ end
158
+
159
+ def watch(theme_name)
160
+ Filewatcher.new(ALLOWED_DIRS).watch do |changes|
161
+ changes.each do |filename, event|
162
+ puts "#{filename} #{event}"
163
+ if event == :updated || event == :created
164
+ sync_file(theme_name, filename)
165
+ elsif event == :deleted
166
+ sync_delete(theme_name, filename)
167
+ end
168
+ end
169
+ end
170
+ end
171
+
172
+ def get_theme_by_name(name:)
173
+ conn = Faraday.new(
174
+ url: "#{@root_api}/api/v1/admin/themes/by_name?name=#{name}",
175
+ headers: {
176
+ 'Content-Type' => 'application/json',
177
+ 'Authorization' => "Bearer #{@token}"
178
+ }
179
+ )
180
+
181
+ response = conn.get
182
+ end
183
+
184
+
185
+
186
+ def pull_theme(name)
187
+ response = get_theme_by_name(name: name)
188
+ check_authorized(response)
189
+ parsed_response = JSON.parse(response.body)
190
+
191
+ conn = Faraday.new(
192
+ url: "#{root_api}/api/v1/admin/themes/#{parsed_response['theme']['id']}/pull",
193
+ params: {param: '1'},
194
+ headers: {
195
+ 'Content-Type' => 'application/json',
196
+ 'Authorization' => "Bearer #{@token}"
197
+ }
198
+ )
199
+ response = conn.get
200
+
201
+ assets = JSON.parse(response.body)['assets']
202
+
203
+ assets.each do |asset|
204
+ say "downloading #{asset['asset_key']}"
205
+ response = download_asset(theme_id: parsed_response['theme']['id'], key: asset['asset_key'])
206
+ path = File.split(asset['asset_key'])
207
+ FileUtils.mkdir(path.first) unless Dir.exists?(path.first)
208
+ File.open(asset['asset_key'], 'wb') do |f|
209
+ f.write(response.body)
210
+ end
211
+ end
212
+
213
+ if response.status == 200
214
+ say "theme created"
215
+ else
216
+ say response.body
217
+ end
218
+ end
219
+
220
+ def delete_theme(name)
221
+ response = get_theme_by_name(name: name)
222
+ check_authorized(response)
223
+ parsed_response = JSON.parse(response.body)
224
+ conn = Faraday.new(
225
+ url: "#{root_api}/api/v1/admin/themes/#{parsed_response['theme']['id']}",
226
+ params: {param: '1'},
227
+ headers: {
228
+ 'Content-Type' => 'application/json',
229
+ 'Authorization' => "Bearer #{@token}"
230
+ }
231
+ )
232
+ response = conn.delete
233
+ end
234
+
235
+ def create_theme(name)
236
+ conn = Faraday.new(
237
+ url: "#{root_api}/api/v1/admin/themes",
238
+ params: {param: '1'},
239
+ headers: {
240
+ 'Content-Type' => 'application/json',
241
+ 'Authorization' => "Bearer #{@token}"
242
+ }
243
+ )
244
+ response = conn.post do |req|
245
+ req.body = {
246
+ theme: {
247
+ name: name
248
+ }
249
+ }.to_json
250
+ end
251
+ end
252
+
253
+ def set_current_theme(name)
254
+ response = get_theme_by_name(name: name)
255
+ check_authorized(response)
256
+ parsed_response = JSON.parse(response.body)
257
+ conn = Faraday.new(
258
+ url: "#{root_api}/api/v1/admin/themes/#{parsed_response['theme']['id']}/set_current",
259
+ params: {param: '1'},
260
+ headers: {
261
+ 'Content-Type' => 'application/json',
262
+ 'Authorization' => "Bearer #{@token}"
263
+ }
264
+ )
265
+ response = conn.patch do |req|
266
+ req.body = {}.to_json
267
+ end
268
+ end
269
+
270
+ private
271
+
272
+ def download_asset(theme_id:, key:)
273
+ conn = Faraday.new(
274
+ url: "#{root_api}/api/v1/admin/themes/#{theme_id}/assets/download?key=#{key}",
275
+ params: {param: '1'},
276
+ headers: {
277
+ 'Content-Type' => 'application/json',
278
+ 'Authorization' => "Bearer #{@token}"
279
+ }
280
+ )
281
+ response = conn.get
282
+ end
283
+
284
+
285
+ end
data/lib/pagiii.rb ADDED
@@ -0,0 +1,5 @@
1
+
2
+ module Pagiii
3
+ end
4
+
5
+ require 'pagiii/theme_sync'
metadata ADDED
@@ -0,0 +1,48 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: pagiii
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.7
5
+ platform: ruby
6
+ authors:
7
+ - Sugiarto
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2023-06-14 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: CLI to support themes on pagiii CMS
14
+ email:
15
+ - ugidmtest@gmail.com
16
+ executables:
17
+ - pagiii
18
+ extensions: []
19
+ extra_rdoc_files: []
20
+ files:
21
+ - bin/pagiii
22
+ - lib/pagiii.rb
23
+ - lib/pagiii/info.rb
24
+ - lib/pagiii/theme_sync.rb
25
+ homepage: http://rubygems.org/gems/pagiii
26
+ licenses:
27
+ - MIT
28
+ metadata: {}
29
+ post_install_message:
30
+ rdoc_options: []
31
+ require_paths:
32
+ - lib
33
+ required_ruby_version: !ruby/object:Gem::Requirement
34
+ requirements:
35
+ - - ">="
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ required_rubygems_version: !ruby/object:Gem::Requirement
39
+ requirements:
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ version: '0'
43
+ requirements: []
44
+ rubygems_version: 3.1.4
45
+ signing_key:
46
+ specification_version: 4
47
+ summary: Pagiii CLI
48
+ test_files: []