txgh 1.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/LICENSE +202 -0
- data/README.md +64 -0
- data/lib/ext/zipline/output_stream.rb +62 -0
- data/lib/txgh.rb +53 -0
- data/lib/txgh/app.rb +135 -0
- data/lib/txgh/category_support.rb +31 -0
- data/lib/txgh/config.rb +11 -0
- data/lib/txgh/config/config_pair.rb +36 -0
- data/lib/txgh/config/key_manager.rb +54 -0
- data/lib/txgh/config/provider_instance.rb +20 -0
- data/lib/txgh/config/provider_support.rb +26 -0
- data/lib/txgh/config/providers.rb +9 -0
- data/lib/txgh/config/providers/file_provider.rb +19 -0
- data/lib/txgh/config/providers/git_provider.rb +58 -0
- data/lib/txgh/config/providers/raw_provider.rb +19 -0
- data/lib/txgh/config/tx_config.rb +77 -0
- data/lib/txgh/config/tx_manager.rb +15 -0
- data/lib/txgh/diff_calculator.rb +90 -0
- data/lib/txgh/empty_resource_contents.rb +43 -0
- data/lib/txgh/errors.rb +9 -0
- data/lib/txgh/github_api.rb +83 -0
- data/lib/txgh/github_repo.rb +88 -0
- data/lib/txgh/github_request_auth.rb +28 -0
- data/lib/txgh/handlers.rb +12 -0
- data/lib/txgh/handlers/download_handler.rb +84 -0
- data/lib/txgh/handlers/github.rb +10 -0
- data/lib/txgh/handlers/github/delete_handler.rb +65 -0
- data/lib/txgh/handlers/github/handler.rb +20 -0
- data/lib/txgh/handlers/github/push_handler.rb +108 -0
- data/lib/txgh/handlers/github/request_handler.rb +106 -0
- data/lib/txgh/handlers/response.rb +17 -0
- data/lib/txgh/handlers/stream_response.rb +39 -0
- data/lib/txgh/handlers/tgz_stream_response.rb +41 -0
- data/lib/txgh/handlers/transifex.rb +8 -0
- data/lib/txgh/handlers/transifex/hook_handler.rb +77 -0
- data/lib/txgh/handlers/transifex/request_handler.rb +78 -0
- data/lib/txgh/handlers/triggers.rb +9 -0
- data/lib/txgh/handlers/triggers/handler.rb +66 -0
- data/lib/txgh/handlers/triggers/pull_handler.rb +29 -0
- data/lib/txgh/handlers/triggers/push_handler.rb +21 -0
- data/lib/txgh/handlers/zip_stream_response.rb +21 -0
- data/lib/txgh/merge_calculator.rb +74 -0
- data/lib/txgh/parse_config.rb +24 -0
- data/lib/txgh/resource_committer.rb +39 -0
- data/lib/txgh/resource_contents.rb +118 -0
- data/lib/txgh/resource_downloader.rb +141 -0
- data/lib/txgh/resource_updater.rb +104 -0
- data/lib/txgh/response_helpers.rb +30 -0
- data/lib/txgh/transifex_api.rb +165 -0
- data/lib/txgh/transifex_project.rb +37 -0
- data/lib/txgh/transifex_request_auth.rb +53 -0
- data/lib/txgh/tx_branch_resource.rb +59 -0
- data/lib/txgh/tx_logger.rb +12 -0
- data/lib/txgh/tx_resource.rb +66 -0
- data/lib/txgh/utils.rb +44 -0
- data/lib/txgh/version.rb +3 -0
- data/spec/app_spec.rb +346 -0
- data/spec/category_support_spec.rb +43 -0
- data/spec/config/config_pair_spec.rb +47 -0
- data/spec/config/key_manager_spec.rb +48 -0
- data/spec/config/provider_instance_spec.rb +30 -0
- data/spec/config/provider_support_spec.rb +55 -0
- data/spec/config/tx_config_spec.rb +49 -0
- data/spec/config/tx_manager_spec.rb +57 -0
- data/spec/diff_calculator_spec.rb +90 -0
- data/spec/github_api_spec.rb +148 -0
- data/spec/github_repo_spec.rb +178 -0
- data/spec/github_request_auth_spec.rb +39 -0
- data/spec/handlers/download_handler_spec.rb +81 -0
- data/spec/handlers/github/delete_handler_spec.rb +71 -0
- data/spec/handlers/github/push_handler_spec.rb +76 -0
- data/spec/handlers/tgz_stream_response_spec.rb +59 -0
- data/spec/handlers/transifex/hook_handler_spec.rb +115 -0
- data/spec/handlers/zip_stream_response_spec.rb +58 -0
- data/spec/helpers/github_payload_builder.rb +141 -0
- data/spec/helpers/integration_setup.rb +47 -0
- data/spec/helpers/nil_logger.rb +10 -0
- data/spec/helpers/standard_txgh_setup.rb +92 -0
- data/spec/helpers/test_provider.rb +12 -0
- data/spec/integration/cassettes/github_l10n_hook_endpoint.yml +536 -0
- data/spec/integration/cassettes/pull.yml +47 -0
- data/spec/integration/cassettes/push.yml +544 -0
- data/spec/integration/cassettes/transifex_hook_endpoint.yml +560 -0
- data/spec/integration/config/tx.config +10 -0
- data/spec/integration/hooks_spec.rb +158 -0
- data/spec/integration/payloads/github_postbody.json +161 -0
- data/spec/integration/payloads/github_postbody_l10n.json +136 -0
- data/spec/integration/payloads/github_postbody_release.json +136 -0
- data/spec/integration/triggers_spec.rb +45 -0
- data/spec/merge_calculator_spec.rb +112 -0
- data/spec/parse_config_spec.rb +52 -0
- data/spec/resource_committer_spec.rb +42 -0
- data/spec/resource_contents_spec.rb +212 -0
- data/spec/resource_downloader_spec.rb +205 -0
- data/spec/resource_updater_spec.rb +147 -0
- data/spec/spec_helper.rb +32 -0
- data/spec/transifex_api_spec.rb +345 -0
- data/spec/transifex_project_spec.rb +45 -0
- data/spec/transifex_request_auth_spec.rb +39 -0
- data/spec/tx_branch_resource_spec.rb +99 -0
- data/spec/tx_resource_spec.rb +47 -0
- data/spec/utils_spec.rb +58 -0
- data/txgh.gemspec +29 -0
- metadata +296 -0
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
require 'base64'
|
|
2
|
+
|
|
3
|
+
module Txgh
|
|
4
|
+
module Handlers
|
|
5
|
+
module Github
|
|
6
|
+
class PushHandler < Handler
|
|
7
|
+
|
|
8
|
+
def execute
|
|
9
|
+
# Check if the branch in the hook data is the configured branch we want
|
|
10
|
+
logger.info("request github branch: #{branch}")
|
|
11
|
+
logger.info("config github branch: #{repo.github_config_branch}")
|
|
12
|
+
|
|
13
|
+
if repo.should_process_ref?(branch)
|
|
14
|
+
logger.info('found branch in github request')
|
|
15
|
+
|
|
16
|
+
tx_resources = tx_resources_for(branch)
|
|
17
|
+
modified_resources = added_and_modified_resources_for(tx_resources)
|
|
18
|
+
modified_resources.merge!(l10n_resources_for(tx_resources))
|
|
19
|
+
|
|
20
|
+
if repo.github_config_branch.include?('tags/')
|
|
21
|
+
modified_resources.merge!(tag_resources_for(tx_resources))
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# Handle DBZ 'L10N' special case
|
|
25
|
+
if branch.include?("L10N")
|
|
26
|
+
logger.info('processing L10N tag')
|
|
27
|
+
|
|
28
|
+
# Create a new branch off tag commit
|
|
29
|
+
if branch.include?('tags/L10N')
|
|
30
|
+
repo.api.create_ref(repo.name, 'heads/L10N', payload['head_commit']['id'])
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
updater = ResourceUpdater.new(project, repo, logger)
|
|
35
|
+
categories = { 'author' => payload['head_commit']['committer']['name'] }
|
|
36
|
+
|
|
37
|
+
modified_resources.each_pair do |resource, commit_sha|
|
|
38
|
+
updater.update_resource(resource, commit_sha, categories)
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
respond_with(200, true)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
private
|
|
46
|
+
|
|
47
|
+
def tag_resources_for(tx_resources)
|
|
48
|
+
payload['head_commit']['modified'].each_with_object({}) do |modified, ret|
|
|
49
|
+
logger.info("processing modified file: #{modified}")
|
|
50
|
+
|
|
51
|
+
if tx_resources.include?(modified)
|
|
52
|
+
ret[tx_resources[modified]] = payload['head_commit']['id']
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def l10n_resources_for(tx_resources)
|
|
58
|
+
payload['head_commit']['modified'].each_with_object({}) do |modified, ret|
|
|
59
|
+
if tx_resources.include?(modified)
|
|
60
|
+
logger.info("setting new resource: #{tx_resources[modified].L10N_resource_slug}")
|
|
61
|
+
ret[tx_resources[modified]] = payload['head_commit']['id']
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# Finds the updated resources and maps the most recent commit in which
|
|
67
|
+
# each was modified
|
|
68
|
+
def added_and_modified_resources_for(tx_resources)
|
|
69
|
+
payload['commits'].each_with_object({}) do |commit, ret|
|
|
70
|
+
logger.info('processing commit')
|
|
71
|
+
|
|
72
|
+
(commit['modified'] + commit['added']).each do |file|
|
|
73
|
+
logger.info("processing added/modified file: #{file}")
|
|
74
|
+
|
|
75
|
+
if tx_resources.include?(file)
|
|
76
|
+
ret[tx_resources[file]] = commit['id']
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
# Build an index of known Tx resources, by source file
|
|
83
|
+
def tx_resources_for(branch)
|
|
84
|
+
tx_config.resources.each_with_object({}) do |resource, ret|
|
|
85
|
+
logger.info('processing resource')
|
|
86
|
+
|
|
87
|
+
# If we're processing by branch, create a branch resource. Otherwise,
|
|
88
|
+
# use the original resource.
|
|
89
|
+
ret[resource.source_file] = if repo.process_all_branches?
|
|
90
|
+
TxBranchResource.new(resource, branch) # maybe find instead?
|
|
91
|
+
else
|
|
92
|
+
resource
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def tx_config
|
|
98
|
+
@tx_config ||= Txgh::Config::TxManager.tx_config(project, repo, branch)
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def branch
|
|
102
|
+
@ref ||= payload['ref'].sub(/^refs\//, '')
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
end
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
require 'json'
|
|
2
|
+
|
|
3
|
+
module Txgh
|
|
4
|
+
module Handlers
|
|
5
|
+
module Github
|
|
6
|
+
class RequestHandler
|
|
7
|
+
class << self
|
|
8
|
+
|
|
9
|
+
include ResponseHelpers
|
|
10
|
+
|
|
11
|
+
def handle_request(request, logger)
|
|
12
|
+
case request.env['HTTP_X_GITHUB_EVENT']
|
|
13
|
+
when 'push'
|
|
14
|
+
handle_push(request, logger)
|
|
15
|
+
when 'delete'
|
|
16
|
+
handle_delete(request, logger)
|
|
17
|
+
else
|
|
18
|
+
handle_unexpected
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
private
|
|
23
|
+
|
|
24
|
+
def handle_push(request, logger)
|
|
25
|
+
klass = Txgh::Handlers::Github::PushHandler
|
|
26
|
+
new(request, logger).handle(klass)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def handle_delete(request, logger)
|
|
30
|
+
klass = Txgh::Handlers::Github::DeleteHandler
|
|
31
|
+
new(request, logger).handle(klass)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def handle_unexpected
|
|
35
|
+
respond_with_error(400, 'Unexpected event type')
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
include ResponseHelpers
|
|
41
|
+
|
|
42
|
+
attr_reader :request, :logger
|
|
43
|
+
|
|
44
|
+
def initialize(request, logger)
|
|
45
|
+
@request = request
|
|
46
|
+
@logger = logger
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def handle(klass)
|
|
50
|
+
handle_safely do
|
|
51
|
+
handler = klass.new(
|
|
52
|
+
project: config.transifex_project,
|
|
53
|
+
repo: config.github_repo,
|
|
54
|
+
payload: payload,
|
|
55
|
+
logger: logger
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
handler.execute
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
private
|
|
63
|
+
|
|
64
|
+
def handle_safely
|
|
65
|
+
if authentic_request?
|
|
66
|
+
yield
|
|
67
|
+
else
|
|
68
|
+
respond_with_error(401, 'Unauthorized')
|
|
69
|
+
end
|
|
70
|
+
rescue => e
|
|
71
|
+
respond_with_error(500, "Internal server error: #{e.message}", e)
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def payload
|
|
75
|
+
@payload ||= if request.params[:payload]
|
|
76
|
+
JSON.parse(request.params[:payload])
|
|
77
|
+
else
|
|
78
|
+
JSON.parse(request.body.read)
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def github_repo_name
|
|
83
|
+
payload['repository']['full_name']
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def config
|
|
87
|
+
@config ||= Txgh::Config::KeyManager.config_from_repo(github_repo_name)
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def repo
|
|
91
|
+
config.github_repo
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def authentic_request?
|
|
95
|
+
if repo.webhook_protected?
|
|
96
|
+
GithubRequestAuth.authentic_request?(
|
|
97
|
+
request, repo.webhook_secret
|
|
98
|
+
)
|
|
99
|
+
else
|
|
100
|
+
true
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
end
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
require 'mime/types'
|
|
2
|
+
|
|
3
|
+
module Txgh
|
|
4
|
+
module Handlers
|
|
5
|
+
class StreamResponse
|
|
6
|
+
attr_reader :attachment, :enum
|
|
7
|
+
|
|
8
|
+
def initialize(attachment, enum)
|
|
9
|
+
@attachment = attachment
|
|
10
|
+
@enum = enum
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def write_to(stream)
|
|
14
|
+
raise NotImplementedError,
|
|
15
|
+
"please implement #{__method__} in derived classes"
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def file_extension
|
|
19
|
+
raise NotImplementedError,
|
|
20
|
+
"please implement #{__method__} in derived classes"
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def headers
|
|
24
|
+
@headers ||= {
|
|
25
|
+
'Content-Disposition' => "attachment; filename=\"#{attachment}#{file_extension}\"",
|
|
26
|
+
'Content-Type' => MIME::Types.type_for(file_extension).first.content_type
|
|
27
|
+
}
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def streaming?
|
|
31
|
+
true
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def error
|
|
35
|
+
nil
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
require 'rubygems/package'
|
|
2
|
+
require 'stringio'
|
|
3
|
+
require 'zlib'
|
|
4
|
+
|
|
5
|
+
module Txgh
|
|
6
|
+
module Handlers
|
|
7
|
+
class TgzStreamResponse < StreamResponse
|
|
8
|
+
PERMISSIONS = 0644
|
|
9
|
+
|
|
10
|
+
def write_to(stream)
|
|
11
|
+
Zlib::GzipWriter.wrap(stream) do |gz|
|
|
12
|
+
pipe = StringIO.new('', 'wb')
|
|
13
|
+
tar = Gem::Package::TarWriter.new(pipe)
|
|
14
|
+
|
|
15
|
+
enum.each do |file_name, contents|
|
|
16
|
+
tar.add_file(file_name, PERMISSIONS) do |f|
|
|
17
|
+
f.write(contents)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
flush(tar, pipe, gz)
|
|
21
|
+
stream.flush
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
flush(tar, pipe, gz)
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def file_extension
|
|
29
|
+
'.tgz'
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
private
|
|
33
|
+
|
|
34
|
+
def flush(tar, pipe, gz)
|
|
35
|
+
tar.flush
|
|
36
|
+
gz.write(pipe.string)
|
|
37
|
+
pipe.reopen('')
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
require 'logger'
|
|
2
|
+
|
|
3
|
+
module Txgh
|
|
4
|
+
module Handlers
|
|
5
|
+
module Transifex
|
|
6
|
+
class HookHandler
|
|
7
|
+
include CategorySupport
|
|
8
|
+
include ResponseHelpers
|
|
9
|
+
|
|
10
|
+
attr_reader :project, :repo, :resource_slug, :language, :logger
|
|
11
|
+
|
|
12
|
+
def initialize(options = {})
|
|
13
|
+
@project = options.fetch(:project)
|
|
14
|
+
@repo = options.fetch(:repo)
|
|
15
|
+
@resource_slug = options.fetch(:resource_slug)
|
|
16
|
+
@language = options.fetch(:language)
|
|
17
|
+
@logger = options.fetch(:logger) { Logger.new(STDOUT) }
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def execute
|
|
21
|
+
logger.info(resource_slug)
|
|
22
|
+
|
|
23
|
+
if tx_config
|
|
24
|
+
if tx_resource
|
|
25
|
+
committer = ResourceCommitter.new(project, repo, logger)
|
|
26
|
+
committer.commit_resource(tx_resource, branch, language)
|
|
27
|
+
|
|
28
|
+
respond_with(200, true)
|
|
29
|
+
else
|
|
30
|
+
respond_with_error(
|
|
31
|
+
404, "Could not find resource '#{resource_slug}' in config"
|
|
32
|
+
)
|
|
33
|
+
end
|
|
34
|
+
else
|
|
35
|
+
respond_with_error(
|
|
36
|
+
404, "Could not find configuration for branch '#{branch}'"
|
|
37
|
+
)
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
private
|
|
42
|
+
|
|
43
|
+
def tx_config
|
|
44
|
+
@tx_config ||= Txgh::Config::TxManager.tx_config(project, repo, branch)
|
|
45
|
+
rescue ConfigNotFoundError, TxghError
|
|
46
|
+
nil
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def branch
|
|
50
|
+
@branch ||= begin
|
|
51
|
+
branch_candidate = if process_all_branches?
|
|
52
|
+
resource = project.api.get_resource(project.name, resource_slug)
|
|
53
|
+
categories = deserialize_categories(Array(resource['categories']))
|
|
54
|
+
categories['branch']
|
|
55
|
+
else
|
|
56
|
+
repo.branch || 'master'
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
Utils.absolute_branch(branch_candidate)
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def tx_resource
|
|
64
|
+
@tx_resource ||= if process_all_branches?
|
|
65
|
+
tx_config.resource(resource_slug, branch)
|
|
66
|
+
else
|
|
67
|
+
tx_config.resource(resource_slug)
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def process_all_branches?
|
|
72
|
+
repo.process_all_branches?
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
require 'uri'
|
|
2
|
+
|
|
3
|
+
module Txgh
|
|
4
|
+
module Handlers
|
|
5
|
+
module Transifex
|
|
6
|
+
class RequestHandler
|
|
7
|
+
class << self
|
|
8
|
+
|
|
9
|
+
def handle_request(request, logger)
|
|
10
|
+
new(request, logger).handle(Txgh::Handlers::Transifex::HookHandler)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
include ResponseHelpers
|
|
16
|
+
|
|
17
|
+
attr_reader :request, :logger
|
|
18
|
+
|
|
19
|
+
def initialize(request, logger)
|
|
20
|
+
@request = request
|
|
21
|
+
@logger = logger
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def handle(klass)
|
|
25
|
+
handle_safely do
|
|
26
|
+
handler = klass.new(
|
|
27
|
+
project: config.transifex_project,
|
|
28
|
+
repo: config.github_repo,
|
|
29
|
+
resource_slug: payload['resource'],
|
|
30
|
+
language: payload['language'],
|
|
31
|
+
logger: logger
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
handler.execute
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
private
|
|
39
|
+
|
|
40
|
+
def handle_safely
|
|
41
|
+
if authentic_request?
|
|
42
|
+
yield
|
|
43
|
+
else
|
|
44
|
+
respond_with_error(401, 'Unauthorized')
|
|
45
|
+
end
|
|
46
|
+
rescue => e
|
|
47
|
+
respond_with_error(500, "Internal server error: #{e.message}", e)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def authentic_request?
|
|
51
|
+
if project.webhook_protected?
|
|
52
|
+
TransifexRequestAuth.authentic_request?(
|
|
53
|
+
request, project.webhook_secret
|
|
54
|
+
)
|
|
55
|
+
else
|
|
56
|
+
true
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def project
|
|
61
|
+
config.transifex_project
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def config
|
|
65
|
+
@config ||= Txgh::Config::KeyManager.config_from_project(payload['project'])
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def payload
|
|
69
|
+
@payload ||= begin
|
|
70
|
+
request.body.rewind
|
|
71
|
+
Hash[URI.decode_www_form(request.body.read)]
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|